Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Difference From f58ef51a621740f2 To ec237b012300b80f
2006-01-20
| ||
16:08 | 1.0.24.5 check-in: c79755ec5b user: rmsimpson tags: sourceforge | |
16:08 | no message check-in: f58ef51a62 user: rmsimpson tags: sourceforge | |
15:59 | no message check-in: da8e102e28 user: rmsimpson tags: sourceforge | |
2005-03-01
| ||
17:32 | Initial revision check-in: 5b6332ffaa user: rmsimpson tags: sourceforge | |
16:04 | Initial checkin Closed-Leaf check-in: 3ca8c53212 user: rmsimpson tags: start, sourceforge | |
16:04 | Initial revision check-in: ec237b0123 user: rmsimpson tags: trunk, sourceforge | |
Deleted Doc/SQLite.NET.Internal.chm.
cannot compute difference between binary files
Deleted Doc/SQLite.NET.Internal.ndoc.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to Doc/SQLite.NET.chm.
cannot compute difference between binary files
Changes to Doc/SQLite.NET.ndoc.
1 2 | <project SchemaVersion="1.3"> <assemblies> | | | 1 2 3 4 5 6 7 8 9 10 | <project SchemaVersion="1.3"> <assemblies> <assembly location="..\System.Data.SQLite\bin\Release\System.Data.SQLite.dll" documentation="..\System.Data.SQLite\bin\Release\System.Data.SQLite.xml" /> </assemblies> <documenters> <documenter name="JavaDoc"> <property name="OutputDirectory" value=".\doc\" /> </documenter> <documenter name="LaTeX"> <property name="OutputDirectory" value=".\doc\" /> |
︙ | ︙ |
Deleted Doc/System.Data.SQLite.XML.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to Doc/ndoc.log.
︙ | ︙ | |||
23 24 25 26 27 28 29 | System.Data.SQLite.SQLiteCommand.html System.Data.SQLite.SQLiteCommandMembers.html System.Data.SQLite.SQLiteCommandConstructor.html System.Data.SQLite.SQLiteCommandConstructor1.html System.Data.SQLite.SQLiteCommandConstructor2.html System.Data.SQLite.SQLiteCommandConstructor3.html System.Data.SQLite.SQLiteCommandConstructor4.html | < | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | System.Data.SQLite.SQLiteCommand.html System.Data.SQLite.SQLiteCommandMembers.html System.Data.SQLite.SQLiteCommandConstructor.html System.Data.SQLite.SQLiteCommandConstructor1.html System.Data.SQLite.SQLiteCommandConstructor2.html System.Data.SQLite.SQLiteCommandConstructor3.html System.Data.SQLite.SQLiteCommandConstructor4.html System.Data.SQLite.SQLiteCommandProperties.html System.Data.SQLite.SQLiteCommand.CommandText.html System.Data.SQLite.SQLiteCommand.CommandTimeout.html System.Data.SQLite.SQLiteCommand.CommandType.html System.Data.SQLite.SQLiteCommand.DesignTimeVisible.html System.Data.SQLite.SQLiteCommand.UpdatedRowSource.html System.Data.SQLite.SQLiteCommandMethods.html |
︙ | ︙ | |||
87 88 89 90 91 92 93 94 95 96 97 98 99 100 | System.Data.SQLite.SQLiteConvert.ToDateTime.html System.Data.SQLite.SQLiteConvert.ToString_overloads.html System.Data.SQLite.SQLiteConvert.ToString_overload_2.html System.Data.SQLite.SQLiteConvert.ToString_overload_1.html System.Data.SQLite.SQLiteConvert.ToUTF8_overloads.html System.Data.SQLite.SQLiteConvert.ToUTF8_overload_2.html System.Data.SQLite.SQLiteConvert.ToUTF8_overload_1.html System.Data.SQLite.SQLiteDataAdapter.html System.Data.SQLite.SQLiteDataAdapterMembers.html System.Data.SQLite.SQLiteDataAdapterConstructor.html System.Data.SQLite.SQLiteDataAdapterConstructor1.html System.Data.SQLite.SQLiteDataAdapterConstructor2.html System.Data.SQLite.SQLiteDataAdapterConstructor3.html System.Data.SQLite.SQLiteDataAdapterConstructor4.html | > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | System.Data.SQLite.SQLiteConvert.ToDateTime.html System.Data.SQLite.SQLiteConvert.ToString_overloads.html System.Data.SQLite.SQLiteConvert.ToString_overload_2.html System.Data.SQLite.SQLiteConvert.ToString_overload_1.html System.Data.SQLite.SQLiteConvert.ToUTF8_overloads.html System.Data.SQLite.SQLiteConvert.ToUTF8_overload_2.html System.Data.SQLite.SQLiteConvert.ToUTF8_overload_1.html System.Data.SQLite.SQLiteConvert.TryToDateTime.html System.Data.SQLite.SQLiteDataAdapter.html System.Data.SQLite.SQLiteDataAdapterMembers.html System.Data.SQLite.SQLiteDataAdapterConstructor.html System.Data.SQLite.SQLiteDataAdapterConstructor1.html System.Data.SQLite.SQLiteDataAdapterConstructor2.html System.Data.SQLite.SQLiteDataAdapterConstructor3.html System.Data.SQLite.SQLiteDataAdapterConstructor4.html |
︙ | ︙ | |||
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | System.Data.SQLite.SQLiteException.html System.Data.SQLite.SQLiteExceptionMembers.html System.Data.SQLite.SQLiteFactory.html System.Data.SQLite.SQLiteFactoryMembers.html System.Data.SQLite.SQLiteFactoryConstructor.html System.Data.SQLite.SQLiteFactoryFields.html System.Data.SQLite.SQLiteFactory.Instance.html System.Data.SQLite.SQLiteFactoryMethods.html System.Data.SQLite.SQLiteFactory.CreateCommand.html System.Data.SQLite.SQLiteFactory.CreateCommandBuilder.html System.Data.SQLite.SQLiteFactory.CreateConnection.html System.Data.SQLite.SQLiteFactory.CreateConnectionStringBuilder.html System.Data.SQLite.SQLiteFactory.CreateDataAdapter.html System.Data.SQLite.SQLiteFactory.CreateParameter.html System.Data.SQLite.SQLiteFunction.html System.Data.SQLite.SQLiteFunctionMembers.html System.Data.SQLite.SQLiteFunctionConstructor.html System.Data.SQLite.SQLiteFunctionProperties.html System.Data.SQLite.SQLiteFunction.SQLiteConvert.html System.Data.SQLite.SQLiteFunctionMethods.html System.Data.SQLite.SQLiteFunction.Compare.html System.Data.SQLite.SQLiteFunction.Dispose_overloads.html System.Data.SQLite.SQLiteFunction.Dispose_overload_2.html System.Data.SQLite.SQLiteFunction.Dispose_overload_1.html System.Data.SQLite.SQLiteFunction.Final.html System.Data.SQLite.SQLiteFunction.Invoke.html System.Data.SQLite.SQLiteFunction.Step.html System.Data.SQLite.SQLiteFunctionAttribute.html System.Data.SQLite.SQLiteFunctionAttributeMembers.html System.Data.SQLite.SQLiteFunctionAttributeConstructor.html System.Data.SQLite.SQLiteFunctionAttributeFields.html System.Data.SQLite.SQLiteFunctionAttribute.Arguments.html System.Data.SQLite.SQLiteFunctionAttribute.FuncType.html | > > > | 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | System.Data.SQLite.SQLiteException.html System.Data.SQLite.SQLiteExceptionMembers.html System.Data.SQLite.SQLiteFactory.html System.Data.SQLite.SQLiteFactoryMembers.html System.Data.SQLite.SQLiteFactoryConstructor.html System.Data.SQLite.SQLiteFactoryFields.html System.Data.SQLite.SQLiteFactory.Instance.html System.Data.SQLite.SQLiteFactoryProperties.html System.Data.SQLite.SQLiteFactory.SupportedClasses.html System.Data.SQLite.SQLiteFactoryMethods.html System.Data.SQLite.SQLiteFactory.CreateCommand.html System.Data.SQLite.SQLiteFactory.CreateCommandBuilder.html System.Data.SQLite.SQLiteFactory.CreateConnection.html System.Data.SQLite.SQLiteFactory.CreateConnectionStringBuilder.html System.Data.SQLite.SQLiteFactory.CreateDataAdapter.html System.Data.SQLite.SQLiteFactory.CreateParameter.html System.Data.SQLite.SQLiteFunction.html System.Data.SQLite.SQLiteFunctionMembers.html System.Data.SQLite.SQLiteFunctionConstructor.html System.Data.SQLite.SQLiteFunctionProperties.html System.Data.SQLite.SQLiteFunction.SQLiteConvert.html System.Data.SQLite.SQLiteFunctionMethods.html System.Data.SQLite.SQLiteFunction.Compare.html System.Data.SQLite.SQLiteFunction.Dispose_overloads.html System.Data.SQLite.SQLiteFunction.Dispose_overload_2.html System.Data.SQLite.SQLiteFunction.Dispose_overload_1.html System.Data.SQLite.SQLiteFunction.Final.html System.Data.SQLite.SQLiteFunction.Invoke.html System.Data.SQLite.SQLiteFunction.RegisterFunction.html System.Data.SQLite.SQLiteFunction.Step.html System.Data.SQLite.SQLiteFunctionAttribute.html System.Data.SQLite.SQLiteFunctionAttributeMembers.html System.Data.SQLite.SQLiteFunctionAttributeConstructor.html System.Data.SQLite.SQLiteFunctionAttributeFields.html System.Data.SQLite.SQLiteFunctionAttribute.Arguments.html System.Data.SQLite.SQLiteFunctionAttribute.FuncType.html |
︙ | ︙ | |||
184 185 186 187 188 189 190 | System.Data.SQLite.SQLiteParameterConstructor8.html System.Data.SQLite.SQLiteParameterConstructor9.html System.Data.SQLite.SQLiteParameterConstructor10.html System.Data.SQLite.SQLiteParameterConstructor11.html System.Data.SQLite.SQLiteParameterConstructor12.html System.Data.SQLite.SQLiteParameterConstructor13.html System.Data.SQLite.SQLiteParameterConstructor14.html | < < < > | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | System.Data.SQLite.SQLiteParameterConstructor8.html System.Data.SQLite.SQLiteParameterConstructor9.html System.Data.SQLite.SQLiteParameterConstructor10.html System.Data.SQLite.SQLiteParameterConstructor11.html System.Data.SQLite.SQLiteParameterConstructor12.html System.Data.SQLite.SQLiteParameterConstructor13.html System.Data.SQLite.SQLiteParameterConstructor14.html System.Data.SQLite.SQLiteParameterProperties.html System.Data.SQLite.SQLiteParameter.DbType.html System.Data.SQLite.SQLiteParameter.Direction.html System.Data.SQLite.SQLiteParameter.IsNullable.html System.Data.SQLite.SQLiteParameter.Offset.html System.Data.SQLite.SQLiteParameter.ParameterName.html System.Data.SQLite.SQLiteParameter.Size.html System.Data.SQLite.SQLiteParameter.SourceColumn.html System.Data.SQLite.SQLiteParameter.SourceColumnNullMapping.html System.Data.SQLite.SQLiteParameter.SourceVersion.html System.Data.SQLite.SQLiteParameter.Value.html System.Data.SQLite.SQLiteParameterMethods.html System.Data.SQLite.SQLiteParameter.CopyTo.html System.Data.SQLite.SQLiteParameter.ResetDbType.html System.Data.SQLite.SQLiteParameterCollection.html System.Data.SQLite.SQLiteParameterCollectionMembers.html System.Data.SQLite.SQLiteParameterCollectionProperties.html System.Data.SQLite.SQLiteParameterCollection.Count.html System.Data.SQLite.SQLiteParameterCollection.IsFixedSize.html System.Data.SQLite.SQLiteParameterCollection.IsReadOnly.html |
︙ | ︙ | |||
250 251 252 253 254 255 256 | Compiling Html Help file Microsoft HTML Help Compiler 4.74.8702 Compiling c:\src\SQLite.NET\Doc\ndoc_msdn_temp\SQLite.NET.chm Compile time: 0 minutes, 3 seconds | | | | | | 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | Compiling Html Help file Microsoft HTML Help Compiler 4.74.8702 Compiling c:\src\SQLite.NET\Doc\ndoc_msdn_temp\SQLite.NET.chm Compile time: 0 minutes, 3 seconds 233 Topics 1,346 Local links 0 Internet links 8 Graphics Created c:\src\SQLite.NET\Doc\ndoc_msdn_temp\SQLite.NET.chm, 135,017 bytes Compression decreased file by 734,402 bytes. Html Help compile complete Done. |
Deleted SQLite.Designer/AssemblyInfo.cs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted SQLite.Designer/SQLite.Designer.csproj.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted SQLite.Designer/SQLiteDataObjectIdentifierResolver.cs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted SQLite.Designer/SQLiteDataSourceInformation.cs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted SQLite.Designer/SR.Designer.cs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted SQLite.Designer/SR.resx.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted SQLite.Interop/AssemblyInfo.cpp.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted SQLite.Interop/SQLite.Interop.rc.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to SQLite.Interop/SQLite.Interop.vcproj.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?xml version="1.0" encoding="Windows-1252"?> <VisualStudioProject ProjectType="Visual C++" Version="8.00" Name="SQLite.Interop" ProjectGUID="{10B51CE8-A838-44DE-BD82-B658F0296F80}" RootNamespace="SQLite.Interop" Keyword="Win32Proj" > <Platforms> <Platform Name="Win32" /> | < < < < < < < < < | | | < < < < < | < | > | < > | | < | > > > | < | | < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | <?xml version="1.0" encoding="Windows-1252"?> <VisualStudioProject ProjectType="Visual C++" Version="8.00" Name="SQLite.Interop" ProjectGUID="{10B51CE8-A838-44DE-BD82-B658F0296F80}" RootNamespace="SQLite.Interop" Keyword="Win32Proj" > <Platforms> <Platform Name="Win32" /> </Platforms> <ToolFiles> </ToolFiles> <Configurations> <Configuration Name="Debug|Win32" OutputDirectory="Debug" IntermediateDirectory="Debug" ConfigurationType="2" CharacterSet="2" > <Tool Name="VCPreBuildEventTool" /> <Tool Name="VCCustomBuildTool" /> <Tool Name="VCXMLDataGeneratorTool" /> <Tool Name="VCWebServiceProxyGeneratorTool" /> <Tool Name="VCMIDLTool" /> <Tool Name="VCCLCompilerTool" Optimization="0" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NO_TCL;THREADSAFE" StringPooling="true" ExceptionHandling="0" BasicRuntimeChecks="3" RuntimeLibrary="1" EnableFunctionLevelLinking="true" UsePrecompiledHeader="0" WarningLevel="1" DebugInformationFormat="3" /> <Tool Name="VCManagedResourceCompilerTool" /> <Tool Name="VCResourceCompilerTool" /> <Tool Name="VCPreLinkEventTool" /> <Tool Name="VCLinkerTool" OutputFile="$(OutDir)/$(ProjectName).dll" LinkIncremental="1" GenerateManifest="false" GenerateDebugInformation="true" ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb" SubSystem="2" ImportLibrary="$(OutDir)/$(ProjectName).lib" TargetMachine="1" /> <Tool Name="VCALinkTool" /> <Tool Name="VCManifestTool" /> <Tool Name="VCXDCMakeTool" /> <Tool Name="VCBscMakeTool" /> |
︙ | ︙ | |||
107 108 109 110 111 112 113 | Name="VCWebDeploymentTool" /> <Tool Name="VCPostBuildEventTool" /> </Configuration> <Configuration | | | | | < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > | | < | > | | | > | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | Name="VCWebDeploymentTool" /> <Tool Name="VCPostBuildEventTool" /> </Configuration> <Configuration Name="Release|Win32" OutputDirectory="Release" IntermediateDirectory="Release" ConfigurationType="2" CharacterSet="2" WholeProgramOptimization="0" > <Tool Name="VCPreBuildEventTool" /> <Tool Name="VCCustomBuildTool" /> <Tool Name="VCXMLDataGeneratorTool" /> <Tool Name="VCWebServiceProxyGeneratorTool" /> <Tool Name="VCMIDLTool" /> <Tool Name="VCCLCompilerTool" Optimization="2" FavorSizeOrSpeed="1" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;NO_TCL;THREADSAFE" StringPooling="true" ExceptionHandling="0" RuntimeLibrary="0" BufferSecurityCheck="false" EnableFunctionLevelLinking="true" UsePrecompiledHeader="0" WarningLevel="1" DebugInformationFormat="0" /> <Tool Name="VCManagedResourceCompilerTool" /> <Tool Name="VCResourceCompilerTool" /> <Tool Name="VCPreLinkEventTool" /> <Tool Name="VCLinkerTool" OutputFile="$(OutDir)/$(ProjectName).dll" LinkIncremental="1" GenerateManifest="false" SubSystem="2" OptimizeReferences="2" EnableCOMDATFolding="2" ImportLibrary="$(OutDir)/$(ProjectName).lib" TargetMachine="1" /> <Tool Name="VCALinkTool" /> <Tool Name="VCManifestTool" /> <Tool Name="VCXDCMakeTool" /> <Tool Name="VCBscMakeTool" /> |
︙ | ︙ | |||
713 714 715 716 717 718 719 | Name="Source Files" Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > <File RelativePath=".\src\alter.c" > | < < < < < < < < < < < < | 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | Name="Source Files" Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > <File RelativePath=".\src\alter.c" > </File> <File RelativePath=".\src\attach.c" > </File> <File RelativePath=".\src\auth.c" > </File> <File RelativePath=".\src\btree.c" > </File> <File RelativePath=".\src\build.c" > </File> <File RelativePath=".\src\date.c" > </File> <File RelativePath=".\src\delete.c" |
︙ | ︙ | |||
779 780 781 782 783 784 785 | > </File> <File RelativePath=".\src\opcodes.c" > </File> <File | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < < < < < < < | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | > </File> <File RelativePath=".\src\opcodes.c" > </File> <File RelativePath=".\src\os_unix.c" > </File> <File RelativePath=".\src\os_win.c" > </File> <File RelativePath=".\src\pager.c" > </File> <File RelativePath=".\src\parse.c" > </File> <File RelativePath=".\src\pragma.c" > </File> <File RelativePath=".\src\printf.c" > </File> <File RelativePath=".\src\random.c" > </File> <File RelativePath=".\src\select.c" > </File> <File RelativePath=".\src\table.c" > </File> <File RelativePath=".\src\tclsqlite.c" > </File> <File RelativePath=".\src\tokenize.c" > </File> <File RelativePath=".\src\trigger.c" |
︙ | ︙ | |||
981 982 983 984 985 986 987 | <File RelativePath=".\src\vdbeapi.c" > </File> <File RelativePath=".\src\vdbeaux.c" > | < < < < | > < < < < < < < < < < < < < < < < | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | <File RelativePath=".\src\vdbeapi.c" > </File> <File RelativePath=".\src\vdbeaux.c" > </File> <File RelativePath=".\src\vdbemem.c" > </File> <File RelativePath=".\src\where.c" > </File> </Filter> <Filter Name="Header Files" Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > <File RelativePath=".\interop.h" FileType="0" > </File> <File RelativePath=".\src\sqlite3.h" > </File> </Filter> </Files> <Globals> </Globals> </VisualStudioProject> |
Deleted SQLite.Interop/crypt.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted SQLite.Interop/fixsource.vbs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted SQLite.Interop/interop.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Added SQLite.Interop/interop.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 | /* This interop file must be included at or near the top of the select.c file of the SQLite3 source distribution. generateColumnNames() in the select.c must be renamed to _generateColumnNames */ #include "os.h" #include "sqliteint.h" static void generateColumnTypes( Parse *pParse, /* Parser context */ SrcList *pTabList, /* List of tables */ ExprList *pEList /* Expressions defining the result set */ ); static void _generateColumnNames( Parse *pParse, /* Parser context */ SrcList *pTabList, /* List of tables */ ExprList *pEList /* Expressions defining the result set */ ); /* ** Generate code that will tell the VDBE the names of columns ** in the result set. This information is used to provide the ** azCol[] values in the callback. */ static void generateColumnNames( Parse *pParse, /* Parser context */ SrcList *pTabList, /* List of tables */ ExprList *pEList /* Expressions defining the result set */ ){ Vdbe *v = pParse->pVdbe; int i, j; sqlite3 *db = pParse->db; int fullNames, shortNames; int realNames; /*** ADDED - SQLite.Interop ***/ realNames = (db->flags & 0x01000000)!=0; /*** ADDED - SQLite.Interop ***/ if (!realNames) // Default to normal Sqlite3 /*** ADDED - SQLite.Interop ***/ { /*** ADDED - SQLite.Interop ***/ _generateColumnNames(pParse, pTabList, pEList); /*** ADDED - SQLite.Interop ***/ return; /*** ADDED - SQLite.Interop ***/ } /*** ADDED - SQLite.Interop ***/ #ifndef SQLITE_OMIT_EXPLAIN /* If this is an EXPLAIN, skip this step */ if( pParse->explain ){ return; } #endif assert( v!=0 ); if( pParse->colNamesSet || v==0 || sqlite3_malloc_failed ) return; pParse->colNamesSet = 1; fullNames = (db->flags & SQLITE_FullColNames)!=0; shortNames = (db->flags & SQLITE_ShortColNames)!=0; if (realNames) fullNames = 1; /*** ADDED - SQLite.Interop ***/ sqlite3VdbeSetNumCols(v, pEList->nExpr); for(i=0; i<pEList->nExpr; i++){ Expr *p; p = pEList->a[i].pExpr; if( p==0 ) continue; if( pEList->a[i].zName && (realNames == 0 || p->op != TK_COLUMN)){ /*** CHANGED - SQLite.Interop ***/ char *zName = pEList->a[i].zName; sqlite3VdbeSetColName(v, i, zName, strlen(zName)); continue; } if( p->op==TK_COLUMN && pTabList ){ Table *pTab; char *zCol; int iCol = p->iColumn; for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){} assert( j<pTabList->nSrc ); pTab = pTabList->a[j].pTab; if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); if( iCol<0 ){ zCol = "rowid"; }else{ zCol = pTab->aCol[iCol].zName; } if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){ sqlite3VdbeSetColName(v, i, p->span.z, p->span.n); }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){ char *zName = 0; char *zTab; char *zDb = 0; /*** ADDED - SQLite.Interop ***/ zTab = pTabList->a[j].zAlias; if( fullNames || zTab==0 ){ if (pTab->iDb > 1) zDb = db->aDb[pTab->iDb].zName; /*** ADDED - SQLite.Interop ***/ zTab = pTab->zName; } if (!zDb || !realNames) sqlite3SetString(&zName, zTab, ".", zCol, 0); /*** CHANGED - SQLite.Interop ***/ else sqlite3SetString(&zName, zDb, ".", zTab, ".", zCol, 0); /*** ADDED - SQLite.Interop ***/ sqlite3VdbeSetColName(v, i, zName, P3_DYNAMIC); }else{ sqlite3VdbeSetColName(v, i, zCol, strlen(zCol)); } }else if( p->span.z && p->span.z[0] ){ sqlite3VdbeSetColName(v, i, p->span.z, p->span.n); /* sqlite3VdbeCompressSpace(v, addr); */ }else{ char zName[30]; assert( p->op!=TK_COLUMN || pTabList==0 ); sprintf(zName, "column%d", i+1); sqlite3VdbeSetColName(v, i, zName, 0); } } generateColumnTypes(pParse, pTabList, pEList); } #ifdef OS_WIN typedef void (__stdcall *SQLITEUSERFUNC)(void *, int, void **); typedef int (__stdcall *SQLITECOLLATION)(int, const void *, int, const void*); // Callback wrappers int sqlite3_interop_collationfunc(void *pv, int len1, const void *pv1, int len2, const void *pv2) { SQLITECOLLATION *p = (SQLITECOLLATION *)pv; return p[0](len1, pv1, len2, pv2); } void sqlite3_interop_func(sqlite3_context *pctx, int n, sqlite3_value **pv) { SQLITEUSERFUNC *pf = (SQLITEUSERFUNC *)sqlite3_user_data(pctx); pf[0](pctx, n, pv); } void sqlite3_interop_step(sqlite3_context *pctx, int n, sqlite3_value **pv) { SQLITEUSERFUNC *pf = (SQLITEUSERFUNC *)sqlite3_user_data(pctx); pf[1](pctx, n, pv); } void sqlite3_interop_final(sqlite3_context *pctx) { SQLITEUSERFUNC *pf = (SQLITEUSERFUNC *)sqlite3_user_data(pctx); pf[2](pctx, 0, 0); } __declspec(dllexport) void __stdcall sqlite3_function_free_callbackcookie(void *pCookie) { if (pCookie) free(pCookie); } // sqlite3 wrappers __declspec(dllexport) const char * __stdcall sqlite3_libversion_interop(int *plen) { const char *val = sqlite3_libversion(); *plen = (val != 0) ? strlen(val) : 0; return val; } __declspec(dllexport) int __stdcall sqlite3_libversion_number_interop(void) { return sqlite3_libversion_number(); } __declspec(dllexport) int __stdcall sqlite3_close_interop(sqlite3 *db) { return sqlite3_close(db); } __declspec(dllexport) int __stdcall sqlite3_exec_interop(sqlite3 *db, const char *sql, sqlite3_callback cb, void *pv, char **errmsg, int *plen) { int n = sqlite3_exec(db, sql, cb, pv, errmsg); *plen = (*errmsg != 0) ? strlen(*errmsg) : 0; return n; } __declspec(dllexport) sqlite_int64 __stdcall sqlite3_last_insert_rowid_interop(sqlite3 *db) { return sqlite3_last_insert_rowid(db); } __declspec(dllexport) int __stdcall sqlite3_changes_interop(sqlite3 *db) { return sqlite3_changes(db); } __declspec(dllexport) int __stdcall sqlite3_total_changes_interop(sqlite3 *db) { return sqlite3_total_changes(db); } __declspec(dllexport) void __stdcall sqlite3_interrupt_interop(sqlite3 *db) { sqlite3_interrupt(db); } __declspec(dllexport) int __stdcall sqlite3_complete_interop(const char *sql) { return sqlite3_complete(sql); } __declspec(dllexport) int __stdcall sqlite3_complete16_interop(const void *sql) { return sqlite3_complete16(sql); } __declspec(dllexport) int __stdcall sqlite3_busy_handler_interop(sqlite3 *db, int(*cb)(void *, int), void *pv) { return sqlite3_busy_handler(db, cb, pv); } __declspec(dllexport) int __stdcall sqlite3_busy_timeout_interop(sqlite3 *db, int ms) { return sqlite3_busy_timeout(db, ms); } __declspec(dllexport) int __stdcall sqlite3_get_table_interop(sqlite3 *db, const char *sql, char ***resultp, int *nrow, int *ncolumn, char **errmsg, int *plen) { int n = sqlite3_get_table(db, sql, resultp, nrow, ncolumn, errmsg); *plen = (*errmsg != 0) ? strlen((char *)*errmsg) : 0; return n; } __declspec(dllexport) void __stdcall sqlite3_free_table_interop(char **result) { sqlite3_free_table(result); } __declspec(dllexport) void __stdcall sqlite3_free_interop(char *z) { sqlite3_free(z); } __declspec(dllexport) int __stdcall sqlite3_open_interop(const char*filename, sqlite3 **ppdb) { return sqlite3_open(filename, ppdb); } __declspec(dllexport) int __stdcall sqlite3_open16_interop(const void *filename, sqlite3 **ppdb) { return sqlite3_open16(filename, ppdb); } __declspec(dllexport) int __stdcall sqlite3_errcode_interop(sqlite3 *db) { return sqlite3_errcode(db); } __declspec(dllexport) const char * __stdcall sqlite3_errmsg_interop(sqlite3 *db, int *plen) { const char *pval = sqlite3_errmsg(db); *plen = (pval != 0) ? strlen(pval) : 0; return pval; } __declspec(dllexport) const void * __stdcall sqlite3_errmsg16_interop(sqlite3 *db) { return sqlite3_errmsg16(db); } __declspec(dllexport) int __stdcall sqlite3_prepare_interop(sqlite3 *db, const char *sql, int nbytes, sqlite3_stmt **ppstmt, const char **pztail, int *plen) { int n = sqlite3_prepare(db, sql, nbytes, ppstmt, pztail); *plen = (*pztail != 0) ? strlen(*pztail) : 0; return n; } __declspec(dllexport) int __stdcall sqlite3_prepare16_interop(sqlite3 *db, const void *sql, int nbytes, sqlite3_stmt **ppstmt, const void **pztail) { return sqlite3_prepare16(db, sql, nbytes, ppstmt, pztail); } __declspec(dllexport) int __stdcall sqlite3_bind_blob_interop(sqlite3_stmt *stmt, int iCol, const void *pv, int n, void(*cb)(void*)) { return sqlite3_bind_blob(stmt, iCol, pv, n, cb); } __declspec(dllexport) int __stdcall sqlite3_bind_double_interop(sqlite3_stmt *stmt, int iCol, double *val) { return sqlite3_bind_double(stmt,iCol,*val); } __declspec(dllexport) int __stdcall sqlite3_bind_int_interop(sqlite3_stmt *stmt, int iCol, int val) { return sqlite3_bind_int(stmt, iCol, val); } __declspec(dllexport) int __stdcall sqlite3_bind_int64_interop(sqlite3_stmt *stmt, int iCol, sqlite_int64 *val) { return sqlite3_bind_int64(stmt,iCol,*val); } __declspec(dllexport) int __stdcall sqlite3_bind_null_interop(sqlite3_stmt *stmt, int iCol) { return sqlite3_bind_null(stmt, iCol); } __declspec(dllexport) int __stdcall sqlite3_bind_text_interop(sqlite3_stmt *stmt, int iCol, const char *val, int n, void(*cb)(void *)) { return sqlite3_bind_text(stmt, iCol, val, n, cb); } __declspec(dllexport) int __stdcall sqlite3_bind_text16_interop(sqlite3_stmt *stmt, int iCol, const void *val, int n, void(*cb)(void *)) { return sqlite3_bind_text16(stmt, iCol, val, n, cb); } __declspec(dllexport) int __stdcall sqlite3_bind_parameter_count_interop(sqlite3_stmt *stmt) { return sqlite3_bind_parameter_count(stmt); } __declspec(dllexport) const char * __stdcall sqlite3_bind_parameter_name_interop(sqlite3_stmt *stmt, int iCol, int *plen) { const char *pval = sqlite3_bind_parameter_name(stmt, iCol); *plen = (pval != 0) ? strlen(pval) : 0; return pval; } __declspec(dllexport) int __stdcall sqlite3_bind_parameter_index_interop(sqlite3_stmt *stmt, const char *zName) { return sqlite3_bind_parameter_index(stmt, zName); } __declspec(dllexport) int __stdcall sqlite3_column_count_interop(sqlite3_stmt *stmt) { return sqlite3_column_count(stmt); } __declspec(dllexport) const char * __stdcall sqlite3_column_name_interop(sqlite3_stmt *stmt, int iCol, int *plen) { const char *pval = sqlite3_column_name(stmt, iCol); *plen = (pval != 0) ? strlen(pval) : 0; return pval; } __declspec(dllexport) const void * __stdcall sqlite3_column_name16_interop(sqlite3_stmt *stmt, int iCol) { return sqlite3_column_name16(stmt, iCol); } __declspec(dllexport) const char * __stdcall sqlite3_column_decltype_interop(sqlite3_stmt *stmt, int iCol, int *plen) { const char *pval = sqlite3_column_decltype(stmt, iCol); *plen = (pval != 0) ? strlen(pval) : 0; return pval; } __declspec(dllexport) const void * __stdcall sqlite3_column_decltype16_interop(sqlite3_stmt *stmt, int iCol) { return sqlite3_column_decltype16(stmt, iCol); } __declspec(dllexport) int __stdcall sqlite3_step_interop(sqlite3_stmt *stmt) { return sqlite3_step(stmt); } __declspec(dllexport) int __stdcall sqlite3_data_count_interop(sqlite3_stmt *stmt) { return sqlite3_data_count(stmt); } __declspec(dllexport) const void * __stdcall sqlite3_column_blob_interop(sqlite3_stmt *stmt, int iCol) { return sqlite3_column_blob(stmt, iCol); } __declspec(dllexport) int __stdcall sqlite3_column_bytes_interop(sqlite3_stmt *stmt, int iCol) { return sqlite3_column_bytes(stmt, iCol); } __declspec(dllexport) int __stdcall sqlite3_column_bytes16_interop(sqlite3_stmt *stmt, int iCol) { return sqlite3_column_bytes16(stmt, iCol); } __declspec(dllexport) void __stdcall sqlite3_column_double_interop(sqlite3_stmt *stmt, int iCol, double *val) { *val = sqlite3_column_double(stmt,iCol); } __declspec(dllexport) int __stdcall sqlite3_column_int_interop(sqlite3_stmt *stmt, int iCol) { return sqlite3_column_int(stmt, iCol); } __declspec(dllexport) void __stdcall sqlite3_column_int64_interop(sqlite3_stmt *stmt, int iCol, sqlite_int64 *val) { *val = sqlite3_column_int64(stmt,iCol); } __declspec(dllexport) const unsigned char * __stdcall sqlite3_column_text_interop(sqlite3_stmt *stmt, int iCol, int *plen) { const unsigned char *pval = sqlite3_column_text(stmt, iCol); *plen = (pval != 0) ? strlen(pval) : 0; return pval; } __declspec(dllexport) const void * __stdcall sqlite3_column_text16_interop(sqlite3_stmt *stmt, int iCol) { return sqlite3_column_text16(stmt, iCol); } __declspec(dllexport) int __stdcall sqlite3_column_type_interop(sqlite3_stmt *stmt, int iCol) { return sqlite3_column_type(stmt, iCol); } __declspec(dllexport) int __stdcall sqlite3_finalize_interop(sqlite3_stmt *stmt) { return sqlite3_finalize(stmt); } __declspec(dllexport) int __stdcall sqlite3_reset_interop(sqlite3_stmt *stmt) { return sqlite3_reset(stmt); } __declspec(dllexport) int __stdcall sqlite3_create_function_interop(sqlite3 *psql, const char *zFunctionName, int nArg, int eTextRep, SQLITEUSERFUNC func, SQLITEUSERFUNC funcstep, SQLITEUSERFUNC funcfinal, void **ppCookie) { int n; SQLITEUSERFUNC *p = malloc(sizeof(SQLITEUSERFUNC) * 3); p[0] = func; p[1] = funcstep; p[2] = funcfinal; *ppCookie = 0; n = sqlite3_create_function(psql, zFunctionName, nArg, eTextRep, p, (func != 0) ? sqlite3_interop_func : 0, (funcstep != 0) ? sqlite3_interop_step : 0, (funcfinal != 0) ? sqlite3_interop_final : 0); if (n != 0) free(p); else *ppCookie = p; return n; } __declspec(dllexport) int __stdcall sqlite3_create_function16_interop(sqlite3 *psql, void *zFunctionName, int nArg, int eTextRep, SQLITEUSERFUNC func, SQLITEUSERFUNC funcstep, SQLITEUSERFUNC funcfinal, void **ppCookie) { int n; SQLITEUSERFUNC *p = malloc(sizeof(SQLITEUSERFUNC) * 3); p[0] = func; p[1] = funcstep; p[2] = funcfinal; *ppCookie = 0; n = sqlite3_create_function16(psql, zFunctionName, nArg, eTextRep, p, (func != 0) ? sqlite3_interop_func : 0, (funcstep != 0) ? sqlite3_interop_step : 0, (funcfinal != 0) ? sqlite3_interop_final : 0); if (n != 0) free(p); else *ppCookie = p; return n; } __declspec(dllexport) int __stdcall sqlite3_create_collation_interop(sqlite3* db, const char *zName, int eTextRep, void* pvUser, SQLITECOLLATION func, void **ppCookie) { int n; SQLITECOLLATION *p = malloc(sizeof(SQLITECOLLATION)); p[0] = func; *ppCookie = 0; n = sqlite3_create_collation(db, zName, eTextRep, p, sqlite3_interop_collationfunc); if (n != 0) free(p); else *ppCookie = p; return n; } __declspec(dllexport) int __stdcall sqlite3_create_collation16_interop(sqlite3* db, const void *zName, int eTextRep, void* pvUser, SQLITECOLLATION func, void **ppCookie) { int n; SQLITECOLLATION *p = malloc(sizeof(SQLITECOLLATION)); p[0] = func; *ppCookie = 0; n = sqlite3_create_collation16(db, (const char *)zName, eTextRep, p, sqlite3_interop_collationfunc); if (n != 0) free(p); else *ppCookie = p; return n; } __declspec(dllexport) int __stdcall sqlite3_aggregate_count_interop(sqlite3_context *pctx) { return sqlite3_aggregate_count(pctx); } __declspec(dllexport) const void * __stdcall sqlite3_value_blob_interop(sqlite3_value *val) { return sqlite3_value_blob(val); } __declspec(dllexport) int __stdcall sqlite3_value_bytes_interop(sqlite3_value *val) { return sqlite3_value_bytes(val); } __declspec(dllexport) int __stdcall sqlite3_value_bytes16_interop(sqlite3_value *val) { return sqlite3_value_bytes16(val); } __declspec(dllexport) void __stdcall sqlite3_value_double_interop(sqlite3_value *pval, double *val) { *val = sqlite3_value_double(pval); } __declspec(dllexport) int __stdcall sqlite3_value_int_interop(sqlite3_value *val) { return sqlite3_value_int(val); } __declspec(dllexport) void __stdcall sqlite3_value_int64_interop(sqlite3_value *pval, sqlite_int64 *val) { *val = sqlite3_value_int64(pval); } __declspec(dllexport) const unsigned char * __stdcall sqlite3_value_text_interop(sqlite3_value *val, int *plen) { const unsigned char *pval = sqlite3_value_text(val); *plen = (pval != 0) ? strlen(pval) : 0; return pval; } __declspec(dllexport) const void * __stdcall sqlite3_value_text16_interop(sqlite3_value *val) { return sqlite3_value_text16(val); } __declspec(dllexport) int __stdcall sqlite3_value_type_interop(sqlite3_value *val) { return sqlite3_value_type(val); } __declspec(dllexport) void * __stdcall sqlite3_aggregate_context_interop(sqlite3_context *pctx, int n) { return sqlite3_aggregate_context(pctx, n); } __declspec(dllexport) void __stdcall sqlite3_result_blob_interop(sqlite3_context *ctx, const void *pv, int n, void(*cb)(void *)) { sqlite3_result_blob(ctx, pv, n, cb); } __declspec(dllexport) void __stdcall sqlite3_result_double_interop(sqlite3_context *pctx, double *val) { sqlite3_result_double(pctx, *val); } __declspec(dllexport) void __stdcall sqlite3_result_int_interop(sqlite3_context *pctx, int val) { sqlite3_result_int(pctx, val); } __declspec(dllexport) void __stdcall sqlite3_result_int64_interop(sqlite3_context *pctx, sqlite_int64 *val) { sqlite3_result_int64(pctx, *val); } __declspec(dllexport) void __stdcall sqlite3_result_null_interop(sqlite3_context *pctx) { sqlite3_result_null(pctx); } __declspec(dllexport) void __stdcall sqlite3_result_error_interop(sqlite3_context *ctx, const char *pv, int n) { sqlite3_result_error(ctx, pv, n); } __declspec(dllexport) void __stdcall sqlite3_result_error16_interop(sqlite3_context *ctx, const void *pv, int n) { sqlite3_result_error16(ctx, pv, n); } __declspec(dllexport) void __stdcall sqlite3_result_text_interop(sqlite3_context *ctx, const char *pv, int n, void(*cb)(void *)) { sqlite3_result_text(ctx, pv, n, cb); } __declspec(dllexport) void __stdcall sqlite3_result_text16_interop(sqlite3_context *ctx, const void *pv, int n, void(*cb)(void *)) { sqlite3_result_text16(ctx, pv, n, cb); } __declspec(dllexport) void __stdcall sqlite3_realcolnames(sqlite3 *db, int bOn) { if (bOn) db->flags |= 0x01000000; else db->flags &= (~0x01000000); } #endif // OS_WIN |
Deleted SQLite.Interop/merge.h.
|
| < < < < < < < < < < < < < < < < < |
Deleted SQLite.Interop/resource.h.
|
| < < < < < < < < < < < < < < |
Changes to SQLite.Interop/src/alter.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** | | < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** ** $Id: alter.c,v 1.1 2005/03/01 16:04:26 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** The code in this file only exists if we are not omitting the ** ALTER TABLE logic from the build. */ #ifndef SQLITE_OMIT_ALTERTABLE |
︙ | ︙ | |||
43 44 45 46 47 48 49 | sqlite3_value **argv ){ unsigned char const *zSql = sqlite3_value_text(argv[0]); unsigned char const *zTableName = sqlite3_value_text(argv[1]); int token; Token tname; | | | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | sqlite3_value **argv ){ unsigned char const *zSql = sqlite3_value_text(argv[0]); unsigned char const *zTableName = sqlite3_value_text(argv[1]); int token; Token tname; char const *zCsr = zSql; int len = 0; char *zRet; /* The principle used to locate the table name in the CREATE TABLE ** statement is that the table name is the first token that is immediatedly ** followed by a left parenthesis - TK_LP. */ |
︙ | ︙ | |||
92 93 94 95 96 97 98 | ){ unsigned char const *zSql = sqlite3_value_text(argv[0]); unsigned char const *zTableName = sqlite3_value_text(argv[1]); int token; Token tname; int dist = 3; | | | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | ){ unsigned char const *zSql = sqlite3_value_text(argv[0]); unsigned char const *zTableName = sqlite3_value_text(argv[1]); int token; Token tname; int dist = 3; char const *zCsr = zSql; int len = 0; char *zRet; /* The principle used to locate the table name in the CREATE TRIGGER ** statement is that the table name is the first token that is immediatedly ** preceded by either TK_ON or TK_DOT and immediatedly followed by one ** of TK_WHEN, TK_BEGIN or TK_FOR. |
︙ | ︙ | |||
163 164 165 166 167 168 169 | for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0); } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > | < | | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0); } } /* ** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" ** command. */ void sqlite3AlterRenameTable( Parse *pParse, /* Parser context. */ SrcList *pSrc, /* The table to rename. */ Token *pName /* The new table name. */ ){ int iDb; /* Database that contains the table */ char *zDb; /* Name of database iDb */ Table *pTab; /* Table being renamed */ char *zName = 0; /* NULL-terminated version of pName */ char *zWhere = 0; /* Where clause of schema elements to reparse */ sqlite3 *db = pParse->db; /* Database connection */ Vdbe *v; #ifndef SQLITE_OMIT_TRIGGER char *zTempTrig = 0; /* Where clause to locate temp triggers */ #endif assert( pSrc->nSrc==1 ); pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase); if( !pTab ) goto exit_rename_table; iDb = pTab->iDb; zDb = db->aDb[iDb].zName; /* Get a NULL terminated version of the new table name. */ zName = sqlite3NameFromToken(pName); if( !zName ) goto exit_rename_table; /* Check that a table or index named 'zName' does not already exist |
︙ | ︙ | |||
333 334 335 336 337 338 339 | "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " "'sqlite_autoindex_' || %Q || substr(name, %d+18,10) " "ELSE name END " "WHERE tbl_name=%Q AND " "(type='table' OR type='index' OR type='trigger');", zDb, SCHEMA_TABLE(iDb), zName, zName, zName, #ifndef SQLITE_OMIT_TRIGGER | | > > > > > > | > > > > > > > > > > > > | | | | | < | > > | > > > > > > > > > > | > > > > > > > > > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 | "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " "'sqlite_autoindex_' || %Q || substr(name, %d+18,10) " "ELSE name END " "WHERE tbl_name=%Q AND " "(type='table' OR type='index' OR type='trigger');", zDb, SCHEMA_TABLE(iDb), zName, zName, zName, #ifndef SQLITE_OMIT_TRIGGER zName, #endif zName, strlen(pTab->zName), pTab->zName ); #ifndef SQLITE_OMIT_AUTOINCREMENT /* If the sqlite_sequence table exists in this database, then update ** it with the new table name. */ if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){ sqlite3NestedParse(pParse, "UPDATE %Q.sqlite_sequence set name = %Q WHERE name = %Q", zDb, zName, pTab->zName); } #endif #ifndef SQLITE_OMIT_TRIGGER /* If there are TEMP triggers on this table, modify the sqlite_temp_master ** table. Don't do this if the table being ALTERed is itself located in ** the temp database. */ if( iDb!=1 ){ Trigger *pTrig; char *tmp = 0; for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){ if( pTrig->iDb==1 ){ if( !zTempTrig ){ zTempTrig = sqlite3MPrintf("type = 'trigger' AND (name=%Q", pTrig->name); }else{ tmp = zTempTrig; zTempTrig = sqlite3MPrintf("%s OR name=%Q", zTempTrig, pTrig->name); sqliteFree(tmp); } } } if( zTempTrig ){ tmp = zTempTrig; zTempTrig = sqlite3MPrintf("%s)", zTempTrig); sqliteFree(tmp); sqlite3NestedParse(pParse, "UPDATE sqlite_temp_master SET " "sql = sqlite_rename_trigger(sql, %Q), " "tbl_name = %Q " "WHERE %s;", zName, zName, zTempTrig); } } #endif /* Drop the elements of the in-memory schema that refered to the table ** renamed and load the new versions from the database. */ if( pParse->nErr==0 ){ #ifndef SQLITE_OMIT_TRIGGER Trigger *pTrig; for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){ assert( pTrig->iDb==iDb || pTrig->iDb==1 ); sqlite3VdbeOp3(v, OP_DropTrigger, pTrig->iDb, 0, pTrig->name, 0); } #endif sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0); zWhere = sqlite3MPrintf("tbl_name=%Q", zName); sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC); #ifndef SQLITE_OMIT_TRIGGER if( zTempTrig ){ sqlite3VdbeOp3(v, OP_ParseSchema, 1, 0, zTempTrig, P3_DYNAMIC); } }else{ sqliteFree(zTempTrig); #endif } exit_rename_table: sqlite3SrcListDelete(pSrc); sqliteFree(zName); } #endif /* SQLITE_ALTER_TABLE */ |
Deleted SQLite.Interop/src/analyze.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to SQLite.Interop/src/attach.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2003 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < | < < < | > | | > > | < > | | < < | | < | | > | | | < < < < < > < | | > | > | > > > | > > > > > > > > > > | | > > < < < | < < | < < | < < < < < | < | | < < < < < < | > > > | > > > > | > > > > | > > | < | < < < < | | < < | | | < | < < < | > | | | < < < < | < | < < | < < < | < | < < < < < < < < | | | < < < < < < < < < < < < < < < < < < < < < < < < | | < < < < < < < < < < < < | < < < < < | < < < | | < < > < | | | < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < | | | | | | | < | | < < | | | | < < < | < < < > | | < < < < < | | > | > > > | | < < | | | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | /* ** 2003 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** ** $Id: attach.c,v 1.1 2005/03/01 16:04:26 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** This routine is called by the parser to process an ATTACH statement: ** ** ATTACH DATABASE filename AS dbname ** ** The pFilename and pDbname arguments are the tokens that define the ** filename and dbname in the ATTACH statement. */ void sqlite3Attach( Parse *pParse, /* The parser context */ Token *pFilename, /* Name of database file */ Token *pDbname, /* Name of the database to use internally */ int keyType, /* 0: no key. 1: TEXT, 2: BLOB */ Token *pKey /* Text of the key for keytype 1 and 2 */ ){ Db *aNew; int rc, i; char *zFile, *zName; sqlite3 *db; Vdbe *v; v = sqlite3GetVdbe(pParse); if( !v ) return; sqlite3VdbeAddOp(v, OP_Expire, 1, 0); sqlite3VdbeAddOp(v, OP_Halt, 0, 0); if( pParse->explain ) return; db = pParse->db; if( db->nDb>=MAX_ATTACHED+2 ){ sqlite3ErrorMsg(pParse, "too many attached databases - max %d", MAX_ATTACHED); pParse->rc = SQLITE_ERROR; return; } if( !db->autoCommit ){ sqlite3ErrorMsg(pParse, "cannot ATTACH database within transaction"); pParse->rc = SQLITE_ERROR; return; } zFile = sqlite3NameFromToken(pFilename);; if( zFile==0 ) return; #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){ sqliteFree(zFile); return; } #endif /* SQLITE_OMIT_AUTHORIZATION */ zName = sqlite3NameFromToken(pDbname); if( zName==0 ) return; for(i=0; i<db->nDb; i++){ char *z = db->aDb[i].zName; if( z && sqlite3StrICmp(z, zName)==0 ){ sqlite3ErrorMsg(pParse, "database %z is already in use", zName); pParse->rc = SQLITE_ERROR; sqliteFree(zFile); return; } } if( db->aDb==db->aDbStatic ){ aNew = sqliteMalloc( sizeof(db->aDb[0])*3 ); if( aNew==0 ) return; memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); }else{ aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); if( aNew==0 ) return; } db->aDb = aNew; aNew = &db->aDb[db->nDb++]; memset(aNew, 0, sizeof(*aNew)); sqlite3HashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0); sqlite3HashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0); sqlite3HashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0); sqlite3HashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1); aNew->zName = zName; aNew->safety_level = 3; rc = sqlite3BtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt); if( rc ){ sqlite3ErrorMsg(pParse, "unable to open database: %s", zFile); } #if SQLITE_HAS_CODEC { extern int sqlite3CodecAttach(sqlite3*, int, void*, int); char *zKey; int nKey; if( keyType==0 ){ /* No key specified. Use the key from the main database */ extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); }else if( keyType==1 ){ /* Key specified as text */ zKey = sqlite3NameFromToken(pKey); nKey = strlen(zKey); }else{ /* Key specified as a BLOB */ char *zTemp; assert( keyType==2 ); pKey->z++; pKey->n--; zTemp = sqlite3NameFromToken(pKey); zKey = sqlite3HexToBlob(zTemp); sqliteFree(zTemp); } sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); if( keyType ){ sqliteFree(zKey); } } #endif sqliteFree(zFile); db->flags &= ~SQLITE_Initialized; if( pParse->nErr==0 && rc==SQLITE_OK ){ rc = sqlite3ReadSchema(pParse); } if( rc ){ int i = db->nDb - 1; assert( i>=2 ); if( db->aDb[i].pBt ){ sqlite3BtreeClose(db->aDb[i].pBt); db->aDb[i].pBt = 0; } sqlite3ResetInternalSchema(db, 0); if( 0==pParse->nErr ){ pParse->nErr++; pParse->rc = SQLITE_ERROR; } } } /* ** This routine is called by the parser to process a DETACH statement: ** ** DETACH DATABASE dbname ** ** The pDbname argument is the name of the database in the DETACH statement. */ void sqlite3Detach(Parse *pParse, Token *pDbname){ int i; sqlite3 *db; Vdbe *v; Db *pDb = 0; v = sqlite3GetVdbe(pParse); if( !v ) return; sqlite3VdbeAddOp(v, OP_Expire, 0, 0); sqlite3VdbeAddOp(v, OP_Halt, 0, 0); if( pParse->explain ) return; db = pParse->db; for(i=0; i<db->nDb; i++){ pDb = &db->aDb[i]; if( pDb->pBt==0 || pDb->zName==0 ) continue; if( strlen(pDb->zName)!=pDbname->n ) continue; if( sqlite3StrNICmp(pDb->zName, pDbname->z, pDbname->n)==0 ) break; } if( i>=db->nDb ){ sqlite3ErrorMsg(pParse, "no such database: %T", pDbname); return; } if( i<2 ){ sqlite3ErrorMsg(pParse, "cannot detach database %T", pDbname); return; } if( !db->autoCommit ){ sqlite3ErrorMsg(pParse, "cannot DETACH database within transaction"); pParse->rc = SQLITE_ERROR; return; } #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){ return; } #endif /* SQLITE_OMIT_AUTHORIZATION */ sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; sqlite3ResetInternalSchema(db, 0); } /* ** Initialize a DbFixer structure. This routine must be called prior ** to passing the structure to one of the sqliteFixAAAA() routines below. ** ** The return value indicates whether or not fixation is required. TRUE |
︙ | ︙ |
Changes to SQLite.Interop/src/auth.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains code used to implement the sqlite3_set_authorizer() ** API. This facility is an optional feature of the library. Embedded ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains code used to implement the sqlite3_set_authorizer() ** API. This facility is an optional feature of the library. Embedded ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 ** ** $Id: auth.c,v 1.1 2005/03/01 16:04:26 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** All of the code in this file may be omitted by defining a single ** macro. */ |
︙ | ︙ | |||
108 109 110 111 112 113 114 | sqlite3 *db = pParse->db; int rc; Table *pTab; /* The table being read */ const char *zCol; /* Name of the column of the table */ int iSrc; /* Index in pTabList->a[] of table being read */ const char *zDBase; /* Name of database being accessed */ TriggerStack *pStack; /* The stack of current triggers */ | < < < < < < < < | 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | sqlite3 *db = pParse->db; int rc; Table *pTab; /* The table being read */ const char *zCol; /* Name of the column of the table */ int iSrc; /* Index in pTabList->a[] of table being read */ const char *zDBase; /* Name of database being accessed */ TriggerStack *pStack; /* The stack of current triggers */ if( db->xAuth==0 ) return; assert( pExpr->op==TK_COLUMN ); for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){ if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; } if( iSrc>=0 && pTabList && iSrc<pTabList->nSrc ){ pTab = pTabList->a[iSrc].pTab; }else if( (pStack = pParse->trigStack)!=0 ){ /* This must be an attempt to read the NEW or OLD pseudo-tables |
︙ | ︙ | |||
143 144 145 146 147 148 149 | zCol = pTab->aCol[pExpr->iColumn].zName; }else if( pTab->iPKey>=0 ){ assert( pTab->iPKey<pTab->nCol ); zCol = pTab->aCol[pTab->iPKey].zName; }else{ zCol = "ROWID"; } | | | | | 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | zCol = pTab->aCol[pExpr->iColumn].zName; }else if( pTab->iPKey>=0 ){ assert( pTab->iPKey<pTab->nCol ); zCol = pTab->aCol[pTab->iPKey].zName; }else{ zCol = "ROWID"; } assert( pExpr->iDb<db->nDb ); zDBase = db->aDb[pExpr->iDb].zName; rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, pParse->zAuthContext); if( rc==SQLITE_IGNORE ){ pExpr->op = TK_NULL; }else if( rc==SQLITE_DENY ){ if( db->nDb>2 || pExpr->iDb!=0 ){ sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited", zDBase, pTab->zName, zCol); }else{ sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited",pTab->zName,zCol); } pParse->rc = SQLITE_AUTH; }else if( rc!=SQLITE_OK ){ |
︙ | ︙ |
Changes to SQLite.Interop/src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: btree.c,v 1.1 2005/03/01 16:04:27 rmsimpson Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. |
︙ | ︙ | |||
207 208 209 210 211 212 213 | */ #include "sqliteInt.h" #include "pager.h" #include "btree.h" #include "os.h" #include <assert.h> | | > | < | < < < < < < < < < < | < < | | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | */ #include "sqliteInt.h" #include "pager.h" #include "btree.h" #include "os.h" #include <assert.h> /* ** This macro rounds values up so that if the value is an address it ** is guaranteed to be an address that is aligned to an 8-byte boundary. */ #define FORCE_ALIGNMENT(X) (((X)+7)&~7) /* The following value is the maximum cell size assuming a maximum page ** size give above. */ #define MX_CELL_SIZE(pBt) (pBt->pageSize-8) /* The maximum number of cells on a single page of the database. This ** assumes a minimum cell size of 3 bytes. Such small cells will be ** exceedingly rare, but they are possible. */ #define MX_CELL(pBt) ((pBt->pageSize-8)/3) /* Forward declarations */ typedef struct MemPage MemPage; /* ** This is a magic string that appears at the beginning of every ** SQLite database in order to identify the file as a real database. ** 123456789 123456 */ static const char zMagicHeader[] = "SQLite format 3"; /* ** Page type flags. An ORed combination of these flags appear as the ** first byte of every BTree page. */ #define PTF_INTKEY 0x01 #define PTF_ZERODATA 0x02 |
︙ | ︙ | |||
282 283 284 285 286 287 288 | u16 maxLocal; /* Copy of Btree.maxLocal or Btree.maxLeaf */ u16 minLocal; /* Copy of Btree.minLocal or Btree.minLeaf */ u16 cellOffset; /* Index in aData of first cell pointer */ u16 idxParent; /* Index in parent of this node */ u16 nFree; /* Number of free bytes on the page */ u16 nCell; /* Number of cells on this page, local and ovfl */ struct _OvflCell { /* Cells that will not fit on aData[] */ | | | | < < < < < < < < < < < < < < < < < < < | > > < < < < < < < < < < > > > > > > > > | 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | u16 maxLocal; /* Copy of Btree.maxLocal or Btree.maxLeaf */ u16 minLocal; /* Copy of Btree.minLocal or Btree.minLeaf */ u16 cellOffset; /* Index in aData of first cell pointer */ u16 idxParent; /* Index in parent of this node */ u16 nFree; /* Number of free bytes on the page */ u16 nCell; /* Number of cells on this page, local and ovfl */ struct _OvflCell { /* Cells that will not fit on aData[] */ u8 *pCell; /* Pointers to the body of the overflow cell */ u16 idx; /* Insert this cell before idx-th non-overflow cell */ } aOvfl[5]; struct Btree *pBt; /* Pointer back to BTree structure */ u8 *aData; /* Pointer back to the start of the page */ Pgno pgno; /* Page number for this page */ MemPage *pParent; /* The parent of this page. NULL for root */ }; /* ** The in-memory image of a disk page has the auxiliary information appended ** to the end. EXTRA_SIZE is the number of bytes of space needed to hold ** that extra information. */ #define EXTRA_SIZE sizeof(MemPage) /* ** Everything we need to know about an open database */ struct Btree { Pager *pPager; /* The page cache */ BtCursor *pCursor; /* A list of all open cursors */ MemPage *pPage1; /* First page of the database */ u8 inTrans; /* True if a transaction is in progress */ u8 inStmt; /* True if we are in a statement subtransaction */ u8 readOnly; /* True if the underlying file is readonly */ u8 maxEmbedFrac; /* Maximum payload as % of total page size */ u8 minEmbedFrac; /* Minimum payload as % of total page size */ u8 minLeafFrac; /* Minimum leaf payload as % of total page size */ u8 pageSizeFixed; /* True if the page size can no longer be changed */ #ifndef SQLITE_OMIT_AUTOVACUUM u8 autoVacuum; /* True if database supports auto-vacuum */ #endif u16 pageSize; /* Total number of bytes on a page */ u16 psAligned; /* pageSize rounded up to a multiple of 8 */ u16 usableSize; /* Number of usable bytes on each page */ int maxLocal; /* Maximum local payload in non-LEAFDATA tables */ int minLocal; /* Minimum local payload in non-LEAFDATA tables */ int maxLeaf; /* Maximum local payload in a LEAFDATA table */ int minLeaf; /* Minimum local payload in a LEAFDATA table */ }; typedef Btree Bt; /* ** Btree.inTrans may take one of the following values. */ #define TRANS_NONE 0 #define TRANS_READ 1 #define TRANS_WRITE 2 /* ** An instance of the following structure is used to hold information ** about a cell. The parseCellPtr() function fills in this structure ** based on information extract from the raw disk page. */ typedef struct CellInfo CellInfo; |
︙ | ︙ | |||
373 374 375 376 377 378 379 | /* ** A cursor is a pointer to a particular entry in the BTree. ** The entry is identified by its MemPage and the index in ** MemPage.aCell[] of the entry. */ struct BtCursor { | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | /* ** A cursor is a pointer to a particular entry in the BTree. ** The entry is identified by its MemPage and the index in ** MemPage.aCell[] of the entry. */ struct BtCursor { Btree *pBt; /* The Btree to which this cursor belongs */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */ void *pArg; /* First arg to xCompare() */ Pgno pgnoRoot; /* The root page of this tree */ MemPage *pPage; /* Page that contains the entry */ int idx; /* Index of the entry in pPage->aCell[] */ CellInfo info; /* A parse of the cell we are pointing at */ u8 wrFlag; /* True if writable */ u8 isValid; /* TRUE if points to a valid entry */ }; /* ** The TRACE macro will print high-level status information about the ** btree operation when the global variable sqlite3_btree_trace is ** enabled. */ #if SQLITE_TEST # define TRACE(X) if( sqlite3_btree_trace )\ { sqlite3DebugPrintf X; fflush(stdout); } #else # define TRACE(X) #endif int sqlite3_btree_trace=0; /* True to enable tracing */ /* ** Forward declaration */ static int checkReadLocks(Btree*,Pgno,BtCursor*); /* ** Read or write a two- and four-byte big-endian integer values. */ static u32 get2byte(unsigned char *p){ return (p[0]<<8) | p[1]; } |
︙ | ︙ | |||
467 468 469 470 471 472 473 | /* The database page the PENDING_BYTE occupies. This page is never used. ** TODO: This macro is very similary to PAGER_MJ_PGNO() in pager.c. They ** should possibly be consolidated (presumably in pager.h). */ #define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1) | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 407 408 409 410 411 412 413 414 415 416 417 418 419 420 | /* The database page the PENDING_BYTE occupies. This page is never used. ** TODO: This macro is very similary to PAGER_MJ_PGNO() in pager.c. They ** should possibly be consolidated (presumably in pager.h). */ #define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1) #ifndef SQLITE_OMIT_AUTOVACUUM /* ** These macros define the location of the pointer-map entry for a ** database page. The first argument to each is the number of usable ** bytes on each page of the database (often 1024). The second is the ** page number to look up in the pointer map. ** |
︙ | ︙ | |||
799 800 801 802 803 804 805 | /* ** Write an entry into the pointer map. ** ** This routine updates the pointer map entry for page number 'key' ** so that it maps to type 'eType' and parent page number 'pgno'. ** An error code is returned if something goes wrong, otherwise SQLITE_OK. */ | | | | 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 | /* ** Write an entry into the pointer map. ** ** This routine updates the pointer map entry for page number 'key' ** so that it maps to type 'eType' and parent page number 'pgno'. ** An error code is returned if something goes wrong, otherwise SQLITE_OK. */ static int ptrmapPut(Btree *pBt, Pgno key, u8 eType, Pgno parent){ u8 *pPtrmap; /* The pointer map page */ Pgno iPtrmap; /* The pointer map page number */ int offset; /* Offset in pointer map page */ int rc; assert( pBt->autoVacuum ); if( key==0 ){ return SQLITE_CORRUPT; } iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key); rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap); if( rc!=SQLITE_OK ){ return rc; } offset = PTRMAP_PTROFFSET(pBt->usableSize, key); |
︙ | ︙ | |||
836 837 838 839 840 841 842 | /* ** Read an entry from the pointer map. ** ** This routine retrieves the pointer map entry for page 'key', writing ** the type and parent page number to *pEType and *pPgno respectively. ** An error code is returned if something goes wrong, otherwise SQLITE_OK. */ | | | | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 | /* ** Read an entry from the pointer map. ** ** This routine retrieves the pointer map entry for page 'key', writing ** the type and parent page number to *pEType and *pPgno respectively. ** An error code is returned if something goes wrong, otherwise SQLITE_OK. */ static int ptrmapGet(Btree *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ int iPtrmap; /* Pointer map page index */ u8 *pPtrmap; /* Pointer map page data */ int offset; /* Offset of entry in pointer map */ int rc; iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key); rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap); if( rc!=0 ){ return rc; } offset = PTRMAP_PTROFFSET(pBt->usableSize, key); if( pEType ) *pEType = pPtrmap[offset]; if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); sqlite3pager_unref(pPtrmap); if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT; return SQLITE_OK; } #endif /* SQLITE_OMIT_AUTOVACUUM */ /* ** Given a btree page and a cell index (0 means the first cell on |
︙ | ︙ | |||
1037 1038 1039 1040 1041 1042 1043 | int cellOffset; int nCell, cellLimit; u8 *used; used = sqliteMallocRaw( pPage->pBt->pageSize ); if( used==0 ) return; usableSize = pPage->pBt->usableSize; | | | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 | int cellOffset; int nCell, cellLimit; u8 *used; used = sqliteMallocRaw( pPage->pBt->pageSize ); if( used==0 ) return; usableSize = pPage->pBt->usableSize; assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->psAligned] ); hdr = pPage->hdrOffset; assert( hdr==(pPage->pgno==1 ? 100 : 0) ); assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) ); c = pPage->aData[hdr]; if( pPage->isInit ){ assert( pPage->leaf == ((c & PTF_LEAF)!=0) ); assert( pPage->zeroData == ((c & PTF_ZERODATA)!=0) ); |
︙ | ︙ | |||
1103 1104 1105 1106 1107 1108 1109 | sqliteFree(used); } #define pageIntegrity(X) _pageIntegrity(X) #else # define pageIntegrity(X) #endif | < < < < < < < < < | | < | 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 | sqliteFree(used); } #define pageIntegrity(X) _pageIntegrity(X) #else # define pageIntegrity(X) #endif /* ** Defragment the page given. All Cells are moved to the ** beginning of the page and all free space is collected ** into one big FreeBlk at the end of the page. */ static int defragmentPage(MemPage *pPage){ int i; /* Loop counter */ int pc; /* Address of a i-th cell */ int addr; /* Offset of first byte after cell pointer array */ int hdr; /* Offset to the page header */ int size; /* Size of a cell */ |
︙ | ︙ | |||
1300 1301 1302 1303 1304 1305 1306 | } /* ** Decode the flags byte (the first byte of the header) for a page ** and initialize fields of the MemPage structure accordingly. */ static void decodeFlags(MemPage *pPage, int flagByte){ | | | 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 | } /* ** Decode the flags byte (the first byte of the header) for a page ** and initialize fields of the MemPage structure accordingly. */ static void decodeFlags(MemPage *pPage, int flagByte){ Btree *pBt; /* A copy of pPage->pBt */ assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); pPage->intKey = (flagByte & (PTF_INTKEY|PTF_LEAFDATA))!=0; pPage->zeroData = (flagByte & PTF_ZERODATA)!=0; pPage->leaf = (flagByte & PTF_LEAF)!=0; pPage->childPtrSize = 4*(pPage->leaf==0); pBt = pPage->pBt; |
︙ | ︙ | |||
1340 1341 1342 1343 1344 1345 1346 | static int initPage( MemPage *pPage, /* The page to be initialized */ MemPage *pParent /* The parent. Might be NULL */ ){ int pc; /* Address of a freeblock within pPage->aData[] */ int hdr; /* Offset to beginning of page header */ u8 *data; /* Equal to pPage->aData */ | | | | | | | | | | | | 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 | static int initPage( MemPage *pPage, /* The page to be initialized */ MemPage *pParent /* The parent. Might be NULL */ ){ int pc; /* Address of a freeblock within pPage->aData[] */ int hdr; /* Offset to beginning of page header */ u8 *data; /* Equal to pPage->aData */ Btree *pBt; /* The main btree structure */ int usableSize; /* Amount of usable space on each page */ int cellOffset; /* Offset from start of page to first cell pointer */ int nFree; /* Number of unused bytes on the page */ int top; /* First byte of the cell content area */ pBt = pPage->pBt; assert( pBt!=0 ); assert( pParent==0 || pParent->pBt==pBt ); assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) ); assert( pPage->aData == &((unsigned char*)pPage)[-pBt->psAligned] ); if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){ /* The parent page should never change unless the file is corrupt */ return SQLITE_CORRUPT; /* bkpt-CORRUPT */ } if( pPage->isInit ) return SQLITE_OK; if( pPage->pParent==0 && pParent!=0 ){ pPage->pParent = pParent; sqlite3pager_ref(pParent->aData); } hdr = pPage->hdrOffset; data = pPage->aData; decodeFlags(pPage, data[hdr]); pPage->nOverflow = 0; pPage->idxShift = 0; usableSize = pBt->usableSize; pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf; top = get2byte(&data[hdr+5]); pPage->nCell = get2byte(&data[hdr+3]); if( pPage->nCell>MX_CELL(pBt) ){ /* To many cells for a single page. The page must be corrupt */ return SQLITE_CORRUPT; /* bkpt-CORRUPT */ } if( pPage->nCell==0 && pParent!=0 && pParent->pgno!=1 ){ /* All pages must have at least one cell, except for root pages */ return SQLITE_CORRUPT; /* bkpt-CORRUPT */ } /* Compute the total free space on the page */ pc = get2byte(&data[hdr+1]); nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell); while( pc>0 ){ int next, size; if( pc>usableSize-4 ){ /* Free block is off the page */ return SQLITE_CORRUPT; /* bkpt-CORRUPT */ } next = get2byte(&data[pc]); size = get2byte(&data[pc+2]); if( next>0 && next<=pc+size+3 ){ /* Free blocks must be in accending order */ return SQLITE_CORRUPT; /* bkpt-CORRUPT */ } nFree += size; pc = next; } pPage->nFree = nFree; if( nFree>=usableSize ){ /* Free space cannot exceed total page size */ return SQLITE_CORRUPT; /* bkpt-CORRUPT */ } pPage->isInit = 1; pageIntegrity(pPage); return SQLITE_OK; } /* ** Set up a raw page so that it looks like a database page holding ** no entries. */ static void zeroPage(MemPage *pPage, int flags){ unsigned char *data = pPage->aData; Btree *pBt = pPage->pBt; int hdr = pPage->hdrOffset; int first; assert( sqlite3pager_pagenumber(data)==pPage->pgno ); assert( &data[pBt->psAligned] == (unsigned char*)pPage ); assert( sqlite3pager_iswriteable(data) ); memset(&data[hdr], 0, pBt->usableSize - hdr); data[hdr] = flags; first = hdr + 8 + 4*((flags&PTF_LEAF)==0); memset(&data[hdr+1], 0, 4); data[hdr+7] = 0; put2byte(&data[hdr+5], pBt->usableSize); |
︙ | ︙ | |||
1441 1442 1443 1444 1445 1446 1447 | pageIntegrity(pPage); } /* ** Get a page from the pager. Initialize the MemPage.pBt and ** MemPage.aData elements if needed. */ | | | | | | < < | < < | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > < < < < | < > > > | > | < < < < < < < < < | | < < < < < < < < < < < < | < < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < | < | < < < < < < < < < < < | < | | | | | | | | < | | | | | < < < < < | > | 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 | pageIntegrity(pPage); } /* ** Get a page from the pager. Initialize the MemPage.pBt and ** MemPage.aData elements if needed. */ static int getPage(Btree *pBt, Pgno pgno, MemPage **ppPage){ int rc; unsigned char *aData; MemPage *pPage; rc = sqlite3pager_get(pBt->pPager, pgno, (void**)&aData); if( rc ) return rc; pPage = (MemPage*)&aData[pBt->psAligned]; pPage->aData = aData; pPage->pBt = pBt; pPage->pgno = pgno; pPage->hdrOffset = pPage->pgno==1 ? 100 : 0; *ppPage = pPage; return SQLITE_OK; } /* ** Get a page from the pager and initialize it. This routine ** is just a convenience wrapper around separate calls to ** getPage() and initPage(). */ static int getAndInitPage( Btree *pBt, /* The database file */ Pgno pgno, /* Number of the page to get */ MemPage **ppPage, /* Write the page pointer here */ MemPage *pParent /* Parent of the page */ ){ int rc; if( pgno==0 ){ return SQLITE_CORRUPT; /* bkpt-CORRUPT */ } rc = getPage(pBt, pgno, ppPage); if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){ rc = initPage(*ppPage, pParent); } return rc; } /* ** Release a MemPage. This should be called once for each prior ** call to getPage. */ static void releasePage(MemPage *pPage){ if( pPage ){ assert( pPage->aData ); assert( pPage->pBt ); assert( &pPage->aData[pPage->pBt->psAligned]==(unsigned char*)pPage ); sqlite3pager_unref(pPage->aData); } } /* ** This routine is called when the reference count for a page ** reaches zero. We need to unref the pParent pointer when that ** happens. */ static void pageDestructor(void *pData, int pageSize){ MemPage *pPage = (MemPage*)&((char*)pData)[FORCE_ALIGNMENT(pageSize)]; if( pPage->pParent ){ MemPage *pParent = pPage->pParent; pPage->pParent = 0; releasePage(pParent); } pPage->isInit = 0; } /* ** During a rollback, when the pager reloads information into the cache ** so that the cache is restored to its original state at the start of ** the transaction, for each page restored this routine is called. ** ** This routine needs to reset the extra data section at the end of the ** page to agree with the restored data. */ static void pageReinit(void *pData, int pageSize){ MemPage *pPage = (MemPage*)&((char*)pData)[FORCE_ALIGNMENT(pageSize)]; if( pPage->isInit ){ pPage->isInit = 0; initPage(pPage, pPage->pParent); } } /* ** Open a database file. ** ** zFilename is the name of the database file. If zFilename is NULL ** a new database with a random name is created. This randomly named ** database file will be deleted when sqlite3BtreeClose() is called. */ int sqlite3BtreeOpen( const char *zFilename, /* Name of the file containing the BTree database */ Btree **ppBtree, /* Pointer to new Btree object written here */ int flags /* Options */ ){ Btree *pBt; int rc; int nReserve; unsigned char zDbHeader[100]; /* ** The following asserts make sure that structures used by the btree are ** the right size. This is to guard against size changes that result ** when compiling on a different architecture. */ assert( sizeof(i64)==8 ); assert( sizeof(u64)==8 ); assert( sizeof(u32)==4 ); assert( sizeof(u16)==2 ); assert( sizeof(Pgno)==4 ); assert( sizeof(ptr)==sizeof(char*) ); assert( sizeof(uptr)==sizeof(ptr) ); pBt = sqliteMalloc( sizeof(*pBt) ); if( pBt==0 ){ *ppBtree = 0; return SQLITE_NOMEM; } rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE, flags); if( rc!=SQLITE_OK ){ if( pBt->pPager ) sqlite3pager_close(pBt->pPager); sqliteFree(pBt); *ppBtree = 0; return rc; } sqlite3pager_set_destructor(pBt->pPager, pageDestructor); sqlite3pager_set_reiniter(pBt->pPager, pageReinit); pBt->pCursor = 0; pBt->pPage1 = 0; pBt->readOnly = sqlite3pager_isreadonly(pBt->pPager); sqlite3pager_read_fileheader(pBt->pPager, sizeof(zDbHeader), zDbHeader); pBt->pageSize = get2byte(&zDbHeader[16]); if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE ){ pBt->pageSize = SQLITE_DEFAULT_PAGE_SIZE; pBt->maxEmbedFrac = 64; /* 25% */ pBt->minEmbedFrac = 32; /* 12.5% */ pBt->minLeafFrac = 32; /* 12.5% */ #ifndef SQLITE_OMIT_AUTOVACUUM /* If the magic name ":memory:" will create an in-memory database, then ** do not set the auto-vacuum flag, even if SQLITE_DEFAULT_AUTOVACUUM ** is true. On the other hand, if SQLITE_OMIT_MEMORYDB has been defined, ** then ":memory:" is just a regular file-name. Respect the auto-vacuum ** default in this case. */ #ifndef SQLITE_OMIT_MEMORYDB if( zFilename && strcmp(zFilename,":memory:") ){ #else if( zFilename ){ #endif pBt->autoVacuum = SQLITE_DEFAULT_AUTOVACUUM; } #endif nReserve = 0; }else{ nReserve = zDbHeader[20]; pBt->maxEmbedFrac = zDbHeader[21]; pBt->minEmbedFrac = zDbHeader[22]; pBt->minLeafFrac = zDbHeader[23]; pBt->pageSizeFixed = 1; #ifndef SQLITE_OMIT_AUTOVACUUM pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0); #endif } pBt->usableSize = pBt->pageSize - nReserve; pBt->psAligned = FORCE_ALIGNMENT(pBt->pageSize); sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize); *ppBtree = pBt; return SQLITE_OK; } /* ** Close an open database and invalidate all cursors. */ int sqlite3BtreeClose(Btree *pBt){ while( pBt->pCursor ){ sqlite3BtreeCloseCursor(pBt->pCursor); } sqlite3pager_close(pBt->pPager); sqliteFree(pBt); return SQLITE_OK; } /* ** Change the busy handler callback function. */ int sqlite3BtreeSetBusyHandler(Btree *pBt, BusyHandler *pHandler){ sqlite3pager_set_busyhandler(pBt->pPager, pHandler); return SQLITE_OK; } /* ** Change the limit on the number of pages allowed in the cache. ** ** The maximum number of cache pages is set to the absolute ** value of mxPage. If mxPage is negative, the pager will ** operate asynchronously - it will not stop to do fsync()s ** to insure data is written to the disk surface before ** continuing. Transactions still work if synchronous is off, ** and the database cannot be corrupted if this program ** crashes. But if the operating system crashes or there is ** an abrupt power failure when synchronous is off, the database ** could be left in an inconsistent and unrecoverable state. ** Synchronous is on by default so database corruption is not ** normally a worry. */ int sqlite3BtreeSetCacheSize(Btree *pBt, int mxPage){ sqlite3pager_set_cachesize(pBt->pPager, mxPage); return SQLITE_OK; } /* ** Change the way data is synced to disk in order to increase or decrease ** how well the database resists damage due to OS crashes and power ** failures. Level 1 is the same as asynchronous (no syncs() occur and ** there is a high probability of damage) Level 2 is the default. There ** is a very low but non-zero probability of damage. Level 3 reduces the ** probability of damage to near zero but with a write performance reduction. */ #ifndef SQLITE_OMIT_PAGER_PRAGMAS int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){ sqlite3pager_set_safety_level(pBt->pPager, level); return SQLITE_OK; } #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) /* ** Change the default pages size and the number of reserved bytes per page. ** ** The page size must be a power of 2 between 512 and 65536. If the page ** size supplied does not meet this constraint then the page size is not ** changed. ** ** Page sizes are constrained to be a power of two so that the region ** of the database file used for locking (beginning at PENDING_BYTE, ** the first byte past the 1GB boundary, 0x40000000) needs to occur ** at the beginning of a page. ** ** If parameter nReserve is less than zero, then the number of reserved ** bytes per page is left unchanged. */ int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){ if( pBt->pageSizeFixed ){ return SQLITE_READONLY; } if( nReserve<0 ){ nReserve = pBt->pageSize - pBt->usableSize; } if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && ((pageSize-1)&pageSize)==0 ){ pBt->pageSize = pageSize; pBt->psAligned = FORCE_ALIGNMENT(pageSize); sqlite3pager_set_pagesize(pBt->pPager, pageSize); } pBt->usableSize = pBt->pageSize - nReserve; return SQLITE_OK; } /* ** Return the currently defined page size */ int sqlite3BtreeGetPageSize(Btree *pBt){ return pBt->pageSize; } int sqlite3BtreeGetReserve(Btree *pBt){ return pBt->pageSize - pBt->usableSize; } #endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ /* ** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' ** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it ** is disabled. The default value for the auto-vacuum property is ** determined by the SQLITE_DEFAULT_AUTOVACUUM macro. */ int sqlite3BtreeSetAutoVacuum(Btree *pBt, int autoVacuum){ #ifdef SQLITE_OMIT_AUTOVACUUM return SQLITE_READONLY; #else if( pBt->pageSizeFixed ){ return SQLITE_READONLY; } pBt->autoVacuum = (autoVacuum?1:0); return SQLITE_OK; #endif } /* ** Return the value of the 'auto-vacuum' property. If auto-vacuum is ** enabled 1 is returned. Otherwise 0. */ int sqlite3BtreeGetAutoVacuum(Btree *pBt){ #ifdef SQLITE_OMIT_AUTOVACUUM return 0; #else return pBt->autoVacuum; #endif } /* ** Get a reference to pPage1 of the database file. This will ** also acquire a readlock on that file. ** ** SQLITE_OK is returned on success. If the file is not a ** well-formed database file, then SQLITE_CORRUPT is returned. ** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM ** is returned if we run out of memory. SQLITE_PROTOCOL is returned ** if there is a locking protocol violation. */ static int lockBtree(Btree *pBt){ int rc; MemPage *pPage1; if( pBt->pPage1 ) return SQLITE_OK; rc = getPage(pBt, 1, &pPage1); if( rc!=SQLITE_OK ) return rc; /* Do some checking to help insure the file we opened really is ** a valid database file. */ rc = SQLITE_NOTADB; if( sqlite3pager_pagecount(pBt->pPager)>0 ){ u8 *page1 = pPage1->aData; if( memcmp(page1, zMagicHeader, 16)!=0 ){ goto page1_init_failed; } if( page1[18]>1 || page1[19]>1 ){ goto page1_init_failed; } pBt->pageSize = get2byte(&page1[16]); pBt->usableSize = pBt->pageSize - page1[20]; if( pBt->usableSize<500 ){ goto page1_init_failed; } pBt->psAligned = FORCE_ALIGNMENT(pBt->pageSize); pBt->maxEmbedFrac = page1[21]; pBt->minEmbedFrac = page1[22]; pBt->minLeafFrac = page1[23]; #ifndef SQLITE_OMIT_AUTOVACUUM pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0); #endif } |
︙ | ︙ | |||
1944 1945 1946 1947 1948 1949 1950 | page1_init_failed: releasePage(pPage1); pBt->pPage1 = 0; return rc; } | < < < < < < < < < < < < < < < < < < < < < | | | | | 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 | page1_init_failed: releasePage(pPage1); pBt->pPage1 = 0; return rc; } /* ** If there are no outstanding cursors and we are not in the middle ** of a transaction but there is a read lock on the database, then ** this routine unrefs the first page of the database file which ** has the effect of releasing the read lock. ** ** If there are any outstanding cursors, this routine is a no-op. ** ** If there is a transaction in progress, this routine is a no-op. */ static void unlockBtreeIfUnused(Btree *pBt){ if( pBt->inTrans==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){ if( pBt->pPage1->aData==0 ){ MemPage *pPage = pBt->pPage1; pPage->aData = &((char*)pPage)[-pBt->psAligned]; pPage->pBt = pBt; pPage->pgno = 1; } releasePage(pBt->pPage1); pBt->pPage1 = 0; pBt->inStmt = 0; } } /* ** Create a new database by initializing the first page of the ** file. */ static int newDatabase(Btree *pBt){ MemPage *pP1; unsigned char *data; int rc; if( sqlite3pager_pagecount(pBt->pPager)>0 ) return SQLITE_OK; pP1 = pBt->pPage1; assert( pP1!=0 ); data = pP1->aData; |
︙ | ︙ | |||
2029 2030 2031 2032 2033 2034 2035 | /* ** Attempt to start a new transaction. A write-transaction ** is started if the second argument is nonzero, otherwise a read- ** transaction. If the second argument is 2 or more and exclusive ** transaction is started, meaning that no other process is allowed ** to access the database. A preexisting transaction may not be | | | | | < < < < < < < < | < | < < < > | < < < < < < < < < < < | | | | | | | | | | | | > | | | | < < < < < < < < < < < < < < | | 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 | /* ** Attempt to start a new transaction. A write-transaction ** is started if the second argument is nonzero, otherwise a read- ** transaction. If the second argument is 2 or more and exclusive ** transaction is started, meaning that no other process is allowed ** to access the database. A preexisting transaction may not be ** upgrade to exclusive by calling this routine a second time - the ** exclusivity flag only works for a new transaction. ** ** A write-transaction must be started before attempting any ** changes to the database. None of the following routines ** will work unless a transaction is started first: ** ** sqlite3BtreeCreateTable() ** sqlite3BtreeCreateIndex() ** sqlite3BtreeClearTable() ** sqlite3BtreeDropTable() ** sqlite3BtreeInsert() ** sqlite3BtreeDelete() ** sqlite3BtreeUpdateMeta() ** ** If wrflag is true, then nMaster specifies the maximum length of ** a master journal file name supplied later via sqlite3BtreeSync(). ** This is so that appropriate space can be allocated in the journal file ** when it is created.. */ int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){ int rc = SQLITE_OK; /* If the btree is already in a write-transaction, or it ** is already in a read-transaction and a read-transaction ** is requested, this is a no-op. */ if( pBt->inTrans==TRANS_WRITE || (pBt->inTrans==TRANS_READ && !wrflag) ){ return SQLITE_OK; } if( pBt->readOnly && wrflag ){ return SQLITE_READONLY; } if( pBt->pPage1==0 ){ rc = lockBtree(pBt); } if( rc==SQLITE_OK && wrflag ){ rc = sqlite3pager_begin(pBt->pPage1->aData, wrflag>1); if( rc==SQLITE_OK ){ rc = newDatabase(pBt); } } if( rc==SQLITE_OK ){ pBt->inTrans = (wrflag?TRANS_WRITE:TRANS_READ); if( wrflag ) pBt->inStmt = 0; }else{ unlockBtreeIfUnused(pBt); } return rc; } #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Set the pointer-map entries for all children of page pPage. Also, if ** pPage contains cells that point to overflow pages, set the pointer ** map entries for the overflow pages as well. */ static int setChildPtrmaps(MemPage *pPage){ int i; /* Counter variable */ int nCell; /* Number of cells in page pPage */ int rc = SQLITE_OK; /* Return code */ Btree *pBt = pPage->pBt; int isInitOrig = pPage->isInit; Pgno pgno = pPage->pgno; initPage(pPage, 0); nCell = pPage->nCell; for(i=0; i<nCell; i++){ |
︙ | ︙ | |||
2181 2182 2183 2184 2185 2186 2187 | ** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next ** overflow page in the list. */ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ if( eType==PTRMAP_OVERFLOW2 ){ /* The pointer is always the first 4 bytes of the page in this case. */ if( get4byte(pPage->aData)!=iFrom ){ | | | 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 | ** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next ** overflow page in the list. */ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ if( eType==PTRMAP_OVERFLOW2 ){ /* The pointer is always the first 4 bytes of the page in this case. */ if( get4byte(pPage->aData)!=iFrom ){ return SQLITE_CORRUPT; } put4byte(pPage->aData, iTo); }else{ int isInitOrig = pPage->isInit; int i; int nCell; |
︙ | ︙ | |||
2214 2215 2216 2217 2218 2219 2220 | } } } if( i==nCell ){ if( eType!=PTRMAP_BTREE || get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ | | | | 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 | } } } if( i==nCell ){ if( eType!=PTRMAP_BTREE || get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ return SQLITE_CORRUPT; } put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); } pPage->isInit = isInitOrig; } return SQLITE_OK; } /* ** Move the open database page pDbPage to location iFreePage in the ** database. The pDbPage reference remains valid. */ static int relocatePage( Btree *pBt, /* Btree */ MemPage *pDbPage, /* Open page to move */ u8 eType, /* Pointer map 'type' entry for pDbPage */ Pgno iPtrPage, /* Pointer map 'page-no' entry for pDbPage */ Pgno iFreePage /* The location to move pDbPage to */ ){ MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */ Pgno iDbPage = pDbPage->pgno; |
︙ | ︙ | |||
2300 2301 2302 2303 2304 2305 2306 | rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage); } } return rc; } /* Forward declaration required by autoVacuumCommit(). */ | | | | | | | | | | | 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 | rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage); } } return rc; } /* Forward declaration required by autoVacuumCommit(). */ static int allocatePage(Btree *, MemPage **, Pgno *, Pgno, u8); /* ** This routine is called prior to sqlite3pager_commit when a transaction ** is commited for an auto-vacuum database. */ static int autoVacuumCommit(Btree *pBt, Pgno *nTrunc){ Pager *pPager = pBt->pPager; Pgno nFreeList; /* Number of pages remaining on the free-list. */ int nPtrMap; /* Number of pointer-map pages deallocated */ Pgno origSize; /* Pages in the database file */ Pgno finSize; /* Pages in the database file after truncation */ int rc; /* Return code */ u8 eType; int pgsz = pBt->pageSize; /* Page size for this database */ Pgno iDbPage; /* The database page to move */ MemPage *pDbMemPage = 0; /* "" */ Pgno iPtrPage; /* The page that contains a pointer to iDbPage */ Pgno iFreePage; /* The free-list page to move iDbPage to */ MemPage *pFreeMemPage = 0; /* "" */ #ifndef NDEBUG int nRef = *sqlite3pager_stats(pPager); #endif assert( pBt->autoVacuum ); if( PTRMAP_ISPAGE(pgsz, sqlite3pager_pagecount(pPager)) ){ return SQLITE_CORRUPT; } /* Figure out how many free-pages are in the database. If there are no ** free pages, then auto-vacuum is a no-op. */ nFreeList = get4byte(&pBt->pPage1->aData[36]); if( nFreeList==0 ){ *nTrunc = 0; return SQLITE_OK; } origSize = sqlite3pager_pagecount(pPager); nPtrMap = (nFreeList-origSize+PTRMAP_PAGENO(pgsz, origSize)+pgsz/5)/(pgsz/5); finSize = origSize - nFreeList - nPtrMap; if( origSize>PENDING_BYTE_PAGE(pBt) && finSize<=PENDING_BYTE_PAGE(pBt) ){ finSize--; if( PTRMAP_ISPAGE(pBt->usableSize, finSize) ){ finSize--; } } TRACE(("AUTOVACUUM: Begin (db size %d->%d)\n", origSize, finSize)); |
︙ | ︙ | |||
2364 2365 2366 2367 2368 2369 2370 | /* If iDbPage is a pointer map page, or the pending-byte page, skip it. */ if( PTRMAP_ISPAGE(pgsz, iDbPage) || iDbPage==PENDING_BYTE_PAGE(pBt) ){ continue; } rc = ptrmapGet(pBt, iDbPage, &eType, &iPtrPage); if( rc!=SQLITE_OK ) goto autovacuum_out; | | < < < | 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 | /* If iDbPage is a pointer map page, or the pending-byte page, skip it. */ if( PTRMAP_ISPAGE(pgsz, iDbPage) || iDbPage==PENDING_BYTE_PAGE(pBt) ){ continue; } rc = ptrmapGet(pBt, iDbPage, &eType, &iPtrPage); if( rc!=SQLITE_OK ) goto autovacuum_out; assert( eType!=PTRMAP_ROOTPAGE ); /* If iDbPage is free, do not swap it. */ if( eType==PTRMAP_FREEPAGE ){ continue; } rc = getPage(pBt, iDbPage, &pDbMemPage); if( rc!=SQLITE_OK ) goto autovacuum_out; |
︙ | ︙ | |||
2395 2396 2397 2398 2399 2400 2401 | goto autovacuum_out; } assert( iFreePage<=origSize ); }while( iFreePage>finSize ); releasePage(pFreeMemPage); pFreeMemPage = 0; | < < < < < < | 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 | goto autovacuum_out; } assert( iFreePage<=origSize ); }while( iFreePage>finSize ); releasePage(pFreeMemPage); pFreeMemPage = 0; rc = relocatePage(pBt, pDbMemPage, eType, iPtrPage, iFreePage); releasePage(pDbMemPage); if( rc!=SQLITE_OK ) goto autovacuum_out; } /* The entire free-list has been swapped to the end of the file. So ** truncate the database file to finSize pages and consider the |
︙ | ︙ | |||
2432 2433 2434 2435 2436 2437 2438 | /* ** Commit the transaction currently in progress. ** ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ | | < < < < < < < < | < < < < < < < < < < < < < < < < < < < < | > < < | | | < | | < < < < < | < < < < < < < < < < < < | < < | < | < | < | < | 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 | /* ** Commit the transaction currently in progress. ** ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ int sqlite3BtreeCommit(Btree *pBt){ int rc = SQLITE_OK; if( pBt->inTrans==TRANS_WRITE ){ rc = sqlite3pager_commit(pBt->pPager); } pBt->inTrans = TRANS_NONE; pBt->inStmt = 0; unlockBtreeIfUnused(pBt); return rc; } #ifndef NDEBUG /* ** Return the number of write-cursors open on this handle. This is for use ** in assert() expressions, so it is only compiled if NDEBUG is not ** defined. */ static int countWriteCursors(Btree *pBt){ BtCursor *pCur; int r = 0; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ if( pCur->wrFlag ) r++; } return r; } #endif #ifdef SQLITE_TEST /* ** Print debugging information about all cursors to standard output. */ void sqlite3BtreeCursorList(Btree *pBt){ BtCursor *pCur; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ MemPage *pPage = pCur->pPage; char *zMode = pCur->wrFlag ? "rw" : "ro"; sqlite3DebugPrintf("CURSOR %p rooted at %4d(%s) currently at %d.%d%s\n", pCur, pCur->pgnoRoot, zMode, pPage ? pPage->pgno : 0, pCur->idx, pCur->isValid ? "" : " eof" ); } } #endif /* ** Rollback the transaction in progress. All cursors will be ** invalided by this operation. Any attempt to use a cursor ** that was open at the beginning of this operation will result ** in an error. ** ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ int sqlite3BtreeRollback(Btree *pBt){ int rc = SQLITE_OK; MemPage *pPage1; if( pBt->inTrans==TRANS_WRITE ){ rc = sqlite3pager_rollback(pBt->pPager); /* The rollback may have destroyed the pPage1->aData value. So ** call getPage() on page 1 again to make sure pPage1->aData is ** set correctly. */ if( getPage(pBt, 1, &pPage1)==SQLITE_OK ){ releasePage(pPage1); } assert( countWriteCursors(pBt)==0 ); } pBt->inTrans = TRANS_NONE; pBt->inStmt = 0; unlockBtreeIfUnused(pBt); return rc; } /* ** Start a statement subtransaction. The subtransaction can ** can be rolled back independently of the main transaction. ** You must start a transaction before starting a subtransaction. ** The subtransaction is ended automatically if the main transaction ** commits or rolls back. ** ** Only one subtransaction may be active at a time. It is an error to try ** to start a new subtransaction if another subtransaction is already active. ** ** Statement subtransactions are used around individual SQL statements ** that are contained within a BEGIN...COMMIT block. If a constraint ** error occurs within the statement, the effect of that one statement ** can be rolled back without having to rollback the entire transaction. */ int sqlite3BtreeBeginStmt(Btree *pBt){ int rc; if( (pBt->inTrans!=TRANS_WRITE) || pBt->inStmt ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } rc = pBt->readOnly ? SQLITE_OK : sqlite3pager_stmt_begin(pBt->pPager); pBt->inStmt = 1; return rc; } /* ** Commit the statment subtransaction currently in progress. If no ** subtransaction is active, this is a no-op. */ int sqlite3BtreeCommitStmt(Btree *pBt){ int rc; if( pBt->inStmt && !pBt->readOnly ){ rc = sqlite3pager_stmt_commit(pBt->pPager); }else{ rc = SQLITE_OK; } pBt->inStmt = 0; return rc; } /* ** Rollback the active statement subtransaction. If no subtransaction ** is active this routine is a no-op. ** ** All cursors will be invalidated by this operation. Any attempt ** to use a cursor that was open at the beginning of this operation ** will result in an error. */ int sqlite3BtreeRollbackStmt(Btree *pBt){ int rc; if( pBt->inStmt==0 || pBt->readOnly ) return SQLITE_OK; rc = sqlite3pager_stmt_rollback(pBt->pPager); assert( countWriteCursors(pBt)==0 ); pBt->inStmt = 0; return rc; } |
︙ | ︙ | |||
2676 2677 2678 2679 2680 2681 2682 | ** The comparison function must be logically the same for every cursor ** on a particular table. Changing the comparison function will result ** in incorrect operations. If the comparison function is NULL, a ** default comparison function is used. The comparison function is ** always ignored for INTKEY tables. */ int sqlite3BtreeCursor( | | < < | | > > < < < < < | > > > | < > | 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 | ** The comparison function must be logically the same for every cursor ** on a particular table. Changing the comparison function will result ** in incorrect operations. If the comparison function is NULL, a ** default comparison function is used. The comparison function is ** always ignored for INTKEY tables. */ int sqlite3BtreeCursor( Btree *pBt, /* The btree */ int iTable, /* Root page of table to open */ int wrFlag, /* 1 to write. 0 read-only */ int (*xCmp)(void*,int,const void*,int,const void*), /* Key Comparison func */ void *pArg, /* First arg to xCompare() */ BtCursor **ppCur /* Write new cursor here */ ){ int rc; BtCursor *pCur; *ppCur = 0; if( wrFlag ){ if( pBt->readOnly ){ return SQLITE_READONLY; } if( checkReadLocks(pBt, iTable, 0) ){ return SQLITE_LOCKED; } } if( pBt->pPage1==0 ){ rc = lockBtree(pBt); if( rc!=SQLITE_OK ){ return rc; } } pCur = sqliteMallocRaw( sizeof(*pCur) ); if( pCur==0 ){ rc = SQLITE_NOMEM; goto create_cursor_exception; } pCur->pgnoRoot = (Pgno)iTable; if( iTable==1 && sqlite3pager_pagecount(pBt->pPager)==0 ){ rc = SQLITE_EMPTY; pCur->pPage = 0; goto create_cursor_exception; } pCur->pPage = 0; /* For exit-handler, in case getAndInitPage() fails. */ rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0); if( rc!=SQLITE_OK ){ goto create_cursor_exception; } pCur->xCompare = xCmp ? xCmp : dfltCompare; pCur->pArg = pArg; pCur->pBt = pBt; pCur->wrFlag = wrFlag; pCur->idx = 0; memset(&pCur->info, 0, sizeof(pCur->info)); pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; } pCur->pPrev = 0; pBt->pCursor = pCur; pCur->isValid = 0; *ppCur = pCur; return SQLITE_OK; create_cursor_exception: if( pCur ){ releasePage(pCur->pPage); sqliteFree(pCur); } unlockBtreeIfUnused(pBt); return rc; |
︙ | ︙ | |||
2763 2764 2765 2766 2767 2768 2769 | #endif /* ** Close a cursor. The read lock on the database file is released ** when the last cursor is closed. */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ | | < | 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 | #endif /* ** Close a cursor. The read lock on the database file is released ** when the last cursor is closed. */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ Btree *pBt = pCur->pBt; if( pCur->pPrev ){ pCur->pPrev->pNext = pCur->pNext; }else{ pBt->pCursor = pCur->pNext; } if( pCur->pNext ){ pCur->pNext->pPrev = pCur->pPrev; |
︙ | ︙ | |||
2831 2832 2833 2834 2835 2836 2837 | ** the key for the current entry. If the cursor is not pointing ** to a valid entry, *pSize is set to 0. ** ** For a table with the INTKEY flag set, this routine returns the key ** itself, not the number of bytes in the key. */ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ | < < < | | | | | | < | < < < | | | | | | | < | | 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 | ** the key for the current entry. If the cursor is not pointing ** to a valid entry, *pSize is set to 0. ** ** For a table with the INTKEY flag set, this routine returns the key ** itself, not the number of bytes in the key. */ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ if( !pCur->isValid ){ *pSize = 0; }else{ getCellInfo(pCur); *pSize = pCur->info.nKey; } return SQLITE_OK; } /* ** Set *pSize to the number of bytes of data in the entry the ** cursor currently points to. Always return SQLITE_OK. ** Failure is not possible. If the cursor is not currently ** pointing to an entry (which can happen, for example, if ** the database is empty) then *pSize is set to 0. */ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ if( !pCur->isValid ){ /* Not pointing at a valid entry - set *pSize to 0. */ *pSize = 0; }else{ getCellInfo(pCur); *pSize = pCur->info.nData; } return SQLITE_OK; } /* ** Read payload information from the entry that the pCur cursor is ** pointing to. Begin reading the payload at "offset" and read ** a total of "amt" bytes. Put the result in zBuf. ** |
︙ | ︙ | |||
2886 2887 2888 2889 2890 2891 2892 | unsigned char *pBuf, /* Write the bytes into this buffer */ int skipKey /* offset begins at data if this is true */ ){ unsigned char *aPayload; Pgno nextPage; int rc; MemPage *pPage; | | | | | > | 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 | unsigned char *pBuf, /* Write the bytes into this buffer */ int skipKey /* offset begins at data if this is true */ ){ unsigned char *aPayload; Pgno nextPage; int rc; MemPage *pPage; Btree *pBt; int ovflSize; u32 nKey; assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->isValid ); pBt = pCur->pBt; pPage = pCur->pPage; pageIntegrity(pPage); assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); getCellInfo(pCur); aPayload = pCur->info.pCell; aPayload += pCur->info.nHeader; if( pPage->intKey ){ nKey = 0; }else{ nKey = pCur->info.nKey; } assert( offset>=0 ); if( skipKey ){ |
︙ | ︙ | |||
2951 2952 2953 2954 2955 2956 2957 | offset -= ovflSize; } sqlite3pager_unref(aPayload); } } if( amt>0 ){ | | < < | | < < < | | | < < < < | | | | < < | 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 | offset -= ovflSize; } sqlite3pager_unref(aPayload); } } if( amt>0 ){ return SQLITE_CORRUPT; /* bkpt-CORRUPT */ } return SQLITE_OK; } /* ** Read part of the key associated with cursor pCur. Exactly ** "amt" bytes will be transfered into pBuf[]. The transfer ** begins at "offset". ** ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ assert( pCur->isValid ); assert( pCur->pPage!=0 ); assert( pCur->pPage->intKey==0 ); assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); return getPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); } /* ** Read part of the data associated with cursor pCur. Exactly ** "amt" bytes will be transfered into pBuf[]. The transfer ** begins at "offset". ** ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ assert( pCur->isValid ); assert( pCur->pPage!=0 ); assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); return getPayload(pCur, offset, amt, pBuf, 1); } /* ** Return a pointer to payload information from the entry that the ** pCur cursor is pointing to. The pointer is to the beginning of ** the key if skipKey==0 and it points to the beginning of data if ** skipKey==1. The number of bytes of available key/data is written |
︙ | ︙ | |||
3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 | static const unsigned char *fetchPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ int *pAmt, /* Write the number of available bytes here */ int skipKey /* read beginning at data if this is true */ ){ unsigned char *aPayload; MemPage *pPage; u32 nKey; int nLocal; assert( pCur!=0 && pCur->pPage!=0 ); | > | > | 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 | static const unsigned char *fetchPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ int *pAmt, /* Write the number of available bytes here */ int skipKey /* read beginning at data if this is true */ ){ unsigned char *aPayload; MemPage *pPage; Btree *pBt; u32 nKey; int nLocal; assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->isValid ); pBt = pCur->pBt; pPage = pCur->pPage; pageIntegrity(pPage); assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); getCellInfo(pCur); aPayload = pCur->info.pCell; aPayload += pCur->info.nHeader; if( pPage->intKey ){ |
︙ | ︙ | |||
3068 3069 3070 3071 3072 3073 3074 | ** The pointer returned is ephemeral. The key/data may move ** or be destroyed on the next call to any Btree routine. ** ** These routines is used to get quick access to key and data ** in the common case where no overflow pages are used. */ const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ | < | | < < < | < < | | | | 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 | ** The pointer returned is ephemeral. The key/data may move ** or be destroyed on the next call to any Btree routine. ** ** These routines is used to get quick access to key and data ** in the common case where no overflow pages are used. */ const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ return (const void*)fetchPayload(pCur, pAmt, 0); } const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){ return (const void*)fetchPayload(pCur, pAmt, 1); } /* ** Move the cursor down to a new child page. The newPgno argument is the ** page number of the child page to move to. */ static int moveToChild(BtCursor *pCur, u32 newPgno){ int rc; MemPage *pNewPage; MemPage *pOldPage; Btree *pBt = pCur->pBt; assert( pCur->isValid ); rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage); if( rc ) return rc; pageIntegrity(pNewPage); pNewPage->idxParent = pCur->idx; pOldPage = pCur->pPage; pOldPage->idxShift = 0; releasePage(pOldPage); pCur->pPage = pNewPage; pCur->idx = 0; pCur->info.nSize = 0; if( pNewPage->nCell<1 ){ return SQLITE_CORRUPT; /* bkpt-CORRUPT */ } return SQLITE_OK; } /* ** Return true if the page is the virtual root of its table. ** |
︙ | ︙ | |||
3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 | ** ** pCur->idx is set to the cell index that contains the pointer ** to the page we are coming from. If we are coming from the ** right-most child page then pCur->idx is set to one more than ** the largest cell index. */ static void moveToParent(BtCursor *pCur){ MemPage *pParent; MemPage *pPage; int idxParent; | > | > | | < < < < < < < | | | | | | | | < | | < < < | < < < | | | | | | 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 | ** ** pCur->idx is set to the cell index that contains the pointer ** to the page we are coming from. If we are coming from the ** right-most child page then pCur->idx is set to one more than ** the largest cell index. */ static void moveToParent(BtCursor *pCur){ Pgno oldPgno; MemPage *pParent; MemPage *pPage; int idxParent; assert( pCur->isValid ); pPage = pCur->pPage; assert( pPage!=0 ); assert( !isRootPage(pPage) ); pageIntegrity(pPage); pParent = pPage->pParent; assert( pParent!=0 ); pageIntegrity(pParent); idxParent = pPage->idxParent; sqlite3pager_ref(pParent->aData); oldPgno = pPage->pgno; releasePage(pPage); pCur->pPage = pParent; pCur->info.nSize = 0; assert( pParent->idxShift==0 ); pCur->idx = idxParent; } /* ** Move the cursor to the root page */ static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; int rc; Btree *pBt = pCur->pBt; rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0); if( rc ){ pCur->isValid = 0; return rc; } releasePage(pCur->pPage); pageIntegrity(pRoot); pCur->pPage = pRoot; pCur->idx = 0; pCur->info.nSize = 0; if( pRoot->nCell==0 && !pRoot->leaf ){ Pgno subpage; assert( pRoot->pgno==1 ); subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); assert( subpage>0 ); pCur->isValid = 1; rc = moveToChild(pCur, subpage); } pCur->isValid = pCur->pPage->nCell>0; return rc; } /* ** Move the cursor down to the left-most leaf entry beneath the ** entry to which it is currently pointing. */ static int moveToLeftmost(BtCursor *pCur){ Pgno pgno; int rc; MemPage *pPage; assert( pCur->isValid ); while( !(pPage = pCur->pPage)->leaf ){ assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); pgno = get4byte(findCell(pPage, pCur->idx)); rc = moveToChild(pCur, pgno); if( rc ) return rc; } return SQLITE_OK; } /* ** Move the cursor down to the right-most leaf entry beneath the ** page to which it is currently pointing. Notice the difference ** between moveToLeftmost() and moveToRightmost(). moveToLeftmost() ** finds the left-most entry beneath the *entry* whereas moveToRightmost() ** finds the right-most entry beneath the *page*. */ static int moveToRightmost(BtCursor *pCur){ Pgno pgno; int rc; MemPage *pPage; assert( pCur->isValid ); while( !(pPage = pCur->pPage)->leaf ){ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); pCur->idx = pPage->nCell; rc = moveToChild(pCur, pgno); if( rc ) return rc; } pCur->idx = pPage->nCell - 1; pCur->info.nSize = 0; return SQLITE_OK; } /* Move the cursor to the first entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ int rc; rc = moveToRoot(pCur); if( rc ) return rc; if( pCur->isValid==0 ){ assert( pCur->pPage->nCell==0 ); *pRes = 1; return SQLITE_OK; } assert( pCur->pPage->nCell>0 ); *pRes = 0; rc = moveToLeftmost(pCur); return rc; } /* Move the cursor to the last entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int rc; rc = moveToRoot(pCur); if( rc ) return rc; if( pCur->isValid==0 ){ assert( pCur->pPage->nCell==0 ); *pRes = 1; return SQLITE_OK; } assert( pCur->isValid ); *pRes = 0; rc = moveToRightmost(pCur); return rc; } /* Move the cursor so that it points to an entry near pKey/nKey. ** Return a success code. ** ** For INTKEY tables, only the nKey parameter is used. pKey is ** ignored. For other tables, nKey is the number of bytes of data ** in nKey. The comparison function specified when the cursor was ** created is used to compare keys. ** ** If an exact match is not found, then the cursor is always ** left pointing at a leaf page which would hold the entry if it ** were present. The cursor might point to an entry that comes ** before or after the key. ** |
︙ | ︙ | |||
3309 3310 3311 3312 3313 3314 3315 | ** exactly matches pKey. ** ** *pRes>0 The cursor is left pointing at an entry that ** is larger than pKey. */ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ int rc; | < < | | > < < < < < < < < < < < < | 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 | ** exactly matches pKey. ** ** *pRes>0 The cursor is left pointing at an entry that ** is larger than pKey. */ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ int rc; rc = moveToRoot(pCur); if( rc ) return rc; assert( pCur->pPage ); assert( pCur->pPage->isInit ); if( pCur->isValid==0 ){ *pRes = -1; assert( pCur->pPage->nCell==0 ); return SQLITE_OK; } for(;;){ int lwr, upr; Pgno chldPg; MemPage *pPage = pCur->pPage; int c = -1; /* pRes return if table is empty must be -1 */ lwr = 0; upr = pPage->nCell-1; if( !pPage->intKey && pKey==0 ){ return SQLITE_CORRUPT; } pageIntegrity(pPage); while( lwr<=upr ){ void *pCellKey; i64 nCellKey; pCur->idx = (lwr+upr)/2; pCur->info.nSize = 0; sqlite3BtreeKeySize(pCur, &nCellKey); if( pPage->intKey ){ if( nCellKey<nKey ){ c = -1; }else if( nCellKey>nKey ){ c = +1; }else{ c = 0; } }else{ int available; pCellKey = (void *)fetchPayload(pCur, &available, 0); if( available>=nCellKey ){ c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); }else{ pCellKey = sqliteMallocRaw( nCellKey ); if( pCellKey==0 ) return SQLITE_NOMEM; rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey); c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); |
︙ | ︙ | |||
3418 3419 3420 3421 3422 3423 3424 | ** Return TRUE if the cursor is not pointing at an entry of the table. ** ** TRUE will be returned after a call to sqlite3BtreeNext() moves ** past the last entry in the table or sqlite3BtreePrev() moves past ** the first entry. TRUE is also returned if the table is empty. */ int sqlite3BtreeEof(BtCursor *pCur){ | < < < < | < < < < < < < < < < < < < | | | 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 | ** Return TRUE if the cursor is not pointing at an entry of the table. ** ** TRUE will be returned after a call to sqlite3BtreeNext() moves ** past the last entry in the table or sqlite3BtreePrev() moves past ** the first entry. TRUE is also returned if the table is empty. */ int sqlite3BtreeEof(BtCursor *pCur){ return pCur->isValid==0; } /* ** Advance the cursor to the next entry in the database. If ** successful then set *pRes=0. If the cursor ** was already pointing to the last entry in the database before ** this routine was called, then set *pRes=1. */ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ int rc; MemPage *pPage = pCur->pPage; assert( pRes!=0 ); if( pCur->isValid==0 ){ *pRes = 1; return SQLITE_OK; } assert( pPage->isInit ); assert( pCur->idx<pPage->nCell ); pCur->idx++; pCur->info.nSize = 0; if( pCur->idx>=pPage->nCell ){ if( !pPage->leaf ){ rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); if( rc ) return rc; rc = moveToLeftmost(pCur); *pRes = 0; return rc; } do{ if( isRootPage(pPage) ){ *pRes = 1; pCur->isValid = 0; return SQLITE_OK; } moveToParent(pCur); pPage = pCur->pPage; }while( pCur->idx>=pPage->nCell ); *pRes = 0; if( pPage->leafData ){ |
︙ | ︙ | |||
3501 3502 3503 3504 3505 3506 3507 | ** was already pointing to the first entry in the database before ** this routine was called, then set *pRes=1. */ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ int rc; Pgno pgno; MemPage *pPage; | < < < < < < | < < < < < < < < | | 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 | ** was already pointing to the first entry in the database before ** this routine was called, then set *pRes=1. */ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ int rc; Pgno pgno; MemPage *pPage; if( pCur->isValid==0 ){ *pRes = 1; return SQLITE_OK; } pPage = pCur->pPage; assert( pPage->isInit ); assert( pCur->idx>=0 ); if( !pPage->leaf ){ pgno = get4byte( findCell(pPage, pCur->idx) ); rc = moveToChild(pCur, pgno); if( rc ) return rc; rc = moveToRightmost(pCur); }else{ while( pCur->idx==0 ){ if( isRootPage(pPage) ){ pCur->isValid = 0; *pRes = 1; return SQLITE_OK; } moveToParent(pCur); pPage = pCur->pPage; } pCur->idx--; |
︙ | ︙ | |||
3572 3573 3574 3575 3576 3577 3578 | ** which in turn can make database access faster. ** ** If the "exact" parameter is not 0, and the page-number nearby exists ** anywhere on the free-list, then it is guarenteed to be returned. This ** is only used by auto-vacuum databases when allocating a new table. */ static int allocatePage( | | | 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 | ** which in turn can make database access faster. ** ** If the "exact" parameter is not 0, and the page-number nearby exists ** anywhere on the free-list, then it is guarenteed to be returned. This ** is only used by auto-vacuum databases when allocating a new table. */ static int allocatePage( Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby, u8 exact ){ MemPage *pPage1; int rc; |
︙ | ︙ | |||
3655 3656 3657 3658 3659 3660 3661 | *pPgno = iTrunk; memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); *ppPage = pTrunk; pTrunk = 0; TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); }else if( k>pBt->usableSize/4 - 8 ){ /* Value of k is out of range. Database corruption */ | | | 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 | *pPgno = iTrunk; memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); *ppPage = pTrunk; pTrunk = 0; TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); }else if( k>pBt->usableSize/4 - 8 ){ /* Value of k is out of range. Database corruption */ return SQLITE_CORRUPT; /* bkpt-CORRUPT */ #ifndef SQLITE_OMIT_AUTOVACUUM }else if( searchList && nearby==iTrunk ){ /* The list is being searched and this trunk page is the page ** to allocate, regardless of whether it has leaves. */ assert( *pPgno==iTrunk ); *ppPage = pTrunk; |
︙ | ︙ | |||
3730 3731 3732 3733 3734 3735 3736 | } iPage = get4byte(&aData[8+closest*4]); if( !searchList || iPage==nearby ){ *pPgno = iPage; if( *pPgno>sqlite3pager_pagecount(pBt->pPager) ){ /* Free page off the end of the file */ | | | 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 | } iPage = get4byte(&aData[8+closest*4]); if( !searchList || iPage==nearby ){ *pPgno = iPage; if( *pPgno>sqlite3pager_pagecount(pBt->pPager) ){ /* Free page off the end of the file */ return SQLITE_CORRUPT; /* bkpt-CORRUPT */ } TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d" ": %d more free pages\n", *pPgno, closest+1, k, pTrunk->pgno, n-1)); if( closest<k-1 ){ memcpy(&aData[8+closest*4], &aData[4+k*4], 4); } |
︙ | ︙ | |||
3790 3791 3792 3793 3794 3795 3796 | /* ** Add a page of the database file to the freelist. ** ** sqlite3pager_unref() is NOT called for pPage. */ static int freePage(MemPage *pPage){ | | | 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 | /* ** Add a page of the database file to the freelist. ** ** sqlite3pager_unref() is NOT called for pPage. */ static int freePage(MemPage *pPage){ Btree *pBt = pPage->pBt; MemPage *pPage1 = pBt->pPage1; int rc, n, k; /* Prepare the page for freeing */ assert( pPage->pgno>1 ); pPage->isInit = 0; releasePage(pPage->pParent); |
︙ | ︙ | |||
3858 3859 3860 3861 3862 3863 3864 | return rc; } /* ** Free any overflow pages associated with the given Cell. */ static int clearCell(MemPage *pPage, unsigned char *pCell){ | | | < > | 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 | return rc; } /* ** Free any overflow pages associated with the given Cell. */ static int clearCell(MemPage *pPage, unsigned char *pCell){ Btree *pBt = pPage->pBt; CellInfo info; Pgno ovflPgno; int rc; parseCellPtr(pPage, pCell, &info); if( info.iOverflow==0 ){ return SQLITE_OK; /* No overflow pages. Return without doing anything */ } ovflPgno = get4byte(&pCell[info.iOverflow]); while( ovflPgno!=0 ){ MemPage *pOvfl; if( ovflPgno>sqlite3pager_pagecount(pBt->pPager) ){ return SQLITE_CORRUPT; } rc = getPage(pBt, ovflPgno, &pOvfl); if( rc ) return rc; ovflPgno = get4byte(pOvfl->aData); rc = freePage(pOvfl); if( rc ) return rc; sqlite3pager_unref(pOvfl->aData); } return SQLITE_OK; } /* ** Create the byte sequence used to represent a cell on page pPage ** and write that byte sequence into pCell[]. Overflow pages are |
︙ | ︙ | |||
3910 3911 3912 3913 3914 3915 3916 | const u8 *pSrc; int nSrc, n, rc; int spaceLeft; MemPage *pOvfl = 0; MemPage *pToRelease = 0; unsigned char *pPrior; unsigned char *pPayload; | | | 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 | const u8 *pSrc; int nSrc, n, rc; int spaceLeft; MemPage *pOvfl = 0; MemPage *pToRelease = 0; unsigned char *pPrior; unsigned char *pPayload; Btree *pBt = pPage->pBt; Pgno pgnoOvfl = 0; int nHeader; CellInfo info; /* Fill in the header. */ nHeader = 0; if( !pPage->leaf ){ |
︙ | ︙ | |||
3999 4000 4001 4002 4003 4004 4005 | } /* ** Change the MemPage.pParent pointer on the page whose number is ** given in the second argument so that MemPage.pParent holds the ** pointer in the third argument. */ | | | | 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 | } /* ** Change the MemPage.pParent pointer on the page whose number is ** given in the second argument so that MemPage.pParent holds the ** pointer in the third argument. */ static int reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){ MemPage *pThis; unsigned char *aData; if( pgno==0 ) return SQLITE_OK; assert( pBt->pPager!=0 ); aData = sqlite3pager_lookup(pBt->pPager, pgno); if( aData ){ pThis = (MemPage*)&aData[pBt->psAligned]; assert( pThis->aData==aData ); if( pThis->isInit ){ if( pThis->pParent!=pNewParent ){ if( pThis->pParent ) sqlite3pager_unref(pThis->pParent->aData); pThis->pParent = pNewParent; if( pNewParent ) sqlite3pager_ref(pNewParent->aData); } |
︙ | ︙ | |||
4042 4043 4044 4045 4046 4047 4048 | ** to make sure that each child knows that pPage is its parent. ** ** This routine gets called after you memcpy() one page into ** another. */ static int reparentChildPages(MemPage *pPage){ int i; | | | 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 | ** to make sure that each child knows that pPage is its parent. ** ** This routine gets called after you memcpy() one page into ** another. */ static int reparentChildPages(MemPage *pPage){ int i; Btree *pBt = pPage->pBt; int rc = SQLITE_OK; if( pPage->leaf ) return SQLITE_OK; for(i=0; i<pPage->nCell; i++){ u8 *pCell = findCell(pPage, i); if( !pPage->leaf ){ |
︙ | ︙ | |||
4150 4151 4152 4153 4154 4155 4156 | data = pPage->aData; hdr = pPage->hdrOffset; top = get2byte(&data[hdr+5]); cellOffset = pPage->cellOffset; end = cellOffset + 2*pPage->nCell + 2; ins = cellOffset + 2*i; if( end > top - sz ){ | | < | 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 | data = pPage->aData; hdr = pPage->hdrOffset; top = get2byte(&data[hdr+5]); cellOffset = pPage->cellOffset; end = cellOffset + 2*pPage->nCell + 2; ins = cellOffset + 2*i; if( end > top - sz ){ defragmentPage(pPage); top = get2byte(&data[hdr+5]); assert( end + sz <= top ); } idx = allocateSpace(pPage, sz); assert( idx>0 ); assert( end <= get2byte(&data[hdr+5]) ); pPage->nCell++; |
︙ | ︙ | |||
4216 4217 4218 4219 4220 4221 4222 | } assert( totalSize+2*nCell<=pPage->nFree ); assert( pPage->nCell==0 ); cellptr = pPage->cellOffset; data = pPage->aData; hdr = pPage->hdrOffset; put2byte(&data[hdr+3], nCell); | < | | | | | | | | | | | < | 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 | } assert( totalSize+2*nCell<=pPage->nFree ); assert( pPage->nCell==0 ); cellptr = pPage->cellOffset; data = pPage->aData; hdr = pPage->hdrOffset; put2byte(&data[hdr+3], nCell); cellbody = allocateSpace(pPage, totalSize); assert( cellbody>0 ); assert( pPage->nFree >= 2*nCell ); pPage->nFree -= 2*nCell; for(i=0; i<nCell; i++){ put2byte(&data[cellptr], cellbody); memcpy(&data[cellbody], apCell[i], aSize[i]); cellptr += 2; cellbody += aSize[i]; } assert( cellbody==pPage->pBt->usableSize ); pPage->nCell = nCell; } /* ** The following parameters determine how many adjacent pages get involved ** in a balancing operation. NN is the number of neighbors on either side ** of the page that participate in the balancing operation. NB is the |
︙ | ︙ | |||
4275 4276 4277 4278 4279 4280 4281 | static int balance_quick(MemPage *pPage, MemPage *pParent){ int rc; MemPage *pNew; Pgno pgnoNew; u8 *pCell; int szCell; CellInfo info; | | | 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 | static int balance_quick(MemPage *pPage, MemPage *pParent){ int rc; MemPage *pNew; Pgno pgnoNew; u8 *pCell; int szCell; CellInfo info; Btree *pBt = pPage->pBt; int parentIdx = pParent->nCell; /* pParent new divider cell index */ int parentSize; /* Size of new divider cell */ u8 parentCell[64]; /* Space for the new divider cell */ /* Allocate a new page. Insert the overflow cell from pPage ** into it. Then remove the overflow cell from pPage. */ |
︙ | ︙ | |||
4384 4385 4386 4387 4388 4389 4390 | ** ** If this routine fails for any reason, it might leave the database ** in a corrupted state. So if this routine fails, the database should ** be rolled back. */ static int balance_nonroot(MemPage *pPage){ MemPage *pParent; /* The parent of pPage */ | | | < > > | | 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 | ** ** If this routine fails for any reason, it might leave the database ** in a corrupted state. So if this routine fails, the database should ** be rolled back. */ static int balance_nonroot(MemPage *pPage){ MemPage *pParent; /* The parent of pPage */ Btree *pBt; /* The whole database */ int nCell = 0; /* Number of cells in aCell[] */ int nOld; /* Number of pages in apOld[] */ int nNew; /* Number of pages in apNew[] */ int nDiv; /* Number of cells in apDiv[] */ int i, j, k; /* Loop counters */ int idx; /* Index of pPage in pParent->aCell[] */ int nxDiv; /* Next divider slot in pParent->aCell[] */ int rc; /* The return code */ int leafCorrection; /* 4 if pPage is a leaf. 0 if not */ int leafData; /* True if pPage is a leaf of a LEAFDATA tree */ int usableSpace; /* Bytes in pPage beyond the header */ int pageFlags; /* Value of pPage->aData[0] */ int subtotal; /* Subtotal of bytes in cells on one page */ int iSpace = 0; /* First unused byte of aSpace[] */ int mxCellPerPage; /* Maximum number of cells in one page */ MemPage *apOld[NB]; /* pPage and up to two siblings */ Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */ MemPage *apCopy[NB]; /* Private copies of apOld[] pages */ MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */ Pgno pgnoNew[NB+2]; /* Page numbers for each page in apNew[] */ int idxDiv[NB]; /* Indices of divider cells in pParent */ u8 *apDiv[NB]; /* Divider cells in pParent */ int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */ int szNew[NB+2]; /* Combined size of cells place on i-th page */ u8 **apCell; /* All cells begin balanced */ int *szCell; /* Local size of all cells in apCell[] */ u8 *aCopy[NB]; /* Space for holding data of apCopy[] */ u8 *aSpace; /* Space to hold copies of dividers cells */ #ifndef SQLITE_OMIT_AUTOVACUUM u8 *aFrom = 0; #endif |
︙ | ︙ | |||
4431 4432 4433 4434 4435 4436 4437 | assert( pParent ); TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); #ifndef SQLITE_OMIT_QUICKBALANCE /* ** A special case: If a new entry has just been inserted into a ** table (that is, a btree with integer keys and all data at the leaves) | | > > > > > > > > > > > > > > > > > > > > > > > > > | 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 | assert( pParent ); TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); #ifndef SQLITE_OMIT_QUICKBALANCE /* ** A special case: If a new entry has just been inserted into a ** table (that is, a btree with integer keys and all data at the leaves) ** an the new entry is the right-most entry in the tree (it has the ** largest key) then use the special balance_quick() routine for ** balancing. balance_quick() is much faster and results in a tighter ** packing of data in the common case. */ if( pPage->leaf && pPage->intKey && pPage->leafData && pPage->nOverflow==1 && pPage->aOvfl[0].idx==pPage->nCell && pPage->pParent->pgno!=1 && get4byte(&pParent->aData[pParent->hdrOffset+8])==pPage->pgno ){ /* ** TODO: Check the siblings to the left of pPage. It may be that ** they are not full and no new page is required. */ return balance_quick(pPage, pParent); } #endif /* ** Allocate space for memory structures */ mxCellPerPage = MX_CELL(pBt); apCell = sqliteMallocRaw( (mxCellPerPage+2)*NB*(sizeof(u8*)+sizeof(int)) + sizeof(MemPage)*NB + pBt->psAligned*(5+NB) + (ISAUTOVACUUM ? (mxCellPerPage+2)*NN*2 : 0) ); if( apCell==0 ){ return SQLITE_NOMEM; } szCell = (int*)&apCell[(mxCellPerPage+2)*NB]; aCopy[0] = (u8*)&szCell[(mxCellPerPage+2)*NB]; for(i=1; i<NB; i++){ aCopy[i] = &aCopy[i-1][pBt->psAligned+sizeof(MemPage)]; } aSpace = &aCopy[NB-1][pBt->psAligned+sizeof(MemPage)]; #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ aFrom = &aSpace[5*pBt->psAligned]; } #endif /* ** Find the cell in the parent page whose left child points back ** to pPage. The "idx" variable is the index of that cell. If pPage ** is the rightmost child of pParent then set idx to pParent->nCell */ if( pParent->idxShift ){ Pgno pgno; |
︙ | ︙ | |||
4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 | } if( nxDiv<0 ){ nxDiv = 0; } nDiv = 0; for(i=0, k=nxDiv; i<NB; i++, k++){ if( k<pParent->nCell ){ apDiv[i] = findCell(pParent, k); nDiv++; assert( !pParent->leaf ); pgnoOld[i] = get4byte(apDiv[i]); }else if( k==pParent->nCell ){ pgnoOld[i] = get4byte(&pParent->aData[pParent->hdrOffset+8]); }else{ break; } rc = getAndInitPage(pBt, pgnoOld[i], &apOld[i], pParent); if( rc ) goto balance_cleanup; apOld[i]->idxParent = k; apCopy[i] = 0; assert( i==nOld ); nOld++; | > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | < < | | 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 | } if( nxDiv<0 ){ nxDiv = 0; } nDiv = 0; for(i=0, k=nxDiv; i<NB; i++, k++){ if( k<pParent->nCell ){ idxDiv[i] = k; apDiv[i] = findCell(pParent, k); nDiv++; assert( !pParent->leaf ); pgnoOld[i] = get4byte(apDiv[i]); }else if( k==pParent->nCell ){ pgnoOld[i] = get4byte(&pParent->aData[pParent->hdrOffset+8]); }else{ break; } rc = getAndInitPage(pBt, pgnoOld[i], &apOld[i], pParent); if( rc ) goto balance_cleanup; apOld[i]->idxParent = k; apCopy[i] = 0; assert( i==nOld ); nOld++; } /* ** Make copies of the content of pPage and its siblings into aOld[]. ** The rest of this function will use data from the copies rather ** that the original pages since the original pages will be in the ** process of being overwritten. */ for(i=0; i<nOld; i++){ MemPage *p = apCopy[i] = (MemPage*)&aCopy[i][pBt->psAligned]; p->aData = &((u8*)p)[-pBt->psAligned]; memcpy(p->aData, apOld[i]->aData, pBt->psAligned + sizeof(MemPage)); p->aData = &((u8*)p)[-pBt->psAligned]; } /* ** Load pointers to all cells on sibling pages and the divider cells ** into the local apCell[] array. Make copies of the divider cells ** into space obtained form aSpace[] and remove the the divider Cells ** from pParent. |
︙ | ︙ | |||
4585 4586 4587 4588 4589 4590 4591 | nCell = 0; leafCorrection = pPage->leaf*4; leafData = pPage->leafData && pPage->leaf; for(i=0; i<nOld; i++){ MemPage *pOld = apCopy[i]; int limit = pOld->nCell+pOld->nOverflow; for(j=0; j<limit; j++){ | < | 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 | nCell = 0; leafCorrection = pPage->leaf*4; leafData = pPage->leafData && pPage->leaf; for(i=0; i<nOld; i++){ MemPage *pOld = apCopy[i]; int limit = pOld->nCell+pOld->nOverflow; for(j=0; j<limit; j++){ apCell[nCell] = findOverflowCell(pOld, j); szCell[nCell] = cellSizePtr(pOld, apCell[nCell]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ int a; aFrom[nCell] = i; for(a=0; a<pOld->nOverflow; a++){ |
︙ | ︙ | |||
4613 4614 4615 4616 4617 4618 4619 | ** are duplicates of keys on the child pages. We need to remove ** the divider cells from pParent, but the dividers cells are not ** added to apCell[] because they are duplicates of child cells. */ dropCell(pParent, nxDiv, sz); }else{ u8 *pTemp; | < | | 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 | ** are duplicates of keys on the child pages. We need to remove ** the divider cells from pParent, but the dividers cells are not ** added to apCell[] because they are duplicates of child cells. */ dropCell(pParent, nxDiv, sz); }else{ u8 *pTemp; szCell[nCell] = sz; pTemp = &aSpace[iSpace]; iSpace += sz; assert( iSpace<=pBt->psAligned*5 ); memcpy(pTemp, apDiv[i], sz); apCell[nCell] = pTemp+leafCorrection; #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ aFrom[nCell] = 0xFF; } #endif |
︙ | ︙ | |||
4659 4660 4661 4662 4663 4664 4665 | ** cntNew[i]: Index in apCell[] and szCell[] for the first cell to ** the right of the i-th sibling page. ** usableSpace: Number of bytes of space available on each sibling. ** */ usableSpace = pBt->usableSize - 12 + leafCorrection; for(subtotal=k=i=0; i<nCell; i++){ | < | 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 | ** cntNew[i]: Index in apCell[] and szCell[] for the first cell to ** the right of the i-th sibling page. ** usableSpace: Number of bytes of space available on each sibling. ** */ usableSpace = pBt->usableSize - 12 + leafCorrection; for(subtotal=k=i=0; i<nCell; i++){ subtotal += szCell[i] + 2; if( subtotal > usableSpace ){ szNew[k] = subtotal - szCell[i]; cntNew[k] = i; if( leafData ){ i--; } subtotal = 0; k++; |
︙ | ︙ | |||
4691 4692 4693 4694 4695 4696 4697 | int szRight = szNew[i]; /* Size of sibling on the right */ int szLeft = szNew[i-1]; /* Size of sibling on the left */ int r; /* Index of right-most cell in left sibling */ int d; /* Index of first cell to the left of right sibling */ r = cntNew[i-1] - 1; d = r + 1 - leafData; | < < < < < < < | | 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 | int szRight = szNew[i]; /* Size of sibling on the right */ int szLeft = szNew[i-1]; /* Size of sibling on the left */ int r; /* Index of right-most cell in left sibling */ int d; /* Index of first cell to the left of right sibling */ r = cntNew[i-1] - 1; d = r + 1 - leafData; while( szRight==0 || szRight+szCell[d]+2<=szLeft-(szCell[r]+2) ){ szRight += szCell[d] + 2; szLeft -= szCell[r] + 2; cntNew[i-1]--; r = cntNew[i-1] - 1; d = r + 1 - leafData; } szNew[i] = szRight; szNew[i-1] = szLeft; } assert( cntNew[0]>0 ); /* ** Allocate k new pages. Reuse old pages where possible. */ assert( pPage->pgno>1 ); pageFlags = pPage->aData[0]; for(i=0; i<k; i++){ |
︙ | ︙ | |||
4794 4795 4796 4797 4798 4799 4800 | ** Evenly distribute the data in apCell[] across the new pages. ** Insert divider cells into pParent as necessary. */ j = 0; for(i=0; i<nNew; i++){ /* Assemble the new sibling page. */ MemPage *pNew = apNew[i]; | < | < < < | | | 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 | ** Evenly distribute the data in apCell[] across the new pages. ** Insert divider cells into pParent as necessary. */ j = 0; for(i=0; i<nNew; i++){ /* Assemble the new sibling page. */ MemPage *pNew = apNew[i]; assert( pNew->pgno==pgnoNew[i] ); assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]); assert( pNew->nCell>0 ); assert( pNew->nOverflow==0 ); #ifndef SQLITE_OMIT_AUTOVACUUM /* If this is an auto-vacuum database, update the pointer map entries ** that point to the siblings that were rearranged. These can be: left ** children of cells, the right-child of the page, or overflow pages ** pointed to by cells. */ if( pBt->autoVacuum ){ for(k=j; k<cntNew[i]; k++){ if( aFrom[k]==0xFF || apCopy[aFrom[k]]->pgno!=pNew->pgno ){ rc = ptrmapPutOvfl(pNew, k-j); if( rc!=SQLITE_OK ){ goto balance_cleanup; } } } } #endif j = cntNew[i]; /* If the sibling page assembled above was not the right-most sibling, ** insert a divider cell into the parent page. */ if( i<nNew-1 && j<nCell ){ u8 *pCell; u8 *pTemp; int sz; pCell = apCell[j]; sz = szCell[j] + leafCorrection; if( !pNew->leaf ){ memcpy(&pNew->aData[8], pCell, 4); pTemp = 0; }else if( leafData ){ /* If the tree is a leaf-data tree, and the siblings are leaves, ** then there is no divider cell in apCell[]. Instead, the divider ** cell consists of the integer key for the right-most cell of ** the sibling-page assembled above only. */ CellInfo info; j--; parseCellPtr(pNew, apCell[j], &info); pCell = &aSpace[iSpace]; fillInCell(pParent, pCell, 0, info.nKey, 0, 0, &sz); iSpace += sz; assert( iSpace<=pBt->psAligned*5 ); pTemp = 0; }else{ pCell -= 4; pTemp = &aSpace[iSpace]; iSpace += sz; assert( iSpace<=pBt->psAligned*5 ); } rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, 4); if( rc!=SQLITE_OK ) goto balance_cleanup; put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno); #ifndef SQLITE_OMIT_AUTOVACUUM /* If this is an auto-vacuum database, and not a leaf-data tree, ** then update the pointer map with an entry for the overflow page |
︙ | ︙ | |||
4933 4934 4935 4936 4937 4938 4939 | ** page contains no cells. This is an opportunity to make the tree ** shallower by one level. */ static int balance_shallower(MemPage *pPage){ MemPage *pChild; /* The only child page of pPage */ Pgno pgnoChild; /* Page number for pChild */ int rc = SQLITE_OK; /* Return code from subprocedures */ | | | 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 | ** page contains no cells. This is an opportunity to make the tree ** shallower by one level. */ static int balance_shallower(MemPage *pPage){ MemPage *pChild; /* The only child page of pPage */ Pgno pgnoChild; /* Page number for pChild */ int rc = SQLITE_OK; /* Return code from subprocedures */ Btree *pBt; /* The main BTree structure */ int mxCellPerPage; /* Maximum number of cells per page */ u8 **apCell; /* All cells from pages being balanced */ int *szCell; /* Local size of all cells */ assert( pPage->pParent==0 ); assert( pPage->nCell==0 ); pBt = pPage->pBt; |
︙ | ︙ | |||
5035 5036 5037 5038 5039 5040 5041 | ** child. Finally, call balance_internal() on the new child ** to cause it to split. */ static int balance_deeper(MemPage *pPage){ int rc; /* Return value from subprocedures */ MemPage *pChild; /* Pointer to a new child page */ Pgno pgnoChild; /* Page number of the new child page */ | | | 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 | ** child. Finally, call balance_internal() on the new child ** to cause it to split. */ static int balance_deeper(MemPage *pPage){ int rc; /* Return value from subprocedures */ MemPage *pChild; /* Pointer to a new child page */ Pgno pgnoChild; /* Page number of the new child page */ Btree *pBt; /* The BTree */ int usableSize; /* Total usable size of a page */ u8 *data; /* Content of the parent page */ u8 *cdata; /* Content of the child page */ int hdr; /* Offset to page header in parent */ int brk; /* Offset to content of first cell in parent */ assert( pPage->pParent==0 ); |
︙ | ︙ | |||
5057 5058 5059 5060 5061 5062 5063 | hdr = pPage->hdrOffset; brk = get2byte(&data[hdr+5]); cdata = pChild->aData; memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr); memcpy(&cdata[brk], &data[brk], usableSize-brk); assert( pChild->isInit==0 ); rc = initPage(pChild, pPage); | | | < < | 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 | hdr = pPage->hdrOffset; brk = get2byte(&data[hdr+5]); cdata = pChild->aData; memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr); memcpy(&cdata[brk], &data[brk], usableSize-brk); assert( pChild->isInit==0 ); rc = initPage(pChild, pPage); if( rc ) return rc; memcpy(pChild->aOvfl, pPage->aOvfl, pPage->nOverflow*sizeof(pPage->aOvfl[0])); pChild->nOverflow = pPage->nOverflow; if( pChild->nOverflow ){ pChild->nFree = 0; } assert( pChild->nCell==pPage->nCell ); zeroPage(pPage, pChild->aData[0] & ~PTF_LEAF); put4byte(&pPage->aData[pPage->hdrOffset+8], pgnoChild); TRACE(("BALANCE: copy root %d into %d\n", pPage->pgno, pChild->pgno)); #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ int i; rc = ptrmapPut(pBt, pChild->pgno, PTRMAP_BTREE, pPage->pgno); if( rc ) return rc; for(i=0; i<pChild->nCell; i++){ rc = ptrmapPutOvfl(pChild, i); if( rc!=SQLITE_OK ){ return rc; } } } #endif rc = balance_nonroot(pChild); releasePage(pChild); return rc; } /* ** Decide if the page pPage needs to be balanced. If balancing is ** required, call the appropriate balancing routine. |
︙ | ︙ | |||
5124 5125 5126 5127 5128 5129 5130 | ** means a cursor opened with wrFlag==0) this routine also moves ** all cursors other than pExclude so that they are pointing to the ** first Cell on root page. This is necessary because an insert ** or delete might change the number of cells on a page or delete ** a page entirely and we do not want to leave any cursors ** pointing to non-existant pages or cells. */ | | < < | 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 | ** means a cursor opened with wrFlag==0) this routine also moves ** all cursors other than pExclude so that they are pointing to the ** first Cell on root page. This is necessary because an insert ** or delete might change the number of cells on a page or delete ** a page entirely and we do not want to leave any cursors ** pointing to non-existant pages or cells. */ static int checkReadLocks(Btree *pBt, Pgno pgnoRoot, BtCursor *pExclude){ BtCursor *p; for(p=pBt->pCursor; p; p=p->pNext){ if( p->pgnoRoot!=pgnoRoot || p==pExclude ) continue; if( p->wrFlag==0 ) return SQLITE_LOCKED; if( p->pPage->pgno!=p->pgnoRoot ){ moveToRoot(p); } } return SQLITE_OK; } |
︙ | ︙ | |||
5156 5157 5158 5159 5160 5161 5162 | const void *pKey, i64 nKey, /* The key of the new record */ const void *pData, int nData /* The data of the new record */ ){ int rc; int loc; int szNew; MemPage *pPage; | | | < < < < < | < | < < | | 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 | const void *pKey, i64 nKey, /* The key of the new record */ const void *pData, int nData /* The data of the new record */ ){ int rc; int loc; int szNew; MemPage *pPage; Btree *pBt = pCur->pBt; unsigned char *oldCell; unsigned char *newCell = 0; if( pBt->inTrans!=TRANS_WRITE ){ /* Must start a transaction before doing an insert */ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } assert( !pBt->readOnly ); if( !pCur->wrFlag ){ return SQLITE_PERM; /* Cursor not open for writing */ } if( checkReadLocks(pBt, pCur->pgnoRoot, pCur) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } rc = sqlite3BtreeMoveto(pCur, pKey, nKey, &loc); if( rc ) return rc; pPage = pCur->pPage; assert( pPage->intKey || nKey>=0 ); assert( pPage->leaf || !pPage->leafData ); TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", pCur->pgnoRoot, nKey, nData, pPage->pgno, loc==0 ? "overwrite" : "new entry")); assert( pPage->isInit ); rc = sqlite3pager_write(pPage->aData); if( rc ) return rc; newCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) ); if( newCell==0 ) return SQLITE_NOMEM; rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, &szNew); if( rc ) goto end_insert; assert( szNew==cellSizePtr(pPage, newCell) ); assert( szNew<=MX_CELL_SIZE(pBt) ); if( loc==0 && pCur->isValid ){ int szOld; assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); oldCell = findCell(pPage, pCur->idx); if( !pPage->leaf ){ memcpy(newCell, oldCell, 4); } szOld = cellSizePtr(pPage, oldCell); |
︙ | ︙ | |||
5236 5237 5238 5239 5240 5241 5242 | ** is left pointing at a random location. */ int sqlite3BtreeDelete(BtCursor *pCur){ MemPage *pPage = pCur->pPage; unsigned char *pCell; int rc; Pgno pgnoChild = 0; | | | < < < < < < < < < | < | < | 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 | ** is left pointing at a random location. */ int sqlite3BtreeDelete(BtCursor *pCur){ MemPage *pPage = pCur->pPage; unsigned char *pCell; int rc; Pgno pgnoChild = 0; Btree *pBt = pCur->pBt; assert( pPage->isInit ); if( pBt->inTrans!=TRANS_WRITE ){ /* Must start a transaction before doing a delete */ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } assert( !pBt->readOnly ); if( pCur->idx >= pPage->nCell ){ return SQLITE_ERROR; /* The cursor is not pointing to anything */ } if( !pCur->wrFlag ){ return SQLITE_PERM; /* Did not open this cursor for writing */ } if( checkReadLocks(pBt, pCur->pgnoRoot, pCur) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } rc = sqlite3pager_write(pPage->aData); if( rc ) return rc; /* Locate the cell within it's page and leave pCell pointing to the ** data. The clearCell() call frees any overflow pages associated with the ** cell. The cell itself is still intact. */ pCell = findCell(pPage, pCur->idx); if( !pPage->leaf ){ |
︙ | ︙ | |||
5290 5291 5292 5293 5294 5295 5296 | ** next Cell after the one to be deleted is guaranteed to exist and ** to be a leaf so we can use it. */ BtCursor leafCur; unsigned char *pNext; int szNext; int notUsed; | | | > < | < | | | | | | | | | < < < < | < | | | < > | | | < < < | < | < | | 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 | ** next Cell after the one to be deleted is guaranteed to exist and ** to be a leaf so we can use it. */ BtCursor leafCur; unsigned char *pNext; int szNext; int notUsed; unsigned char *tempCell; assert( !pPage->leafData ); getTempCursor(pCur, &leafCur); rc = sqlite3BtreeNext(&leafCur, ¬Used); if( rc!=SQLITE_OK ){ if( rc!=SQLITE_NOMEM ){ rc = SQLITE_CORRUPT; /* bkpt-CORRUPT */ } return rc; } rc = sqlite3pager_write(leafCur.pPage->aData); if( rc ) return rc; TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n", pCur->pgnoRoot, pPage->pgno, leafCur.pPage->pgno)); dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); pNext = findCell(leafCur.pPage, leafCur.idx); szNext = cellSizePtr(leafCur.pPage, pNext); assert( MX_CELL_SIZE(pBt)>=szNext+4 ); tempCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) ); if( tempCell==0 ) return SQLITE_NOMEM; rc = insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell, 0); if( rc!=SQLITE_OK ) return rc; put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild); rc = balance(pPage, 0); sqliteFree(tempCell); if( rc ) return rc; dropCell(leafCur.pPage, leafCur.idx, szNext); rc = balance(leafCur.pPage, 0); releaseTempCursor(&leafCur); }else{ TRACE(("DELETE: table=%d delete from leaf %d\n", pCur->pgnoRoot, pPage->pgno)); dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); rc = balance(pPage, 0); } moveToRoot(pCur); return rc; } /* ** Create a new BTree table. Write into *piTable the page ** number for the root page of the new table. ** ** The type of type is determined by the flags parameter. Only the ** following values of flags are currently in use. Other values for ** flags might not work: ** ** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys ** BTREE_ZERODATA Used for SQL indices */ int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){ MemPage *pRoot; Pgno pgnoRoot; int rc; if( pBt->inTrans!=TRANS_WRITE ){ /* Must start a transaction first */ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } assert( !pBt->readOnly ); /* It is illegal to create a table if any cursors are open on the ** database. This is because in auto-vacuum mode the backend may |
︙ | ︙ | |||
5382 5383 5384 5385 5386 5387 5388 | Pgno pgnoMove; /* Move a page here to make room for the root-page */ MemPage *pPageMove; /* The page to move to. */ /* Read the value of meta[3] from the database to determine where the ** root page of the new table should go. meta[3] is the largest root-page ** created so far, so the new root-page is (meta[3]+1). */ | | | 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 | Pgno pgnoMove; /* Move a page here to make room for the root-page */ MemPage *pPageMove; /* The page to move to. */ /* Read the value of meta[3] from the database to determine where the ** root page of the new table should go. meta[3] is the largest root-page ** created so far, so the new root-page is (meta[3]+1). */ rc = sqlite3BtreeGetMeta(pBt, 4, &pgnoRoot); if( rc!=SQLITE_OK ) return rc; pgnoRoot++; /* The new root-page may not be allocated on a pointer-map page, or the ** PENDING_BYTE page. */ if( pgnoRoot==PTRMAP_PAGENO(pBt->usableSize, pgnoRoot) || |
︙ | ︙ | |||
5414 5415 5416 5417 5418 5419 5420 | releasePage(pPageMove); rc = getPage(pBt, pgnoRoot, &pRoot); if( rc!=SQLITE_OK ){ return rc; } rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage); | < < < < < | 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 | releasePage(pPageMove); rc = getPage(pBt, pgnoRoot, &pRoot); if( rc!=SQLITE_OK ){ return rc; } rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage); assert( eType!=PTRMAP_ROOTPAGE ); assert( eType!=PTRMAP_FREEPAGE ); if( rc!=SQLITE_OK ){ releasePage(pRoot); return rc; } rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove); releasePage(pRoot); if( rc!=SQLITE_OK ){ |
︙ | ︙ | |||
5449 5450 5451 5452 5453 5454 5455 | /* Update the pointer-map and meta-data with the new root-page number. */ rc = ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0); if( rc ){ releasePage(pRoot); return rc; } | | | 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 | /* Update the pointer-map and meta-data with the new root-page number. */ rc = ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0); if( rc ){ releasePage(pRoot); return rc; } rc = sqlite3BtreeUpdateMeta(pBt, 4, pgnoRoot); if( rc ){ releasePage(pRoot); return rc; } }else{ rc = allocatePage(pBt, &pRoot, &pgnoRoot, 1, 0); |
︙ | ︙ | |||
5472 5473 5474 5475 5476 5477 5478 | } /* ** Erase the given database page and all its children. Return ** the page to the freelist. */ static int clearDatabasePage( | | | | | | | | | < < | < | < < | 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 | } /* ** Erase the given database page and all its children. Return ** the page to the freelist. */ static int clearDatabasePage( Btree *pBt, /* The BTree that contains the table */ Pgno pgno, /* Page number to clear */ MemPage *pParent, /* Parent page. NULL for the root */ int freePageFlag /* Deallocate page if true */ ){ MemPage *pPage; int rc; unsigned char *pCell; int i; if( pgno>sqlite3pager_pagecount(pBt->pPager) ){ return SQLITE_CORRUPT; } rc = getAndInitPage(pBt, pgno, &pPage, pParent); if( rc ) return rc; rc = sqlite3pager_write(pPage->aData); if( rc ) return rc; for(i=0; i<pPage->nCell; i++){ pCell = findCell(pPage, i); if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(pCell), pPage->pParent, 1); if( rc ) return rc; } rc = clearCell(pPage, pCell); if( rc ) return rc; } if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), pPage->pParent, 1); if( rc ) return rc; } if( freePageFlag ){ rc = freePage(pPage); }else{ zeroPage(pPage, pPage->aData[0] | PTF_LEAF); } releasePage(pPage); return rc; } /* ** Delete all information from a single table in the database. iTable is ** the page number of the root of the table. After this routine returns, ** the root page is empty, but still exists. ** ** This routine will fail with SQLITE_LOCKED if there are any open ** read cursors on the table. Open write cursors are moved to the ** root of the table. */ int sqlite3BtreeClearTable(Btree *pBt, int iTable){ int rc; BtCursor *pCur; if( pBt->inTrans!=TRANS_WRITE ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ if( pCur->pgnoRoot==(Pgno)iTable ){ if( pCur->wrFlag==0 ) return SQLITE_LOCKED; moveToRoot(pCur); } } rc = clearDatabasePage(pBt, (Pgno)iTable, 0, 0); if( rc ){ sqlite3BtreeRollback(pBt); } return rc; } /* ** Erase all information in a table and add the root of the table to ** the freelist. Except, the root of the principle table (the one on ** page 1) is never added to the freelist. |
︙ | ︙ | |||
5565 5566 5567 5568 5569 5570 5571 | ** root pages are kept at the beginning of the database file, which ** is necessary for AUTOVACUUM to work right. *piMoved is set to the ** page number that used to be the last root page in the file before ** the move. If no page gets moved, *piMoved is set to 0. ** The last root page is recorded in meta[3] and the value of ** meta[3] is updated by this procedure. */ | | < | | | < < < | | 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 | ** root pages are kept at the beginning of the database file, which ** is necessary for AUTOVACUUM to work right. *piMoved is set to the ** page number that used to be the last root page in the file before ** the move. If no page gets moved, *piMoved is set to 0. ** The last root page is recorded in meta[3] and the value of ** meta[3] is updated by this procedure. */ int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){ int rc; MemPage *pPage = 0; if( pBt->inTrans!=TRANS_WRITE ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } /* It is illegal to drop a table if any cursors are open on the ** database. This is because in auto-vacuum mode the backend may ** need to move another root-page to fill a gap left by the deleted ** root page. If an open cursor was using this page a problem would ** occur. */ if( pBt->pCursor ){ return SQLITE_LOCKED; } rc = getPage(pBt, (Pgno)iTable, &pPage); if( rc ) return rc; rc = sqlite3BtreeClearTable(pBt, iTable); if( rc ) return rc; *piMoved = 0; if( iTable>1 ){ #ifdef SQLITE_OMIT_AUTOVACUUM rc = freePage(pPage); releasePage(pPage); #else if( pBt->autoVacuum ){ Pgno maxRootPgno; rc = sqlite3BtreeGetMeta(pBt, 4, &maxRootPgno); if( rc!=SQLITE_OK ){ releasePage(pPage); return rc; } if( iTable==maxRootPgno ){ /* If the table being dropped is the table with the largest root-page |
︙ | ︙ | |||
5658 5659 5660 5661 5662 5663 5664 | maxRootPgno--; } if( maxRootPgno==PTRMAP_PAGENO(pBt->usableSize, maxRootPgno) ){ maxRootPgno--; } assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) ); | | | 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 | maxRootPgno--; } if( maxRootPgno==PTRMAP_PAGENO(pBt->usableSize, maxRootPgno) ){ maxRootPgno--; } assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) ); rc = sqlite3BtreeUpdateMeta(pBt, 4, maxRootPgno); }else{ rc = freePage(pPage); releasePage(pPage); } #endif }else{ /* If sqlite3BtreeDropTable was called on page 1. */ |
︙ | ︙ | |||
5683 5684 5685 5686 5687 5688 5689 | ** through meta[15] are available for use by higher layers. Meta[0] ** is read-only, the others are read/write. ** ** The schema layer numbers meta values differently. At the schema ** layer (and the SetCookie and ReadCookie opcodes) the number of ** free pages is not visible. So Cookie[0] is the same as Meta[1]. */ | | < < < < < < < < < < < < < | | < | < < < | | 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 | ** through meta[15] are available for use by higher layers. Meta[0] ** is read-only, the others are read/write. ** ** The schema layer numbers meta values differently. At the schema ** layer (and the SetCookie and ReadCookie opcodes) the number of ** free pages is not visible. So Cookie[0] is the same as Meta[1]. */ int sqlite3BtreeGetMeta(Btree *pBt, int idx, u32 *pMeta){ int rc; unsigned char *pP1; assert( idx>=0 && idx<=15 ); rc = sqlite3pager_get(pBt->pPager, 1, (void**)&pP1); if( rc ) return rc; *pMeta = get4byte(&pP1[36 + idx*4]); sqlite3pager_unref(pP1); /* If autovacuumed is disabled in this build but we are trying to ** access an autovacuumed database, then make the database readonly. */ #ifdef SQLITE_OMIT_AUTOVACUUM if( idx==4 && *pMeta>0 ) pBt->readOnly = 1; #endif return SQLITE_OK; } /* ** Write meta-information back into the database. Meta[0] is ** read-only and may not be written. */ int sqlite3BtreeUpdateMeta(Btree *pBt, int idx, u32 iMeta){ unsigned char *pP1; int rc; assert( idx>=1 && idx<=15 ); if( pBt->inTrans!=TRANS_WRITE ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } assert( pBt->pPage1!=0 ); pP1 = pBt->pPage1->aData; rc = sqlite3pager_write(pP1); if( rc ) return rc; put4byte(&pP1[36 + idx*4], iMeta); return SQLITE_OK; } /* ** Return the flag byte at the beginning of the page that the cursor ** is currently pointing to. */ int sqlite3BtreeFlags(BtCursor *pCur){ MemPage *pPage = pCur->pPage; return pPage ? pPage->aData[pPage->hdrOffset] : 0; } #ifdef SQLITE_DEBUG /* ** Print a disassembly of the given page on standard output. This routine ** is used for debugging and testing only. */ static int btreePageDump(Btree *pBt, int pgno, int recursive, MemPage *pParent){ int rc; MemPage *pPage; int i, j, c; int nFree; u16 idx; int hdr; int nCell; |
︙ | ︙ | |||
5849 5850 5851 5852 5853 5854 5855 | btreePageDump(pBt, get4byte(&data[hdr+8]), 1, pPage); } pPage->isInit = isInit; sqlite3pager_unref(data); fflush(stdout); return SQLITE_OK; } | | | | 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 | btreePageDump(pBt, get4byte(&data[hdr+8]), 1, pPage); } pPage->isInit = isInit; sqlite3pager_unref(data); fflush(stdout); return SQLITE_OK; } int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){ return btreePageDump(pBt, pgno, recursive, 0); } #endif #ifdef SQLITE_TEST /* ** Fill aResult[] with information about the entry and page that the ** cursor is pointing to. |
︙ | ︙ | |||
5877 5878 5879 5880 5881 5882 5883 | ** This routine is used for testing and debugging only. */ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){ int cnt, idx; MemPage *pPage = pCur->pPage; BtCursor tmpCur; | < < < < < | 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 | ** This routine is used for testing and debugging only. */ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){ int cnt, idx; MemPage *pPage = pCur->pPage; BtCursor tmpCur; pageIntegrity(pPage); assert( pPage->isInit ); getTempCursor(pCur, &tmpCur); while( upCnt-- ){ moveToParent(&tmpCur); } pPage = tmpCur.pPage; |
︙ | ︙ | |||
5928 5929 5930 5931 5932 5933 5934 | } #endif /* ** Return the pager associated with a BTree. This routine is used for ** testing and debugging only. */ | | | | | 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 | } #endif /* ** Return the pager associated with a BTree. This routine is used for ** testing and debugging only. */ Pager *sqlite3BtreePager(Btree *pBt){ return pBt->pPager; } /* ** This structure is passed around through all the sanity checking routines ** in order to keep track of some global state information. */ typedef struct IntegrityCk IntegrityCk; struct IntegrityCk { Btree *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ int nPage; /* Number of pages in the database */ int *anRef; /* Number of times each page is referenced */ char *zErrMsg; /* An error message. NULL of no errors seen. */ }; #ifndef SQLITE_OMIT_INTEGRITY_CHECK |
︙ | ︙ | |||
6129 6130 6131 6132 6133 6134 6135 | int nUpper /* Number of characters in zUpperBound */ ){ MemPage *pPage; int i, rc, depth, d2, pgno, cnt; int hdr, cellStart; int nCell; u8 *data; | > | | | > > | 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 | int nUpper /* Number of characters in zUpperBound */ ){ MemPage *pPage; int i, rc, depth, d2, pgno, cnt; int hdr, cellStart; int nCell; u8 *data; BtCursor cur; Btree *pBt; int maxLocal, usableSize; char zContext[100]; char *hit; sprintf(zContext, "Page %d: ", iPage); /* Check that the page exists */ cur.pBt = pBt = pCheck->pBt; usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage, zParentContext) ) return 0; if( (rc = getPage(pBt, (Pgno)iPage, &pPage))!=0 ){ checkAppendMsg(pCheck, zContext, "unable to get the page. error code=%d", rc); return 0; } maxLocal = pPage->leafData ? pBt->maxLeaf : pBt->maxLocal; if( (rc = initPage(pPage, pParent))!=0 ){ checkAppendMsg(pCheck, zContext, "initPage() returns error code %d", rc); releasePage(pPage); return 0; } /* Check out all the cells. */ depth = 0; cur.pPage = pPage; for(i=0; i<pPage->nCell; i++){ u8 *pCell; int sz; CellInfo info; /* Check payload overflow pages */ |
︙ | ︙ | |||
6271 6272 6273 6274 6275 6276 6277 | ** a table. nRoot is the number of entries in aRoot. ** ** If everything checks out, this routine returns NULL. If something is ** amiss, an error message is written into memory obtained from malloc() ** and a pointer to that error message is returned. The calling function ** is responsible for freeing the error message when it is done. */ | | < | | 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 | ** a table. nRoot is the number of entries in aRoot. ** ** If everything checks out, this routine returns NULL. If something is ** amiss, an error message is written into memory obtained from malloc() ** and a pointer to that error message is returned. The calling function ** is responsible for freeing the error message when it is done. */ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){ int i; int nRef; IntegrityCk sCheck; nRef = *sqlite3pager_stats(pBt->pPager); if( lockBtree(pBt)!=SQLITE_OK ){ return sqliteStrDup("Unable to acquire a read lock on the database"); } sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; sCheck.nPage = sqlite3pager_pagecount(sCheck.pPager); if( sCheck.nPage==0 ){ unlockBtreeIfUnused(pBt); |
︙ | ︙ | |||
6360 6361 6362 6363 6364 6365 6366 | return sCheck.zErrMsg; } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* ** Return the full pathname of the underlying database file. */ | | | | | | | | | | | | < < < | < < < | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 | return sCheck.zErrMsg; } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* ** Return the full pathname of the underlying database file. */ const char *sqlite3BtreeGetFilename(Btree *pBt){ assert( pBt->pPager!=0 ); return sqlite3pager_filename(pBt->pPager); } /* ** Return the pathname of the directory that contains the database file. */ const char *sqlite3BtreeGetDirname(Btree *pBt){ assert( pBt->pPager!=0 ); return sqlite3pager_dirname(pBt->pPager); } /* ** Return the pathname of the journal file for this database. The return ** value of this routine is the same regardless of whether the journal file ** has been created or not. */ const char *sqlite3BtreeGetJournalname(Btree *pBt){ assert( pBt->pPager!=0 ); return sqlite3pager_journalname(pBt->pPager); } #ifndef SQLITE_OMIT_VACUUM /* ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. ** ** The size of file pBtFrom may be reduced by this operation. ** If anything goes wrong, the transaction on pBtFrom is rolled back. */ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ int rc = SQLITE_OK; Pgno i, nPage, nToPage; if( pBtTo->inTrans!=TRANS_WRITE || pBtFrom->inTrans!=TRANS_WRITE ){ return SQLITE_ERROR; } if( pBtTo->pCursor ) return SQLITE_BUSY; nToPage = sqlite3pager_pagecount(pBtTo->pPager); nPage = sqlite3pager_pagecount(pBtFrom->pPager); for(i=1; rc==SQLITE_OK && i<=nPage; i++){ void *pPage; rc = sqlite3pager_get(pBtFrom->pPager, i, &pPage); if( rc ) break; rc = sqlite3pager_overwrite(pBtTo->pPager, i, pPage); if( rc ) break; sqlite3pager_unref(pPage); } for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){ void *pPage; rc = sqlite3pager_get(pBtTo->pPager, i, &pPage); if( rc ) break; rc = sqlite3pager_write(pPage); sqlite3pager_unref(pPage); sqlite3pager_dont_write(pBtTo->pPager, i); } if( !rc && nPage<nToPage ){ rc = sqlite3pager_truncate(pBtTo->pPager, nPage); } if( rc ){ sqlite3BtreeRollback(pBtTo); } return rc; } #endif /* SQLITE_OMIT_VACUUM */ /* ** Return non-zero if a transaction is active. */ int sqlite3BtreeIsInTrans(Btree *pBt){ return (pBt && (pBt->inTrans==TRANS_WRITE)); } /* ** Return non-zero if a statement transaction is active. */ int sqlite3BtreeIsInStmt(Btree *pBt){ return (pBt && pBt->inStmt); } /* ** This call is a no-op if no write-transaction is currently active on pBt. ** ** Otherwise, sync the database file for the btree pBt. zMaster points to ** the name of a master journal file that should be written into the ** individual journal file, or is NULL, indicating no master journal file ** (single database transaction). ** ** When this is called, the master journal should already have been ** created, populated with this journal pointer and synced to disk. ** ** Once this is routine has returned, the only thing required to commit ** the write-transaction for this database file is to delete the journal. */ int sqlite3BtreeSync(Btree *pBt, const char *zMaster){ if( pBt->inTrans==TRANS_WRITE ){ #ifndef SQLITE_OMIT_AUTOVACUUM Pgno nTrunc = 0; if( pBt->autoVacuum ){ int rc = autoVacuumCommit(pBt, &nTrunc); if( rc!=SQLITE_OK ) return rc; } return sqlite3pager_sync(pBt->pPager, zMaster, nTrunc); #endif return sqlite3pager_sync(pBt->pPager, zMaster, 0); } return SQLITE_OK; } |
Changes to SQLite.Interop/src/btree.h.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** ** @(#) $Id: btree.h,v 1.1 2005/03/01 16:04:27 rmsimpson Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It ** needs to be revisited. */ |
︙ | ︙ | |||
32 33 34 35 36 37 38 | #endif /* ** Forward declarations of structure */ typedef struct Btree Btree; typedef struct BtCursor BtCursor; | < < < < < < | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | #endif /* ** Forward declarations of structure */ typedef struct Btree Btree; typedef struct BtCursor BtCursor; int sqlite3BtreeOpen( const char *zFilename, /* Name of database file to open */ Btree **, /* Return open Btree* here */ int flags /* Flags */ ); /* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the ** following values. ** ** NOTE: These values must match the corresponding PAGER_ values in ** pager.h. */ #define BTREE_OMIT_JOURNAL 1 /* Do not use journal. No argument */ #define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */ #define BTREE_MEMORY 4 /* In-memory DB. No argument */ int sqlite3BtreeClose(Btree*); int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*); int sqlite3BtreeSetCacheSize(Btree*,int); int sqlite3BtreeSetSafetyLevel(Btree*,int); int sqlite3BtreeSetPageSize(Btree*,int,int); int sqlite3BtreeGetPageSize(Btree*); int sqlite3BtreeGetReserve(Btree*); int sqlite3BtreeSetAutoVacuum(Btree *, int); int sqlite3BtreeGetAutoVacuum(Btree *); int sqlite3BtreeBeginTrans(Btree*,int); int sqlite3BtreeCommit(Btree*); int sqlite3BtreeRollback(Btree*); int sqlite3BtreeBeginStmt(Btree*); int sqlite3BtreeCommitStmt(Btree*); int sqlite3BtreeRollbackStmt(Btree*); int sqlite3BtreeCreateTable(Btree*, int*, int flags); int sqlite3BtreeIsInTrans(Btree*); int sqlite3BtreeIsInStmt(Btree*); int sqlite3BtreeSync(Btree*, const char *zMaster); const char *sqlite3BtreeGetFilename(Btree *); const char *sqlite3BtreeGetDirname(Btree *); const char *sqlite3BtreeGetJournalname(Btree *); int sqlite3BtreeCopyFile(Btree *, Btree *); /* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR |
︙ | ︙ |
Changes to SQLite.Interop/src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.1 2005/03/01 16:04:28 rmsimpson Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. */ void sqlite3BeginParse(Parse *pParse, int explainFlag){ pParse->explain = explainFlag; pParse->nVar = 0; } /* ** This routine is called after a single SQL statement has been ** parsed and a VDBE program to execute that statement has been ** prepared. This routine puts the finishing touches on the ** VDBE program and resets the pParse structure for the next ** parse. ** ** Note that if an error occurred, it might be the case that ** no VDBE code was generated. */ void sqlite3FinishCoding(Parse *pParse){ sqlite3 *db; Vdbe *v; if( sqlite3_malloc_failed ) return; if( pParse->nested ) return; if( !pParse->pVdbe ){ if( pParse->rc==SQLITE_OK && pParse->nErr ){ pParse->rc = SQLITE_ERROR; } return; } |
︙ | ︙ | |||
152 153 154 155 156 157 158 | ** set for each database that is used. Generate code to start a ** transaction on each used database and to verify the schema cookie ** on each used database. */ if( pParse->cookieGoto>0 ){ u32 mask; int iDb; | | < < < < < < < < | | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | ** set for each database that is used. Generate code to start a ** transaction on each used database and to verify the schema cookie ** on each used database. */ if( pParse->cookieGoto>0 ){ u32 mask; int iDb; sqlite3VdbeChangeP2(v, pParse->cookieGoto-1, sqlite3VdbeCurrentAddr(v)); for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){ if( (mask & pParse->cookieMask)==0 ) continue; sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0); sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); } sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->cookieGoto); } /* Add a No-op that contains the complete text of the compiled SQL ** statement as its P3 argument. This does not change the functionality ** of the program. ** ** This is used to implement sqlite3_trace(). */ sqlite3VdbeOp3(v, OP_Noop, 0, 0, pParse->zSql, pParse->zTail-pParse->zSql); } /* Get the VDBE program ready for execution */ if( v && pParse->nErr==0 ){ FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqlite3VdbeTrace(v, trace); sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3, pParse->nTab+3, pParse->nMaxDepth+1, pParse->explain); pParse->rc = SQLITE_DONE; pParse->colNamesSet = 0; }else if( pParse->rc==SQLITE_OK ){ pParse->rc = SQLITE_ERROR; } pParse->nTab = 0; pParse->nMem = 0; |
︙ | ︙ | |||
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | ** Not everything is nestable. This facility is designed to permit ** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use ** care if you decide to try to use this routine for some other purposes. */ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ va_list ap; char *zSql; # define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar)) char saveBuf[SAVE_SZ]; if( pParse->nErr ) return; assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ va_start(ap, zFormat); zSql = sqlite3VMPrintf(zFormat, ap); va_end(ap); if( zSql==0 ){ return; /* A malloc must have failed */ } pParse->nested++; memcpy(saveBuf, &pParse->nVar, SAVE_SZ); memset(&pParse->nVar, 0, SAVE_SZ); | > | | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | ** Not everything is nestable. This facility is designed to permit ** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use ** care if you decide to try to use this routine for some other purposes. */ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ va_list ap; char *zSql; int rc; # define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar)) char saveBuf[SAVE_SZ]; if( pParse->nErr ) return; assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ va_start(ap, zFormat); zSql = sqlite3VMPrintf(zFormat, ap); va_end(ap); if( zSql==0 ){ return; /* A malloc must have failed */ } pParse->nested++; memcpy(saveBuf, &pParse->nVar, SAVE_SZ); memset(&pParse->nVar, 0, SAVE_SZ); rc = sqlite3RunParser(pParse, zSql, 0); sqliteFree(zSql); memcpy(&pParse->nVar, saveBuf, SAVE_SZ); pParse->nested--; } /* ** Locate the in-memory structure that describes a particular database |
︙ | ︙ | |||
250 251 252 253 254 255 256 | ** ** See also sqlite3LocateTable(). */ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ Table *p = 0; int i; assert( zName!=0 ); | > | | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | ** ** See also sqlite3LocateTable(). */ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ Table *p = 0; int i; assert( zName!=0 ); assert( (db->flags & SQLITE_Initialized) || db->init.busy ); for(i=0; i<db->nDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; p = sqlite3HashFind(&db->aDb[j].tblHash, zName, strlen(zName)+1); if( p ) break; } return p; } /* ** Locate the in-memory structure that describes a particular database |
︙ | ︙ | |||
282 283 284 285 286 287 288 289 290 291 292 293 294 295 | return 0; } p = sqlite3FindTable(pParse->db, zName, zDbase); if( p==0 ){ if( zDbase ){ sqlite3ErrorMsg(pParse, "no such table: %s.%s", zDbase, zName); }else{ sqlite3ErrorMsg(pParse, "no such table: %s", zName); } pParse->checkSchema = 1; } return p; } | > > > | 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | return 0; } p = sqlite3FindTable(pParse->db, zName, zDbase); if( p==0 ){ if( zDbase ){ sqlite3ErrorMsg(pParse, "no such table: %s.%s", zDbase, zName); }else if( sqlite3FindTable(pParse->db, zName, 0)!=0 ){ sqlite3ErrorMsg(pParse, "table \"%s\" is not in database \"%s\"", zName, zDbase); }else{ sqlite3ErrorMsg(pParse, "no such table: %s", zName); } pParse->checkSchema = 1; } return p; } |
︙ | ︙ | |||
305 306 307 308 309 310 311 | ** for duplicate index names is done.) The search order is ** TEMP first, then MAIN, then any auxiliary databases added ** using the ATTACH command. */ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ Index *p = 0; int i; | > | < < < | < | 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | ** for duplicate index names is done.) The search order is ** TEMP first, then MAIN, then any auxiliary databases added ** using the ATTACH command. */ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ Index *p = 0; int i; assert( (db->flags & SQLITE_Initialized) || db->init.busy ); for(i=0; i<db->nDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; p = sqlite3HashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1); if( p ) break; } return p; } /* ** Reclaim the memory used by an index |
︙ | ︙ | |||
336 337 338 339 340 341 342 | ** ** The index is removed from the database hash tables but ** it is not unlinked from the Table that it indexes. ** Unlinking from the Table must be done by the calling function. */ static void sqliteDeleteIndex(sqlite3 *db, Index *p){ Index *pOld; | < > | > | > > > < | | | < | | 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | ** ** The index is removed from the database hash tables but ** it is not unlinked from the Table that it indexes. ** Unlinking from the Table must be done by the calling function. */ static void sqliteDeleteIndex(sqlite3 *db, Index *p){ Index *pOld; assert( db!=0 && p->zName!=0 ); pOld = sqlite3HashInsert(&db->aDb[p->iDb].idxHash, p->zName, strlen(p->zName)+1, 0); if( pOld!=0 && pOld!=p ){ sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName, strlen(pOld->zName)+1, pOld); } freeIndex(p); } /* ** Unlink the given index from its table, then remove ** the index from the index hash table and free its memory ** structures. */ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ Index *pIndex; int len; len = strlen(zIdxName); pIndex = sqlite3HashInsert(&db->aDb[iDb].idxHash, zIdxName, len+1, 0); if( pIndex ){ if( pIndex->pTable->pIndex==pIndex ){ pIndex->pTable->pIndex = pIndex->pNext; }else{ Index *p; for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){} if( p && p->pNext==pIndex ){ |
︙ | ︙ | |||
383 384 385 386 387 388 389 390 391 392 393 394 | ** schema-cookie mismatch occurs. ** ** If iDb<=0 then reset the internal schema tables for all database ** files. If iDb>=2 then reset the internal schema for only the ** single file indicated. */ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ int i, j; assert( iDb>=0 && iDb<db->nDb ); for(i=iDb; i<db->nDb; i++){ Db *pDb = &db->aDb[i]; | > > > > | > > > > > > > | > > > > > > > | | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | ** schema-cookie mismatch occurs. ** ** If iDb<=0 then reset the internal schema tables for all database ** files. If iDb>=2 then reset the internal schema for only the ** single file indicated. */ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ HashElem *pElem; Hash temp1; Hash temp2; int i, j; assert( iDb>=0 && iDb<db->nDb ); db->flags &= ~SQLITE_Initialized; for(i=iDb; i<db->nDb; i++){ Db *pDb = &db->aDb[i]; temp1 = pDb->tblHash; temp2 = pDb->trigHash; sqlite3HashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0); sqlite3HashClear(&pDb->aFKey); sqlite3HashClear(&pDb->idxHash); for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem)); } sqlite3HashClear(&temp2); sqlite3HashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0); for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ Table *pTab = sqliteHashData(pElem); sqlite3DeleteTable(db, pTab); } sqlite3HashClear(&temp1); pDb->pSeqTab = 0; DbClearProperty(db, i, DB_SchemaLoaded); if( iDb>0 ) return; } assert( iDb==0 ); db->flags &= ~SQLITE_InternChanges; /* If one or more of the auxiliary database files has been closed, ** then remove then from the auxiliary database list. We take the ** opportunity to do this here since we have just deleted all of the ** schema hash tables and therefore do not have to make any changes ** to any of those tables. */ for(i=0; i<db->nDb; i++){ struct Db *pDb = &db->aDb[i]; if( pDb->pBt==0 ){ |
︙ | ︙ | |||
455 456 457 458 459 460 461 | /* ** Clear the column names from a table or view. */ static void sqliteResetColumnNames(Table *pTable){ int i; Column *pCol; assert( pTable!=0 ); | < | | | | < | | < | 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | /* ** Clear the column names from a table or view. */ static void sqliteResetColumnNames(Table *pTable){ int i; Column *pCol; assert( pTable!=0 ); for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){ sqliteFree(pCol->zName); sqlite3ExprDelete(pCol->pDflt); sqliteFree(pCol->zType); } sqliteFree(pTable->aCol); pTable->aCol = 0; pTable->nCol = 0; } /* ** Remove the memory data structures associated with the given ** Table. No changes are made to disk by this routine. |
︙ | ︙ | |||
487 488 489 490 491 492 493 | ** the table are deleted, but it is assumed they have already been ** unlinked. */ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ Index *pIndex, *pNext; FKey *pFKey, *pNextFKey; | < < < < < < < < < | > | < < < | | | | | | < < | < | | 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | ** the table are deleted, but it is assumed they have already been ** unlinked. */ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ Index *pIndex, *pNext; FKey *pFKey, *pNextFKey; if( pTable==0 ) return; /* Delete all indices associated with this table */ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) ); sqliteDeleteIndex(db, pIndex); } #ifndef SQLITE_OMIT_FOREIGN_KEY /* Delete all foreign keys associated with this table. The keys ** should have already been unlinked from the db->aFKey hash table */ for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){ pNextFKey = pFKey->pNextFrom; assert( pTable->iDb<db->nDb ); assert( sqlite3HashFind(&db->aDb[pTable->iDb].aFKey, pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey ); sqliteFree(pFKey); } #endif /* Delete the Table structure itself. */ sqliteResetColumnNames(pTable); sqliteFree(pTable->zName); sqliteFree(pTable->zColAff); sqlite3SelectDelete(pTable->pSelect); sqliteFree(pTable); } /* ** Unlink the given table from the hash tables and the delete the ** table structure with all its indices and foreign keys. */ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ Table *p; FKey *pF1, *pF2; Db *pDb; assert( db!=0 ); assert( iDb>=0 && iDb<db->nDb ); assert( zTabName && zTabName[0] ); pDb = &db->aDb[iDb]; p = sqlite3HashInsert(&pDb->tblHash, zTabName, strlen(zTabName)+1, 0); if( p ){ #ifndef SQLITE_OMIT_FOREIGN_KEY for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){ int nTo = strlen(pF1->zTo) + 1; pF2 = sqlite3HashFind(&pDb->aFKey, pF1->zTo, nTo); if( pF2==pF1 ){ sqlite3HashInsert(&pDb->aFKey, pF1->zTo, nTo, pF1->pNextTo); }else{ while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; } if( pF2 ){ pF2->pNextTo = pF1->pNextTo; } } } #endif sqlite3DeleteTable(db, p); } db->flags |= SQLITE_InternChanges; } /* ** Given a token, return a string that consists of the text of that ** token with any quotations removed. Space to hold the returned string ** is obtained from sqliteMalloc() and must be freed by the calling ** function. ** ** Tokens are really just pointers into the original SQL text and so ** are not \000 terminated and are not persistent. The returned string ** is \000 terminated and is persistent. */ char *sqlite3NameFromToken(Token *pName){ char *zName; if( pName ){ zName = sqliteStrNDup(pName->z, pName->n); sqlite3Dequote(zName); }else{ zName = 0; } return zName; } /* ** Open the sqlite_master table stored in database number iDb for ** writing. The table is opened using cursor 0. */ void sqlite3OpenMasterTable(Vdbe *v, int iDb){ sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 0, MASTER_ROOT); sqlite3VdbeAddOp(v, OP_SetNumColumns, 0, 5); /* sqlite_master has 5 columns */ } /* ** The token *pName contains the name of a database (either "main" or ** "temp" or the name of an attached db). This routine returns the ** index of the named database in db->aDb[], or -1 if the named db ** does not exist. */ static int findDb(sqlite3 *db, Token *pName){ int i = -1; /* Database number */ int n; /* Number of characters in the name */ Db *pDb; /* A database whose name space is being searched */ char *zName; /* Name we are searching for */ zName = sqlite3NameFromToken(pName); if( zName ){ n = strlen(zName); for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){ if( n==strlen(pDb->zName) && 0==sqlite3StrICmp(pDb->zName, zName) ){ break; } } sqliteFree(zName); } return i; } |
︙ | ︙ | |||
651 652 653 654 655 656 657 | ){ int iDb; /* Database holding the object */ sqlite3 *db = pParse->db; if( pName2 && pName2->n>0 ){ assert( !db->init.busy ); *pUnqual = pName2; | | | 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 | ){ int iDb; /* Database holding the object */ sqlite3 *db = pParse->db; if( pName2 && pName2->n>0 ){ assert( !db->init.busy ); *pUnqual = pName2; iDb = findDb(db, pName1); if( iDb<0 ){ sqlite3ErrorMsg(pParse, "unknown database %T", pName1); pParse->nErr++; return -1; } }else{ assert( db->init.iDb==0 || db->init.busy ); |
︙ | ︙ | |||
674 675 676 677 678 679 680 | ** unqualified name for a new schema object (table, index, view or ** trigger). All names are legal except those that begin with the string ** "sqlite_" (in upper, lower or mixed case). This portion of the namespace ** is reserved for internal use. */ int sqlite3CheckObjectName(Parse *pParse, const char *zName){ if( !pParse->db->init.busy && pParse->nested==0 | < | 591 592 593 594 595 596 597 598 599 600 601 602 603 604 | ** unqualified name for a new schema object (table, index, view or ** trigger). All names are legal except those that begin with the string ** "sqlite_" (in upper, lower or mixed case). This portion of the namespace ** is reserved for internal use. */ int sqlite3CheckObjectName(Parse *pParse, const char *zName){ if( !pParse->db->init.busy && pParse->nested==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName); return SQLITE_ERROR; } return SQLITE_OK; } |
︙ | ︙ | |||
705 706 707 708 709 710 711 | */ void sqlite3StartTable( Parse *pParse, /* Parser context */ Token *pStart, /* The "CREATE" token */ Token *pName1, /* First part of the name of the table or view */ Token *pName2, /* Second part of the name of the table or view */ int isTemp, /* True if this is a TEMP table */ | | < > | 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 | */ void sqlite3StartTable( Parse *pParse, /* Parser context */ Token *pStart, /* The "CREATE" token */ Token *pName1, /* First part of the name of the table or view */ Token *pName2, /* Second part of the name of the table or view */ int isTemp, /* True if this is a TEMP table */ int isView /* True if this is a VIEW */ ){ Table *pTable; Index *pIdx; char *zName = 0; /* The name of the new table */ sqlite3 *db = pParse->db; Vdbe *v; int iDb; /* Database number to create the table in */ Token *pName; /* Unqualified name of the table to create */ /* The table or view name to create is passed to this routine via tokens |
︙ | ︙ | |||
734 735 736 737 738 739 740 | ** The call below sets the pName pointer to point at the token (pName1 or ** pName2) that stores the unqualified table name. The variable iDb is ** set to the index of the database that the table or view is to be ** created in. */ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); if( iDb<0 ) return; | | | | | < | < > | < | | | < < < | | | | | | | 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 | ** The call below sets the pName pointer to point at the token (pName1 or ** pName2) that stores the unqualified table name. The variable iDb is ** set to the index of the database that the table or view is to be ** created in. */ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); if( iDb<0 ) return; if( isTemp && iDb>1 ){ /* If creating a temp table, the name may not be qualified */ sqlite3ErrorMsg(pParse, "temporary table name must be unqualified"); return; } if( isTemp ) iDb = 1; pParse->sNameToken = *pName; zName = sqlite3NameFromToken(pName); if( zName==0 ) return; if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto begin_table_error; } if( db->init.iDb==1 ) isTemp = 1; #ifndef SQLITE_OMIT_AUTHORIZATION assert( (isTemp & 1)==isTemp ); { int code; char *zDb = db->aDb[iDb].zName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ goto begin_table_error; } if( isView ){ if( isTemp ){ code = SQLITE_CREATE_TEMP_VIEW; }else{ code = SQLITE_CREATE_VIEW; } }else{ if( isTemp ){ code = SQLITE_CREATE_TEMP_TABLE; }else{ code = SQLITE_CREATE_TABLE; } } if( sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){ goto begin_table_error; } } #endif /* Make sure the new table name does not collide with an existing ** index or table name in the same database. Issue an error message if ** it does. */ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto begin_table_error; } pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName); if( pTable ){ sqlite3ErrorMsg(pParse, "table %T already exists", pName); goto begin_table_error; } if( (pIdx = sqlite3FindIndex(db, zName, 0))!=0 && ( iDb==0 || !db->init.busy) ){ sqlite3ErrorMsg(pParse, "there is already an index named %s", zName); goto begin_table_error; } pTable = sqliteMalloc( sizeof(Table) ); if( pTable==0 ){ pParse->rc = SQLITE_NOMEM; pParse->nErr++; goto begin_table_error; } pTable->zName = zName; pTable->nCol = 0; pTable->aCol = 0; pTable->iPKey = -1; pTable->pIndex = 0; pTable->iDb = iDb; if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable); pParse->pNewTable = pTable; /* If this is the magic sqlite_sequence table used by autoincrement, ** then record a pointer to this table in the main database structure ** so that INSERT can find the table easily. */ #ifndef SQLITE_OMIT_AUTOINCREMENT if( strcmp(zName, "sqlite_sequence")==0 ){ db->aDb[iDb].pSeqTab = pTable; } #endif /* Begin generating the code that will insert the table record into ** the SQLITE_MASTER table. Note in particular that we must go ahead ** and allocate the record number for the table entry now. Before any ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause ** indices to be created and the table record must come before the ** indices. Hence, the record number for the table must be allocated ** now. */ if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ int lbl; sqlite3BeginWriteOperation(pParse, 0, iDb); /* If the file format and encoding in the database have not been set, ** set them now. */ sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); /* file_format */ lbl = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_If, 0, lbl); sqlite3VdbeAddOp(v, OP_Integer, db->file_format, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4); sqlite3VdbeResolveLabel(v, lbl); /* This just creates a place-holder record in the sqlite_master table. ** The record created does not contain anything yet. It will be replaced ** by the real entry in code generated at sqlite3EndTable(). ** ** The rowid for the new entry is left on the top of the stack. ** The rowid value is needed by the code that sqlite3EndTable will ** generate. */ #ifndef SQLITE_OMIT_VIEW if( isView ){ sqlite3VdbeAddOp(v, OP_Integer, 0, 0); }else #endif { sqlite3VdbeAddOp(v, OP_CreateTable, iDb, 0); } sqlite3OpenMasterTable(v, iDb); sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_String8, 0, 0); sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); } /* Normal (non-error) return. */ return; |
︙ | ︙ | |||
919 920 921 922 923 924 925 | sqliteFree(z); return; } } if( (p->nCol & 0x7)==0 ){ Column *aNew; aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0])); | | < < < > | 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 | sqliteFree(z); return; } } if( (p->nCol & 0x7)==0 ){ Column *aNew; aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0])); if( aNew==0 ) return; p->aCol = aNew; } pCol = &p->aCol[p->nCol]; memset(pCol, 0, sizeof(p->aCol[0])); pCol->zName = z; /* If there is no type specified, columns have the default affinity ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will ** be called next to set pCol->affinity correctly. */ pCol->affinity = SQLITE_AFF_NONE; pCol->pColl = pParse->db->pDfltColl; p->nCol++; } /* ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. A "NOT NULL" constraint has ** been seen on a column. This routine sets the notNull flag on |
︙ | ︙ | |||
969 970 971 972 973 974 975 | ** Substring | Affinity ** -------------------------------- ** 'INT' | SQLITE_AFF_INTEGER ** 'CHAR' | SQLITE_AFF_TEXT ** 'CLOB' | SQLITE_AFF_TEXT ** 'TEXT' | SQLITE_AFF_TEXT ** 'BLOB' | SQLITE_AFF_NONE | < < < | | | < < < < | < < < < < < < | | | > | > > > > | | > > > > > > > | | | | | | | | | < | 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 | ** Substring | Affinity ** -------------------------------- ** 'INT' | SQLITE_AFF_INTEGER ** 'CHAR' | SQLITE_AFF_TEXT ** 'CLOB' | SQLITE_AFF_TEXT ** 'TEXT' | SQLITE_AFF_TEXT ** 'BLOB' | SQLITE_AFF_NONE ** ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. */ static char sqlite3AffinityType(const char *zType, int nType){ u32 h = 0; char aff = SQLITE_AFF_NUMERIC; const unsigned char *zIn = zType; const unsigned char *zEnd = (zIn+nType); while( zIn!=zEnd ){ h = (h<<8) + sqlite3UpperToLower[*zIn]; zIn++; if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */ aff = SQLITE_AFF_TEXT; }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */ aff = SQLITE_AFF_TEXT; }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */ aff = SQLITE_AFF_TEXT; }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */ && aff==SQLITE_AFF_NUMERIC ){ aff = SQLITE_AFF_NONE; }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */ aff = SQLITE_AFF_INTEGER; break; } } return aff; } /* ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. The pFirst token is the first ** token in the sequence of tokens that describe the type of the ** column currently under construction. pLast is the last token ** in the sequence. Use this information to construct a string ** that contains the typename of the column and store that string ** in zType. */ void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){ Table *p; int i, j; int n; char *z; const unsigned char *zIn; Column *pCol; if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; if( i<0 ) return; pCol = &p->aCol[i]; zIn = pFirst->z; n = pLast->n + (pLast->z - zIn); assert( pCol->zType==0 ); z = pCol->zType = sqliteMallocRaw(n+1); if( z==0 ) return; for(i=j=0; i<n; i++){ int c = zIn[i]; if( isspace(c) ) continue; z[j++] = c; } z[j] = 0; pCol->affinity = sqlite3AffinityType(z, n); } /* ** The expression is the default value for the most recently added column ** of the table currently under construction. ** ** Default value expressions must be constant. Raise an exception if this ** is not the case. ** ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. */ void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){ Table *p; Column *pCol; if( (p = pParse->pNewTable)==0 ) return; pCol = &(p->aCol[p->nCol-1]); if( !sqlite3ExprIsConstant(pExpr) ){ sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", pCol->zName); }else{ sqlite3ExprDelete(pCol->pDflt); pCol->pDflt = sqlite3ExprDup(pExpr); } sqlite3ExprDelete(pExpr); } /* ** Designate the PRIMARY KEY for the table. pList is a list of names ** of columns that form the primary key. If pList is NULL, then the |
︙ | ︙ | |||
1085 1086 1087 1088 1089 1090 1091 | ** If the key is not an INTEGER PRIMARY KEY, then create a unique ** index for the key. No index is created for INTEGER PRIMARY KEYs. */ void sqlite3AddPrimaryKey( Parse *pParse, /* Parsing context */ ExprList *pList, /* List of field names to be indexed */ int onError, /* What to do with a uniqueness conflict */ | | < | 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 | ** If the key is not an INTEGER PRIMARY KEY, then create a unique ** index for the key. No index is created for INTEGER PRIMARY KEYs. */ void sqlite3AddPrimaryKey( Parse *pParse, /* Parsing context */ ExprList *pList, /* List of field names to be indexed */ int onError, /* What to do with a uniqueness conflict */ int autoInc /* True if the AUTOINCREMENT keyword is present */ ){ Table *pTab = pParse->pNewTable; char *zType = 0; int iCol = -1, i; if( pTab==0 ) goto primary_key_exit; if( pTab->hasPrimKey ){ sqlite3ErrorMsg(pParse, |
︙ | ︙ | |||
1108 1109 1110 1111 1112 1113 1114 | }else{ for(i=0; i<pList->nExpr; i++){ for(iCol=0; iCol<pTab->nCol; iCol++){ if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){ break; } } | | < < | < | < < < < < < < < < < < < < < < < < < < > > | < | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > | > > > > > > | > | > > > < | | | | < > > > | > | > > > | < > < < > > > > > > > | 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 | }else{ for(i=0; i<pList->nExpr; i++){ for(iCol=0; iCol<pTab->nCol; iCol++){ if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){ break; } } if( iCol<pTab->nCol ) pTab->aCol[iCol].isPrimKey = 1; } if( pList->nExpr>1 ) iCol = -1; } if( iCol>=0 && iCol<pTab->nCol ){ zType = pTab->aCol[iCol].zType; } if( zType && sqlite3StrICmp(zType, "INTEGER")==0 ){ pTab->iPKey = iCol; pTab->keyConf = onError; pTab->autoInc = autoInc; }else if( autoInc ){ #ifndef SQLITE_OMIT_AUTOINCREMENT sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an " "INTEGER PRIMARY KEY"); #endif }else{ sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0); pList = 0; } primary_key_exit: sqlite3ExprListDelete(pList); return; } /* ** Set the collation function of the most recently parsed table column ** to the CollSeq given. */ void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){ Table *p; Index *pIdx; CollSeq *pColl; int i; if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; pColl = sqlite3LocateCollSeq(pParse, zType, nType); p->aCol[i].pColl = pColl; /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>", ** then an index may have been created on this column before the ** collation type was added. Correct this if it is the case. */ for(pIdx = p->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->nColumn==1 ); if( pIdx->aiColumn[0]==i ) pIdx->keyInfo.aColl[0] = pColl; } } /* ** Locate and return an entry from the db.aCollSeq hash table. If the entry ** specified by zName and nName is not found and parameter 'create' is ** true, then create a new entry. Otherwise return NULL. ** ** Each pointer stored in the sqlite3.aCollSeq hash table contains an ** array of three CollSeq structures. The first is the collation sequence ** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be. ** ** Stored immediately after the three collation sequences is a copy of ** the collation sequence name. A pointer to this string is stored in ** each collation sequence structure. */ static CollSeq * findCollSeqEntry( sqlite3 *db, const char *zName, int nName, int create ){ CollSeq *pColl; if( nName<0 ) nName = strlen(zName); pColl = sqlite3HashFind(&db->aCollSeq, zName, nName); if( 0==pColl && create ){ pColl = sqliteMalloc( 3*sizeof(*pColl) + nName + 1 ); if( pColl ){ pColl[0].zName = (char*)&pColl[3]; pColl[0].enc = SQLITE_UTF8; pColl[1].zName = (char*)&pColl[3]; pColl[1].enc = SQLITE_UTF16LE; pColl[2].zName = (char*)&pColl[3]; pColl[2].enc = SQLITE_UTF16BE; memcpy(pColl[0].zName, zName, nName); pColl[0].zName[nName] = 0; sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl); } } return pColl; } /* ** Parameter zName points to a UTF-8 encoded string nName bytes long. ** Return the CollSeq* pointer for the collation sequence named zName ** for the encoding 'enc' from the database 'db'. ** ** If the entry specified is not found and 'create' is true, then create a ** new entry. Otherwise return NULL. */ CollSeq *sqlite3FindCollSeq( sqlite3 *db, u8 enc, const char *zName, int nName, int create ){ CollSeq *pColl = findCollSeqEntry(db, zName, nName, create); assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); if( pColl ) pColl += enc-1; return pColl; } /* ** Invoke the 'collation needed' callback to request a collation sequence ** in the database text encoding of name zName, length nName. ** If the collation sequence */ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){ assert( !db->xCollNeeded || !db->xCollNeeded16 ); if( nName<0 ) nName = strlen(zName); if( db->xCollNeeded ){ char *zExternal = sqliteStrNDup(zName, nName); if( !zExternal ) return; db->xCollNeeded(db->pCollNeededArg, db, (int)db->enc, zExternal); sqliteFree(zExternal); } #ifndef SQLITE_OMIT_UTF16 if( db->xCollNeeded16 ){ char const *zExternal; sqlite3_value *pTmp = sqlite3GetTransientValue(db); sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC); zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); if( !zExternal ) return; db->xCollNeeded16(db->pCollNeededArg, db, (int)db->enc, zExternal); } #endif } /* ** This routine is called if the collation factory fails to deliver a ** collation function in the best encoding but there may be other versions ** of this collation function (for other text encodings) available. Use one ** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if ** possible. */ static int synthCollSeq(Parse *pParse, CollSeq *pColl){ CollSeq *pColl2; char *z = pColl->zName; int n = strlen(z); sqlite3 *db = pParse->db; int i; static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 }; for(i=0; i<3; i++){ pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, n, 0); if( pColl2->xCmp!=0 ){ memcpy(pColl, pColl2, sizeof(CollSeq)); return SQLITE_OK; } } if( pParse->nErr==0 ){ sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", n, z); } pParse->nErr++; return SQLITE_ERROR; } /* ** This routine is called on a collation sequence before it is used to ** check that it is defined. An undefined collation sequence exists when ** a database is loaded that contains references to collation sequences ** that have not been defined by sqlite3_create_collation() etc. ** ** If required, this routine calls the 'collation needed' callback to ** request a definition of the collating sequence. If this doesn't work, ** an equivalent collating sequence that uses a text encoding different ** from the main database is substituted, if one is available. */ int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ if( pColl && !pColl->xCmp ){ /* No collation sequence of this type for this encoding is registered. ** Call the collation factory to see if it can supply us with one. */ callCollNeeded(pParse->db, pColl->zName, strlen(pColl->zName)); if( !pColl->xCmp && synthCollSeq(pParse, pColl) ){ return SQLITE_ERROR; } } return SQLITE_OK; } /* ** Call sqlite3CheckCollSeq() for all collating sequences in an index, ** in order to verify that all the necessary collating sequences are ** loaded. */ int sqlite3CheckIndexCollSeq(Parse *pParse, Index *pIdx){ if( pIdx ){ int i; for(i=0; i<pIdx->nColumn; i++){ if( sqlite3CheckCollSeq(pParse, pIdx->keyInfo.aColl[i]) ){ return SQLITE_ERROR; } } } return SQLITE_OK; } /* ** This function returns the collation sequence for database native text ** encoding identified by the string zName, length nName. ** ** If the requested collation sequence is not available, or not available ** in the database native encoding, the collation factory is invoked to ** request it. If the collation factory does not supply such a sequence, ** and the sequence is available in another text encoding, then that is ** returned instead. ** ** If no versions of the requested collations sequence are available, or ** another error occurs, NULL is returned and an error message written into ** pParse. */ CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){ u8 enc = pParse->db->enc; u8 initbusy = pParse->db->init.busy; CollSeq *pColl = sqlite3FindCollSeq(pParse->db, enc, zName, nName, initbusy); if( nName<0 ) nName = strlen(zName); if( !initbusy && (!pColl || !pColl->xCmp) ){ /* No collation sequence of this type for this encoding is registered. ** Call the collation factory to see if it can supply us with one. */ callCollNeeded(pParse->db, zName, nName); pColl = sqlite3FindCollSeq(pParse->db, enc, zName, nName, 0); if( pColl && !pColl->xCmp ){ /* There may be a version of the collation sequence that requires ** translation between encodings. Search for it with synthCollSeq(). */ if( synthCollSeq(pParse, pColl) ){ return 0; } } } /* If nothing has been found, write the error message into pParse */ if( !initbusy && (!pColl || !pColl->xCmp) ){ if( pParse->nErr==0 ){ sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", nName, zName); } pColl = 0; } return pColl; } /* ** Generate code that will increment the schema cookie. ** |
︙ | ︙ | |||
1237 1238 1239 1240 1241 1242 1243 | ** This plan is not completely bullet-proof. It is possible for ** the schema to change multiple times and for the cookie to be ** set back to prior value. But schema changes are infrequent ** and the probability of hitting the same cookie value is only ** 1 chance in 2^32. So we're safe enough. */ void sqlite3ChangeCookie(sqlite3 *db, Vdbe *v, int iDb){ | | | 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 | ** This plan is not completely bullet-proof. It is possible for ** the schema to change multiple times and for the cookie to be ** set back to prior value. But schema changes are infrequent ** and the probability of hitting the same cookie value is only ** 1 chance in 2^32. So we're safe enough. */ void sqlite3ChangeCookie(sqlite3 *db, Vdbe *v, int iDb){ sqlite3VdbeAddOp(v, OP_Integer, db->aDb[iDb].schema_cookie+1, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 0); } /* ** Measure the number of characters needed to output the given ** identifier. The number returned includes any quotes used ** but does not include the null terminator. |
︙ | ︙ | |||
1285 1286 1287 1288 1289 1290 1291 | } /* ** Generate a CREATE TABLE statement appropriate for the given ** table. Memory to hold the text of the statement is obtained ** from sqliteMalloc() and must be freed by the calling function. */ | | | 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 | } /* ** Generate a CREATE TABLE statement appropriate for the given ** table. Memory to hold the text of the statement is obtained ** from sqliteMalloc() and must be freed by the calling function. */ static char *createTableStmt(Table *p){ int i, k, n; char *zStmt; char *zSep, *zSep2, *zEnd, *z; Column *pCol; n = 0; for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){ n += identLength(pCol->zName); |
︙ | ︙ | |||
1311 1312 1313 1314 1315 1316 1317 | zSep = "\n "; zSep2 = ",\n "; zEnd = "\n)"; } n += 35 + 6*p->nCol; zStmt = sqliteMallocRaw( n ); if( zStmt==0 ) return 0; | | | 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 | zSep = "\n "; zSep2 = ",\n "; zEnd = "\n)"; } n += 35 + 6*p->nCol; zStmt = sqliteMallocRaw( n ); if( zStmt==0 ) return 0; strcpy(zStmt, p->iDb==1 ? "CREATE TEMP TABLE " : "CREATE TABLE "); k = strlen(zStmt); identPut(zStmt, &k, p->zName); zStmt[k++] = '('; for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){ strcpy(&zStmt[k], zSep); k += strlen(&zStmt[k]); zSep = zSep2; |
︙ | ︙ | |||
1342 1343 1344 1345 1346 1347 1348 | ** is added to the internal hash tables, assuming no errors have ** occurred. ** ** An entry for the table is made in the master table on disk, unless ** this is a temporary table or db->init.busy==1. When db->init.busy==1 ** it means we are reading the sqlite_master table because we just ** connected to the database or because the sqlite_master table has | | | < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 | ** is added to the internal hash tables, assuming no errors have ** occurred. ** ** An entry for the table is made in the master table on disk, unless ** this is a temporary table or db->init.busy==1. When db->init.busy==1 ** it means we are reading the sqlite_master table because we just ** connected to the database or because the sqlite_master table has ** recently changes, so the entry for this table already exists in ** the sqlite_master table. We do not want to create it again. ** ** If the pSelect argument is not NULL, it means that this routine ** was called to create a table generated from a ** "CREATE TABLE ... AS SELECT ..." statement. The column names of ** the new table will match the result set of the SELECT. */ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){ Table *p; sqlite3 *db = pParse->db; if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite3_malloc_failed ) return; p = pParse->pNewTable; if( p==0 ) return; assert( !db->init.busy || !pSelect ); /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" or "sqlite_temp_master" table on the disk. ** So do not write to the disk again. Extract the root page number ** for the table from the db->init.newTnum field. (The page number ** should have been put there by the sqliteOpenCb routine.) */ if( db->init.busy ){ |
︙ | ︙ | |||
1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 | /* Create the rootpage for the new table and push it onto the stack. ** A view has no rootpage, so just push a zero onto the stack for ** views. Initialize zType at the same time. */ if( p->pSelect==0 ){ /* A regular table */ zType = "table"; zType2 = "TABLE"; #ifndef SQLITE_OMIT_VIEW }else{ /* A view */ zType = "view"; zType2 = "VIEW"; #endif } /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT ** statement to populate the new table. The root-page number for the ** new table is on the top of the vdbe stack. ** ** Once the SELECT has been coded by sqlite3Select(), it is in a ** suitable state to query for the column names and types to be used ** by the new table. | > > < < < < < | | | | | | | | | | | | < < < < < < < < < | 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 | /* Create the rootpage for the new table and push it onto the stack. ** A view has no rootpage, so just push a zero onto the stack for ** views. Initialize zType at the same time. */ if( p->pSelect==0 ){ /* A regular table */ /* sqlite3VdbeAddOp(v, OP_CreateTable, p->iDb, 0); */ zType = "table"; zType2 = "TABLE"; #ifndef SQLITE_OMIT_VIEW }else{ /* A view */ /* sqlite3VdbeAddOp(v, OP_Integer, 0, 0); */ zType = "view"; zType2 = "VIEW"; #endif } /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT ** statement to populate the new table. The root-page number for the ** new table is on the top of the vdbe stack. ** ** Once the SELECT has been coded by sqlite3Select(), it is in a ** suitable state to query for the column names and types to be used ** by the new table. */ if( pSelect ){ Table *pSelTab; sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Integer, p->iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0); pParse->nTab = 2; sqlite3Select(pParse, pSelect, SRT_Table, 1, 0, 0, 0, 0); sqlite3VdbeAddOp(v, OP_Close, 1, 0); if( pParse->nErr==0 ){ pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect); if( pSelTab==0 ) return; assert( p->aCol==0 ); p->nCol = pSelTab->nCol; p->aCol = pSelTab->aCol; pSelTab->nCol = 0; pSelTab->aCol = 0; sqlite3DeleteTable(0, pSelTab); } } /* Compute the complete text of the CREATE statement */ if( pSelect ){ zStmt = createTableStmt(p); }else{ n = Addr(pEnd->z) - Addr(pParse->sNameToken.z) + 1; zStmt = sqlite3MPrintf("CREATE %s %.*s", zType2, n, pParse->sNameToken.z); } /* A slot for the record has already been allocated in the ** SQLITE_MASTER table. We just need to update that slot with all ** the information we've collected. The rowid for the preallocated ** slot is the 2nd item on the stack. The top of the stack is the ** root page for the new table (or a 0 if this is a view). */ sqlite3NestedParse(pParse, "UPDATE %Q.%s " "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#0, sql=%Q " "WHERE rowid=#1", db->aDb[p->iDb].zName, SCHEMA_TABLE(p->iDb), zType, p->zName, p->zName, zStmt ); sqliteFree(zStmt); sqlite3ChangeCookie(db, v, p->iDb); #ifndef SQLITE_OMIT_AUTOINCREMENT /* Check to see if we need to create an sqlite_sequence table for ** keeping track of autoincrement keys. */ if( p->autoInc ){ Db *pDb = &db->aDb[p->iDb]; if( pDb->pSeqTab==0 ){ sqlite3NestedParse(pParse, "CREATE TABLE %Q.sqlite_sequence(name,seq)", pDb->zName ); } } #endif /* Reparse everything to update our internal data structures */ sqlite3VdbeOp3(v, OP_ParseSchema, p->iDb, 0, sqlite3MPrintf("tbl_name='%q'",p->zName), P3_DYNAMIC); } /* Add the table to the in-memory representation of the database. */ if( db->init.busy && pParse->nErr==0 ){ Table *pOld; FKey *pFKey; Db *pDb = &db->aDb[p->iDb]; pOld = sqlite3HashInsert(&pDb->tblHash, p->zName, strlen(p->zName)+1, p); if( pOld ){ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ return; } #ifndef SQLITE_OMIT_FOREIGN_KEY for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){ int nTo = strlen(pFKey->zTo) + 1; pFKey->pNextTo = sqlite3HashFind(&pDb->aFKey, pFKey->zTo, nTo); sqlite3HashInsert(&pDb->aFKey, pFKey->zTo, nTo, pFKey); } #endif pParse->pNewTable = 0; db->nTable++; db->flags |= SQLITE_InternChanges; } } #ifndef SQLITE_OMIT_VIEW /* ** The parser calls this routine in order to create a new VIEW */ |
︙ | ︙ | |||
1570 1571 1572 1573 1574 1575 1576 | ){ Table *p; int n; const unsigned char *z; Token sEnd; DbFixer sFix; Token *pName; | < < < < < < | < | < < < | | 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 | ){ Table *p; int n; const unsigned char *z; Token sEnd; DbFixer sFix; Token *pName; sqlite3StartTable(pParse, pBegin, pName1, pName2, isTemp, 1); p = pParse->pNewTable; if( p==0 || pParse->nErr ){ sqlite3SelectDelete(pSelect); return; } sqlite3TwoPartName(pParse, pName1, pName2, &pName); if( sqlite3FixInit(&sFix, pParse, p->iDb, "view", pName) && sqlite3FixSelect(&sFix, pSelect) ){ sqlite3SelectDelete(pSelect); return; } /* Make a copy of the entire SELECT statement that defines the view. ** This will force all the Expr.token.z values to be dynamically ** allocated rather than point to the input string - which means that ** they will persist after the current sqlite3_exec() call returns. */ p->pSelect = sqlite3SelectDup(pSelect); sqlite3SelectDelete(pSelect); if( !pParse->db->init.busy ){ sqlite3ViewGetColumnNames(pParse, p); } /* Locate the end of the CREATE VIEW statement. Make sEnd point to ** the end. */ sEnd = pParse->sLastToken; if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){ sEnd.z += sEnd.n; } sEnd.n = 0; n = sEnd.z - pBegin->z; z = (const unsigned char*)pBegin->z; while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; } sEnd.z = &z[n-1]; sEnd.n = 1; /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */ sqlite3EndTable(pParse, &sEnd, 0); return; } #endif /* SQLITE_OMIT_VIEW */ #ifndef SQLITE_OMIT_VIEW /* ** The Table structure pTable is really a VIEW. Fill in the names of |
︙ | ︙ | |||
1655 1656 1657 1658 1659 1660 1661 | ** ** CREATE VIEW one AS SELECT * FROM two; ** CREATE VIEW two AS SELECT * FROM one; ** ** Actually, this error is caught previously and so the following test ** should always fail. But we will leave it in place just to be safe. */ | < < < < | | | | | | | | | | | | | | | | | | < < < | < | < | < | | 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 | ** ** CREATE VIEW one AS SELECT * FROM two; ** CREATE VIEW two AS SELECT * FROM one; ** ** Actually, this error is caught previously and so the following test ** should always fail. But we will leave it in place just to be safe. */ if( pTable->nCol<0 ){ sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName); return 1; } /* If we get this far, it means we need to compute the table names. ** Note that the call to sqlite3ResultSetOfSelect() will expand any ** "*" elements in the results set of the view and will assign cursors ** to the elements of the FROM clause. But we do not want these changes ** to be permanent. So the computation is done on a copy of the SELECT ** statement that defines the view. */ assert( pTable->pSelect ); pSel = sqlite3SelectDup(pTable->pSelect); n = pParse->nTab; sqlite3SrcListAssignCursors(pParse, pSel->pSrc); pTable->nCol = -1; pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel); pParse->nTab = n; if( pSelTab ){ assert( pTable->aCol==0 ); pTable->nCol = pSelTab->nCol; pTable->aCol = pSelTab->aCol; pSelTab->nCol = 0; pSelTab->aCol = 0; sqlite3DeleteTable(0, pSelTab); DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews); }else{ pTable->nCol = 0; nErr++; } sqlite3SelectDelete(pSel); return nErr; } #endif /* SQLITE_OMIT_VIEW */ #ifndef SQLITE_OMIT_VIEW /* ** Clear the column names from every VIEW in database idx. */ static void sqliteViewResetAll(sqlite3 *db, int idx){ HashElem *i; if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); if( pTab->pSelect ){ sqliteResetColumnNames(pTab); } } DbClearProperty(db, idx, DB_UnresetViews); } #else # define sqliteViewResetAll(A,B) #endif /* SQLITE_OMIT_VIEW */ /* ** This function is called by the VDBE to adjust the internal schema ** used by SQLite when the btree layer moves a table root page. The ** root-page of a table or index in database iDb has changed from iFrom ** to iTo. */ #ifndef SQLITE_OMIT_AUTOVACUUM void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){ HashElem *pElem; for(pElem=sqliteHashFirst(&pDb->tblHash); pElem; pElem=sqliteHashNext(pElem)){ Table *pTab = sqliteHashData(pElem); if( pTab->tnum==iFrom ){ pTab->tnum = iTo; return; } } for(pElem=sqliteHashFirst(&pDb->idxHash); pElem; pElem=sqliteHashNext(pElem)){ Index *pIdx = sqliteHashData(pElem); if( pIdx->tnum==iFrom ){ pIdx->tnum = iTo; return; } } assert(0); |
︙ | ︙ | |||
1781 1782 1783 1784 1785 1786 1787 | ** Code to update the sqlite_master tables and internal schema definitions ** in case a root-page belonging to another table is moved by the btree layer ** is also added (this can happen with an auto-vacuum database). */ static void destroyTable(Parse *pParse, Table *pTab){ #ifdef SQLITE_OMIT_AUTOVACUUM Index *pIdx; | < | | | 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 | ** Code to update the sqlite_master tables and internal schema definitions ** in case a root-page belonging to another table is moved by the btree layer ** is also added (this can happen with an auto-vacuum database). */ static void destroyTable(Parse *pParse, Table *pTab){ #ifdef SQLITE_OMIT_AUTOVACUUM Index *pIdx; destroyRootPage(pParse, pTab->tnum, pTab->iDb); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ destroyRootPage(pParse, pIdx->tnum, pIdx->iDb); } #else /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM ** is not defined), then it is important to call OP_Destroy on the ** table and index root-pages in order, starting with the numerically ** largest root-page number. This guarantees that none of the root-pages ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the |
︙ | ︙ | |||
1815 1816 1817 1818 1819 1820 1821 | int iLargest = 0; if( iDestroyed==0 || iTab<iDestroyed ){ iLargest = iTab; } for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int iIdx = pIdx->tnum; | | | < < < | | < | < | < | < < < < < | | | | | | | 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 | int iLargest = 0; if( iDestroyed==0 || iTab<iDestroyed ){ iLargest = iTab; } for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int iIdx = pIdx->tnum; assert( pIdx->iDb==pTab->iDb ); if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){ iLargest = iIdx; } } if( iLargest==0 ) return; destroyRootPage(pParse, iLargest, pTab->iDb); iDestroyed = iLargest; } #endif } /* ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. */ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ Table *pTab; Vdbe *v; sqlite3 *db = pParse->db; int iDb; if( pParse->nErr || sqlite3_malloc_failed ) goto exit_drop_table; assert( pName->nSrc==1 ); pTab = sqlite3LocateTable(pParse, pName->a[0].zName, pName->a[0].zDatabase); if( pTab==0 ) goto exit_drop_table; iDb = pTab->iDb; assert( iDb>=0 && iDb<db->nDb ); #ifndef SQLITE_OMIT_AUTHORIZATION { int code; const char *zTab = SCHEMA_TABLE(pTab->iDb); const char *zDb = db->aDb[pTab->iDb].zName; if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ goto exit_drop_table; } if( isView ){ if( iDb==1 ){ code = SQLITE_DROP_TEMP_VIEW; }else{ code = SQLITE_DROP_VIEW; } }else{ if( iDb==1 ){ code = SQLITE_DROP_TEMP_TABLE; }else{ code = SQLITE_DROP_TABLE; } } if( sqlite3AuthCheck(pParse, code, pTab->zName, 0, zDb) ){ goto exit_drop_table; } if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ goto exit_drop_table; } } #endif if( pTab->readOnly || pTab==db->aDb[iDb].pSeqTab ){ sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); goto exit_drop_table; } #ifndef SQLITE_OMIT_VIEW /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used ** on a table. |
︙ | ︙ | |||
1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 | /* Generate code to remove the table from the master table ** on disk. */ v = sqlite3GetVdbe(pParse); if( v ){ Trigger *pTrigger; Db *pDb = &db->aDb[iDb]; sqlite3BeginWriteOperation(pParse, 0, iDb); /* Drop all triggers associated with the table being dropped. Code ** is generated to remove entries from sqlite_master and/or ** sqlite_temp_master if required. */ pTrigger = pTab->pTrigger; while( pTrigger ){ | > | < | 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 | /* Generate code to remove the table from the master table ** on disk. */ v = sqlite3GetVdbe(pParse); if( v ){ Trigger *pTrigger; int iDb = pTab->iDb; Db *pDb = &db->aDb[iDb]; sqlite3BeginWriteOperation(pParse, 0, iDb); /* Drop all triggers associated with the table being dropped. Code ** is generated to remove entries from sqlite_master and/or ** sqlite_temp_master if required. */ pTrigger = pTab->pTrigger; while( pTrigger ){ assert( pTrigger->iDb==iDb || pTrigger->iDb==1 ); sqlite3DropTriggerPtr(pParse, pTrigger, 1); pTrigger = pTrigger->pNext; } #ifndef SQLITE_OMIT_AUTOINCREMENT /* Remove any entries of the sqlite_sequence table associated with ** the table being dropped. This is done before the table is dropped |
︙ | ︙ | |||
2115 2116 2117 2118 2119 2120 2121 | static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ Table *pTab = pIndex->pTable; /* The table that is indexed */ int iTab = pParse->nTab; /* Btree cursor used for pTab */ int iIdx = pParse->nTab+1; /* Btree cursor used for pIndex */ int addr1; /* Address of top of loop */ int tnum; /* Root page of index */ Vdbe *v; /* Generate code into this virtual machine */ | | < | | > > > | > > | | < | > > | > | < < < < | | < | < < | | 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 | static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ Table *pTab = pIndex->pTable; /* The table that is indexed */ int iTab = pParse->nTab; /* Btree cursor used for pTab */ int iIdx = pParse->nTab+1; /* Btree cursor used for pIndex */ int addr1; /* Address of top of loop */ int tnum; /* Root page of index */ Vdbe *v; /* Generate code into this virtual machine */ int isUnique; /* True for a unique index */ #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, pParse->db->aDb[pIndex->iDb].zName ) ){ return; } #endif /* Ensure all the required collation sequences are available. This ** routine will invoke the collation-needed callback if necessary (and ** if one has been registered). */ if( sqlite3CheckIndexCollSeq(pParse, pIndex) ){ return; } v = sqlite3GetVdbe(pParse); if( v==0 ) return; if( memRootPage>=0 ){ sqlite3VdbeAddOp(v, OP_MemLoad, memRootPage, 0); tnum = 0; }else{ tnum = pIndex->tnum; sqlite3VdbeAddOp(v, OP_Clear, tnum, pIndex->iDb); } sqlite3VdbeAddOp(v, OP_Integer, pIndex->iDb, 0); sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum, (char*)&pIndex->keyInfo, P3_KEYINFO); sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqlite3VdbeAddOp(v, OP_OpenRead, iTab, pTab->tnum); sqlite3VdbeAddOp(v, OP_SetNumColumns, iTab, pTab->nCol); addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0); sqlite3GenerateIndexKey(v, pIndex, iTab); isUnique = pIndex->onError!=OE_None; sqlite3VdbeAddOp(v, OP_IdxPut, iIdx, isUnique); if( isUnique ){ sqlite3VdbeChangeP3(v, -1, "indexed columns are not unique", P3_STATIC); } sqlite3VdbeAddOp(v, OP_Next, iTab, addr1+1); sqlite3VdbeChangeP2(v, addr1, sqlite3VdbeCurrentAddr(v)); sqlite3VdbeAddOp(v, OP_Close, iTab, 0); sqlite3VdbeAddOp(v, OP_Close, iIdx, 0); } /* ** Create a new index for an SQL table. pName1.pName2 is the name of the index ** and pTblList is the name of the table that is to be indexed. Both will |
︙ | ︙ | |||
2181 2182 2183 2184 2185 2186 2187 | Parse *pParse, /* All information about this parse */ Token *pName1, /* First part of index name. May be NULL */ Token *pName2, /* Second part of index name. May be NULL */ SrcList *pTblName, /* Table to index. Use pParse->pNewTable if 0 */ ExprList *pList, /* A list of columns to be indexed */ int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */ | | < < | | | < | | < > | | | < < < < < | < < | < | < < | | < | < > | 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 | Parse *pParse, /* All information about this parse */ Token *pName1, /* First part of index name. May be NULL */ Token *pName2, /* Second part of index name. May be NULL */ SrcList *pTblName, /* Table to index. Use pParse->pNewTable if 0 */ ExprList *pList, /* A list of columns to be indexed */ int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */ Token *pEnd /* The ")" that closes the CREATE INDEX statement */ ){ Table *pTab = 0; /* Table to be indexed */ Index *pIndex = 0; /* The index to be created */ char *zName = 0; int i, j; Token nullId; /* Fake token for an empty ID list */ DbFixer sFix; /* For assigning database names to pTable */ int isTemp; /* True for a temporary index */ sqlite3 *db = pParse->db; int iDb; /* Index of the database that is being written */ Token *pName = 0; /* Unqualified name of the index to create */ if( pParse->nErr || sqlite3_malloc_failed ) goto exit_create_index; /* ** Find the table that is to be indexed. Return early if not found. */ if( pTblName!=0 ){ /* Use the two-part index name to determine the database ** to search for the table. 'Fix' the table name to this db ** before looking up the table. */ assert( pName1 && pName2 ); iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); if( iDb<0 ) goto exit_create_index; /* If the index name was unqualified, check if the the table ** is a temp table. If so, set the database to 1. */ pTab = sqlite3SrcListLookup(pParse, pTblName); if( pName2 && pName2->n==0 && pTab && pTab->iDb==1 ){ iDb = 1; } if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) && sqlite3FixSrcList(&sFix, pTblName) ){ goto exit_create_index; } pTab = sqlite3LocateTable(pParse, pTblName->a[0].zName, pTblName->a[0].zDatabase); if( !pTab ) goto exit_create_index; assert( iDb==pTab->iDb ); }else{ assert( pName==0 ); pTab = pParse->pNewTable; iDb = pTab->iDb; } if( pTab==0 || pParse->nErr ) goto exit_create_index; if( pTab->readOnly ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; } #ifndef SQLITE_OMIT_VIEW if( pTab->pSelect ){ sqlite3ErrorMsg(pParse, "views may not be indexed"); goto exit_create_index; } #endif isTemp = pTab->iDb==1; /* ** Find the name of the index. Make sure there is not already another ** index or table with the same name. ** ** Exception: If we are reading the names of permanent indices from the ** sqlite_master table (because some other process changed the schema) and |
︙ | ︙ | |||
2281 2282 2283 2284 2285 2286 2287 2288 | zName = sqlite3NameFromToken(pName); if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; if( zName==0 ) goto exit_create_index; if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto exit_create_index; } if( !db->init.busy ){ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; | > > | < | < | | | | | | < < < < < < < < < < < < < | < | < < < < < < | | < < < | < < | < < < < < < < | < < < < < | | | | | < | < | < < | < > | > > < < < | | 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 | zName = sqlite3NameFromToken(pName); if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; if( zName==0 ) goto exit_create_index; if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto exit_create_index; } if( !db->init.busy ){ Index *pISameName; /* Another index with the same name */ Table *pTSameName; /* A table with same name as the index */ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; if( (pISameName = sqlite3FindIndex(db, zName, db->aDb[iDb].zName))!=0 ){ sqlite3ErrorMsg(pParse, "index %s already exists", zName); goto exit_create_index; } if( (pTSameName = sqlite3FindTable(db, zName, 0))!=0 ){ sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); goto exit_create_index; } } }else{ char zBuf[30]; int n; Index *pLoop; for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){} sprintf(zBuf,"_%d",n); zName = 0; sqlite3SetString(&zName, "sqlite_autoindex_", pTab->zName, zBuf, (char*)0); if( zName==0 ) goto exit_create_index; } /* Check for authorization to create an index. */ #ifndef SQLITE_OMIT_AUTHORIZATION { const char *zDb = db->aDb[pTab->iDb].zName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ goto exit_create_index; } i = SQLITE_CREATE_INDEX; if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX; if( sqlite3AuthCheck(pParse, i, zName, pTab->zName, zDb) ){ goto exit_create_index; } } #endif /* If pList==0, it means this routine was called to make a primary ** key out of the last column added to the table under construction. ** So create a fake list to simulate this. */ if( pList==0 ){ nullId.z = pTab->aCol[pTab->nCol-1].zName; nullId.n = strlen(nullId.z); pList = sqlite3ExprListAppend(0, 0, &nullId); if( pList==0 ) goto exit_create_index; } /* ** Allocate the index structure. */ pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 + (sizeof(int) + sizeof(CollSeq*))*pList->nExpr ); if( pIndex==0 ) goto exit_create_index; pIndex->aiColumn = (int*)&pIndex->keyInfo.aColl[pList->nExpr]; pIndex->zName = (char*)&pIndex->aiColumn[pList->nExpr]; strcpy(pIndex->zName, zName); pIndex->pTable = pTab; pIndex->nColumn = pList->nExpr; pIndex->onError = onError; pIndex->autoIndex = pName==0; pIndex->iDb = iDb; /* Scan the names of the columns of the table to be indexed and ** load the column indices into the Index structure. Report an error ** if any column is not found. */ for(i=0; i<pList->nExpr; i++){ for(j=0; j<pTab->nCol; j++){ if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break; } if( j>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "table %s has no column named %s", pTab->zName, pList->a[i].zName); goto exit_create_index; } pIndex->aiColumn[i] = j; if( pList->a[i].pExpr ){ assert( pList->a[i].pExpr->pColl ); pIndex->keyInfo.aColl[i] = pList->a[i].pExpr->pColl; }else{ pIndex->keyInfo.aColl[i] = pTab->aCol[j].pColl; } assert( pIndex->keyInfo.aColl[i] ); if( !db->init.busy && sqlite3CheckCollSeq(pParse, pIndex->keyInfo.aColl[i]) ){ goto exit_create_index; } } pIndex->keyInfo.nField = pList->nExpr; if( pTab==pParse->pNewTable ){ /* This routine has been called to create an automatic index as a ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or ** a PRIMARY KEY or UNIQUE clause following the column definitions. ** i.e. one of: ** |
︙ | ︙ | |||
2440 2441 2442 2443 2444 2445 2446 | int k; assert( pIdx->onError!=OE_None ); assert( pIdx->autoIndex ); assert( pIndex->onError!=OE_None ); if( pIdx->nColumn!=pIndex->nColumn ) continue; for(k=0; k<pIdx->nColumn; k++){ | < < | < | 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 | int k; assert( pIdx->onError!=OE_None ); assert( pIdx->autoIndex ); assert( pIndex->onError!=OE_None ); if( pIdx->nColumn!=pIndex->nColumn ) continue; for(k=0; k<pIdx->nColumn; k++){ if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break; if( pIdx->keyInfo.aColl[k]!=pIndex->keyInfo.aColl[k] ) break; } if( k==pIdx->nColumn ){ if( pIdx->onError!=pIndex->onError ){ /* This constraint creates the same index as a previous ** constraint specified somewhere in the CREATE TABLE statement. ** However the ON CONFLICT clauses are different. If both this ** constraint and the previous equivalent constraint have explicit |
︙ | ︙ | |||
2473 2474 2475 2476 2477 2478 2479 | } /* Link the new Index structure to its table and to the other ** in-memory database structures. */ if( db->init.busy ){ Index *p; | | | 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 | } /* Link the new Index structure to its table and to the other ** in-memory database structures. */ if( db->init.busy ){ Index *p; p = sqlite3HashInsert(&db->aDb[pIndex->iDb].idxHash, pIndex->zName, strlen(pIndex->zName)+1, pIndex); if( p ){ assert( p==pIndex ); /* Malloc must have failed */ goto exit_create_index; } db->flags |= SQLITE_InternChanges; if( pTblName!=0 ){ |
︙ | ︙ | |||
2508 2509 2510 2511 2512 2513 2514 | Vdbe *v; char *zStmt; int iMem = pParse->nMem++; v = sqlite3GetVdbe(pParse); if( v==0 ) goto exit_create_index; | < | | 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 | Vdbe *v; char *zStmt; int iMem = pParse->nMem++; v = sqlite3GetVdbe(pParse); if( v==0 ) goto exit_create_index; /* Create the rootpage for the index */ sqlite3BeginWriteOperation(pParse, 1, iDb); sqlite3VdbeAddOp(v, OP_CreateIndex, iDb, 0); sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0); /* Gather the complete text of the CREATE INDEX statement into ** the zStmt variable */ if( pStart && pEnd ){ /* A named index with an explicit CREATE INDEX statement */ zStmt = sqlite3MPrintf("CREATE%s INDEX %.*s", onError==OE_None ? "" : " UNIQUE", Addr(pEnd->z) - Addr(pName->z) + 1, pName->z); }else{ /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */ /* zStmt = sqlite3MPrintf(""); */ zStmt = 0; } |
︙ | ︙ | |||
2586 2587 2588 2589 2590 2591 2592 2593 | } sqlite3ExprListDelete(pList); sqlite3SrcListDelete(pTblName); sqliteFree(zName); return; } /* | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | < < | < < < | < < | | | > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > > | | | | | | < | | < < < < < < < < < < < < | < < < < < < < | < < | | 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 | } sqlite3ExprListDelete(pList); sqlite3SrcListDelete(pTblName); sqliteFree(zName); return; } /* ** This routine will drop an existing named index. This routine ** implements the DROP INDEX statement. */ void sqlite3DropIndex(Parse *pParse, SrcList *pName){ Index *pIndex; Vdbe *v; sqlite3 *db = pParse->db; if( pParse->nErr || sqlite3_malloc_failed ) return; assert( pName->nSrc==1 ); if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) return; pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); if( pIndex==0 ){ sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0); pParse->checkSchema = 1; goto exit_drop_index; } if( pIndex->autoIndex ){ sqlite3ErrorMsg(pParse, "index associated with UNIQUE " "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_INDEX; Table *pTab = pIndex->pTable; const char *zDb = db->aDb[pIndex->iDb].zName; const char *zTab = SCHEMA_TABLE(pIndex->iDb); if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ goto exit_drop_index; } if( pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX; if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ goto exit_drop_index; } } #endif /* Generate code to remove the index and from the master table */ v = sqlite3GetVdbe(pParse); if( v ){ int iDb = pIndex->iDb; sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q", db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName ); sqlite3ChangeCookie(db, v, iDb); destroyRootPage(pParse, pIndex->tnum, iDb); sqlite3VdbeOp3(v, OP_DropIndex, iDb, 0, pIndex->zName, 0); } exit_drop_index: sqlite3SrcListDelete(pName); } /* ** Append a new element to the given IdList. Create a new IdList if ** need be. ** ** A new IdList is returned, or NULL if malloc() fails. */ IdList *sqlite3IdListAppend(IdList *pList, Token *pToken){ if( pList==0 ){ pList = sqliteMalloc( sizeof(IdList) ); if( pList==0 ) return 0; pList->nAlloc = 0; } if( pList->nId>=pList->nAlloc ){ struct IdList_item *a; pList->nAlloc = pList->nAlloc*2 + 5; a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) ); if( a==0 ){ sqlite3IdListDelete(pList); return 0; } pList->a = a; } memset(&pList->a[pList->nId], 0, sizeof(pList->a[0])); pList->a[pList->nId].zName = sqlite3NameFromToken(pToken); pList->nId++; return pList; } /* ** Append a new table name to the given SrcList. Create a new SrcList if ** need be. A new entry is created in the SrcList even if pToken is NULL. ** ** A new SrcList is returned, or NULL if malloc() fails. |
︙ | ︙ | |||
2852 2853 2854 2855 2856 2857 2858 | /* ** Assign cursors to all tables in a SrcList */ void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ int i; struct SrcList_item *pItem; | < < | | | | | < > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | | | 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 | /* ** Assign cursors to all tables in a SrcList */ void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ int i; struct SrcList_item *pItem; for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ if( pItem->iCursor>=0 ) break; pItem->iCursor = pParse->nTab++; if( pItem->pSelect ){ sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc); } } } /* ** Add an alias to the last identifier on the given identifier list. */ void sqlite3SrcListAddAlias(SrcList *pList, Token *pToken){ if( pList && pList->nSrc>0 ){ pList->a[pList->nSrc-1].zAlias = sqlite3NameFromToken(pToken); } } /* ** Delete an IdList. */ void sqlite3IdListDelete(IdList *pList){ int i; if( pList==0 ) return; for(i=0; i<pList->nId; i++){ sqliteFree(pList->a[i].zName); } sqliteFree(pList->a); sqliteFree(pList); } /* ** Return the index in pList of the identifier named zId. Return -1 ** if not found. */ int sqlite3IdListIndex(IdList *pList, const char *zName){ int i; if( pList==0 ) return -1; for(i=0; i<pList->nId; i++){ if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i; } return -1; } /* ** Delete an entire SrcList including all its substructure. */ void sqlite3SrcListDelete(SrcList *pList){ int i; struct SrcList_item *pItem; if( pList==0 ) return; for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){ sqliteFree(pItem->zDatabase); sqliteFree(pItem->zName); sqliteFree(pItem->zAlias); if( pItem->pTab && pItem->pTab->isTransient ){ sqlite3DeleteTable(0, pItem->pTab); } sqlite3SelectDelete(pItem->pSelect); sqlite3ExprDelete(pItem->pOn); sqlite3IdListDelete(pItem->pUsing); } sqliteFree(pList); } /* ** Begin a transaction */ void sqlite3BeginTransaction(Parse *pParse, int type){ sqlite3 *db; Vdbe *v; int i; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; if( pParse->nErr || sqlite3_malloc_failed ) return; if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; v = sqlite3GetVdbe(pParse); if( !v ) return; if( type!=TK_DEFERRED ){ for(i=0; i<db->nDb; i++){ sqlite3VdbeAddOp(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); } } sqlite3VdbeAddOp(v, OP_AutoCommit, 0, 0); } /* ** Commit a transaction */ void sqlite3CommitTransaction(Parse *pParse){ sqlite3 *db; Vdbe *v; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; if( pParse->nErr || sqlite3_malloc_failed ) return; if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp(v, OP_AutoCommit, 1, 0); } } /* ** Rollback a transaction */ void sqlite3RollbackTransaction(Parse *pParse){ sqlite3 *db; Vdbe *v; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; if( pParse->nErr || sqlite3_malloc_failed ) return; if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp(v, OP_AutoCommit, 1, 1); } } |
︙ | ︙ | |||
2971 2972 2973 2974 2975 2976 2977 | if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "unable to get a write lock on " "the temporary database file"); pParse->rc = rc; return 1; } } | < | 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 | if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "unable to get a write lock on " "the temporary database file"); pParse->rc = rc; return 1; } } } return 0; } /* ** Generate VDBE code that will verify the schema cookie and start ** a read-transaction for all named database files. |
︙ | ︙ | |||
3016 3017 3018 3019 3020 3021 3022 | if( iDb>=0 ){ assert( iDb<db->nDb ); assert( db->aDb[iDb].pBt!=0 || iDb==1 ); assert( iDb<32 ); mask = 1<<iDb; if( (pParse->cookieMask & mask)==0 ){ pParse->cookieMask |= mask; | | | | 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 | if( iDb>=0 ){ assert( iDb<db->nDb ); assert( db->aDb[iDb].pBt!=0 || iDb==1 ); assert( iDb<32 ); mask = 1<<iDb; if( (pParse->cookieMask & mask)==0 ){ pParse->cookieMask |= mask; pParse->cookieValue[iDb] = db->aDb[iDb].schema_cookie; if( iDb==1 ){ sqlite3OpenTempDatabase(pParse); } } } } /* |
︙ | ︙ | |||
3050 3051 3052 3053 3054 3055 3056 | Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return; sqlite3CodeVerifySchema(pParse, iDb); pParse->writeMask |= 1<<iDb; if( setStatement && pParse->nested==0 ){ sqlite3VdbeAddOp(v, OP_Statement, iDb, 0); } | | > > > > > > > > > > > > > | < | | < > | < > | | < | | | | | 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 | Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return; sqlite3CodeVerifySchema(pParse, iDb); pParse->writeMask |= 1<<iDb; if( setStatement && pParse->nested==0 ){ sqlite3VdbeAddOp(v, OP_Statement, iDb, 0); } if( iDb!=1 && pParse->db->aDb[1].pBt!=0 ){ sqlite3BeginWriteOperation(pParse, setStatement, 1); } } #ifndef SQLITE_OMIT_UTF16 /* ** Return the transient sqlite3_value object used for encoding conversions ** during SQL compilation. */ sqlite3_value *sqlite3GetTransientValue(sqlite3 *db){ if( !db->pValue ){ db->pValue = sqlite3ValueNew(); } return db->pValue; } #endif /* ** Check to see if pIndex uses the collating sequence pColl. Return ** true if it does and false if it does not. */ #ifndef SQLITE_OMIT_REINDEX static int collationMatch(CollSeq *pColl, Index *pIndex){ int n = pIndex->keyInfo.nField; CollSeq **pp = pIndex->keyInfo.aColl; while( n-- ){ if( *pp==pColl ) return 1; pp++; } return 0; } #endif /* ** Recompute all indices of pTab that use the collating sequence pColl. ** If pColl==0 then recompute all indices of pTab. */ #ifndef SQLITE_OMIT_REINDEX void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){ Index *pIndex; /* An index associated with pTab */ for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ if( pColl==0 || collationMatch(pColl,pIndex) ){ sqlite3BeginWriteOperation(pParse, 0, pTab->iDb); sqlite3RefillIndex(pParse, pIndex, -1); } } } #endif /* ** Recompute all indices of all tables in all databases where the ** indices use the collating sequence pColl. If pColl==0 then recompute ** all indices everywhere. */ #ifndef SQLITE_OMIT_REINDEX void reindexDatabases(Parse *pParse, CollSeq *pColl){ Db *pDb; /* A single database */ int iDb; /* The database index number */ sqlite3 *db = pParse->db; /* The database connection */ HashElem *k; /* For looping over tables in pDb */ Table *pTab; /* A table in the database */ for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){ if( pDb==0 ) continue; for(k=sqliteHashFirst(&pDb->tblHash); k; k=sqliteHashNext(k)){ pTab = (Table*)sqliteHashData(k); reindexTable(pParse, pTab, pColl); } } } #endif /* ** Generate code for the REINDEX command. |
︙ | ︙ | |||
3147 3148 3149 3150 3151 3152 3153 | return; } if( pName1==0 || pName1->z==0 ){ reindexDatabases(pParse, 0); return; }else if( pName2==0 || pName2->z==0 ){ | < | < < | < < | 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 | return; } if( pName1==0 || pName1->z==0 ){ reindexDatabases(pParse, 0); return; }else if( pName2==0 || pName2->z==0 ){ pColl = sqlite3FindCollSeq(db, db->enc, pName1->z, pName1->n, 0); if( pColl ){ reindexDatabases(pParse, pColl); return; } } iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); if( iDb<0 ) return; z = sqlite3NameFromToken(pObjName); zDb = db->aDb[iDb].zName; |
︙ | ︙ | |||
3178 3179 3180 3181 3182 3183 3184 | sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3RefillIndex(pParse, pIndex, -1); return; } sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed"); } #endif | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 3003 3004 3005 3006 3007 3008 3009 | sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3RefillIndex(pParse, pIndex, -1); return; } sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed"); } #endif |
Deleted SQLite.Interop/src/callback.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted SQLite.Interop/src/complete.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Added SQLite.Interop/src/config.h.
> | 1 | #define SQLITE_PTR_SZ 4 |
Changes to SQLite.Interop/src/date.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This file contains the C functions that implement date and time ** functions for SQLite. ** ** There is only one exported symbol in this file - the function ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This file contains the C functions that implement date and time ** functions for SQLite. ** ** There is only one exported symbol in this file - the function ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: date.c,v 1.1 2005/03/01 16:04:28 rmsimpson Exp $ ** ** NOTES: ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon ** in Greenwich on November 24, 4714 B.C. according to the Gregorian ** calendar system. |
︙ | ︙ | |||
101 102 103 104 105 106 107 | min = va_arg(ap, int); max = va_arg(ap, int); nextC = va_arg(ap, int); pVal = va_arg(ap, int*); val = 0; while( N-- ){ if( !isdigit(*(u8*)zDate) ){ | | | < < > > | > > | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | min = va_arg(ap, int); max = va_arg(ap, int); nextC = va_arg(ap, int); pVal = va_arg(ap, int*); val = 0; while( N-- ){ if( !isdigit(*(u8*)zDate) ){ return cnt; } val = val*10 + *zDate - '0'; zDate++; } if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){ return cnt; } *pVal = val; zDate++; cnt++; }while( nextC ); return cnt; } /* ** Read text from z[] and convert into a floating point number. Return ** the number of digits converted. */ static int getValue(const char *z, double *pR){ const char *zEnd; *pR = sqlite3AtoF(z, &zEnd); return zEnd - z; } /* ** Parse a timezone extension on the end of a date-time. ** The extension is of the form: ** ** (+/-)HH:MM ** |
︙ | ︙ | |||
234 235 236 237 238 239 240 | X2 = 30.6001*(M+1); p->rJD = X1 + X2 + D + B - 1524.5; p->validJD = 1; p->validYMD = 0; if( p->validHMS ){ p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0; if( p->validTZ ){ | | | 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | X2 = 30.6001*(M+1); p->rJD = X1 + X2 + D + B - 1524.5; p->validJD = 1; p->validYMD = 0; if( p->validHMS ){ p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0; if( p->validTZ ){ p->rJD += p->tz*60/86400.0; p->validHMS = 0; p->validTZ = 0; } } } /* |
︙ | ︙ | |||
266 267 268 269 270 271 272 | }else{ neg = 0; } if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){ return 1; } zDate += 10; | | | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | }else{ neg = 0; } if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){ return 1; } zDate += 10; while( isspace(*(u8*)zDate) ){ zDate++; } if( parseHhMmSs(zDate, p)==0 ){ /* We got the time */ }else if( *zDate==0 ){ p->validHMS = 0; }else{ return 1; } |
︙ | ︙ | |||
314 315 316 317 318 319 320 | }else if( sqlite3StrICmp(zDate,"now")==0){ double r; sqlite3OsCurrentTime(&r); p->rJD = r; p->validJD = 1; return 0; }else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){ | | | 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | }else if( sqlite3StrICmp(zDate,"now")==0){ double r; sqlite3OsCurrentTime(&r); p->rJD = r; p->validJD = 1; return 0; }else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){ p->rJD = sqlite3AtoF(zDate, 0); p->validJD = 1; return 0; } return 1; } /* |
︙ | ︙ | |||
637 638 639 640 641 642 643 | ** the resulting time into the DateTime structure p. Return 0 ** on success and 1 if there are any errors. */ static int isDate(int argc, sqlite3_value **argv, DateTime *p){ int i; if( argc==0 ) return 1; if( SQLITE_NULL==sqlite3_value_type(argv[0]) || | | | | 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 | ** the resulting time into the DateTime structure p. Return 0 ** on success and 1 if there are any errors. */ static int isDate(int argc, sqlite3_value **argv, DateTime *p){ int i; if( argc==0 ) return 1; if( SQLITE_NULL==sqlite3_value_type(argv[0]) || parseDateOrTime(sqlite3_value_text(argv[0]), p) ) return 1; for(i=1; i<argc; i++){ if( SQLITE_NULL==sqlite3_value_type(argv[i]) || parseModifier(sqlite3_value_text(argv[i]), p) ) return 1; } return 0; } /* ** The following routines implement the various date and time functions |
︙ | ︙ | |||
753 754 755 756 757 758 759 | sqlite3_context *context, int argc, sqlite3_value **argv ){ DateTime x; int n, i, j; char *z; | | | 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 | sqlite3_context *context, int argc, sqlite3_value **argv ){ DateTime x; int n, i, j; char *z; const char *zFmt = sqlite3_value_text(argv[0]); char zBuf[100]; if( zFmt==0 || isDate(argc-1, argv+1, &x) ) return; for(i=0, n=1; zFmt[i]; i++, n++){ if( zFmt[i]=='%' ){ switch( zFmt[i+1] ){ case 'd': case 'H': |
︙ | ︙ |
Changes to SQLite.Interop/src/delete.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** | | < < < < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** ** $Id: delete.c,v 1.1 2005/03/01 16:04:29 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Look up every table that is named in pSrc. If any table is not found, ** add an error message to pParse->zErrMsg and return NULL. If all tables ** are found, return a pointer to the last table. */ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ Table *pTab = 0; int i; struct SrcList_item *pItem; for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){ pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase); pItem->pTab = pTab; } return pTab; } /* ** Check to make sure the given table is writable. If it is not ** writable, generate an error message and return 1. If it is |
︙ | ︙ | |||
55 56 57 58 59 60 61 | #endif return 0; } /* ** Generate code that will open a table for reading. */ | | | < | < < < < | > < | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | #endif return 0; } /* ** Generate code that will open a table for reading. */ void sqlite3OpenTableForReading( Vdbe *v, /* Generate code into this VDBE */ int iCur, /* The cursor number of the table */ Table *pTab /* The table to be opened */ ){ sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum); VdbeComment((v, "# %s", pTab->zName)); sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol); } /* ** Generate code for a DELETE FROM statement. ** |
︙ | ︙ | |||
96 97 98 99 100 101 102 | WhereInfo *pWInfo; /* Information about the WHERE clause */ Index *pIdx; /* For looping over indices of the table */ int iCur; /* VDBE Cursor number for pTab */ sqlite3 *db; /* Main database structure */ AuthContext sContext; /* Authorization context */ int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */ NameContext sNC; /* Name context to resolve expressions in */ | < | > | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | WhereInfo *pWInfo; /* Information about the WHERE clause */ Index *pIdx; /* For looping over indices of the table */ int iCur; /* VDBE Cursor number for pTab */ sqlite3 *db; /* Main database structure */ AuthContext sContext; /* Authorization context */ int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */ NameContext sNC; /* Name context to resolve expressions in */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ int triggers_exist = 0; /* True if any triggers exist */ #endif sContext.pParse = 0; if( pParse->nErr || sqlite3_malloc_failed ){ pTabList = 0; goto delete_from_cleanup; } db = pParse->db; assert( pTabList->nSrc==1 ); /* Locate the table which we want to delete. This table has to be ** put in an SrcList structure because some of the subroutines we |
︙ | ︙ | |||
136 137 138 139 140 141 142 | # undef isView # define isView 0 #endif if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ goto delete_from_cleanup; } | < | | | 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | # undef isView # define isView 0 #endif if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ goto delete_from_cleanup; } assert( pTab->iDb<db->nDb ); zDb = db->aDb[pTab->iDb].zName; if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ goto delete_from_cleanup; } /* If pTab is really a view, make sure it has been initialized. */ if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){ |
︙ | ︙ | |||
179 180 181 182 183 184 185 | /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ){ goto delete_from_cleanup; } if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); | | | | | | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ){ goto delete_from_cleanup; } if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, triggers_exist, pTab->iDb); /* If we are trying to delete from a view, construct that view into ** a temporary table. */ if( isView ){ Select *pView = sqlite3SelectDup(pTab->pSelect); sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0); sqlite3SelectDelete(pView); } /* Initialize the counter of the number of rows deleted, if ** we are counting rows. */ if( db->flags & SQLITE_CountRows ){ |
︙ | ︙ | |||
208 209 210 211 212 213 214 | if( pWhere==0 && !triggers_exist ){ if( db->flags & SQLITE_CountRows ){ /* If counting rows deleted, just count the total number of ** entries in the table. */ int endOfLoop = sqlite3VdbeMakeLabel(v); int addr; if( !isView ){ | | | < < < < | > > > > > > > | | | > | < | > | | | | | | | > | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | if( pWhere==0 && !triggers_exist ){ if( db->flags & SQLITE_CountRows ){ /* If counting rows deleted, just count the total number of ** entries in the table. */ int endOfLoop = sqlite3VdbeMakeLabel(v); int addr; if( !isView ){ sqlite3OpenTableForReading(v, iCur, pTab); } sqlite3VdbeAddOp(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2); addr = sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); sqlite3VdbeAddOp(v, OP_Next, iCur, addr); sqlite3VdbeResolveLabel(v, endOfLoop); sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } if( !isView ){ sqlite3VdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb); } } } /* The usual case: There is a WHERE clause so we have to scan through ** the table and pick which records to delete. */ else{ /* Ensure all required collation sequences are available. */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){ goto delete_from_cleanup; } } /* Begin the database scan */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0); if( pWInfo==0 ) goto delete_from_cleanup; /* Remember the rowid of every item to be deleted. */ sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0); if( db->flags & SQLITE_CountRows ){ sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); } /* End the database scan loop. */ sqlite3WhereEnd(pWInfo); /* Open the pseudo-table used to store OLD if there are triggers. */ if( triggers_exist ){ sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol); } /* Delete every item whose key was written to the list during the ** database scan. We have to delete items after the scan is complete ** because deleting an item can change the scan order. */ sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0); end = sqlite3VdbeMakeLabel(v); /* This is the beginning of the delete loop when there are ** row triggers. */ if( triggers_exist ){ addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); if( !isView ){ sqlite3OpenTableForReading(v, iCur, pTab); } sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); sqlite3VdbeAddOp(v, OP_RowData, iCur, 0); sqlite3VdbeAddOp(v, OP_PutIntKey, oldIdx, 0); if( !isView ){ sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab, -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, addr); } if( !isView ){ /* Open cursors for the table we are deleting from and all its ** indices. If there are row triggers, this happens inside the ** OP_ListRead loop because the cursor have to all be closed ** before the trigger fires. If there are no row triggers, the ** cursors are opened only once on the outside the loop. */ sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite); /* This is the beginning of the delete loop when there are no ** row triggers */ if( !triggers_exist ){ addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end); } /* Delete the row */ sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0); } /* If there are row triggers, close all cursors then invoke ** the AFTER triggers */ if( triggers_exist ){ if( !isView ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, addr); } /* End of the delete loop */ sqlite3VdbeAddOp(v, OP_Goto, 0, addr); sqlite3VdbeResolveLabel(v, end); sqlite3VdbeAddOp(v, OP_ListReset, 0, 0); /* Close the cursors after the loop if there are no row triggers */ if( !triggers_exist ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } sqlite3VdbeAddOp(v, OP_Close, iCur, 0); |
︙ | ︙ | |||
380 381 382 383 384 385 386 | int iCur, /* Cursor number for the table */ int count /* Increment the row change counter */ ){ int addr; addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0); sqlite3GenerateRowIndexDelete(db, v, pTab, iCur, 0); sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); | < | < < | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | int iCur, /* Cursor number for the table */ int count /* Increment the row change counter */ ){ int addr; addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0); sqlite3GenerateRowIndexDelete(db, v, pTab, iCur, 0); sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v)); } /* ** This routine generates VDBE code that causes the deletion of all ** index entries associated with a single row of a single table. ** ** The VDBE must be in a particular state when this routine is called. |
︙ | ︙ | |||
433 434 435 436 437 438 439 | Vdbe *v, /* Generate code into this VDBE */ Index *pIdx, /* The index for which to generate a key */ int iCur /* Cursor number for the pIdx->pTable table */ ){ int j; Table *pTab = pIdx->pTable; | | < | | 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 | Vdbe *v, /* Generate code into this VDBE */ Index *pIdx, /* The index for which to generate a key */ int iCur /* Cursor number for the pIdx->pTable table */ ){ int j; Table *pTab = pIdx->pTable; sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); for(j=0; j<pIdx->nColumn; j++){ int idx = pIdx->aiColumn[j]; if( idx==pTab->iPKey ){ sqlite3VdbeAddOp(v, OP_Dup, j, 0); }else{ sqlite3VdbeAddOp(v, OP_Column, iCur, idx); } } sqlite3VdbeAddOp(v, OP_MakeRecord, pIdx->nColumn, (1<<24)); sqlite3IndexAffinityStr(v, pIdx); } |
Deleted SQLite.Interop/src/experimental.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to SQLite.Interop/src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.1 2005/03/01 16:04:29 rmsimpson Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
30 31 32 33 34 35 36 | ** ** CREATE TABLE t1(a); ** SELECT * FROM t1 WHERE a; ** SELECT a AS b FROM t1 WHERE b; ** SELECT * FROM t1 WHERE (select a from t1); */ char sqlite3ExprAffinity(Expr *pExpr){ | < | | < < < < < | | | | > > > < | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | ** ** CREATE TABLE t1(a); ** SELECT * FROM t1 WHERE a; ** SELECT a AS b FROM t1 WHERE b; ** SELECT * FROM t1 WHERE (select a from t1); */ char sqlite3ExprAffinity(Expr *pExpr){ if( pExpr->op==TK_AS ){ return sqlite3ExprAffinity(pExpr->pLeft); } if( pExpr->op==TK_SELECT ){ return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].pExpr); } return pExpr->affinity; } /* ** Return the default collation sequence for the expression pExpr. If ** there is no default collation type, return 0. */ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ CollSeq *pColl = 0; if( pExpr ){ pColl = pExpr->pColl; if( pExpr->op==TK_AS && !pColl ){ return sqlite3ExprCollSeq(pParse, pExpr->pLeft); } } if( sqlite3CheckCollSeq(pParse, pColl) ){ pColl = 0; } return pColl; } /* ** pExpr is an operand of a comparison operator. aff2 is the ** type affinity of the other operand. This routine returns the ** type affinity that should be used for the comparison operator. */ char sqlite3CompareAffinity(Expr *pExpr, char aff2){ char aff1 = sqlite3ExprAffinity(pExpr); if( aff1 && aff2 ){ /* Both sides of the comparison are columns. If one has numeric or ** integer affinity, use that. Otherwise use no affinity. */ if( aff1==SQLITE_AFF_INTEGER || aff2==SQLITE_AFF_INTEGER ){ return SQLITE_AFF_INTEGER; }else if( aff1==SQLITE_AFF_NUMERIC || aff2==SQLITE_AFF_NUMERIC ){ return SQLITE_AFF_NUMERIC; }else{ return SQLITE_AFF_NONE; } }else if( !aff1 && !aff2 ){ /* Neither side of the comparison is a column. Compare the ** results directly. */ /* return SQLITE_AFF_NUMERIC; // Ticket #805 */ return SQLITE_AFF_NONE; }else{ /* One side is a column, the other is not. Use the columns affinity. */ return (aff1 + aff2); } } /* ** pExpr is a comparison operator. Return the type affinity that should ** be applied to both operands prior to doing the comparison. |
︙ | ︙ | |||
122 123 124 125 126 127 128 | ** pExpr is a comparison expression, eg. '=', '<', IN(...) etc. ** idx_affinity is the affinity of an indexed column. Return true ** if the index with affinity idx_affinity may be used to implement ** the comparison in pExpr. */ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ char aff = comparisonAffinity(pExpr); | < < | | | < > | < | | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | ** pExpr is a comparison expression, eg. '=', '<', IN(...) etc. ** idx_affinity is the affinity of an indexed column. Return true ** if the index with affinity idx_affinity may be used to implement ** the comparison in pExpr. */ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ char aff = comparisonAffinity(pExpr); return (aff==SQLITE_AFF_NONE) || (aff==SQLITE_AFF_NUMERIC && idx_affinity==SQLITE_AFF_INTEGER) || (aff==SQLITE_AFF_INTEGER && idx_affinity==SQLITE_AFF_NUMERIC) || (aff==idx_affinity); } /* ** Return the P1 value that should be used for a binary comparison ** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2. ** If jumpIfNull is true, then set the low byte of the returned ** P1 value to tell the opcode to jump if either expression ** evaluates to NULL. */ static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){ char aff = sqlite3ExprAffinity(pExpr2); return (((int)sqlite3CompareAffinity(pExpr1, aff))<<8)+(jumpIfNull?1:0); } /* ** Return a pointer to the collation sequence that should be used by ** a binary comparison operator comparing pLeft and pRight. ** ** If the left hand expression has a collating sequence type, then it is |
︙ | ︙ | |||
186 187 188 189 190 191 192 | ** for this node is obtained from sqliteMalloc(). The calling function ** is responsible for making sure the node eventually gets freed. */ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){ Expr *pNew; pNew = sqliteMalloc( sizeof(Expr) ); if( pNew==0 ){ | | < < < < < | | > > < | > | | | > > > | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | ** for this node is obtained from sqliteMalloc(). The calling function ** is responsible for making sure the node eventually gets freed. */ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){ Expr *pNew; pNew = sqliteMalloc( sizeof(Expr) ); if( pNew==0 ){ /* When malloc fails, we leak memory from pLeft and pRight */ return 0; } pNew->op = op; pNew->pLeft = pLeft; pNew->pRight = pRight; pNew->iAgg = -1; if( pToken ){ assert( pToken->dyn==0 ); pNew->span = pNew->token = *pToken; }else if( pLeft && pRight ){ sqlite3ExprSpan(pNew, &pLeft->span, &pRight->span); } return pNew; } /* ** When doing a nested parse, you can include terms in an expression ** that look like this: #0 #1 #2 ... These terms refer to elements ** on the stack. "#0" (or just "#") means the top of the stack. ** "#1" means the next down on the stack. And so forth. #-1 means ** memory location 0. #-2 means memory location 1. And so forth. ** ** This routine is called by the parser to deal with on of those terms. ** It immediately generates code to store the value in a memory location. ** The returns an expression that will code to extract the value from ** that memory location as needed. */ Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){ Vdbe *v = pParse->pVdbe; Expr *p; int depth; if( v==0 ) return 0; if( pParse->nested==0 ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken); return 0; } p = sqlite3Expr(TK_REGISTER, 0, 0, pToken); if( p==0 ){ return 0; /* Malloc failed */ } depth = atoi(&pToken->z[1]); if( depth>=0 ){ p->iTable = pParse->nMem++; sqlite3VdbeAddOp(v, OP_Dup, depth, 0); sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1); }else{ p->iTable = -1-depth; } return p; } /* ** Join two expressions using an AND operator. If either expression is ** NULL, then just return the other expression. */ |
︙ | ︙ | |||
259 260 261 262 263 264 265 | /* ** Set the Expr.span field of the given expression to span all ** text between the two given tokens. */ void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ assert( pRight!=0 ); assert( pLeft!=0 ); | | | | | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | /* ** Set the Expr.span field of the given expression to span all ** text between the two given tokens. */ void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ assert( pRight!=0 ); assert( pLeft!=0 ); if( !sqlite3_malloc_failed && pRight->z && pLeft->z ){ assert( pLeft->dyn==0 || pLeft->z[pLeft->n]==0 ); if( pLeft->dyn==0 && pRight->dyn==0 ){ pExpr->span.z = pLeft->z; pExpr->span.n = pRight->n + Addr(pRight->z) - Addr(pLeft->z); }else{ pExpr->span.z = 0; } } } /* ** Construct a new expression node for a function with multiple ** arguments. */ Expr *sqlite3ExprFunction(ExprList *pList, Token *pToken){ Expr *pNew; pNew = sqliteMalloc( sizeof(Expr) ); if( pNew==0 ){ /* sqlite3ExprListDelete(pList); // Leak pList when malloc fails */ return 0; } pNew->op = TK_FUNCTION; pNew->pList = pList; if( pToken ){ assert( pToken->dyn==0 ); pNew->token = *pToken; |
︙ | ︙ | |||
323 324 325 326 327 328 329 | if( pToken->n==1 ){ /* Wildcard of the form "?". Assign the next variable number */ pExpr->iTable = ++pParse->nVar; }else if( pToken->z[0]=='?' ){ /* Wildcard of the form "?nnn". Convert "nnn" to an integer and ** use it as the variable number */ int i; | | | 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | if( pToken->n==1 ){ /* Wildcard of the form "?". Assign the next variable number */ pExpr->iTable = ++pParse->nVar; }else if( pToken->z[0]=='?' ){ /* Wildcard of the form "?nnn". Convert "nnn" to an integer and ** use it as the variable number */ int i; pExpr->iTable = i = atoi(&pToken->z[1]); if( i<1 || i>SQLITE_MAX_VARIABLE_NUMBER ){ sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", SQLITE_MAX_VARIABLE_NUMBER); } if( i>pParse->nVar ){ pParse->nVar = i; } |
︙ | ︙ | |||
351 352 353 354 355 356 357 | break; } } if( i>=pParse->nVarExpr ){ pExpr->iTable = ++pParse->nVar; if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){ pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10; | | | | 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | break; } } if( i>=pParse->nVarExpr ){ pExpr->iTable = ++pParse->nVar; if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){ pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10; pParse->apVarExpr = sqliteRealloc(pParse->apVarExpr, pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) ); } if( !sqlite3_malloc_failed ){ assert( pParse->apVarExpr!=0 ); pParse->apVarExpr[pParse->nVarExpr++] = pExpr; } } } } |
︙ | ︙ | |||
376 377 378 379 380 381 382 | sqlite3ExprDelete(p->pLeft); sqlite3ExprDelete(p->pRight); sqlite3ExprListDelete(p->pList); sqlite3SelectDelete(p->pSelect); sqliteFree(p); } | < < < < < < < < < < < < < < < | < | | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 | sqlite3ExprDelete(p->pLeft); sqlite3ExprDelete(p->pRight); sqlite3ExprListDelete(p->pList); sqlite3SelectDelete(p->pSelect); sqliteFree(p); } /* ** The following group of routines make deep copies of expressions, ** expression lists, ID lists, and select statements. The copies can ** be deleted (by being passed to their respective ...Delete() routines) ** without effecting the originals. ** ** The expression list, ID, and source lists return by sqlite3ExprListDup(), ** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded ** by subsequent calls to sqlite*ListAppend() routines. ** ** Any tables that the SrcList might point to are not duplicated. */ Expr *sqlite3ExprDup(Expr *p){ Expr *pNew; if( p==0 ) return 0; pNew = sqliteMallocRaw( sizeof(*p) ); if( pNew==0 ) return 0; memcpy(pNew, p, sizeof(*pNew)); if( p->token.z!=0 ){ pNew->token.z = sqliteStrNDup(p->token.z, p->token.n); pNew->token.dyn = 1; }else{ assert( pNew->token.z==0 ); } pNew->span.z = 0; pNew->pLeft = sqlite3ExprDup(p->pLeft); pNew->pRight = sqlite3ExprDup(p->pRight); pNew->pList = sqlite3ExprListDup(p->pList); pNew->pSelect = sqlite3SelectDup(p->pSelect); return pNew; } void sqlite3TokenCopy(Token *pTo, Token *pFrom){ if( pTo->dyn ) sqliteFree((char*)pTo->z); if( pFrom->z ){ pTo->n = pFrom->n; pTo->z = sqliteStrNDup(pFrom->z, pFrom->n); pTo->dyn = 1; }else{ pTo->z = 0; } } ExprList *sqlite3ExprListDup(ExprList *p){ ExprList *pNew; |
︙ | ︙ | |||
458 459 460 461 462 463 464 | if( pOldExpr->span.z!=0 && pNewExpr ){ /* Always make a copy of the span for top-level expressions in the ** expression list. The logic in SELECT processing that determines ** the names of columns in the result set needs this information */ sqlite3TokenCopy(&pNewExpr->span, &pOldExpr->span); } assert( pNewExpr==0 || pNewExpr->span.z!=0 | | < | 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 | if( pOldExpr->span.z!=0 && pNewExpr ){ /* Always make a copy of the span for top-level expressions in the ** expression list. The logic in SELECT processing that determines ** the names of columns in the result set needs this information */ sqlite3TokenCopy(&pNewExpr->span, &pOldExpr->span); } assert( pNewExpr==0 || pNewExpr->span.z!=0 || pOldExpr->span.z==0 || sqlite3_malloc_failed ); pItem->zName = sqliteStrDup(pOldItem->zName); pItem->sortOrder = pOldItem->sortOrder; pItem->isAgg = pOldItem->isAgg; pItem->done = 0; } return pNew; } |
︙ | ︙ | |||
488 489 490 491 492 493 494 | nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); pNew = sqliteMallocRaw( nByte ); if( pNew==0 ) return 0; pNew->nSrc = pNew->nAlloc = p->nSrc; for(i=0; i<p->nSrc; i++){ struct SrcList_item *pNewItem = &pNew->a[i]; struct SrcList_item *pOldItem = &p->a[i]; | < | | | | < < < | 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); pNew = sqliteMallocRaw( nByte ); if( pNew==0 ) return 0; pNew->nSrc = pNew->nAlloc = p->nSrc; for(i=0; i<p->nSrc; i++){ struct SrcList_item *pNewItem = &pNew->a[i]; struct SrcList_item *pOldItem = &p->a[i]; pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase); pNewItem->zName = sqliteStrDup(pOldItem->zName); pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; pNewItem->pTab = pOldItem->pTab; if( pNewItem->pTab ){ pNewItem->pTab->isTransient = 0; } pNewItem->pSelect = sqlite3SelectDup(pOldItem->pSelect); pNewItem->pOn = sqlite3ExprDup(pOldItem->pOn); pNewItem->pUsing = sqlite3IdListDup(pOldItem->pUsing); pNewItem->colUsed = pOldItem->colUsed; } return pNew; } IdList *sqlite3IdListDup(IdList *p){ IdList *pNew; int i; if( p==0 ) return 0; pNew = sqliteMallocRaw( sizeof(*pNew) ); if( pNew==0 ) return 0; pNew->nId = pNew->nAlloc = p->nId; pNew->a = sqliteMallocRaw( p->nId*sizeof(p->a[0]) ); if( pNew->a==0 ) return 0; for(i=0; i<p->nId; i++){ struct IdList_item *pNewItem = &pNew->a[i]; struct IdList_item *pOldItem = &p->a[i]; pNewItem->zName = sqliteStrDup(pOldItem->zName); pNewItem->idx = pOldItem->idx; } return pNew; |
︙ | ︙ | |||
543 544 545 546 547 548 549 550 551 | pNew->pOrderBy = sqlite3ExprListDup(p->pOrderBy); pNew->op = p->op; pNew->pPrior = sqlite3SelectDup(p->pPrior); pNew->pLimit = sqlite3ExprDup(p->pLimit); pNew->pOffset = sqlite3ExprDup(p->pOffset); pNew->iLimit = -1; pNew->iOffset = -1; pNew->isResolved = p->isResolved; pNew->isAgg = p->isAgg; | > > < < < < < < > | < | | | > | > < < < > < < < < < < | 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 | pNew->pOrderBy = sqlite3ExprListDup(p->pOrderBy); pNew->op = p->op; pNew->pPrior = sqlite3SelectDup(p->pPrior); pNew->pLimit = sqlite3ExprDup(p->pLimit); pNew->pOffset = sqlite3ExprDup(p->pOffset); pNew->iLimit = -1; pNew->iOffset = -1; pNew->ppOpenTemp = 0; pNew->pFetch = 0; pNew->isResolved = p->isResolved; pNew->isAgg = p->isAgg; return pNew; } #else Select *sqlite3SelectDup(Select *p){ assert( p==0 ); return 0; } #endif /* ** Add a new element to the end of an expression list. If pList is ** initially NULL, then create a new expression list. */ ExprList *sqlite3ExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){ if( pList==0 ){ pList = sqliteMalloc( sizeof(ExprList) ); if( pList==0 ){ /* sqlite3ExprDelete(pExpr); // Leak memory if malloc fails */ return 0; } assert( pList->nAlloc==0 ); } if( pList->nAlloc<=pList->nExpr ){ pList->nAlloc = pList->nAlloc*2 + 4; pList->a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0])); if( pList->a==0 ){ /* sqlite3ExprDelete(pExpr); // Leak memory if malloc fails */ pList->nExpr = pList->nAlloc = 0; return pList; } } assert( pList->a!=0 ); if( pExpr || pName ){ struct ExprList_item *pItem = &pList->a[pList->nExpr++]; memset(pItem, 0, sizeof(*pItem)); pItem->pExpr = pExpr; pItem->zName = sqlite3NameFromToken(pName); } return pList; } /* ** Delete an entire expression list. */ void sqlite3ExprListDelete(ExprList *pList){ int i; |
︙ | ︙ | |||
626 627 628 629 630 631 632 | ** The return value from xFunc determines whether the tree walk continues. ** 0 means continue walking the tree. 1 means do not walk children ** of the current node but continue with siblings. 2 means abandon ** the tree walk completely. ** ** The return value from this routine is 1 to abandon the tree walk ** and 0 to continue. | < < | 588 589 590 591 592 593 594 595 596 597 598 599 600 601 | ** The return value from xFunc determines whether the tree walk continues. ** 0 means continue walking the tree. 1 means do not walk children ** of the current node but continue with siblings. 2 means abandon ** the tree walk completely. ** ** The return value from this routine is 1 to abandon the tree walk ** and 0 to continue. */ static int walkExprList(ExprList *, int (*)(void *, Expr*), void *); static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){ int rc; if( pExpr==0 ) return 0; rc = (*xFunc)(pArg, pExpr); if( rc==0 ){ |
︙ | ︙ | |||
685 686 687 688 689 690 691 | ** ** After walking the whole tree, if no nodes are found that disqualify ** the expression as constant, then we assume the whole expression ** is constant. See sqlite3ExprIsConstant() for additional information. */ static int exprNodeIsConstant(void *pArg, Expr *pExpr){ switch( pExpr->op ){ | < < < < < | < < < < < | < < < < < < < < < < < < < < < | | 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 | ** ** After walking the whole tree, if no nodes are found that disqualify ** the expression as constant, then we assume the whole expression ** is constant. See sqlite3ExprIsConstant() for additional information. */ static int exprNodeIsConstant(void *pArg, Expr *pExpr){ switch( pExpr->op ){ case TK_ID: case TK_COLUMN: case TK_DOT: case TK_AGG_FUNCTION: case TK_FUNCTION: #ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: case TK_EXISTS: #endif *((int*)pArg) = 0; return 2; default: return 0; } } /* ** Walk an expression tree. Return 1 if the expression is constant ** and 0 if it involves variables. ** ** For the purposes of this function, a double-quoted string (ex: "abc") ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. */ int sqlite3ExprIsConstant(Expr *p){ int isConst = 1; walkExprTree(p, exprNodeIsConstant, &isConst); return isConst; } /* ** If the expression p codes a constant integer that is small enough ** to fit in a 32-bit integer, return 1 and put the value of the integer ** in *pValue. If the expression is not an integer or if it is too big ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. */ int sqlite3ExprIsInteger(Expr *p, int *pValue){ switch( p->op ){ case TK_INTEGER: { if( sqlite3GetInt32(p->token.z, pValue) ){ return 1; } break; } case TK_UPLUS: { return sqlite3ExprIsInteger(p->pLeft, pValue); } |
︙ | ︙ | |||
806 807 808 809 810 811 812 | ** means that the form of the name is Z and that columns from any table ** can be used. ** ** If the name cannot be resolved unambiguously, leave an error message ** in pParse and return non-zero. Return zero on success. */ static int lookupName( | | | 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 | ** means that the form of the name is Z and that columns from any table ** can be used. ** ** If the name cannot be resolved unambiguously, leave an error message ** in pParse and return non-zero. Return zero on success. */ static int lookupName( Parse *pParse, /* The parsing context */ Token *pDbToken, /* Name of the database containing table, or NULL */ Token *pTableToken, /* Name of table containing column, or NULL */ Token *pColumnToken, /* Name of the column. */ NameContext *pNC, /* The name context used to resolve the name */ Expr *pExpr /* Make this EXPR node point to the selected column */ ){ char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */ |
︙ | ︙ | |||
828 829 830 831 832 833 834 | struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */ zDb = sqlite3NameFromToken(pDbToken); zTab = sqlite3NameFromToken(pTableToken); zCol = sqlite3NameFromToken(pColumnToken); | | | < > > > < | | < < | | < < < < < < < < < < < < < < < < < < < | 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 | struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */ zDb = sqlite3NameFromToken(pDbToken); zTab = sqlite3NameFromToken(pTableToken); zCol = sqlite3NameFromToken(pColumnToken); if( sqlite3_malloc_failed ){ return 1; /* Leak memory (zDb and zTab) if malloc fails */ } pExpr->iTable = -1; while( pNC && cnt==0 ){ SrcList *pSrcList = pNC->pSrcList; ExprList *pEList = pNC->pEList; pNC->nRef++; /* assert( zTab==0 || pEList==0 ); */ if( pSrcList ){ for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ Table *pTab = pItem->pTab; Column *pCol; if( pTab==0 ) continue; assert( pTab->nCol>0 ); if( zTab ){ if( pItem->zAlias ){ char *zTabName = pItem->zAlias; if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue; }else{ char *zTabName = pTab->zName; if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue; if( zDb!=0 && sqlite3StrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){ continue; } } } if( 0==(cntTab++) ){ pExpr->iTable = pItem->iCursor; pExpr->iDb = pTab->iDb; pMatch = pItem; } for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ cnt++; pExpr->iTable = pItem->iCursor; pMatch = pItem; pExpr->iDb = pTab->iDb; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->affinity = pTab->aCol[j].affinity; pExpr->pColl = pTab->aCol[j].pColl; break; } } } } #ifndef SQLITE_OMIT_TRIGGER |
︙ | ︙ | |||
920 921 922 923 924 925 926 | pTab = pTriggerStack->pTab; } if( pTab ){ int j; Column *pCol = pTab->aCol; | | < | < | 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 | pTab = pTriggerStack->pTab; } if( pTab ){ int j; Column *pCol = pTab->aCol; pExpr->iDb = pTab->iDb; cntTab++; for(j=0; j < pTab->nCol; j++, pCol++) { if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ cnt++; pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->affinity = pTab->aCol[j].affinity; pExpr->pColl = pTab->aCol[j].pColl; break; } } } } #endif /* !defined(SQLITE_OMIT_TRIGGER) */ |
︙ | ︙ | |||
958 959 960 961 962 963 964 | ** SELECT a+b AS x FROM table WHERE x<10; ** ** In cases like this, replace pExpr with a copy of the expression that ** forms the result set entry ("a+b" in the example) and return immediately. ** Note that the expression in the result set should have already been ** resolved by the time the WHERE clause is resolved. */ | | | | < < < | | | 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 | ** SELECT a+b AS x FROM table WHERE x<10; ** ** In cases like this, replace pExpr with a copy of the expression that ** forms the result set entry ("a+b" in the example) and return immediately. ** Note that the expression in the result set should have already been ** resolved by the time the WHERE clause is resolved. */ if( cnt==0 && pEList!=0 && zTab==0 ){ for(j=0; j<pEList->nExpr; j++){ char *zAs = pEList->a[j].zName; if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ assert( pExpr->pLeft==0 && pExpr->pRight==0 ); pExpr->op = TK_AS; pExpr->iColumn = j; pExpr->pLeft = sqlite3ExprDup(pEList->a[j].pExpr); sqliteFree(zCol); assert( zTab==0 && zDb==0 ); return 0; } } } /* Advance to the next name context. The loop will exit when either ** we have a match (cnt>0) or when we run out of name contexts. */ if( cnt==0 ){ pNC = pNC->pNext; } } /* ** If X and Y are NULL (in other words if only the column name Z is ** supplied) and the value of Z is enclosed in double-quotes, then ** Z is a string literal if it doesn't match any column names. In that ** case, we need to return right away and not make any changes to ** pExpr. */ if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){ sqliteFree(zCol); return 0; } /* ** cnt==0 means there was not match. cnt>1 means there were two or ** more matches. Either way, we have an error. */ if( cnt!=1 ){ char *z = 0; char *zErr; zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s"; if( zDb ){ sqlite3SetString(&z, zDb, ".", zTab, ".", zCol, 0); }else if( zTab ){ sqlite3SetString(&z, zTab, ".", zCol, 0); }else{ z = sqliteStrDup(zCol); } sqlite3ErrorMsg(pParse, zErr, z); sqliteFree(z); pTopNC->nErr++; } |
︙ | ︙ | |||
1031 1032 1033 1034 1035 1036 1037 | if( n>=sizeof(Bitmask)*8 ){ n = sizeof(Bitmask)*8-1; } assert( pMatch->iCursor==pExpr->iTable ); pMatch->colUsed |= 1<<n; } | < > < < > > > | > > > > > > > > > | > > > > > | | | > | < > > | > > > | > > > > | > | > > | > | 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 | if( n>=sizeof(Bitmask)*8 ){ n = sizeof(Bitmask)*8-1; } assert( pMatch->iCursor==pExpr->iTable ); pMatch->colUsed |= 1<<n; } /* Clean up and return */ sqliteFree(zDb); sqliteFree(zTab); sqliteFree(zCol); sqlite3ExprDelete(pExpr->pLeft); pExpr->pLeft = 0; sqlite3ExprDelete(pExpr->pRight); pExpr->pRight = 0; pExpr->op = TK_COLUMN; if( cnt==1 ){ assert( pNC!=0 ); sqlite3AuthRead(pParse, pExpr, pNC->pSrcList); } return cnt!=1; } /* ** pExpr is a node that defines a function of some kind. It might ** be a syntactic function like "count(x)" or it might be a function ** that implements an operator, like "a LIKE b". ** ** This routine makes *pzName point to the name of the function and ** *pnName hold the number of characters in the function name. */ static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){ switch( pExpr->op ){ case TK_FUNCTION: { *pzName = pExpr->token.z; *pnName = pExpr->token.n; break; } case TK_LIKE: { *pzName = "like"; *pnName = 4; break; } case TK_GLOB: { *pzName = "glob"; *pnName = 4; break; } case TK_CTIME: { *pzName = "current_time"; *pnName = 12; break; } case TK_CDATE: { *pzName = "current_date"; *pnName = 12; break; } case TK_CTIMESTAMP: { *pzName = "current_timestamp"; *pnName = 17; break; } } } /* ** This routine is designed as an xFunc for walkExprTree(). ** ** Resolve symbolic names into TK_COLUMN operators for the current |
︙ | ︙ | |||
1087 1088 1089 1090 1091 1092 1093 | assert( pNC!=0 ); pSrcList = pNC->pSrcList; pParse = pNC->pParse; if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1; ExprSetProperty(pExpr, EP_Resolved); #ifndef NDEBUG | | | 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 | assert( pNC!=0 ); pSrcList = pNC->pSrcList; pParse = pNC->pParse; if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1; ExprSetProperty(pExpr, EP_Resolved); #ifndef NDEBUG if( pSrcList ){ int i; for(i=0; i<pSrcList->nSrc; i++){ assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab); } } #endif switch( pExpr->op ){ |
︙ | ︙ | |||
1137 1138 1139 1140 1141 1142 1143 | } lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr); return 1; } /* Resolve function names */ | | > > > > | < | | 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 | } lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr); return 1; } /* Resolve function names */ case TK_CTIME: case TK_CTIMESTAMP: case TK_CDATE: case TK_GLOB: case TK_LIKE: case TK_FUNCTION: { ExprList *pList = pExpr->pList; /* The argument list */ int n = pList ? pList->nExpr : 0; /* Number of arguments */ int no_such_func = 0; /* True if no such function exists */ int wrong_num_args = 0; /* True if wrong number of arguments */ int is_agg = 0; /* True if is an aggregate function */ int i; int nId; /* Number of characters in function name */ const char *zId; /* The function name. */ FuncDef *pDef; /* Information about the function */ int enc = pParse->db->enc; /* The database encoding */ getFunctionName(pExpr, &zId, &nId); pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); if( pDef==0 ){ pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0); if( pDef==0 ){ no_such_func = 1; }else{ wrong_num_args = 1; |
︙ | ︙ | |||
1196 1197 1198 1199 1200 1201 1202 | #ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: case TK_EXISTS: #endif case TK_IN: { if( pExpr->pSelect ){ int nRef = pNC->nRef; | < < < < < < < < < < < < < < | 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 | #ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: case TK_EXISTS: #endif case TK_IN: { if( pExpr->pSelect ){ int nRef = pNC->nRef; sqlite3SelectResolve(pParse, pExpr->pSelect, pNC); assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ ExprSetProperty(pExpr, EP_VarSelect); } } } } return 0; } /* ** This routine walks an expression tree and resolves references to ** table columns. Nodes of the form ID.ID or ID resolve into an |
︙ | ︙ | |||
1246 1247 1248 1249 1250 1251 1252 | ** If the expression contains aggregate functions then set the EP_Agg ** property on the expression. */ int sqlite3ExprResolveNames( NameContext *pNC, /* Namespace to resolve expressions in. */ Expr *pExpr /* The expression to be analyzed. */ ){ | < < < < < < < < | > | | | < | | > | | | | | < < < < < < > | > > > | > | | | | | 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 | ** If the expression contains aggregate functions then set the EP_Agg ** property on the expression. */ int sqlite3ExprResolveNames( NameContext *pNC, /* Namespace to resolve expressions in. */ Expr *pExpr /* The expression to be analyzed. */ ){ if( pExpr==0 ) return 0; walkExprTree(pExpr, nameResolverStep, pNC); if( pNC->nErr>0 ){ ExprSetProperty(pExpr, EP_Error); } return ExprHasProperty(pExpr, EP_Error); } /* ** A pointer instance of this structure is used to pass information ** through walkExprTree into codeSubqueryStep(). */ typedef struct QueryCoder QueryCoder; struct QueryCoder { Parse *pParse; /* The parsing context */ NameContext *pNC; /* Namespace of first enclosing query */ }; /* ** Generate code for subqueries and IN operators. ** ** IN operators comes in two forms: ** ** expr IN (exprlist) ** and ** expr IN (SELECT ...) ** ** The first form is handled by creating a set holding the list ** of allowed values. The second form causes the SELECT to generate ** a temporary table. */ #ifndef SQLITE_OMIT_SUBQUERY void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ int label = 0; /* Address after sub-select code */ Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return; /* If this is not a variable (correlated) select, then execute ** it only once. Unless this is part of a trigger program. In ** that case re-execute every time (this could be optimized). */ if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){ int mem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0); label = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_If, 0, label); sqlite3VdbeAddOp(v, OP_Integer, 1, 0); sqlite3VdbeAddOp(v, OP_MemStore, mem, 1); } if( pExpr->pSelect ){ sqlite3VdbeAddOp(v, OP_AggContextPush, 0, 0); } switch( pExpr->op ){ case TK_IN: { char affinity; KeyInfo keyInfo; int addr; /* Address of OP_OpenTemp instruction */ affinity = sqlite3ExprAffinity(pExpr->pLeft); /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)' ** expression it is handled the same way. A temporary table is ** filled with single-field index keys representing the results ** from the SELECT or the <exprlist>. ** ** If the 'x' expression is a column value, or the SELECT... ** statement returns a column value, then the affinity of that ** column is used to build the index keys. If both 'x' and the ** SELECT... statement are columns, then numeric affinity is used ** if either column has NUMERIC or INTEGER affinity. If neither ** 'x' nor the SELECT... statement are columns, then numeric affinity ** is used. */ pExpr->iTable = pParse->nTab++; addr = sqlite3VdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 0); memset(&keyInfo, 0, sizeof(keyInfo)); keyInfo.nField = 1; sqlite3VdbeAddOp(v, OP_SetNumColumns, pExpr->iTable, 1); if( pExpr->pSelect ){ /* Case 1: expr IN (SELECT ...) ** |
︙ | ︙ | |||
1360 1361 1362 1363 1364 1365 1366 | ** ** For each expression, build an index key from the evaluation and ** store it in the temporary table. If <expr> is a column, then use ** that columns affinity when building index keys. If <expr> is not ** a column, use numeric affinity. */ int i; | < < < | | | < < < < | | > | < < < < | > | < < | < < > | > | < < | > > > | | | < < | < < < < < < < < < < < < < | < < | < < | < | < > | | | < | < < < | < < < < < < < < | > > > > > | < < < < < < < < < < < < < < < < < < | 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 | ** ** For each expression, build an index key from the evaluation and ** store it in the temporary table. If <expr> is a column, then use ** that columns affinity when building index keys. If <expr> is not ** a column, use numeric affinity. */ int i; if( !affinity ){ affinity = SQLITE_AFF_NUMERIC; } keyInfo.aColl[0] = pExpr->pLeft->pColl; /* Loop through each expression in <exprlist>. */ for(i=0; i<pExpr->pList->nExpr; i++){ Expr *pE2 = pExpr->pList->a[i].pExpr; /* Check that the expression is constant and valid. */ if( !sqlite3ExprIsConstant(pE2) ){ sqlite3ErrorMsg(pParse, "right-hand side of IN operator must be constant"); return; } /* Evaluate the expression and insert it into the temp table */ sqlite3ExprCode(pParse, pE2); sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1); sqlite3VdbeAddOp(v, OP_String8, 0, 0); sqlite3VdbeAddOp(v, OP_PutStrKey, pExpr->iTable, 0); } } sqlite3VdbeChangeP3(v, addr, (void *)&keyInfo, P3_KEYINFO); break; } case TK_EXISTS: case TK_SELECT: { /* This has to be a scalar SELECT. Generate code to put the ** value of this select in a memory cell and record the number ** of the memory cell in iColumn. */ int sop; Select *pSel; pExpr->iColumn = pParse->nMem++; pSel = pExpr->pSelect; if( pExpr->op==TK_SELECT ){ sop = SRT_Mem; }else{ static const Token one = { "1", 0, 1 }; sop = SRT_Exists; sqlite3ExprListDelete(pSel->pEList); pSel->pEList = sqlite3ExprListAppend(0, sqlite3Expr(TK_INTEGER, 0, 0, &one), 0); } sqlite3Select(pParse, pSel, sop, pExpr->iColumn, 0, 0, 0, 0); break; } } if( pExpr->pSelect ){ sqlite3VdbeAddOp(v, OP_AggContextPop, 0, 0); } if( label<0 ){ sqlite3VdbeResolveLabel(v, label); } return; } #endif /* SQLITE_OMIT_SUBQUERY */ /* ** Generate an instruction that will put the integer describe by ** text z[0..n-1] on the stack. */ static void codeInteger(Vdbe *v, const char *z, int n){ int i; if( sqlite3GetInt32(z, &i) ){ sqlite3VdbeAddOp(v, OP_Integer, i, 0); }else if( sqlite3FitsIn64Bits(z) ){ sqlite3VdbeOp3(v, OP_Integer, 0, 0, z, n); }else{ sqlite3VdbeOp3(v, OP_Real, 0, 0, z, n); } } /* ** Generate code into the current Vdbe to evaluate the given ** expression and leave the result on the top of stack. ** ** This code depends on the fact that certain token values (ex: TK_EQ) ** are the same as opcode values (ex: OP_Eq) that implement the corresponding ** operation. Special comments in vdbe.c and the mkopcodeh.awk script in ** the make process cause these values to align. Assert()s in the code ** below verify that the numbers are aligned correctly. */ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ Vdbe *v = pParse->pVdbe; int op; if( v==0 ) return; if( pExpr==0 ){ sqlite3VdbeAddOp(v, OP_String8, 0, 0); /* Empty expression evals to NULL */ return; } op = pExpr->op; switch( op ){ case TK_COLUMN: { if( !pParse->fillAgg && pExpr->iAgg>=0 ){ sqlite3VdbeAddOp(v, OP_AggGet, pExpr->iAggCtx, pExpr->iAgg); }else if( pExpr->iColumn>=0 ){ sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn); #ifndef NDEBUG if( pExpr->span.z && pExpr->span.n>0 && pExpr->span.n<100 ){ VdbeComment((v, "# %T", &pExpr->span)); } #endif }else{ sqlite3VdbeAddOp(v, OP_Recno, pExpr->iTable, 0); } break; } case TK_INTEGER: { codeInteger(v, pExpr->token.z, pExpr->token.n); break; } case TK_FLOAT: case TK_STRING: { assert( TK_FLOAT==OP_Real ); assert( TK_STRING==OP_String8 ); sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z, pExpr->token.n); sqlite3VdbeDequoteP3(v, -1); break; } #ifndef SQLITE_OMIT_BLOB_LITERAL case TK_BLOB: { assert( TK_BLOB==OP_HexBlob ); sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z+1, pExpr->token.n-1); sqlite3VdbeDequoteP3(v, -1); break; } #endif case TK_NULL: { sqlite3VdbeAddOp(v, OP_String8, 0, 0); break; } case TK_VARIABLE: { sqlite3VdbeAddOp(v, OP_Variable, pExpr->iTable, 0); if( pExpr->token.n>1 ){ sqlite3VdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n); } break; } case TK_REGISTER: { sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iTable, 0); break; } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { assert( TK_LT==OP_Lt ); assert( TK_LE==OP_Le ); assert( TK_GT==OP_Gt ); assert( TK_GE==OP_Ge ); assert( TK_EQ==OP_Eq ); assert( TK_NE==OP_Ne ); sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3ExprCode(pParse, pExpr->pRight); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, 0, 0); break; } case TK_AND: case TK_OR: case TK_PLUS: case TK_STAR: case TK_MINUS: |
︙ | ︙ | |||
1605 1606 1607 1608 1609 1610 1611 | assert( TK_SLASH==OP_Divide ); assert( TK_LSHIFT==OP_ShiftLeft ); assert( TK_RSHIFT==OP_ShiftRight ); assert( TK_CONCAT==OP_Concat ); sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3ExprCode(pParse, pExpr->pRight); sqlite3VdbeAddOp(v, op, 0, 0); | < > | < < < < < < < | < | > > > > | | < | | | < | 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 | assert( TK_SLASH==OP_Divide ); assert( TK_LSHIFT==OP_ShiftLeft ); assert( TK_RSHIFT==OP_ShiftRight ); assert( TK_CONCAT==OP_Concat ); sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3ExprCode(pParse, pExpr->pRight); sqlite3VdbeAddOp(v, op, 0, 0); break; } case TK_UMINUS: { Expr *pLeft = pExpr->pLeft; assert( pLeft ); if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){ Token *p = &pLeft->token; char *z = sqliteMalloc( p->n + 2 ); sprintf(z, "-%.*s", p->n, p->z); if( pLeft->op==TK_FLOAT ){ sqlite3VdbeOp3(v, OP_Real, 0, 0, z, p->n+1); }else{ codeInteger(v, z, p->n+1); } sqliteFree(z); break; } /* Fall through into TK_NOT */ } case TK_BITNOT: case TK_NOT: { assert( TK_BITNOT==OP_BitNot ); assert( TK_NOT==OP_Not ); sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3VdbeAddOp(v, op, 0, 0); break; } case TK_ISNULL: case TK_NOTNULL: { int dest; assert( TK_ISNULL==OP_IsNull ); assert( TK_NOTNULL==OP_NotNull ); sqlite3VdbeAddOp(v, OP_Integer, 1, 0); sqlite3ExprCode(pParse, pExpr->pLeft); dest = sqlite3VdbeCurrentAddr(v) + 2; sqlite3VdbeAddOp(v, op, 1, dest); sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); break; } case TK_AGG_FUNCTION: { sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); break; } case TK_CDATE: case TK_CTIME: case TK_CTIMESTAMP: case TK_GLOB: case TK_LIKE: case TK_FUNCTION: { ExprList *pList = pExpr->pList; int nExpr = pList ? pList->nExpr : 0; FuncDef *pDef; int nId; const char *zId; int p2 = 0; int i; u8 enc = pParse->db->enc; CollSeq *pColl = 0; getFunctionName(pExpr, &zId, &nId); pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0); assert( pDef!=0 ); nExpr = sqlite3ExprCodeExprList(pParse, pList); for(i=0; i<nExpr && i<32; i++){ if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){ p2 |= (1<<i); } if( pDef->needCollSeq && !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); } } if( pDef->needCollSeq ){ if( !pColl ) pColl = pParse->db->pDfltColl; sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ); } sqlite3VdbeOp3(v, OP_Function, nExpr, p2, (char*)pDef, P3_FUNCDEF); break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: case TK_SELECT: { sqlite3CodeSubselect(pParse, pExpr); sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0); |
︙ | ︙ | |||
1716 1717 1718 1719 1720 1721 1722 | /* Code the <expr> from "<expr> IN (...)". The temporary table ** pExpr->iTable contains the values that make up the (...) set. */ sqlite3ExprCode(pParse, pExpr->pLeft); addr = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+4); /* addr + 0 */ sqlite3VdbeAddOp(v, OP_Pop, 2, 0); | | | 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 | /* Code the <expr> from "<expr> IN (...)". The temporary table ** pExpr->iTable contains the values that make up the (...) set. */ sqlite3ExprCode(pParse, pExpr->pLeft); addr = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+4); /* addr + 0 */ sqlite3VdbeAddOp(v, OP_Pop, 2, 0); sqlite3VdbeAddOp(v, OP_String8, 0, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, addr+7); sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1); /* addr + 4 */ sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+7); sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); /* addr + 6 */ break; } |
︙ | ︙ | |||
1744 1745 1746 1747 1748 1749 1750 | codeCompare(pParse, pLeft, pRight, OP_Le, 0, 0); sqlite3VdbeAddOp(v, OP_And, 0, 0); break; } case TK_UPLUS: case TK_AS: { sqlite3ExprCode(pParse, pExpr->pLeft); | < > | 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 | codeCompare(pParse, pLeft, pRight, OP_Le, 0, 0); sqlite3VdbeAddOp(v, OP_And, 0, 0); break; } case TK_UPLUS: case TK_AS: { sqlite3ExprCode(pParse, pExpr->pLeft); break; } case TK_CASE: { int expr_end_label; int jumpInst; int addr; int nExpr; int i; ExprList *pEList; struct ExprList_item *aListelem; assert(pExpr->pList); assert((pExpr->pList->nExpr % 2) == 0); |
︙ | ︙ | |||
1777 1778 1779 1780 1781 1782 1783 | OP_Ne, 0, 1); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); }else{ jumpInst = sqlite3VdbeAddOp(v, OP_IfNot, 1, 0); } sqlite3ExprCode(pParse, aListelem[i+1].pExpr); sqlite3VdbeAddOp(v, OP_Goto, 0, expr_end_label); | | > | < | > < < < | < < < | 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 | OP_Ne, 0, 1); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); }else{ jumpInst = sqlite3VdbeAddOp(v, OP_IfNot, 1, 0); } sqlite3ExprCode(pParse, aListelem[i+1].pExpr); sqlite3VdbeAddOp(v, OP_Goto, 0, expr_end_label); addr = sqlite3VdbeCurrentAddr(v); sqlite3VdbeChangeP2(v, jumpInst, addr); } if( pExpr->pLeft ){ sqlite3VdbeAddOp(v, OP_Pop, 1, 0); } if( pExpr->pRight ){ sqlite3ExprCode(pParse, pExpr->pRight); }else{ sqlite3VdbeAddOp(v, OP_String8, 0, 0); } sqlite3VdbeResolveLabel(v, expr_end_label); break; } #ifndef SQLITE_OMIT_TRIGGER case TK_RAISE: { if( !pParse->trigStack ){ sqlite3ErrorMsg(pParse, "RAISE() may only be used within a trigger-program"); return; } if( pExpr->iColumn!=OE_Ignore ){ assert( pExpr->iColumn==OE_Rollback || pExpr->iColumn == OE_Abort || pExpr->iColumn == OE_Fail ); sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, pExpr->token.z, pExpr->token.n); sqlite3VdbeDequoteP3(v, -1); } else { assert( pExpr->iColumn == OE_Ignore ); sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->trigStack->ignoreJump); VdbeComment((v, "# raise(IGNORE)")); } } #endif break; } } #ifndef SQLITE_OMIT_TRIGGER /* ** Generate code that evalutes the given expression and leaves the result ** on the stack. See also sqlite3ExprCode(). |
︙ | ︙ | |||
1861 1862 1863 1864 1865 1866 1867 1868 1869 | */ int sqlite3ExprCodeExprList( Parse *pParse, /* Parsing context */ ExprList *pList /* The expression list to be coded */ ){ struct ExprList_item *pItem; int i, n; if( pList==0 ) return 0; n = pList->nExpr; | > > | | 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 | */ int sqlite3ExprCodeExprList( Parse *pParse, /* Parsing context */ ExprList *pList /* The expression list to be coded */ ){ struct ExprList_item *pItem; int i, n; Vdbe *v; if( pList==0 ) return 0; v = sqlite3GetVdbe(pParse); n = pList->nExpr; for(pItem=pList->a, i=0; i<n; i++, pItem++){ sqlite3ExprCode(pParse, pItem->pExpr); } return n; } /* ** Generate code for a boolean expression such that a jump is made |
︙ | ︙ | |||
1886 1887 1888 1889 1890 1891 1892 | ** operation. Special comments in vdbe.c and the mkopcodeh.awk script in ** the make process cause these values to align. Assert()s in the code ** below verify that the numbers are aligned correctly. */ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; | < | 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 | ** operation. Special comments in vdbe.c and the mkopcodeh.awk script in ** the make process cause these values to align. Assert()s in the code ** below verify that the numbers are aligned correctly. */ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; if( v==0 || pExpr==0 ) return; op = pExpr->op; switch( op ){ case TK_AND: { int d2 = sqlite3VdbeMakeLabel(v); sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); |
︙ | ︙ | |||
1951 1952 1953 1954 1955 1956 1957 | addr = codeCompare(pParse, pLeft, pRight, OP_Lt, 0, !jumpIfNull); pRight = pExpr->pList->a[1].pExpr; sqlite3ExprCode(pParse, pRight); codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull); sqlite3VdbeAddOp(v, OP_Integer, 0, 0); | | < < | 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 | addr = codeCompare(pParse, pLeft, pRight, OP_Lt, 0, !jumpIfNull); pRight = pExpr->pList->a[1].pExpr; sqlite3ExprCode(pParse, pRight); codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull); sqlite3VdbeAddOp(v, OP_Integer, 0, 0); sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v)); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); break; } default: { sqlite3ExprCode(pParse, pExpr); sqlite3VdbeAddOp(v, OP_If, jumpIfNull, dest); break; } } } /* ** Generate code for a boolean expression such that a jump is made ** to the label "dest" if the expression is false but execution ** continues straight thru if the expression is true. ** ** If the expression evaluates to NULL (neither true nor false) then ** jump if jumpIfNull is true or fall through if jumpIfNull is false. */ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; if( v==0 || pExpr==0 ) return; /* The value of pExpr->op and op are related as follows: ** ** pExpr->op op ** --------- ---------- ** TK_ISNULL OP_NotNull |
︙ | ︙ | |||
2072 2073 2074 2075 2076 2077 2078 | } default: { sqlite3ExprCode(pParse, pExpr); sqlite3VdbeAddOp(v, OP_IfNot, jumpIfNull, dest); break; } } | < < | < | < < | | > | > | | | | | < < | < < < < < < < < < > | | > < < < < < < | < | < < < < < < | | > | | | | | | | < < > | < | < < < < < < < < < < < | < < < < < < < < < < < | < | | < < > < < < < < | | > | | < < | | | | | < | | | < < < < | < < < < < < < < < < | 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 | } default: { sqlite3ExprCode(pParse, pExpr); sqlite3VdbeAddOp(v, OP_IfNot, jumpIfNull, dest); break; } } } /* ** Do a deep comparison of two expression trees. Return TRUE (non-zero) ** if they are identical and return FALSE if they differ in any way. */ int sqlite3ExprCompare(Expr *pA, Expr *pB){ int i; if( pA==0 ){ return pB==0; }else if( pB==0 ){ return 0; } if( pA->op!=pB->op ) return 0; if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0; if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0; if( pA->pList ){ if( pB->pList==0 ) return 0; if( pA->pList->nExpr!=pB->pList->nExpr ) return 0; for(i=0; i<pA->pList->nExpr; i++){ if( !sqlite3ExprCompare(pA->pList->a[i].pExpr, pB->pList->a[i].pExpr) ){ return 0; } } }else if( pB->pList ){ return 0; } if( pA->pSelect || pB->pSelect ) return 0; if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; if( pA->token.z ){ if( pB->token.z==0 ) return 0; if( pB->token.n!=pA->token.n ) return 0; if( sqlite3StrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0; } return 1; } /* ** Add a new element to the pParse->aAgg[] array and return its index. ** The new element is initialized to zero. The calling function is ** expected to fill it in. */ static int appendAggInfo(Parse *pParse){ if( (pParse->nAgg & 0x7)==0 ){ int amt = pParse->nAgg + 8; AggExpr *aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0])); if( aAgg==0 ){ return -1; } pParse->aAgg = aAgg; } memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0])); return pParse->nAgg++; } /* ** This is an xFunc for walkExprTree() used to implement ** sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates ** for additional information. ** ** This routine analyzes the aggregate function at pExpr. */ static int analyzeAggregate(void *pArg, Expr *pExpr){ int i; AggExpr *aAgg; NameContext *pNC = (NameContext *)pArg; Parse *pParse = pNC->pParse; SrcList *pSrcList = pNC->pSrcList; switch( pExpr->op ){ case TK_COLUMN: { for(i=0; pSrcList && i<pSrcList->nSrc; i++){ if( pExpr->iTable==pSrcList->a[i].iCursor ){ aAgg = pParse->aAgg; for(i=0; i<pParse->nAgg; i++){ if( aAgg[i].isAgg ) continue; if( aAgg[i].pExpr->iTable==pExpr->iTable && aAgg[i].pExpr->iColumn==pExpr->iColumn ){ break; } } if( i>=pParse->nAgg ){ i = appendAggInfo(pParse); if( i<0 ) return 1; pParse->aAgg[i].isAgg = 0; pParse->aAgg[i].pExpr = pExpr; } pExpr->iAgg = i; pExpr->iAggCtx = pNC->nDepth; return 1; } } return 1; } case TK_AGG_FUNCTION: { if( pNC->nDepth==0 ){ aAgg = pParse->aAgg; for(i=0; i<pParse->nAgg; i++){ if( !aAgg[i].isAgg ) continue; if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){ break; } } if( i>=pParse->nAgg ){ u8 enc = pParse->db->enc; i = appendAggInfo(pParse); if( i<0 ) return 1; pParse->aAgg[i].isAgg = 1; pParse->aAgg[i].pExpr = pExpr; pParse->aAgg[i].pFunc = sqlite3FindFunction(pParse->db, pExpr->token.z, pExpr->token.n, pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0); } pExpr->iAgg = i; return 1; } } } if( pExpr->pSelect ){ pNC->nDepth++; walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC); pNC->nDepth--; } return 0; } |
︙ | ︙ | |||
2287 2288 2289 2290 2291 2292 2293 | int sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ int nErr = pNC->pParse->nErr; walkExprTree(pExpr, analyzeAggregate, pNC); return pNC->pParse->nErr - nErr; } /* | | > > > > > > > > | | > > > > > > > > > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > | > > > > > > | > | > > > > > > | > > > > > > | > > > > > > > > > > > > > > > > > | > > | 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 | int sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ int nErr = pNC->pParse->nErr; walkExprTree(pExpr, analyzeAggregate, pNC); return pNC->pParse->nErr - nErr; } /* ** Locate a user function given a name, a number of arguments and a flag ** indicating whether the function prefers UTF-16 over UTF-8. Return a ** pointer to the FuncDef structure that defines that function, or return ** NULL if the function does not exist. ** ** If the createFlag argument is true, then a new (blank) FuncDef ** structure is created and liked into the "db" structure if a ** no matching function previously existed. When createFlag is true ** and the nArg parameter is -1, then only a function that accepts ** any number of arguments will be returned. ** ** If createFlag is false and nArg is -1, then the first valid ** function found is returned. A function is valid if either xFunc ** or xStep is non-zero. ** ** If createFlag is false, then a function with the required name and ** number of arguments may be returned even if the eTextRep flag does not ** match that requested. */ FuncDef *sqlite3FindFunction( sqlite3 *db, /* An open database */ const char *zName, /* Name of the function. Not null-terminated */ int nName, /* Number of characters in the name */ int nArg, /* Number of arguments. -1 means any number */ u8 enc, /* Preferred text encoding */ int createFlag /* Create new entry if true and does not otherwise exist */ ){ FuncDef *p; /* Iterator variable */ FuncDef *pFirst; /* First function with this name */ FuncDef *pBest = 0; /* Best match found so far */ int bestmatch = 0; assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); if( nArg<-1 ) nArg = -1; pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName); for(p=pFirst; p; p=p->pNext){ /* During the search for the best function definition, bestmatch is set ** as follows to indicate the quality of the match with the definition ** pointed to by pBest: ** ** 0: pBest is NULL. No match has been found. ** 1: A variable arguments function that prefers UTF-8 when a UTF-16 ** encoding is requested, or vice versa. ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is ** requested, or vice versa. ** 3: A variable arguments function using the same text encoding. ** 4: A function with the exact number of arguments requested that ** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa. ** 5: A function with the exact number of arguments requested that ** prefers UTF-16LE when UTF-16BE is requested, or vice versa. ** 6: An exact match. ** ** A larger value of 'matchqual' indicates a more desirable match. */ if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){ int match = 1; /* Quality of this match */ if( p->nArg==nArg || nArg==-1 ){ match = 4; } if( enc==p->iPrefEnc ){ match += 2; } else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) || (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){ match += 1; } if( match>bestmatch ){ pBest = p; bestmatch = match; } } } /* If the createFlag parameter is true, and the seach did not reveal an ** exact match for the name, number of arguments and encoding, then add a ** new entry to the hash table and return it. */ if( createFlag && bestmatch<6 && (pBest = sqliteMalloc(sizeof(*pBest)+nName+1)) ){ pBest->nArg = nArg; pBest->pNext = pFirst; pBest->zName = (char*)&pBest[1]; pBest->iPrefEnc = enc; memcpy(pBest->zName, zName, nName); pBest->zName[nName] = 0; if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){ sqliteFree(pBest); return 0; } } if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){ return pBest; } return 0; } |
Changes to SQLite.Interop/src/func.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** | | | < < < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: func.c,v 1.1 2005/03/01 16:04:29 rmsimpson Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include <math.h> #include <stdlib.h> #include <assert.h> #include "vdbeInt.h" #include "os.h" static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ return context->pColl; } /* ** Implementation of the non-aggregate min() and max() functions */ |
︙ | ︙ | |||
77 78 79 80 81 82 83 | case SQLITE_TEXT: z = "text"; break; case SQLITE_FLOAT: z = "real"; break; case SQLITE_BLOB: z = "blob"; break; } sqlite3_result_text(context, z, -1, SQLITE_STATIC); } | < | | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | case SQLITE_TEXT: z = "text"; break; case SQLITE_FLOAT: z = "real"; break; case SQLITE_BLOB: z = "blob"; break; } sqlite3_result_text(context, z, -1, SQLITE_STATIC); } /* ** Implementation of the length() function */ static void lengthFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ int len; assert( argc==1 ); switch( sqlite3_value_type(argv[0]) ){ case SQLITE_BLOB: case SQLITE_INTEGER: case SQLITE_FLOAT: { sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); break; } case SQLITE_TEXT: { const char *z = sqlite3_value_text(argv[0]); for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; } sqlite3_result_int(context, len); break; } default: { sqlite3_result_null(context); break; |
︙ | ︙ | |||
142 143 144 145 146 147 148 | ** Implementation of the substr() function */ static void substrFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ | | | | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | ** Implementation of the substr() function */ static void substrFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const char *z; const char *z2; int i; int p1, p2, len; assert( argc==3 ); z = sqlite3_value_text(argv[0]); if( z==0 ) return; p1 = sqlite3_value_int(argv[1]); |
︙ | ︙ | |||
174 175 176 177 178 179 180 | } while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p1++; } for(; i<p1+p2 && z[i]; i++){ if( (z[i]&0xc0)==0x80 ) p2++; } while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p2++; } if( p2<0 ) p2 = 0; | | | | | | | | | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | } while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p1++; } for(; i<p1+p2 && z[i]; i++){ if( (z[i]&0xc0)==0x80 ) p2++; } while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p2++; } if( p2<0 ) p2 = 0; sqlite3_result_text(context, &z[p1], p2, SQLITE_TRANSIENT); } /* ** Implementation of the round() function */ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ int n = 0; double r; char zBuf[100]; assert( argc==1 || argc==2 ); if( argc==2 ){ if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return; n = sqlite3_value_int(argv[1]); if( n>30 ) n = 30; if( n<0 ) n = 0; } if( SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; r = sqlite3_value_double(argv[0]); sprintf(zBuf,"%.*f",n,r); sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); } /* ** Implementation of the upper() and lower() SQL functions. */ static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ unsigned char *z; int i; if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1); if( z==0 ) return; strcpy(z, sqlite3_value_text(argv[0])); for(i=0; z[i]; i++){ z[i] = toupper(z[i]); } sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); sqliteFree(z); } static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ unsigned char *z; int i; if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1); if( z==0 ) return; strcpy(z, sqlite3_value_text(argv[0])); for(i=0; z[i]; i++){ z[i] = tolower(z[i]); } sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); sqliteFree(z); } /* ** Implementation of the IFNULL(), NVL(), and COALESCE() functions. ** All three do the same thing. They return the first non-NULL ** argument. |
︙ | ︙ | |||
307 308 309 310 311 312 313 | */ struct compareInfo { u8 matchAll; u8 matchOne; u8 matchSet; u8 noCase; }; | < < < < < < | | 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | */ struct compareInfo { u8 matchAll; u8 matchOne; u8 matchSet; u8 noCase; }; static const struct compareInfo globInfo = { '*', '?', '[', 0 }; static const struct compareInfo likeInfo = { '%', '_', 0, 1 }; /* ** X is a pointer to the first byte of a UTF-8 character. Increment ** X so that it points to the next character. This only works right ** if X points to a well-formed UTF-8 string. */ #define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){} |
︙ | ︙ | |||
456 457 458 459 460 461 462 | zString++; prevEscape = 0; } } return *zString==0; } | < < < < < < < < < > | < | | > > | > > > > > > > > > > | > | | | 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 | zString++; prevEscape = 0; } } return *zString==0; } /* ** Implementation of the like() SQL function. This function implements ** the build-in LIKE operator. The first argument to the function is the ** pattern and the second argument is the string. So, the SQL statements: ** ** A LIKE B ** ** is implemented as like(B,A). ** ** If the pointer retrieved by via a call to sqlite3_user_data() is ** not NULL, then this function uses UTF-16. Otherwise UTF-8. */ static void likeFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const unsigned char *zA = sqlite3_value_text(argv[0]); const unsigned char *zB = sqlite3_value_text(argv[1]); int escape = 0; if( argc==3 ){ /* The escape character string must consist of a single UTF-8 character. ** Otherwise, return an error. */ const unsigned char *zEsc = sqlite3_value_text(argv[2]); if( sqlite3utf8CharLen(zEsc, -1)!=1 ){ sqlite3_result_error(context, "ESCAPE expression must be a single character", -1); return; } escape = sqlite3ReadUtf8(zEsc); } if( zA && zB ){ sqlite3_result_int(context, patternCompare(zA, zB, &likeInfo, escape)); } } /* ** Implementation of the glob() SQL function. This function implements ** the build-in GLOB operator. The first argument to the function is the ** string and the second argument is the pattern. So, the SQL statements: ** ** A GLOB B ** ** is implemented as glob(B,A). */ static void globFunc(sqlite3_context *context, int arg, sqlite3_value **argv){ const unsigned char *zA = sqlite3_value_text(argv[0]); const unsigned char *zB = sqlite3_value_text(argv[1]); if( zA && zB ){ sqlite3_result_int(context, patternCompare(zA, zB, &globInfo, 0)); } } /* ** Implementation of the NULLIF(x,y) function. The result is the first ** argument if the arguments are different. The result is NULL if the ** arguments are equal to each other. |
︙ | ︙ | |||
588 589 590 591 592 593 594 | sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); sqliteFree(zText); } break; } case SQLITE_TEXT: { int i,j,n; | | | 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 | sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); sqliteFree(zText); } break; } case SQLITE_TEXT: { int i,j,n; const char *zArg = sqlite3_value_text(argv[0]); char *z; for(i=n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } z = sqliteMalloc( i+n+3 ); if( z==0 ) return; z[0] = '\''; for(i=0, j=1; zArg[i]; i++){ |
︙ | ︙ | |||
688 689 690 691 692 693 694 | } assert( n<sizeof(zBuf) ); sqlite3Randomness(n, zBuf); for(i=0; i<n; i++){ zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)]; } zBuf[n] = 0; | | | 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 | } assert( n<sizeof(zBuf) ); sqlite3Randomness(n, zBuf); for(i=0; i<n; i++){ zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)]; } zBuf[n] = 0; sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT); } #endif /* SQLITE_TEST */ #ifdef SQLITE_TEST /* ** The following two SQL functions are used to test returning a text ** result with a destructor. Function 'test_destructor' takes one argument |
︙ | ︙ | |||
724 725 726 727 728 729 730 | char *zVal; int len; sqlite3 *db = sqlite3_user_data(pCtx); test_destructor_count_var++; assert( nArg==1 ); if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; | | | | | | 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 | char *zVal; int len; sqlite3 *db = sqlite3_user_data(pCtx); test_destructor_count_var++; assert( nArg==1 ); if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; len = sqlite3ValueBytes(argv[0], db->enc); zVal = sqliteMalloc(len+3); zVal[len] = 0; zVal[len-1] = 0; assert( zVal ); zVal++; memcpy(zVal, sqlite3ValueText(argv[0], db->enc), len); if( db->enc==SQLITE_UTF8 ){ sqlite3_result_text(pCtx, zVal, -1, destructor); #ifndef SQLITE_OMIT_UTF16 }else if( db->enc==SQLITE_UTF16LE ){ sqlite3_result_text16le(pCtx, zVal, -1, destructor); }else{ sqlite3_result_text16be(pCtx, zVal, -1, destructor); #endif /* SQLITE_OMIT_UTF16 */ } } static void test_destructor_count( |
︙ | ︙ | |||
772 773 774 775 776 777 778 | int nArg, sqlite3_value **argv ){ int i; char *zRet = sqliteMalloc(nArg*2); if( !zRet ) return; for(i=0; i<nArg; i++){ | | | 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 | int nArg, sqlite3_value **argv ){ int i; char *zRet = sqliteMalloc(nArg*2); if( !zRet ) return; for(i=0; i<nArg; i++){ char const *z = sqlite3_value_text(argv[i]); if( z ){ char *zAux = sqlite3_get_auxdata(pCtx, i); if( zAux ){ zRet[i*2] = '1'; if( strcmp(zAux, z) ){ sqlite3_result_error(pCtx, "Auxilary data corruption", -1); return; |
︙ | ︙ | |||
803 804 805 806 807 808 809 | ** returns a copy of it's first argument as an error. */ static void test_error( sqlite3_context *pCtx, int nArg, sqlite3_value **argv ){ | | < | < < < < < < < | | < < < < | < < | < < < < | < < < < < | 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 | ** returns a copy of it's first argument as an error. */ static void test_error( sqlite3_context *pCtx, int nArg, sqlite3_value **argv ){ sqlite3_result_error(pCtx, sqlite3_value_text(argv[0]), 0); } #endif /* SQLITE_TEST */ /* ** An instance of the following structure holds the context of a ** sum() or avg() aggregate computation. */ typedef struct SumCtx SumCtx; struct SumCtx { double sum; /* Sum of terms */ int cnt; /* Number of elements summed */ }; /* ** Routines used to compute the sum or average. */ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){ SumCtx *p; if( argc<1 ) return; p = sqlite3_aggregate_context(context, sizeof(*p)); if( p && SQLITE_NULL!=sqlite3_value_type(argv[0]) ){ p->sum += sqlite3_value_double(argv[0]); p->cnt++; } } static void sumFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, sizeof(*p)); sqlite3_result_double(context, p ? p->sum : 0.0); } static void avgFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, sizeof(*p)); if( p && p->cnt>0 ){ sqlite3_result_double(context, p->sum/(double)p->cnt); } } /* ** An instance of the following structure holds the context of a ** variance or standard deviation computation. */ typedef struct StdDevCtx StdDevCtx; struct StdDevCtx { |
︙ | ︙ | |||
897 898 899 900 901 902 903 | p = sqlite3_aggregate_context(context, sizeof(*p)); if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){ p->n++; } } static void countFinalize(sqlite3_context *context){ CountCtx *p; | | > > > > > > > > > > | 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 | p = sqlite3_aggregate_context(context, sizeof(*p)); if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){ p->n++; } } static void countFinalize(sqlite3_context *context){ CountCtx *p; p = sqlite3_aggregate_context(context, sizeof(*p)); sqlite3_result_int(context, p ? p->n : 0); } /* ** This function tracks state information for the min() and max() ** aggregate functions. */ typedef struct MinMaxCtx MinMaxCtx; struct MinMaxCtx { char *z; /* The best so far */ char zBuf[28]; /* Space that can be used for storage */ }; /* ** Routines to implement min() and max() aggregate functions. */ static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv){ Mem *pArg = (Mem *)argv[0]; Mem *pBest; |
︙ | ︙ | |||
935 936 937 938 939 940 941 | } }else{ sqlite3VdbeMemCopy(pBest, pArg); } } static void minMaxFinalize(sqlite3_context *context){ sqlite3_value *pRes; | | < | | | | < | 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 | } }else{ sqlite3VdbeMemCopy(pBest, pArg); } } static void minMaxFinalize(sqlite3_context *context){ sqlite3_value *pRes; pRes = (sqlite3_value *)sqlite3_aggregate_context(context, sizeof(Mem)); if( pRes->flags ){ sqlite3_result_value(context, pRes); } sqlite3VdbeMemRelease(pRes); } /* ** This function registered all of the above C functions as SQL ** functions. This should be the only routine in this file with ** external linkage. |
︙ | ︙ | |||
979 980 981 982 983 984 985 986 987 988 989 990 991 992 | { "upper", 1, 0, SQLITE_UTF8, 0, upperFunc }, { "lower", 1, 0, SQLITE_UTF8, 0, lowerFunc }, { "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc }, { "coalesce", 0, 0, SQLITE_UTF8, 0, 0 }, { "coalesce", 1, 0, SQLITE_UTF8, 0, 0 }, { "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc }, { "random", -1, 0, SQLITE_UTF8, 0, randomFunc }, { "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc }, { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc}, { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc }, { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid }, { "changes", 0, 1, SQLITE_UTF8, 0, changes }, { "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes }, #ifdef SQLITE_SOUNDEX | > > > | 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 | { "upper", 1, 0, SQLITE_UTF8, 0, upperFunc }, { "lower", 1, 0, SQLITE_UTF8, 0, lowerFunc }, { "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc }, { "coalesce", 0, 0, SQLITE_UTF8, 0, 0 }, { "coalesce", 1, 0, SQLITE_UTF8, 0, 0 }, { "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc }, { "random", -1, 0, SQLITE_UTF8, 0, randomFunc }, { "like", 2, 0, SQLITE_UTF8, 0, likeFunc }, { "like", 3, 0, SQLITE_UTF8, 0, likeFunc }, { "glob", 2, 0, SQLITE_UTF8, 0, globFunc }, { "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc }, { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc}, { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc }, { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid }, { "changes", 0, 1, SQLITE_UTF8, 0, changes }, { "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes }, #ifdef SQLITE_SOUNDEX |
︙ | ︙ | |||
1007 1008 1009 1010 1011 1012 1013 | u8 needCollSeq; void (*xStep)(sqlite3_context*,int,sqlite3_value**); void (*xFinalize)(sqlite3_context*); } aAggs[] = { { "min", 1, 0, 1, minmaxStep, minMaxFinalize }, { "max", 1, 2, 1, minmaxStep, minMaxFinalize }, { "sum", 1, 0, 0, sumStep, sumFinalize }, | < | 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 | u8 needCollSeq; void (*xStep)(sqlite3_context*,int,sqlite3_value**); void (*xFinalize)(sqlite3_context*); } aAggs[] = { { "min", 1, 0, 1, minmaxStep, minMaxFinalize }, { "max", 1, 2, 1, minmaxStep, minMaxFinalize }, { "sum", 1, 0, 0, sumStep, sumFinalize }, { "avg", 1, 0, 0, sumStep, avgFinalize }, { "count", 0, 0, 0, countStep, countFinalize }, { "count", 1, 0, 0, countStep, countFinalize }, }; int i; for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ |
︙ | ︙ | |||
1033 1034 1035 1036 1037 1038 1039 | pFunc->needCollSeq = 1; } } } #ifndef SQLITE_OMIT_ALTERTABLE sqlite3AlterFunctions(db); #endif | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 | pFunc->needCollSeq = 1; } } } #ifndef SQLITE_OMIT_ALTERTABLE sqlite3AlterFunctions(db); #endif for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){ void *pArg = 0; switch( aAggs[i].argType ){ case 1: pArg = db; break; case 2: pArg = (void *)(-1); break; } sqlite3_create_function(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8, pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize); if( aAggs[i].needCollSeq ){ FuncDef *pFunc = sqlite3FindFunction( db, aAggs[i].zName, strlen(aAggs[i].zName), aAggs[i].nArg, SQLITE_UTF8, 0); if( pFunc && aAggs[i].needCollSeq ){ pFunc->needCollSeq = 1; } } } sqlite3RegisterDateTimeFunctions(db); } |
Changes to SQLite.Interop/src/hash.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the implementation of generic hash-tables ** used in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the implementation of generic hash-tables ** used in SQLite. ** ** $Id: hash.c,v 1.1 2005/03/01 16:04:29 rmsimpson Exp $ */ #include "sqliteInt.h" #include <assert.h> /* Turn bulk memory into a hash table object by initializing the ** fields of the Hash structure. ** |
︙ | ︙ | |||
290 291 292 293 294 295 296 | pEntry->chain = 0; } if( pH->copyKey && elem->pKey ){ sqliteFree(elem->pKey); } sqliteFree( elem ); pH->count--; | < < < < < | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | pEntry->chain = 0; } if( pH->copyKey && elem->pKey ){ sqliteFree(elem->pKey); } sqliteFree( elem ); pH->count--; } /* Attempt to locate an element of the hash table pH with a key ** that matches pKey,nKey. Return the data for this element if it is ** found, or NULL if there is no match. */ void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){ |
︙ | ︙ |
Changes to SQLite.Interop/src/hash.h.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the header file for the generic hash-table implemenation ** used in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the header file for the generic hash-table implemenation ** used in SQLite. ** ** $Id: hash.h,v 1.1 2005/03/01 16:04:29 rmsimpson Exp $ */ #ifndef _SQLITE_HASH_H_ #define _SQLITE_HASH_H_ /* Forward declarations of structures. */ typedef struct Hash Hash; typedef struct HashElem HashElem; |
︙ | ︙ |
Changes to SQLite.Interop/src/insert.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** | | | | | < | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** ** $Id: insert.c,v 1.1 2005/03/01 16:04:30 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Set P3 of the most recently inserted opcode to a column affinity ** string for index pIdx. A column affinity string has one character ** for each column in the table, according to the affinity of the column: ** ** Character Column affinity ** ------------------------------ ** 'n' NUMERIC ** 'i' INTEGER ** 't' TEXT ** 'o' NONE */ void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ if( !pIdx->zColAff ){ /* The first time a column affinity string for a particular index is ** required, it is allocated and populated here. It is then stored as ** a member of the Index structure for subsequent use. ** |
︙ | ︙ | |||
58 59 60 61 62 63 64 | ** Set P3 of the most recently inserted opcode to a column affinity ** string for table pTab. A column affinity string has one character ** for each column indexed by the index, according to the affinity of the ** column: ** ** Character Column affinity ** ------------------------------ | | | | < | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | ** Set P3 of the most recently inserted opcode to a column affinity ** string for table pTab. A column affinity string has one character ** for each column indexed by the index, according to the affinity of the ** column: ** ** Character Column affinity ** ------------------------------ ** 'n' NUMERIC ** 'i' INTEGER ** 't' TEXT ** 'o' NONE */ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ /* The first time a column affinity string for a particular table ** is required, it is allocated and populated here. It is then ** stored as a member of the Table structure for subsequent use. ** ** The column affinity string will eventually be deleted by |
︙ | ︙ | |||
100 101 102 103 104 105 106 | ** Return non-zero if SELECT statement p opens the table with rootpage ** iTab in database iDb. This is used to see if a statement of the form ** "INSERT INTO <iDb, iTab> SELECT ..." can run without using temporary ** table for the results of the SELECT. ** ** No checking is done for sub-selects that are part of expressions. */ | | | | | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | ** Return non-zero if SELECT statement p opens the table with rootpage ** iTab in database iDb. This is used to see if a statement of the form ** "INSERT INTO <iDb, iTab> SELECT ..." can run without using temporary ** table for the results of the SELECT. ** ** No checking is done for sub-selects that are part of expressions. */ static int selectReadsTable(Select *p, int iDb, int iTab){ int i; struct SrcList_item *pItem; if( p->pSrc==0 ) return 0; for(i=0, pItem=p->pSrc->a; i<p->pSrc->nSrc; i++, pItem++){ if( pItem->pSelect ){ if( selectReadsTable(p, iDb, iTab) ) return 1; }else{ if( pItem->pTab->iDb==iDb && pItem->pTab->tnum==iTab ) return 1; } } return 0; } /* ** This routine is call to handle SQL of the following forms: |
︙ | ︙ | |||
210 211 212 213 214 215 216 | int iSelectLoop = 0; /* Address of code that implements the SELECT */ int iCleanup = 0; /* Address of the cleanup code */ int iInsertBlock = 0; /* Address of the subroutine used to insert data */ int iCntMem = 0; /* Memory cell used for the row counter */ int newIdx = -1; /* Cursor for the NEW table */ Db *pDb; /* The database containing table being inserted into */ int counterMem = 0; /* Memory cell holding AUTOINCREMENT counter */ | < < | < < | | | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | int iSelectLoop = 0; /* Address of code that implements the SELECT */ int iCleanup = 0; /* Address of the cleanup code */ int iInsertBlock = 0; /* Address of the subroutine used to insert data */ int iCntMem = 0; /* Memory cell used for the row counter */ int newIdx = -1; /* Cursor for the NEW table */ Db *pDb; /* The database containing table being inserted into */ int counterMem = 0; /* Memory cell holding AUTOINCREMENT counter */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to insert into a view */ int triggers_exist = 0; /* True if there are FOR EACH ROW triggers */ #endif #ifndef SQLITE_OMIT_AUTOINCREMENT int counterRowid; /* Memory cell holding rowid of autoinc counter */ #endif if( pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup; db = pParse->db; /* Locate the table into which we will be inserting new information. */ assert( pTabList->nSrc==1 ); zTab = pTabList->a[0].zName; if( zTab==0 ) goto insert_cleanup; pTab = sqlite3SrcListLookup(pParse, pTabList); if( pTab==0 ){ goto insert_cleanup; } assert( pTab->iDb<db->nDb ); pDb = &db->aDb[pTab->iDb]; zDb = pDb->zName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ goto insert_cleanup; } /* Figure out if we have any triggers and if the table being ** inserted into is a view |
︙ | ︙ | |||
272 273 274 275 276 277 278 279 280 281 282 283 284 | if( pTab==0 ) goto insert_cleanup; /* If pTab is really a view, make sure it has been initialized. */ if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){ goto insert_cleanup; } /* Allocate a VDBE */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto insert_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); | > > > > > > > | > | > | | | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | if( pTab==0 ) goto insert_cleanup; /* If pTab is really a view, make sure it has been initialized. */ if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){ goto insert_cleanup; } /* Ensure all required collation sequences are available. */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){ goto insert_cleanup; } } /* Allocate a VDBE */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto insert_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, pTab->iDb); /* if there are row triggers, allocate a temp table for new.* references. */ if( triggers_exist ){ newIdx = pParse->nTab++; } #ifndef SQLITE_OMIT_AUTOINCREMENT /* If this is an AUTOINCREMENT table, look up the sequence number in the ** sqlite_sequence table and store it in memory cell counterMem. Also ** remember the rowid of the sqlite_sequence table entry in memory cell ** counterRowid. */ if( pTab->autoInc ){ int iCur = pParse->nTab; int base = sqlite3VdbeCurrentAddr(v); counterRowid = pParse->nMem++; counterMem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pDb->pSeqTab->tnum); sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, 2); sqlite3VdbeAddOp(v, OP_Rewind, iCur, base+13); sqlite3VdbeAddOp(v, OP_Column, iCur, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); sqlite3VdbeAddOp(v, OP_Ne, 28417, base+12); sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); sqlite3VdbeAddOp(v, OP_MemStore, counterRowid, 1); sqlite3VdbeAddOp(v, OP_Column, iCur, 1); sqlite3VdbeAddOp(v, OP_MemStore, counterMem, 1); sqlite3VdbeAddOp(v, OP_Goto, 0, base+13); sqlite3VdbeAddOp(v, OP_Next, iCur, base+4); sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } |
︙ | ︙ | |||
329 330 331 332 333 334 335 | int rc, iInitCode; iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); iSelectLoop = sqlite3VdbeCurrentAddr(v); iInsertBlock = sqlite3VdbeMakeLabel(v); /* Resolve the expressions in the SELECT statement and execute it. */ rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock,0,0,0,0); | | < < | > | | | | | | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 | int rc, iInitCode; iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); iSelectLoop = sqlite3VdbeCurrentAddr(v); iInsertBlock = sqlite3VdbeMakeLabel(v); /* Resolve the expressions in the SELECT statement and execute it. */ rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock,0,0,0,0); if( rc || pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup; iCleanup = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Goto, 0, iCleanup); assert( pSelect->pEList ); nColumn = pSelect->pEList->nExpr; /* Set useTempTable to TRUE if the result of the SELECT statement ** should be written into a temporary table. Set to FALSE if each ** row of the SELECT can be written directly into the result table. ** ** A temp table must be used if the table being updated is also one ** of the tables being read by the SELECT statement. Also use a ** temp table in the case of row triggers. */ if( triggers_exist || selectReadsTable(pSelect, pTab->iDb, pTab->tnum) ){ useTempTable = 1; } if( useTempTable ){ /* Generate the subroutine that SELECT calls to process each row of ** the result. Store the result in a temporary table */ srcTab = pParse->nTab++; sqlite3VdbeResolveLabel(v, iInsertBlock); sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqlite3TableAffinityStr(v, pTab); sqlite3VdbeAddOp(v, OP_NewRecno, srcTab, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); sqlite3VdbeAddOp(v, OP_PutIntKey, srcTab, 0); sqlite3VdbeAddOp(v, OP_Return, 0, 0); /* The following code runs first because the GOTO at the very top ** of the program jumps to it. Create the temporary table, then jump ** back up and execute the SELECT code above. */ sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v)); sqlite3VdbeAddOp(v, OP_OpenTemp, srcTab, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, srcTab, nColumn); sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop); sqlite3VdbeResolveLabel(v, iCleanup); }else{ sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v)); } }else{ /* This is the case if the data for the INSERT is coming from a VALUES ** clause */ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); |
︙ | ︙ | |||
464 465 466 467 468 469 470 | sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol); } /* Initialize the count of rows to be inserted */ if( db->flags & SQLITE_CountRows ){ iCntMem = pParse->nMem++; | > | | 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 | sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol); } /* Initialize the count of rows to be inserted */ if( db->flags & SQLITE_CountRows ){ iCntMem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_Integer, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, iCntMem, 1); } /* Open tables and indices if there are no row triggers */ if( !triggers_exist ){ base = pParse->nTab; sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite); } |
︙ | ︙ | |||
540 541 542 543 544 545 546 | ** do not attempt any conversions before assembling the record. ** If this is a real table, attempt conversions as required by the ** table column affinities. */ if( !isView ){ sqlite3TableAffinityStr(v, pTab); } | | | | | | | | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 | ** do not attempt any conversions before assembling the record. ** If this is a real table, attempt conversions as required by the ** table column affinities. */ if( !isView ){ sqlite3TableAffinityStr(v, pTab); } sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0); /* Fire BEFORE or INSTEAD OF triggers */ if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab, newIdx, -1, onError, endOfLoop) ){ goto insert_cleanup; } } /* If any triggers exists, the opening of tables and indices is deferred ** until now. */ if( triggers_exist && !isView ){ base = pParse->nTab; sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite); } /* Push the record number for the new entry onto the stack. The ** record number is a randomly generate integer created by NewRecno ** except when the table has an INTEGER PRIMARY KEY column, in which ** case the record number is the same as that column. */ if( !isView ){ if( keyColumn>=0 ){ if( useTempTable ){ sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn); }else if( pSelect ){ sqlite3VdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1); }else{ sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr); } /* If the PRIMARY KEY expression is NULL, then use OP_NewRecno ** to generate a unique primary key value. */ sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem); sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); }else{ sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem); } #ifndef SQLITE_OMIT_AUTOINCREMENT if( pTab->autoInc ){ sqlite3VdbeAddOp(v, OP_MemMax, counterMem, 0); } #endif /* SQLITE_OMIT_AUTOINCREMENT */ /* Push onto the stack, data for all columns of the new entry, beginning ** with the first column. */ for(i=0; i<pTab->nCol; i++){ if( i==pTab->iPKey ){ /* The value of the INTEGER PRIMARY KEY column is always a NULL. ** Whenever this column is read, the record number will be substituted ** in its place. So will fill this column with a NULL to avoid ** taking up data space with information that will never be used. */ sqlite3VdbeAddOp(v, OP_String8, 0, 0); continue; } if( pColumn==0 ){ j = i; }else{ for(j=0; j<pColumn->nId; j++){ if( pColumn->a[j].idx==i ) break; |
︙ | ︙ | |||
629 630 631 632 633 634 635 | sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0, (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1); } /* Update the count of rows that are inserted */ if( (db->flags & SQLITE_CountRows)!=0 ){ | | | 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 | sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0, (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1); } /* Update the count of rows that are inserted */ if( (db->flags & SQLITE_CountRows)!=0 ){ sqlite3VdbeAddOp(v, OP_MemIncr, iCntMem, 0); } if( triggers_exist ){ /* Close all tables opened */ if( !isView ){ sqlite3VdbeAddOp(v, OP_Close, base, 0); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ |
︙ | ︙ | |||
677 678 679 680 681 682 683 | /* Update the sqlite_sequence table by storing the content of the ** counter value in memory counterMem back into the sqlite_sequence ** table. */ if( pTab->autoInc ){ int iCur = pParse->nTab; int base = sqlite3VdbeCurrentAddr(v); | > | > | | | | | | | | | | 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 | /* Update the sqlite_sequence table by storing the content of the ** counter value in memory counterMem back into the sqlite_sequence ** table. */ if( pTab->autoInc ){ int iCur = pParse->nTab; int base = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, iCur, pDb->pSeqTab->tnum); sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, 2); sqlite3VdbeAddOp(v, OP_MemLoad, counterRowid, 0); sqlite3VdbeAddOp(v, OP_NotNull, -1, base+7); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_NewRecno, iCur, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); sqlite3VdbeAddOp(v, OP_MemLoad, counterMem, 0); sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0); sqlite3VdbeAddOp(v, OP_PutIntKey, iCur, 0); sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } #endif /* ** Return the number of rows inserted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0); sqlite3VdbeAddOp(v, OP_Callback, 1, 0); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, "rows inserted", P3_STATIC); } insert_cleanup: sqlite3SrcListDelete(pTabList); if( pList ) sqlite3ExprListDelete(pList); if( pSelect ) sqlite3SelectDelete(pSelect); sqlite3IdListDelete(pColumn); } /* ** Generate code to do a constraint check prior to an INSERT or an UPDATE. ** ** When this routine is called, the stack contains (from bottom to top) ** the following values: ** ** 1. The recno of the row to be updated before the update. This ** value is omitted unless we are doing an UPDATE that involves a ** change to the record number. ** ** 2. The recno of the row after the update. ** ** 3. The data in the first column of the entry after the update. ** ** i. Data from middle columns... ** ** N. The data in the last column of the entry after the update. ** ** The old recno shown as entry (1) above is omitted unless both isUpdate ** and recnoChng are 1. isUpdate is true for UPDATEs and false for ** INSERTs and recnoChng is true if the record number is being changed. ** ** The code generated by this routine pushes additional entries onto ** the stack which are the keys for new index entries for the new record. ** The order of index keys is the same as the order of the indices on ** the pTable->pIndex list. A key is only created for index i if ** aIdxUsed!=0 and aIdxUsed[i]!=0. ** |
︙ | ︙ | |||
793 794 795 796 797 798 799 | ** Without the isUpdate flag, the "base" cursor might be moved. */ void sqlite3GenerateConstraintChecks( Parse *pParse, /* The parser context */ Table *pTab, /* the table into which we are inserting */ int base, /* Index of a read/write cursor pointing at pTab */ char *aIdxUsed, /* Which indices are used. NULL means all are used */ | | > | | 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 | ** Without the isUpdate flag, the "base" cursor might be moved. */ void sqlite3GenerateConstraintChecks( Parse *pParse, /* The parser context */ Table *pTab, /* the table into which we are inserting */ int base, /* Index of a read/write cursor pointing at pTab */ char *aIdxUsed, /* Which indices are used. NULL means all are used */ int recnoChng, /* True if the record number will change */ int isUpdate, /* True for UPDATE, False for INSERT */ int overrideError, /* Override onError to this if not OE_Default */ int ignoreDest /* Jump to this label on an OE_Ignore resolution */ ){ int i; Vdbe *v; int nCol; int onError; int addr; int extra; int iCur; Index *pIdx; int seenReplace = 0; int jumpInst1=0, jumpInst2; int contAddr; int hasTwoRecnos = (isUpdate && recnoChng); v = sqlite3GetVdbe(pParse); assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ nCol = pTab->nCol; /* Test all NOT NULL constraints. |
︙ | ︙ | |||
847 848 849 850 851 852 853 | sqlite3VdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError); sqlite3SetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName, " may not be NULL", (char*)0); sqlite3VdbeChangeP3(v, -1, zMsg, P3_DYNAMIC); break; } case OE_Ignore: { | | | | < < < < < < < < < < < | | 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 | sqlite3VdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError); sqlite3SetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName, " may not be NULL", (char*)0); sqlite3VdbeChangeP3(v, -1, zMsg, P3_DYNAMIC); break; } case OE_Ignore: { sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest); break; } case OE_Replace: { sqlite3ExprCode(pParse, pTab->aCol[i].pDflt); sqlite3VdbeAddOp(v, OP_Push, nCol-i, 0); break; } } sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v)); } /* Test all CHECK constraints */ /**** TBD ****/ /* If we have an INTEGER PRIMARY KEY, make sure the primary key ** of the new record does not previously exist. Except, if this ** is an UPDATE and the primary key is not changing, that is OK. */ if( recnoChng ){ onError = pTab->keyConf; if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = OE_Abort; } |
︙ | ︙ | |||
909 910 911 912 913 914 915 | sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, "PRIMARY KEY must be unique", P3_STATIC); break; } case OE_Replace: { sqlite3GenerateRowIndexDelete(pParse->db, v, pTab, base, 0); if( isUpdate ){ | | | > | | | 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 | sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, "PRIMARY KEY must be unique", P3_STATIC); break; } case OE_Replace: { sqlite3GenerateRowIndexDelete(pParse->db, v, pTab, base, 0); if( isUpdate ){ sqlite3VdbeAddOp(v, OP_Dup, nCol+hasTwoRecnos, 1); sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); } seenReplace = 1; break; } case OE_Ignore: { assert( seenReplace==0 ); sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest); break; } } contAddr = sqlite3VdbeCurrentAddr(v); sqlite3VdbeChangeP2(v, jumpInst2, contAddr); if( isUpdate ){ sqlite3VdbeChangeP2(v, jumpInst1, contAddr); sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1); sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); } } /* Test all UNIQUE constraints by creating entries for each UNIQUE ** index and making sure that duplicate entries do not already exist. |
︙ | ︙ | |||
949 950 951 952 953 954 955 | int idx = pIdx->aiColumn[i]; if( idx==pTab->iPKey ){ sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1); }else{ sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1); } } | | | | 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 | int idx = pIdx->aiColumn[i]; if( idx==pTab->iPKey ){ sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1); }else{ sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1); } } jumpInst1 = sqlite3VdbeAddOp(v, OP_MakeRecord, pIdx->nColumn, (1<<24)); sqlite3IndexAffinityStr(v, pIdx); /* Find out what action to take in case there is an indexing conflict */ onError = pIdx->onError; if( onError==OE_None ) continue; /* pIdx is not a UNIQUE index */ if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = OE_Abort; } if( seenReplace ){ if( onError==OE_Ignore ) onError = OE_Replace; else if( onError==OE_Fail ) onError = OE_Abort; } /* Check to see if the new index entry will be unique */ sqlite3VdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1); jumpInst2 = sqlite3VdbeAddOp(v, OP_IsUnique, base+iCur+1, 0); /* Generate code that executes if the new index entry is not unique */ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail || onError==OE_Ignore || onError==OE_Replace ); switch( onError ){ case OE_Rollback: |
︙ | ︙ | |||
1004 1005 1006 1007 1008 1009 1010 | strcpy(&zErrMsg[n1], pIdx->nColumn>1 ? " are not unique" : " is not unique"); sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, zErrMsg, 0); break; } case OE_Ignore: { assert( seenReplace==0 ); | | | > > | | | | | | | < | < < | < | < > | > > < < | < | > | 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 | strcpy(&zErrMsg[n1], pIdx->nColumn>1 ? " are not unique" : " is not unique"); sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, zErrMsg, 0); break; } case OE_Ignore: { assert( seenReplace==0 ); sqlite3VdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRecnos, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest); break; } case OE_Replace: { sqlite3GenerateRowDelete(pParse->db, v, pTab, base, 0); if( isUpdate ){ sqlite3VdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1); sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); } seenReplace = 1; break; } } contAddr = sqlite3VdbeCurrentAddr(v); assert( contAddr<(1<<24) ); #if NULL_DISTINCT_FOR_UNIQUE sqlite3VdbeChangeP2(v, jumpInst1, contAddr | (1<<24)); #endif sqlite3VdbeChangeP2(v, jumpInst2, contAddr); } } /* ** This routine generates code to finish the INSERT or UPDATE operation ** that was started by a prior call to sqlite3GenerateConstraintChecks. ** The stack must contain keys for all active indices followed by data ** and the recno for the new entry. This routine creates the new ** entries in all indices and in the main table. ** ** The arguments to this routine should be the same as the first six ** arguments to sqlite3GenerateConstraintChecks. */ void sqlite3CompleteInsertion( Parse *pParse, /* The parser context */ Table *pTab, /* the table into which we are inserting */ int base, /* Index of a read/write cursor pointing at pTab */ char *aIdxUsed, /* Which indices are used. NULL means all are used */ int recnoChng, /* True if the record number will change */ int isUpdate, /* True for UPDATE, False for INSERT */ int newIdx /* Index of NEW table for triggers. -1 if none */ ){ int i; Vdbe *v; int nIdx; Index *pIdx; int pik_flags; v = sqlite3GetVdbe(pParse); assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){} for(i=nIdx-1; i>=0; i--){ if( aIdxUsed && aIdxUsed[i]==0 ) continue; sqlite3VdbeAddOp(v, OP_IdxPut, base+i+1, 0); } sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); sqlite3TableAffinityStr(v, pTab); #ifndef SQLITE_OMIT_TRIGGER if( newIdx>=0 ){ sqlite3VdbeAddOp(v, OP_Dup, 1, 0); sqlite3VdbeAddOp(v, OP_Dup, 1, 0); sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0); } #endif if( pParse->nested ){ pik_flags = 0; }else{ pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID)); } sqlite3VdbeAddOp(v, OP_PutIntKey, base, pik_flags); if( isUpdate && recnoChng ){ sqlite3VdbeAddOp(v, OP_Pop, 1, 0); } } /* ** Generate code that will open cursors for a table and for all ** indices of that table. The "base" parameter is the cursor number used ** for the table. Indices are opened on subsequent cursors. */ void sqlite3OpenTableAndIndices( Parse *pParse, /* Parsing context */ Table *pTab, /* Table to be opened */ int base, /* Cursor number assigned to the table */ int op /* OP_OpenRead or OP_OpenWrite */ ){ int i; Index *pIdx; Vdbe *v = sqlite3GetVdbe(pParse); assert( v!=0 ); sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqlite3VdbeAddOp(v, op, base, pTab->tnum); VdbeComment((v, "# %s", pTab->zName)); sqlite3VdbeAddOp(v, OP_SetNumColumns, base, pTab->nCol); for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, (char*)&pIdx->keyInfo, P3_KEYINFO); } if( pParse->nTab<=base+i ){ pParse->nTab = base+i; } } |
Changes to SQLite.Interop/src/keywordhash.h.
|
| | | | | | | | | | < | | | | | | | | > > < < | | > | < | | < | | > | | | | | | > | > > < < < | | | | | < < > > | > > | < < | < < | > | | | > | | | | | < | | > | < | | | < | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | /* Hash score: 148 */ static int keywordCode(const char *z, int n){ static const char zText[504] = "ABORTABLEFTEMPORARYAFTERAISELECTHENDATABASEACHECKEYALTEREFERENCES" "CAPELSEXCEPTRANSACTIONATURALIKEXCLUSIVEXISTSTATEMENTRIGGEREINDEX" "PLAINITIALLYANDEFAULTATTACHAVINGLOBEFOREIGNORENAMEAUTOINCREMENT" "BEGINNEREPLACEBETWEENOTNULLIMITBYCASCADEFERRABLECASECOLLATECOMMIT" "CONFLICTCONSTRAINTERSECTCREATECROSSCURRENT_DATECURRENT_TIMESTAMP" "RAGMATCHDEFERREDELETEDESCDETACHDISTINCTDROPRIMARYFAILFROMFULL" "GROUPDATEIMMEDIATEINSERTINSTEADINTOFFSETISNULLJOINORDERESTRICT" "OUTERIGHTROLLBACKROWHENUNIONUNIQUEUSINGVACUUMVALUESVIEWHERE"; static const unsigned char aHash[127] = { 87, 78, 99, 86, 0, 4, 0, 0, 106, 0, 72, 0, 0, 90, 43, 0, 88, 0, 98, 101, 92, 0, 0, 9, 0, 0, 105, 0, 102, 96, 0, 10, 46, 0, 40, 0, 0, 61, 66, 0, 60, 14, 0, 0, 35, 80, 0, 100, 69, 0, 0, 26, 0, 73, 59, 0, 12, 0, 107, 37, 11, 0, 75, 39, 20, 0, 0, 0, 34, 79, 51, 33, 48, 15, 84, 0, 36, 0, 70, 21, 0, 67, 0, 0, 0, 0, 45, 62, 17, 83, 32, 64, 82, 0, 1, 0, 13, 50, 56, 8, 0, 104, 71, 94, 52, 6, 55, 0, 0, 47, 89, 0, 97, 0, 65, 0, 0, 23, 0, 108, 49, 54, 0, 2, 53, 0, 103, }; static const unsigned char aNext[108] = { 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 18, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 44, 0, 0, 0, 30, 57, 0, 0, 0, 0, 0, 0, 0, 68, 41, 0, 0, 0, 0, 19, 58, 16, 0, 77, 0, 63, 0, 81, 31, 0, 0, 0, 0, 0, 0, 0, 38, 91, 93, 0, 0, 95, 22, 29, 76, 0, 25, 85, 0, 28, 0, 74, 0, }; static const unsigned char aLen[108] = { 5, 5, 4, 4, 9, 2, 5, 5, 6, 4, 3, 8, 2, 4, 5, 3, 5, 10, 6, 4, 6, 11, 2, 7, 4, 9, 6, 9, 7, 7, 5, 7, 9, 3, 3, 7, 6, 6, 4, 6, 3, 7, 6, 6, 13, 2, 2, 5, 5, 7, 7, 3, 7, 4, 5, 2, 7, 3, 10, 4, 7, 6, 8, 10, 9, 6, 5, 12, 12, 17, 6, 5, 8, 6, 4, 6, 8, 2, 4, 7, 4, 4, 4, 5, 6, 9, 6, 7, 4, 2, 6, 3, 6, 4, 5, 8, 5, 5, 8, 3, 4, 5, 6, 5, 6, 6, 4, 5, }; static const unsigned short int aOffset[108] = { 0, 4, 7, 10, 10, 14, 19, 23, 26, 31, 33, 35, 40, 42, 44, 48, 51, 55, 63, 68, 71, 76, 85, 86, 92, 95, 103, 108, 116, 122, 124, 127, 132, 137, 141, 143, 150, 155, 160, 163, 165, 165, 169, 173, 179, 181, 183, 192, 195, 199, 206, 212, 212, 215, 218, 223, 225, 226, 230, 240, 244, 251, 257, 265, 272, 281, 287, 292, 304, 304, 320, 324, 329, 336, 342, 346, 352, 353, 360, 363, 370, 374, 378, 382, 385, 391, 400, 406, 413, 416, 416, 419, 422, 428, 432, 436, 444, 448, 453, 461, 463, 467, 472, 478, 483, 489, 495, 498, }; static const unsigned char aCode[108] = { TK_ABORT, TK_TABLE, TK_JOIN_KW, TK_TEMP, TK_TEMP, TK_OR, TK_AFTER, TK_RAISE, TK_SELECT, TK_THEN, TK_END, TK_DATABASE, TK_AS, TK_EACH, TK_CHECK, TK_KEY, TK_ALTER, TK_REFERENCES, TK_ESCAPE, TK_ELSE, TK_EXCEPT, TK_TRANSACTION,TK_ON, TK_JOIN_KW, TK_LIKE, TK_EXCLUSIVE, TK_EXISTS, TK_STATEMENT, TK_TRIGGER, TK_REINDEX, TK_INDEX, TK_EXPLAIN, TK_INITIALLY, TK_ALL, TK_AND, TK_DEFAULT, TK_ATTACH, TK_HAVING, TK_GLOB, TK_BEFORE, TK_FOR, TK_FOREIGN, TK_IGNORE, TK_RENAME, TK_AUTOINCR, TK_TO, TK_IN, TK_BEGIN, TK_JOIN_KW, TK_REPLACE, TK_BETWEEN, TK_NOT, TK_NOTNULL, TK_NULL, TK_LIMIT, TK_BY, TK_CASCADE, TK_ASC, TK_DEFERRABLE, TK_CASE, TK_COLLATE, TK_COMMIT, TK_CONFLICT, TK_CONSTRAINT, TK_INTERSECT, TK_CREATE, TK_JOIN_KW, TK_CDATE, TK_CTIME, TK_CTIMESTAMP, TK_PRAGMA, TK_MATCH, TK_DEFERRED, TK_DELETE, TK_DESC, TK_DETACH, TK_DISTINCT, TK_IS, TK_DROP, TK_PRIMARY, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_GROUP, TK_UPDATE, TK_IMMEDIATE, TK_INSERT, TK_INSTEAD, TK_INTO, TK_OF, TK_OFFSET, TK_SET, TK_ISNULL, TK_JOIN, TK_ORDER, TK_RESTRICT, TK_JOIN_KW, TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_WHEN, TK_UNION, TK_UNIQUE, TK_USING, TK_VACUUM, TK_VALUES, TK_VIEW, TK_WHERE, }; int h, i; if( n<2 ) return TK_ID; h = ((sqlite3UpperToLower[((unsigned char*)z)[0]]*4) ^ (sqlite3UpperToLower[((unsigned char*)z)[n-1]]*3) ^ n) % 127; for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){ if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){ return aCode[i]; } } return TK_ID; } int sqlite3KeywordCode(const char *z, int n){ return keywordCode(z, n); } |
Changes to SQLite.Interop/src/legacy.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: legacy.c,v 1.1 2005/03/01 16:04:30 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* |
︙ | ︙ | |||
66 67 68 69 70 71 72 73 74 75 76 77 78 79 | db->nChange += nChange; nCallback = 0; nCol = sqlite3_column_count(pStmt); azCols = sqliteMalloc(2*nCol*sizeof(const char *)); if( nCol && !azCols ){ goto exec_out; } while( 1 ){ int i; rc = sqlite3_step(pStmt); | > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | db->nChange += nChange; nCallback = 0; nCol = sqlite3_column_count(pStmt); azCols = sqliteMalloc(2*nCol*sizeof(const char *)); if( nCol && !azCols ){ rc = SQLITE_NOMEM; goto exec_out; } while( 1 ){ int i; rc = sqlite3_step(pStmt); |
︙ | ︙ | |||
117 118 119 120 121 122 123 | azCols = 0; } exec_out: if( pStmt ) sqlite3_finalize(pStmt); if( azCols ) sqliteFree(azCols); | | < < | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | azCols = 0; } exec_out: if( pStmt ) sqlite3_finalize(pStmt); if( azCols ) sqliteFree(azCols); if( sqlite3_malloc_failed ){ rc = SQLITE_NOMEM; } if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){ *pzErrMsg = malloc(1+strlen(sqlite3_errmsg(db))); if( *pzErrMsg ){ strcpy(*pzErrMsg, sqlite3_errmsg(db)); } }else if( pzErrMsg ){ *pzErrMsg = 0; } return rc; } |
Changes to SQLite.Interop/src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.1 2005/03/01 16:04:30 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** The following constant value is used by the SQLITE_BIGENDIAN and ** SQLITE_LITTLEENDIAN macros. */ const int sqlite3one = 1; /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. */ static void corruptSchema(InitData *pData, const char *zExtra){ if( !sqlite3_malloc_failed ){ sqlite3SetString(pData->pzErrMsg, "malformed database schema", zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0); } } /* ** This is the callback routine for the code that initializes the ** database. See sqlite3Init() below for additional information. ** This routine is also called from the OP_ParseSchema opcode of the VDBE. ** ** Each callback contains the following information: ** ** argv[0] = name of thing being created ** argv[1] = root page number for table or index. NULL for trigger or view. ** argv[2] = SQL text for the CREATE statement. ** argv[3] = "1" for temporary files, "0" for main database, "2" or more ** for auxiliary database files. ** */ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ InitData *pData = (InitData*)pInit; sqlite3 *db = pData->db; int iDb; assert( argc==4 ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[1]==0 || argv[3]==0 ){ corruptSchema(pData, 0); return 1; } iDb = atoi(argv[3]); assert( iDb>=0 && iDb<db->nDb ); if( argv[2] && argv[2][0] ){ /* Call the parser to process a CREATE TABLE, INDEX or VIEW. ** But because db->init.busy is set to 1, no VDBE code is generated ** or executed. All the parser does is build the internal data ** structures that describe the table, index, or view. */ char *zErr; int rc; assert( db->init.busy ); db->init.iDb = iDb; db->init.newTnum = atoi(argv[1]); rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); db->init.iDb = 0; if( SQLITE_OK!=rc ){ corruptSchema(pData, zErr); sqlite3_free(zErr); return rc; } }else{ /* If the SQL column is blank it means this is an index that ** was created to be the PRIMARY KEY or to fulfill a UNIQUE ** constraint for a CREATE TABLE. The index should have already ** been created when we processed the CREATE TABLE. All we have ** to do here is record the root page number for that index. */ Index *pIndex; pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName); if( pIndex==0 || pIndex->tnum!=0 ){ /* This can occur if there exists an index on a TEMP table which ** has the same name as another index on a permanent index. Since ** the permanent table is hidden by the TEMP table, we can also ** safely ignore the index on the permanent table. */ /* Do Nothing */; }else{ pIndex->tnum = atoi(argv[1]); } } return 0; } /* ** Attempt to read the database schema and initialize internal ** data structures for a single database file. The index of the ** database file is given by iDb. iDb==0 is used for the main ** database. iDb==1 should never be used. iDb>=2 is used for ** auxiliary databases. Return one of the SQLITE_ error codes to ** indicate success or failure. */ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ int rc; BtCursor *curMain; int size; Table *pTab; char const *azArg[5]; char zDbNum[30]; int meta[10]; InitData initData; char const *zMasterSchema; char const *zMasterName; /* ** The master database table has a structure like this */ static const char master_schema[] = "CREATE TABLE sqlite_master(\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")" ; static const char temp_master_schema[] = "CREATE TEMP TABLE sqlite_temp_master(\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")" ; assert( iDb>=0 && iDb<db->nDb ); /* zMasterSchema and zInitScript are set to point at the master schema ** and initialisation script appropriate for the database being ** initialised. zMasterName is the name of the master table. */ if( iDb==1 ){ zMasterSchema = temp_master_schema; zMasterName = TEMP_MASTER_NAME; }else{ zMasterSchema = master_schema; zMasterName = MASTER_NAME; } /* Construct the schema tables. */ sqlite3SafetyOff(db); azArg[0] = zMasterName; azArg[1] = "1"; azArg[2] = zMasterSchema; sprintf(zDbNum, "%d", iDb); azArg[3] = zDbNum; azArg[4] = 0; initData.db = db; initData.pzErrMsg = pzErrMsg; rc = sqlite3InitCallback(&initData, 4, (char **)azArg, 0); if( rc!=SQLITE_OK ){ sqlite3SafetyOn(db); return rc; } pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName); if( pTab ){ pTab->readOnly = 1; } sqlite3SafetyOn(db); /* Create a cursor to hold the database open */ if( db->aDb[iDb].pBt==0 ){ if( iDb==1 ) DbSetProperty(db, 1, DB_SchemaLoaded); return SQLITE_OK; } rc = sqlite3BtreeCursor(db->aDb[iDb].pBt, MASTER_ROOT, 0, 0, 0, &curMain); if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){ sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); return rc; } /* Get the database meta information. ** ** Meta values are as follows: ** meta[0] Schema cookie. Changes with each schema change. ** meta[1] File format of schema layer. ** meta[2] Size of the page cache. ** meta[3] Use freelist if 0. Autovacuum if greater than zero. ** meta[4] Db text encoding. 1:UTF-8 3:UTF-16 LE 4:UTF-16 BE ** meta[5] The user cookie. Used by the application. ** meta[6] ** meta[7] ** meta[8] ** meta[9] ** ** Note: The hash defined SQLITE_UTF* symbols in sqliteInt.h correspond to ** the possible values of meta[4]. */ if( rc==SQLITE_OK ){ int i; for(i=0; rc==SQLITE_OK && i<sizeof(meta)/sizeof(meta[0]); i++){ rc = sqlite3BtreeGetMeta(db->aDb[iDb].pBt, i+1, (u32 *)&meta[i]); } if( rc ){ sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); sqlite3BtreeCloseCursor(curMain); return rc; } }else{ memset(meta, 0, sizeof(meta)); } db->aDb[iDb].schema_cookie = meta[0]; /* If opening a non-empty database, check the text encoding. For the ** main database, set sqlite3.enc to the encoding of the main database. ** For an attached db, it is an error if the encoding is not the same ** as sqlite3.enc. */ if( meta[4] ){ /* text encoding */ if( iDb==0 ){ /* If opening the main database, set db->enc. */ db->enc = (u8)meta[4]; db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0); }else{ /* If opening an attached database, the encoding much match db->enc */ if( meta[4]!=db->enc ){ sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "attached databases must use the same" " text encoding as main database", (char*)0); return SQLITE_ERROR; } } } size = meta[2]; if( size==0 ){ size = MAX_PAGES; } db->aDb[iDb].cache_size = size; if( iDb==0 ){ db->file_format = meta[1]; if( db->file_format==0 ){ /* This happens if the database was initially empty */ db->file_format = 1; } if( db->file_format==2 ){ /* File format 2 is treated exactly as file format 1. New ** databases are created with file format 1. */ db->file_format = 1; } } /* ** file_format==1 Version 3.0.0. ** file_format==2 Version 3.1.3. ** ** Version 3.0 can only use files with file_format==1. Version 3.1.3 ** can read and write files with file_format==1 or file_format==2. */ if( meta[1]>2 ){ sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0); return SQLITE_ERROR; } sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size); /* Read the schema information out of the schema tables */ assert( db->init.busy ); if( rc==SQLITE_EMPTY ){ /* For an empty database, there is nothing to read */ rc = SQLITE_OK; }else{ char *zSql; zSql = sqlite3MPrintf( "SELECT name, rootpage, sql, '%s' FROM '%q'.%s", zDbNum, db->aDb[iDb].zName, zMasterName); sqlite3SafetyOff(db); rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); sqlite3SafetyOn(db); sqliteFree(zSql); sqlite3BtreeCloseCursor(curMain); } if( sqlite3_malloc_failed ){ sqlite3SetString(pzErrMsg, "out of memory", (char*)0); rc = SQLITE_NOMEM; sqlite3ResetInternalSchema(db, 0); } if( rc==SQLITE_OK ){ DbSetProperty(db, iDb, DB_SchemaLoaded); }else{ sqlite3ResetInternalSchema(db, iDb); } return rc; } /* ** Initialize all database files - the main database file, the file ** used to store temporary tables, and any additional database files ** created using ATTACH statements. Return a success code. If an ** error occurs, write an error message into *pzErrMsg. ** ** After the database is initialized, the SQLITE_Initialized ** bit is set in the flags field of the sqlite structure. */ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ int i, rc; if( db->init.busy ) return SQLITE_OK; assert( (db->flags & SQLITE_Initialized)==0 ); rc = SQLITE_OK; db->init.busy = 1; for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; rc = sqlite3InitOne(db, i, pzErrMsg); if( rc ){ sqlite3ResetInternalSchema(db, i); } } /* Once all the other databases have been initialised, load the schema ** for the TEMP database. This is loaded last, as the TEMP database ** schema may contain references to objects in other databases. */ if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ rc = sqlite3InitOne(db, 1, pzErrMsg); if( rc ){ sqlite3ResetInternalSchema(db, 1); } } db->init.busy = 0; if( rc==SQLITE_OK ){ db->flags |= SQLITE_Initialized; sqlite3CommitInternalChanges(db); } if( rc!=SQLITE_OK ){ db->flags &= ~SQLITE_Initialized; } return rc; } /* ** This routine is a no-op if the database schema is already initialised. ** Otherwise, the schema is loaded. An error code is returned. */ int sqlite3ReadSchema(Parse *pParse){ int rc = SQLITE_OK; sqlite3 *db = pParse->db; if( !db->init.busy ){ if( (db->flags & SQLITE_Initialized)==0 ){ rc = sqlite3Init(db, &pParse->zErrMsg); } } assert( rc!=SQLITE_OK || (db->flags & SQLITE_Initialized)||db->init.busy ); if( rc!=SQLITE_OK ){ pParse->rc = rc; pParse->nErr++; } return rc; } /* ** The version of the library */ const char rcsid3[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $"; const char sqlite3_version[] = SQLITE_VERSION; const char *sqlite3_libversion(void){ return sqlite3_version; } |
︙ | ︙ | |||
105 106 107 108 109 110 111 | if( !db ){ return SQLITE_OK; } if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } | < < < < < < < < < < | 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 | if( !db ){ return SQLITE_OK; } if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } /* If there are any outstanding VMs, return SQLITE_BUSY. */ if( db->pVdbe ){ sqlite3Error(db, SQLITE_BUSY, "Unable to close due to unfinalised statements"); return SQLITE_BUSY; } assert( !sqlite3SafetyCheck(db) ); /* FIX ME: db->magic may be set to SQLITE_MAGIC_CLOSED if the database ** cannot be opened for some reason. So this routine needs to run in ** that case. But maybe there should be an extra magic value for the ** "failed to open" state. */ if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){ /* printf("DID NOT CLOSE\n"); fflush(stdout); */ return SQLITE_ERROR; } for(j=0; j<db->nDb; j++){ struct Db *pDb = &db->aDb[j]; if( pDb->pBt ){ sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; } } sqlite3ResetInternalSchema(db, 0); assert( db->nDb<=2 ); assert( db->aDb==db->aDbStatic ); for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ FuncDef *pFunc, *pNext; |
︙ | ︙ | |||
159 160 161 162 163 164 165 166 167 168 169 170 | CollSeq *pColl = (CollSeq *)sqliteHashData(i); sqliteFree(pColl); } sqlite3HashClear(&db->aCollSeq); sqlite3HashClear(&db->aFunc); sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ if( db->pErr ){ sqlite3ValueFree(db->pErr); } db->magic = SQLITE_MAGIC_ERROR; | > > > < < < < < < < < < < < < < < < | < < < < < < > > | > | | | | | | | < | | | | | < < < < < < < < < < < < < < < < < < < < | 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 | CollSeq *pColl = (CollSeq *)sqliteHashData(i); sqliteFree(pColl); } sqlite3HashClear(&db->aCollSeq); sqlite3HashClear(&db->aFunc); sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ if( db->pValue ){ sqlite3ValueFree(db->pValue); } if( db->pErr ){ sqlite3ValueFree(db->pErr); } db->magic = SQLITE_MAGIC_ERROR; sqliteFree(db); return SQLITE_OK; } /* ** Rollback all database files. */ void sqlite3RollbackAll(sqlite3 *db){ int i; for(i=0; i<db->nDb; i++){ if( db->aDb[i].pBt ){ sqlite3BtreeRollback(db->aDb[i].pBt); db->aDb[i].inTrans = 0; } } sqlite3ResetInternalSchema(db, 0); } /* ** Return a static string that describes the kind of error specified in the ** argument. */ const char *sqlite3ErrStr(int rc){ const char *z; switch( rc ){ case SQLITE_ROW: case SQLITE_DONE: case SQLITE_OK: z = "not an error"; break; case SQLITE_ERROR: z = "SQL logic error or missing database"; break; case SQLITE_INTERNAL: z = "internal SQLite implementation flaw"; break; case SQLITE_PERM: z = "access permission denied"; break; case SQLITE_ABORT: z = "callback requested query abort"; break; case SQLITE_BUSY: z = "database is locked"; break; case SQLITE_LOCKED: z = "database table is locked"; break; case SQLITE_NOMEM: z = "out of memory"; break; case SQLITE_READONLY: z = "attempt to write a readonly database"; break; case SQLITE_INTERRUPT: z = "interrupted"; break; case SQLITE_IOERR: z = "disk I/O error"; break; case SQLITE_CORRUPT: z = "database disk image is malformed"; break; case SQLITE_NOTFOUND: z = "table or record not found"; break; case SQLITE_FULL: z = "database is full"; break; case SQLITE_CANTOPEN: z = "unable to open database file"; break; case SQLITE_PROTOCOL: z = "database locking protocol failure"; break; case SQLITE_EMPTY: z = "table contains no data"; break; case SQLITE_SCHEMA: z = "database schema has changed"; break; case SQLITE_TOOBIG: z = "too much data for one table row"; break; case SQLITE_CONSTRAINT: z = "constraint failed"; break; case SQLITE_MISMATCH: z = "datatype mismatch"; break; case SQLITE_MISUSE: z = "library routine called out of sequence";break; case SQLITE_NOLFS: z = "kernel lacks large file support"; break; case SQLITE_AUTH: z = "authorization denied"; break; case SQLITE_FORMAT: z = "auxiliary database format error"; break; case SQLITE_RANGE: z = "bind or column index out of range"; break; case SQLITE_NOTADB: z = "file is encrypted or is not a database";break; default: z = "unknown error"; break; } return z; } /* ** This routine implements a busy callback that sleeps and tries ** again until a timeout value is reached. The timeout value is ** an integer number of milliseconds passed in as the first ** argument. */ static int sqliteDefaultBusyCallback( void *Timeout, /* Maximum amount of time to wait */ int count /* Number of times table has been busy */ ){ #if SQLITE_MIN_SLEEP_MS==1 static const char delays[] = { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 50, 100}; static const short int totals[] = { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228, 287}; # define NDELAY (sizeof(delays)/sizeof(delays[0])) ptr timeout = (ptr)Timeout; ptr delay, prior; if( count <= NDELAY ){ delay = delays[count-1]; prior = totals[count-1]; }else{ delay = delays[NDELAY-1]; prior = totals[NDELAY-1] + delay*(count-NDELAY-1); } if( prior + delay > timeout ){ delay = timeout - prior; if( delay<=0 ) return 0; } sqlite3OsSleep(delay); return 1; #else int timeout = (int)Timeout; if( (count+1)*1000 > timeout ){ return 0; } sqlite3OsSleep(1000); return 1; #endif } /* ** This routine sets the busy callback for an Sqlite database to the ** given callback function with the given argument. */ int sqlite3_busy_handler( sqlite3 *db, int (*xBusy)(void*,int), void *pArg ){ if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } db->busyHandler.xFunc = xBusy; db->busyHandler.pArg = pArg; return SQLITE_OK; } #ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* ** This routine sets the progress callback for an Sqlite database to the ** given callback function with the given argument. The progress callback will |
︙ | ︙ | |||
354 355 356 357 358 359 360 | /* ** This routine installs a default busy handler that waits for the ** specified number of milliseconds before returning 0. */ int sqlite3_busy_timeout(sqlite3 *db, int ms){ if( ms>0 ){ | < | | 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 | /* ** This routine installs a default busy handler that waits for the ** specified number of milliseconds before returning 0. */ int sqlite3_busy_timeout(sqlite3 *db, int ms){ if( ms>0 ){ sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)(ptr)ms); }else{ sqlite3_busy_handler(db, 0, 0); } return SQLITE_OK; } /* |
︙ | ︙ | |||
451 452 453 454 455 456 457 | }else{ sqlite3ExpirePreparedStatements(db); } } p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1); if( p==0 ) return SQLITE_NOMEM; | < | > > > | > < < | < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 | }else{ sqlite3ExpirePreparedStatements(db); } } p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1); if( p==0 ) return SQLITE_NOMEM; p->xFunc = xFunc; p->xStep = xStep; p->xFinalize = xFinal; p->pUserData = pUserData; return SQLITE_OK; } #ifndef SQLITE_OMIT_UTF16 int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, int eTextRep, void *pUserData, void (*xFunc)(sqlite3_context*,int,sqlite3_value**), void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ){ int rc; char const *zFunc8; sqlite3_value *pTmp; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } pTmp = sqlite3GetTransientValue(db); sqlite3ValueSetStr(pTmp, -1, zFunctionName, SQLITE_UTF16NATIVE,SQLITE_STATIC); zFunc8 = sqlite3ValueText(pTmp, SQLITE_UTF8); if( !zFunc8 ){ return SQLITE_NOMEM; } rc = sqlite3_create_function(db, zFunc8, nArg, eTextRep, pUserData, xFunc, xStep, xFinal); return rc; } #endif /* ** Register a trace function. The pArg from the previously registered trace ** is returned. ** ** A NULL trace function means that no tracing is executes. A non-NULL ** trace is a pointer to a function that is invoked at the start of each ** sqlite3_exec(). */ void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ void *pOld = db->pTraceArg; db->xTrace = xTrace; db->pTraceArg = pArg; return pOld; } /*** EXPERIMENTAL *** ** ** Register a function to be invoked when a transaction comments. ** If either function returns non-zero, then the commit becomes a ** rollback. */ void *sqlite3_commit_hook( sqlite3 *db, /* Attach the hook to this database */ int (*xCallback)(void*), /* Function to invoke on each commit */ void *pArg /* Argument to the function */ ){ void *pOld = db->pCommitArg; db->xCommitCallback = xCallback; db->pCommitArg = pArg; return pOld; } /* ** This routine is called to create a connection to a database BTree ** driver. If zFilename is the name of a file, then that file is ** opened and used. If zFilename is the magic name ":memory:" then ** the database is stored in memory (and is thus forgotten as soon as ** the connection is closed.) If zFilename is NULL then the database ** is for temporary use only and is deleted as soon as the connection ** is closed. ** ** A temporary database can be either a disk file (that is automatically ** deleted when the file is closed) or a set of red-black trees held in memory, ** depending on the values of the TEMP_STORE compile-time macro and the ** db->temp_store variable, according to the following chart: ** ** TEMP_STORE db->temp_store Location of temporary database ** ---------- -------------- ------------------------------ ** 0 any file ** 1 1 file |
︙ | ︙ | |||
627 628 629 630 631 632 633 | #endif #if TEMP_STORE==3 zFilename = ":memory:"; #endif #endif /* SQLITE_OMIT_MEMORYDB */ } | | | | | 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 | #endif #if TEMP_STORE==3 zFilename = ":memory:"; #endif #endif /* SQLITE_OMIT_MEMORYDB */ } rc = sqlite3BtreeOpen(zFilename, ppBtree, btree_flags); if( rc==SQLITE_OK ){ sqlite3BtreeSetBusyHandler(*ppBtree, (void*)&db->busyHandler); sqlite3BtreeSetCacheSize(*ppBtree, nCache); } return rc; } /* ** Return UTF-8 encoded English language explanation of the most recent ** error. */ const char *sqlite3_errmsg(sqlite3 *db){ const char *z; if( sqlite3_malloc_failed ){ return sqlite3ErrStr(SQLITE_NOMEM); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ return sqlite3ErrStr(SQLITE_MISUSE); } z = sqlite3_value_text(db->pErr); if( z==0 ){ z = sqlite3ErrStr(db->errCode); } return z; } #ifndef SQLITE_OMIT_UTF16 |
︙ | ︙ | |||
680 681 682 683 684 685 686 | 0, 'c', 0, 'a', 0, 'l', 0, 'l', 0, 'e', 0, 'd', 0, ' ', 0, 'o', 0, 'u', 0, 't', 0, ' ', 0, 'o', 0, 'f', 0, ' ', 0, 's', 0, 'e', 0, 'q', 0, 'u', 0, 'e', 0, 'n', 0, 'c', 0, 'e', 0, 0, 0 }; const void *z; | | | < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > | < < < > < < < | | < < < < | > < < < < < < < < < < < | | < | < | | < < < < < | | < < | | 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 | 0, 'c', 0, 'a', 0, 'l', 0, 'l', 0, 'e', 0, 'd', 0, ' ', 0, 'o', 0, 'u', 0, 't', 0, ' ', 0, 'o', 0, 'f', 0, ' ', 0, 's', 0, 'e', 0, 'q', 0, 'u', 0, 'e', 0, 'n', 0, 'c', 0, 'e', 0, 0, 0 }; const void *z; if( sqlite3_malloc_failed ){ return (void *)(&outOfMemBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ return (void *)(&misuseBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); } z = sqlite3_value_text16(db->pErr); if( z==0 ){ sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode), SQLITE_UTF8, SQLITE_STATIC); z = sqlite3_value_text16(db->pErr); } return z; } #endif /* SQLITE_OMIT_UTF16 */ /* ** Return the most recent error code generated by an SQLite routine. */ int sqlite3_errcode(sqlite3 *db){ if( sqlite3_malloc_failed ){ return SQLITE_NOMEM; } if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } return db->errCode; } /* ** Check schema cookies in all databases. If any cookie is out ** of date, return 0. If all schema cookies are current, return 1. */ static int schemaIsValid(sqlite3 *db){ int iDb; int rc; BtCursor *curTemp; int cookie; int allOk = 1; for(iDb=0; allOk && iDb<db->nDb; iDb++){ Btree *pBt; pBt = db->aDb[iDb].pBt; if( pBt==0 ) continue; rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, 0, &curTemp); if( rc==SQLITE_OK ){ rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie); if( rc==SQLITE_OK && cookie!=db->aDb[iDb].schema_cookie ){ allOk = 0; } sqlite3BtreeCloseCursor(curTemp); } } return allOk; } /* ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. */ int sqlite3_prepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char** pzTail /* OUT: End of parsed string */ ){ Parse sParse; char *zErrMsg = 0; int rc = SQLITE_OK; if( sqlite3_malloc_failed ){ return SQLITE_NOMEM; } assert( ppStmt ); *ppStmt = 0; if( sqlite3SafetyOn(db) ){ return SQLITE_MISUSE; } memset(&sParse, 0, sizeof(sParse)); sParse.db = db; sqlite3RunParser(&sParse, zSql, &zErrMsg); if( sqlite3_malloc_failed ){ rc = SQLITE_NOMEM; sqlite3RollbackAll(db); sqlite3ResetInternalSchema(db, 0); db->flags &= ~SQLITE_InTrans; goto prepare_out; } if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; if( sParse.rc!=SQLITE_OK && sParse.checkSchema && !schemaIsValid(db) ){ sParse.rc = SQLITE_SCHEMA; } if( sParse.rc==SQLITE_SCHEMA ){ sqlite3ResetInternalSchema(db, 0); } if( pzTail ) *pzTail = sParse.zTail; rc = sParse.rc; #ifndef SQLITE_OMIT_EXPLAIN if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ sqlite3VdbeSetNumCols(sParse.pVdbe, 5); sqlite3VdbeSetColName(sParse.pVdbe, 0, "addr", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 1, "opcode", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 2, "p1", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC); } #endif prepare_out: if( sqlite3SafetyOff(db) ){ rc = SQLITE_MISUSE; } if( rc==SQLITE_OK ){ *ppStmt = (sqlite3_stmt*)sParse.pVdbe; }else if( sParse.pVdbe ){ sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe); } if( zErrMsg ){ sqlite3Error(db, rc, "%s", zErrMsg); sqliteFree(zErrMsg); }else{ sqlite3Error(db, rc, 0); } return rc; } #ifndef SQLITE_OMIT_UTF16 /* ** Compile the UTF-16 encoded SQL statement zSql into a statement handle. */ int sqlite3_prepare16( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const void **pzTail /* OUT: End of parsed string */ ){ /* This function currently works by first transforming the UTF-16 ** encoded string to UTF-8, then invoking sqlite3_prepare(). The ** tricky bit is figuring out the pointer to return in *pzTail. */ char const *zSql8 = 0; char const *zTail8 = 0; int rc; sqlite3_value *pTmp; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } pTmp = sqlite3GetTransientValue(db); sqlite3ValueSetStr(pTmp, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); zSql8 = sqlite3ValueText(pTmp, SQLITE_UTF8); if( !zSql8 ){ sqlite3Error(db, SQLITE_NOMEM, 0); return SQLITE_NOMEM; } rc = sqlite3_prepare(db, zSql8, -1, ppStmt, &zTail8); if( zTail8 && pzTail ){ /* If sqlite3_prepare returns a tail pointer, we calculate the ** equivalent pointer into the UTF-16 string by counting the unicode ** characters between zSql8 and zTail8, and then returning a pointer ** the same number of characters into the UTF-16 string. */ int chars_parsed = sqlite3utf8CharLen(zSql8, zTail8-zSql8); *pzTail = (u8 *)zSql + sqlite3utf16ByteLen(zSql, chars_parsed); } return rc; } #endif /* SQLITE_OMIT_UTF16 */ /* ** This routine does the work of opening a database on behalf of ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" ** is UTF-8 encoded. The fourth argument, "def_enc" is one of the TEXT_* ** macros from sqliteInt.h. If we end up creating a new database file ** (not opening an existing one), the text encoding of the database ** will be set to this value. */ static int openDatabase( const char *zFilename, /* Database filename UTF-8 encoded */ sqlite3 **ppDb /* OUT: Returned database handle */ ){ sqlite3 *db; int rc, i; /* Allocate the sqlite data structure */ db = sqliteMalloc( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; db->priorNewRowid = 0; db->magic = SQLITE_MAGIC_BUSY; db->nDb = 2; db->aDb = db->aDbStatic; db->enc = SQLITE_UTF8; db->autoCommit = 1; db->flags |= SQLITE_ShortColNames; sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0); sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0); for(i=0; i<db->nDb; i++){ sqlite3HashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0); sqlite3HashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0); sqlite3HashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0); sqlite3HashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1); } /* Add the default collation sequence BINARY. BINARY works for both UTF-8 ** and UTF-16, so add a version for each to avoid any unnecessary ** conversions. The only error that can occur here is a malloc() failure. */ if( sqlite3_create_collation(db, "BINARY", SQLITE_UTF8, 0,binCollFunc) || sqlite3_create_collation(db, "BINARY", SQLITE_UTF16, 0,binCollFunc) || !(db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0)) ){ rc = db->errCode; assert( rc!=SQLITE_OK ); db->magic = SQLITE_MAGIC_CLOSED; goto opendb_out; } /* Also add a UTF-8 case-insensitive collation sequence. */ sqlite3_create_collation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc); /* Open the backend database driver */ rc = sqlite3BtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt); if( rc!=SQLITE_OK ){ sqlite3Error(db, rc, 0); db->magic = SQLITE_MAGIC_CLOSED; goto opendb_out; } db->aDb[0].zName = "main"; db->aDb[1].zName = "temp"; /* The default safety_level for the main database is 'full' for the temp ** database it is 'NONE'. This matches the pager layer defaults. */ db->aDb[0].safety_level = 3; db->aDb[1].safety_level = 1; /* Register all built-in functions, but do not attempt to read the ** database schema yet. This is delayed until the first time the database ** is accessed. */ sqlite3RegisterBuiltinFunctions(db); sqlite3Error(db, SQLITE_OK, 0); db->magic = SQLITE_MAGIC_OPEN; opendb_out: if( sqlite3_errcode(db)==SQLITE_OK && sqlite3_malloc_failed ){ sqlite3Error(db, SQLITE_NOMEM, 0); } *ppDb = db; return sqlite3_errcode(db); } /* ** Open a new database handle. */ int sqlite3_open( const char *zFilename, |
︙ | ︙ | |||
838 839 840 841 842 843 844 | const void *zFilename, sqlite3 **ppDb ){ char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */ int rc = SQLITE_NOMEM; sqlite3_value *pVal; | < | < < < > | > | 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 | const void *zFilename, sqlite3 **ppDb ){ char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */ int rc = SQLITE_NOMEM; sqlite3_value *pVal; assert( ppDb ); *ppDb = 0; pVal = sqlite3ValueNew(); sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC); zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8); if( zFilename8 ){ rc = openDatabase(zFilename8, ppDb); if( rc==SQLITE_OK && *ppDb ){ sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0); } } if( pVal ){ sqlite3ValueFree(pVal); } return rc; } #endif /* SQLITE_OMIT_UTF16 */ /* ** The following routine destroys a virtual machine that is created by |
︙ | ︙ | |||
892 893 894 895 896 897 898 | */ int sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ rc = sqlite3VdbeReset((Vdbe*)pStmt); | | | 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 | */ int sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ rc = sqlite3VdbeReset((Vdbe*)pStmt); sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0, 0); } return rc; } /* ** Register a new collation sequence with the database handle db. */ |
︙ | ︙ | |||
946 947 948 949 950 951 952 | return SQLITE_BUSY; } sqlite3ExpirePreparedStatements(db); } pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1); if( 0==pColl ){ | | | | > > | | < < | 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 | return SQLITE_BUSY; } sqlite3ExpirePreparedStatements(db); } pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1); if( 0==pColl ){ rc = SQLITE_NOMEM; }else{ pColl->xCmp = xCompare; pColl->pUser = pCtx; pColl->enc = enc; } sqlite3Error(db, rc, 0); return rc; } #ifndef SQLITE_OMIT_UTF16 /* ** Register a new collation sequence with the database handle db. */ int sqlite3_create_collation16( sqlite3* db, const char *zName, int enc, void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*) ){ char const *zName8; sqlite3_value *pTmp; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } pTmp = sqlite3GetTransientValue(db); sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF16NATIVE, SQLITE_STATIC); zName8 = sqlite3ValueText(pTmp, SQLITE_UTF8); return sqlite3_create_collation(db, zName8, enc, pCtx, xCompare); } #endif /* SQLITE_OMIT_UTF16 */ /* ** Register a collation sequence factory callback with the database handle ** db. Replace any previously installed collation sequence factory. */ |
︙ | ︙ | |||
1016 1017 1018 1019 1020 1021 1022 | } db->xCollNeeded = 0; db->xCollNeeded16 = xCollNeeded16; db->pCollNeededArg = pCollNeededArg; return SQLITE_OK; } #endif /* SQLITE_OMIT_UTF16 */ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1394 1395 1396 1397 1398 1399 1400 | } db->xCollNeeded = 0; db->xCollNeeded16 = xCollNeeded16; db->pCollNeededArg = pCollNeededArg; return SQLITE_OK; } #endif /* SQLITE_OMIT_UTF16 */ |
Deleted SQLite.Interop/src/md5.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to SQLite.Interop/src/opcodes.c.
1 2 3 4 | /* Automatically generated. Do not edit */ /* See the mkopcodec.awk script for details. */ #if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) const char *const sqlite3OpcodeNames[] = { "?", | | < | | | < | | < | < | < | < < | | | | | < | > | | < < | | < | < | | | | | | | | | | | | | | | | | | | | < | | | < | < | | < < | | > > > > > > > > > > > > > > | | | > > > | > | | | | | | | | | | | > | > > | < | | < | | | | | | < < < < < < | > | > | | | < < | < | | | < | | | | | | | | | | | < | | | < | | | > > | | | < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | /* Automatically generated. Do not edit */ /* See the mkopcodec.awk script for details. */ #if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) const char *const sqlite3OpcodeNames[] = { "?", /* 1 */ "ContextPop", /* 2 */ "IntegrityCk", /* 3 */ "DropTrigger", /* 4 */ "DropIndex", /* 5 */ "Recno", /* 6 */ "KeyAsData", /* 7 */ "Delete", /* 8 */ "MoveGt", /* 9 */ "VerifyCookie", /* 10 */ "Push", /* 11 */ "Dup", /* 12 */ "Blob", /* 13 */ "IdxGT", /* 14 */ "IdxRecno", /* 15 */ "RowKey", /* 16 */ "PutStrKey", /* 17 */ "IsUnique", /* 18 */ "SetNumColumns", /* 19 */ "Expire", /* 20 */ "IdxIsNull", /* 21 */ "NullRow", /* 22 */ "OpenPseudo", /* 23 */ "OpenWrite", /* 24 */ "OpenRead", /* 25 */ "Transaction", /* 26 */ "AutoCommit", /* 27 */ "Pop", /* 28 */ "Halt", /* 29 */ "Vacuum", /* 30 */ "ListRead", /* 31 */ "RowData", /* 32 */ "NotExists", /* 33 */ "MoveLe", /* 34 */ "SetCookie", /* 35 */ "Variable", /* 36 */ "AggNext", /* 37 */ "AggReset", /* 38 */ "Sort", /* 39 */ "AggContextPush", /* 40 */ "IdxDelete", /* 41 */ "ResetCount", /* 42 */ "OpenTemp", /* 43 */ "Integer", /* 44 */ "AggSet", /* 45 */ "CreateIndex", /* 46 */ "IdxPut", /* 47 */ "MoveLt", /* 48 */ "Return", /* 49 */ "MemLoad", /* 50 */ "SortNext", /* 51 */ "IdxLT", /* 52 */ "Rewind", /* 53 */ "AddImm", /* 54 */ "AggFunc", /* 55 */ "AggInit", /* 56 */ "MemIncr", /* 57 */ "ListReset", /* 58 */ "Clear", /* 59 */ "PutIntKey", /* 60 */ "If", /* 61 */ "Callback", /* 62 */ "SortReset", /* 63 */ "SortPut", /* 64 */ "Or", /* 65 */ "And", /* 66 */ "Not", /* 67 */ "AggContextPop", /* 68 */ "Last", /* 69 */ "NotFound", /* 70 */ "IsNull", /* 71 */ "NotNull", /* 72 */ "Ne", /* 73 */ "Eq", /* 74 */ "Gt", /* 75 */ "Le", /* 76 */ "Lt", /* 77 */ "Ge", /* 78 */ "MakeRecord", /* 79 */ "BitAnd", /* 80 */ "BitOr", /* 81 */ "ShiftLeft", /* 82 */ "ShiftRight", /* 83 */ "Add", /* 84 */ "Subtract", /* 85 */ "Multiply", /* 86 */ "Divide", /* 87 */ "Remainder", /* 88 */ "Concat", /* 89 */ "Negative", /* 90 */ "String", /* 91 */ "BitNot", /* 92 */ "String8", /* 93 */ "Goto", /* 94 */ "AggFocus", /* 95 */ "IfMemPos", /* 96 */ "DropTable", /* 97 */ "Column", /* 98 */ "Noop", /* 99 */ "AggGet", /* 100 */ "CreateTable", /* 101 */ "NewRecno", /* 102 */ "Found", /* 103 */ "Distinct", /* 104 */ "Close", /* 105 */ "Statement", /* 106 */ "IfNot", /* 107 */ "Pull", /* 108 */ "MemMax", /* 109 */ "MemStore", /* 110 */ "Next", /* 111 */ "Prev", /* 112 */ "MoveGe", /* 113 */ "MustBeInt", /* 114 */ "ForceInt", /* 115 */ "CollSeq", /* 116 */ "Gosub", /* 117 */ "ContextPush", /* 118 */ "ListRewind", /* 119 */ "ListWrite", /* 120 */ "ParseSchema", /* 121 */ "Destroy", /* 122 */ "IdxGE", /* 123 */ "FullKey", /* 124 */ "ReadCookie", /* 125 */ "AbsValue", /* 126 */ "Function", /* 127 */ "NotUsed_127", /* 128 */ "NotUsed_128", /* 129 */ "NotUsed_129", /* 130 */ "Real", /* 131 */ "HexBlob", }; #endif |
Changes to SQLite.Interop/src/opcodes.h.
1 2 | /* Automatically generated. Do not edit */ /* See the mkopcodeh.awk script for details */ | > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | | > > > > | | | | | | | | | | | | | < < < < < < | | | < | < < < < < < < | | | < < < | | < | | < | > > | | | | < < < | | < | < < | < < < < | | < < < < | | | | < < < < | | | | < | | | | | < < | | < | | < < | | > > | | | | | > | | | | > > | > > | | | < | | | | | | | | | | | | | | | | | < < < < < < < < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | /* Automatically generated. Do not edit */ /* See the mkopcodeh.awk script for details */ #define OP_ContextPop 1 #define OP_IntegrityCk 2 #define OP_DropTrigger 3 #define OP_DropIndex 4 #define OP_Recno 5 #define OP_KeyAsData 6 #define OP_Delete 7 #define OP_MoveGt 8 #define OP_VerifyCookie 9 #define OP_Push 10 #define OP_Dup 11 #define OP_Blob 12 #define OP_IdxGT 13 #define OP_IdxRecno 14 #define OP_RowKey 15 #define OP_PutStrKey 16 #define OP_IsUnique 17 #define OP_SetNumColumns 18 #define OP_Eq 73 /* same as TK_EQ */ #define OP_Expire 19 #define OP_IdxIsNull 20 #define OP_NullRow 21 #define OP_OpenPseudo 22 #define OP_OpenWrite 23 #define OP_OpenRead 24 #define OP_Transaction 25 #define OP_AutoCommit 26 #define OP_Negative 89 /* same as TK_UMINUS */ #define OP_Pop 27 #define OP_Halt 28 #define OP_Vacuum 29 #define OP_ListRead 30 #define OP_RowData 31 #define OP_NotExists 32 #define OP_MoveLe 33 #define OP_SetCookie 34 #define OP_Variable 35 #define OP_AggNext 36 #define OP_AggReset 37 #define OP_Sort 38 #define OP_AggContextPush 39 #define OP_IdxDelete 40 #define OP_ResetCount 41 #define OP_OpenTemp 42 #define OP_NotNull 71 /* same as TK_NOTNULL */ #define OP_Ge 77 /* same as TK_GE */ #define OP_Remainder 87 /* same as TK_REM */ #define OP_Divide 86 /* same as TK_SLASH */ #define OP_Integer 43 #define OP_AggSet 44 #define OP_CreateIndex 45 #define OP_IdxPut 46 #define OP_MoveLt 47 #define OP_And 65 /* same as TK_AND */ #define OP_ShiftLeft 81 /* same as TK_LSHIFT */ #define OP_Real 130 /* same as TK_FLOAT */ #define OP_Return 48 #define OP_MemLoad 49 #define OP_SortNext 50 #define OP_IdxLT 51 #define OP_Rewind 52 #define OP_Gt 74 /* same as TK_GT */ #define OP_AddImm 53 #define OP_Subtract 84 /* same as TK_MINUS */ #define OP_AggFunc 54 #define OP_AggInit 55 #define OP_MemIncr 56 #define OP_ListReset 57 #define OP_Clear 58 #define OP_PutIntKey 59 #define OP_IsNull 70 /* same as TK_ISNULL */ #define OP_If 60 #define OP_Callback 61 #define OP_SortReset 62 #define OP_SortPut 63 #define OP_AggContextPop 67 #define OP_Last 68 #define OP_NotFound 69 #define OP_MakeRecord 78 #define OP_BitAnd 79 /* same as TK_BITAND */ #define OP_Add 83 /* same as TK_PLUS */ #define OP_HexBlob 131 /* same as TK_BLOB */ #define OP_String 90 #define OP_Goto 93 #define OP_AggFocus 94 #define OP_IfMemPos 95 #define OP_DropTable 96 #define OP_Column 97 #define OP_Noop 98 #define OP_Not 66 /* same as TK_NOT */ #define OP_Le 75 /* same as TK_LE */ #define OP_BitOr 80 /* same as TK_BITOR */ #define OP_Multiply 85 /* same as TK_STAR */ #define OP_String8 92 /* same as TK_STRING */ #define OP_AggGet 99 #define OP_CreateTable 100 #define OP_NewRecno 101 #define OP_Found 102 #define OP_Distinct 103 #define OP_Close 104 #define OP_Statement 105 #define OP_IfNot 106 #define OP_Pull 107 #define OP_MemMax 108 #define OP_MemStore 109 #define OP_Next 110 #define OP_Prev 111 #define OP_MoveGe 112 #define OP_Lt 76 /* same as TK_LT */ #define OP_Ne 72 /* same as TK_NE */ #define OP_MustBeInt 113 #define OP_ForceInt 114 #define OP_ShiftRight 82 /* same as TK_RSHIFT */ #define OP_CollSeq 115 #define OP_Gosub 116 #define OP_ContextPush 117 #define OP_ListRewind 118 #define OP_ListWrite 119 #define OP_ParseSchema 120 #define OP_Destroy 121 #define OP_IdxGE 122 #define OP_FullKey 123 #define OP_ReadCookie 124 #define OP_BitNot 91 /* same as TK_BITNOT */ #define OP_AbsValue 125 #define OP_Or 64 /* same as TK_OR */ #define OP_Function 126 #define OP_Concat 88 /* same as TK_CONCAT */ /* The following opcode values are never used */ #define OP_NotUsed_127 127 #define OP_NotUsed_128 128 #define OP_NotUsed_129 129 |
Deleted SQLite.Interop/src/os.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to SQLite.Interop/src/os.h.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** "os.c") attempt to abstract the underlying operating system so that ** the SQLite library will work on both POSIX and windows systems. */ #ifndef _SQLITE_OS_H_ #define _SQLITE_OS_H_ /* | | | > > | < < | | | < | < > > | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | ** "os.c") attempt to abstract the underlying operating system so that ** the SQLite library will work on both POSIX and windows systems. */ #ifndef _SQLITE_OS_H_ #define _SQLITE_OS_H_ /* ** Figure out if we are dealing with Unix, Windows or MacOS. ** ** N.B. MacOS means Mac Classic (or Carbon). Treat Darwin (OS X) as Unix. ** The MacOS build is designed to use CodeWarrior (tested with v8) */ #if !defined(OS_UNIX) && !defined(OS_TEST) # ifndef OS_WIN # if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) # define OS_WIN 1 # define OS_UNIX 0 # else # define OS_WIN 0 # define OS_UNIX 1 # endif # else # define OS_UNIX 0 # endif #else # ifndef OS_WIN # define OS_WIN 0 # endif #endif /* ** Invoke the appropriate operating-system specific header file. */ #if OS_TEST # include "os_test.h" #endif #if OS_UNIX # include "os_unix.h" #endif #if OS_WIN # include "os_win.h" #endif /* ** Temporary files are named starting with this prefix followed by 16 random ** alphanumeric characters, and no file extension. They are stored in the ** OS's standard temporary file directory, and are deleted prior to exit. ** If sqlite is being embedded in another program, you may wish to change the ** prefix to reflect your program's name, so that if your program exits ** prematurely, old temporary files can be easily identified. This can be done ** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line. */ #ifndef TEMP_FILE_PREFIX # define TEMP_FILE_PREFIX "sqlite_" #endif /* ** The following values may be passed as the second argument to ** sqlite3OsLock(). The various locks exhibit the following semantics: ** ** SHARED: Any number of processes may hold a SHARED lock simultaneously. ** RESERVED: A single process may hold a RESERVED lock on a file at ** any time. Other processes may hold and obtain new SHARED locks. |
︙ | ︙ | |||
219 220 221 222 223 224 225 | ** WinNT reader will lock out all other Win95 readers. ** ** The following #defines specify the range of bytes used for locking. ** SHARED_SIZE is the number of bytes available in the pool from which ** a random byte is selected for a shared lock. The pool of bytes for ** shared locks begins at SHARED_FIRST. ** | | < < | | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | ** WinNT reader will lock out all other Win95 readers. ** ** The following #defines specify the range of bytes used for locking. ** SHARED_SIZE is the number of bytes available in the pool from which ** a random byte is selected for a shared lock. The pool of bytes for ** shared locks begins at SHARED_FIRST. ** ** These #defines are available in os.h so that Unix can use the same ** byte ranges for locking. This leaves open the possiblity of having ** clients on win95, winNT, and unix all talking to the same shared file ** and all locking correctly. To do so would require that samba (or whatever ** tool is being used for file sharing) implements locks correctly between ** windows and unix. I'm guessing that isn't likely to happen, but by ** using the same locking range we are at least open to the possibility. ** ** Locking in windows is manditory. For this reason, we cannot store |
︙ | ︙ | |||
245 246 247 248 249 250 251 | ** Changing the value of PENDING_BYTE results in a subtly incompatible ** file format. Depending on how it is changed, you might not notice ** the incompatibility right away, even running a full regression test. ** The default location of PENDING_BYTE is the first byte past the ** 1GB boundary. ** */ | < < < | < < | | < | > > > | > > > > < | < | < < < < < < < < < < < < < > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < | < < < < < < < | < < < < < < < < < < < < < < < < < < < < < | < | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | ** Changing the value of PENDING_BYTE results in a subtly incompatible ** file format. Depending on how it is changed, you might not notice ** the incompatibility right away, even running a full regression test. ** The default location of PENDING_BYTE is the first byte past the ** 1GB boundary. ** */ #define PENDING_BYTE 0x40000000 /* First byte past the 1GB boundary */ /* #define PENDING_BYTE 0x5400 // Page 22 - for testing */ #define RESERVED_BYTE (PENDING_BYTE+1) #define SHARED_FIRST (PENDING_BYTE+2) #define SHARED_SIZE 510 int sqlite3OsDelete(const char*); int sqlite3OsFileExists(const char*); int sqlite3OsOpenReadWrite(const char*, OsFile*, int*); int sqlite3OsOpenExclusive(const char*, OsFile*, int); int sqlite3OsOpenReadOnly(const char*, OsFile*); int sqlite3OsOpenDirectory(const char*, OsFile*); int sqlite3OsSyncDirectory(const char*); int sqlite3OsTempFileName(char*); int sqlite3OsIsDirWritable(char*); int sqlite3OsClose(OsFile*); int sqlite3OsRead(OsFile*, void*, int amt); int sqlite3OsWrite(OsFile*, const void*, int amt); int sqlite3OsSeek(OsFile*, i64 offset); int sqlite3OsSync(OsFile*); int sqlite3OsTruncate(OsFile*, i64 size); int sqlite3OsFileSize(OsFile*, i64 *pSize); int sqlite3OsRandomSeed(char*); int sqlite3OsSleep(int ms); int sqlite3OsCurrentTime(double*); int sqlite3OsFileModTime(OsFile*, double*); void sqlite3OsEnterMutex(void); void sqlite3OsLeaveMutex(void); char *sqlite3OsFullPathname(const char*); int sqlite3OsLock(OsFile*, int); int sqlite3OsUnlock(OsFile*, int); int sqlite3OsCheckReservedLock(OsFile *id); #endif /* _SQLITE_OS_H_ */ |
Changes to SQLite.Interop/src/os_common.h.
︙ | ︙ | |||
24 25 26 27 28 29 30 | ** switch. The following code should catch this problem at compile-time. */ #ifdef MEMORY_DEBUG # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif | < < < < < < < < | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | ** switch. The following code should catch this problem at compile-time. */ #ifdef MEMORY_DEBUG # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif int sqlite3_os_trace = 0; #ifdef SQLITE_DEBUG static int last_page = 0; #define SEEK(X) last_page=(X) #define TRACE1(X) if( sqlite3_os_trace ) sqlite3DebugPrintf(X) #define TRACE2(X,Y) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y) #define TRACE3(X,Y,Z) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z) |
︙ | ︙ | |||
84 85 86 87 88 89 90 | /* ** If we compile with the SQLITE_TEST macro set, then the following block ** of code will give us the ability to simulate a disk I/O error. This ** is used for testing the I/O recovery logic. */ #ifdef SQLITE_TEST | < < | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | /* ** If we compile with the SQLITE_TEST macro set, then the following block ** of code will give us the ability to simulate a disk I/O error. This ** is used for testing the I/O recovery logic. */ #ifdef SQLITE_TEST int sqlite3_io_error_pending = 0; int sqlite3_diskfull_pending = 0; #define SimulateIOError(A) \ if( sqlite3_io_error_pending ) \ if( sqlite3_io_error_pending-- == 1 ){ local_ioerr(); return A; } static void local_ioerr(){ sqlite3_io_error_pending = 0; /* Really just a place to set a breakpoint */ } #define SimulateDiskfullError \ if( sqlite3_diskfull_pending ) \ if( sqlite3_diskfull_pending-- == 1 ){ local_ioerr(); return SQLITE_FULL; } #else #define SimulateIOError(A) #define SimulateDiskfullError #endif /* ** When testing, keep a count of the number of open files. */ #ifdef SQLITE_TEST int sqlite3_open_file_count = 0; #define OpenCounter(X) sqlite3_open_file_count+=(X) #else #define OpenCounter(X) #endif |
Changes to SQLite.Interop/src/os_unix.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** ** This file contains code that is specific to Unix systems. */ #include "sqliteInt.h" #include "os.h" #if OS_UNIX /* This file is used on unix only */ | < < < < < < < < < < < < < < < < < < < < < < < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > | | | > > | | < | > < < < < < < < < < < < < | < > | < < < < | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | ** ** This file contains code that is specific to Unix systems. */ #include "sqliteInt.h" #include "os.h" #if OS_UNIX /* This file is used on unix only */ #include <time.h> #include <errno.h> #include <unistd.h> #ifndef O_LARGEFILE # define O_LARGEFILE 0 #endif #ifdef SQLITE_DISABLE_LFS # undef O_LARGEFILE # define O_LARGEFILE 0 #endif #ifndef O_NOFOLLOW # define O_NOFOLLOW 0 #endif #ifndef O_BINARY # define O_BINARY 0 #endif /* ** The DJGPP compiler environment looks mostly like Unix, but it ** lacks the fcntl() system call. So redefine fcntl() to be something ** that always succeeds. This means that locking does not occur under ** DJGPP. But its DOS - what did you expect? */ #ifdef __DJGPP__ # define fcntl(A,B,C) 0 #endif /* ** Macros used to determine whether or not to use threads. The ** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for ** Posix threads and SQLITE_W32_THREADS is defined if we are ** synchronizing using Win32 threads. */ #if defined(THREADSAFE) && THREADSAFE # include <pthread.h> # define SQLITE_UNIX_THREADS 1 #endif /* ** Include code that is common to all os_*.c files */ #include "os_common.h" #if defined(THREADSAFE) && THREADSAFE && defined(__linux__) #define getpid pthread_self #endif /* ** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996) ** section 6.5.2.2 lines 483 through 490 specify that when a process ** sets or clears a lock, that operation overrides any prior locks set ** by the same process. It does not explicitly say so, but this implies |
︙ | ︙ | |||
279 280 281 282 283 284 285 | /* ** An instance of the following structure serves as the key used ** to locate a particular lockInfo structure given its inode. ** ** If threads cannot override each others locks, then we set the ** lockKey.tid field to the thread ID. If threads can override | | | | | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | /* ** An instance of the following structure serves as the key used ** to locate a particular lockInfo structure given its inode. ** ** If threads cannot override each others locks, then we set the ** lockKey.tid field to the thread ID. If threads can override ** each others locks then tid is always set to zero. tid is also ** set to zero if we compile without threading support. */ struct lockKey { dev_t dev; /* Device number */ ino_t ino; /* Inode number */ #ifdef SQLITE_UNIX_THREADS pthread_t tid; /* Thread ID or zero if threads cannot override each other */ #endif }; /* ** An instance of the following structure is allocated for each open ** inode on each thread with a different process ID. (Threads have ** different process IDs on linux, but not on most other unixes.) |
︙ | ︙ | |||
332 333 334 335 336 337 338 | int nRef; /* Number of pointers to this structure */ int nLock; /* Number of outstanding locks */ int nPending; /* Number of pending close() operations */ int *aPending; /* Malloced space holding fd's awaiting a close() */ }; /* | | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | int nRef; /* Number of pointers to this structure */ int nLock; /* Number of outstanding locks */ int nPending; /* Number of pending close() operations */ int *aPending; /* Malloced space holding fd's awaiting a close() */ }; /* ** These hash table maps inodes and process IDs into lockInfo and openCnt ** structures. Access to these hash tables must be protected by a mutex. */ static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; #ifdef SQLITE_UNIX_THREADS /* ** This variable records whether or not threads can override each others ** locks. ** ** 0: No. Threads cannot override each others locks. ** 1: Yes. Threads can override each others locks. ** -1: We don't know yet. */ static int threadsOverrideEachOthersLocks = -1; /* ** This structure holds information passed into individual test ** threads by the testThreadLockingBehavior() routine. */ struct threadTestData { int fd; /* File to be locked */ struct flock lock; /* The locking operation */ int result; /* Result of the locking operation */ }; /* ** The testThreadLockingBehavior() routine launches two separate ** threads on this routine. This routine attempts to lock a file ** descriptor then returns. The success or failure of that attempt ** allows the testThreadLockingBehavior() procedure to determine ** whether or not threads can override each others locks. */ |
︙ | ︙ | |||
474 475 476 477 478 479 480 | } #endif /* SQLITE_UNIX_THREADS */ /* ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ | < < | | | < < | < < < | < < | | | | | | | < | | | | | | | | | | | | < | | | | | < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < < < | | < < < | | < | < | | | | | | > | > | | < < < | < | | | < | | | | > | > | | < < < | < | | | | | | > | | | | | < | > < | < | | | | < < | | 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 | } #endif /* SQLITE_UNIX_THREADS */ /* ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ pLock->nRef--; if( pLock->nRef==0 ){ sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); sqliteFree(pLock); } } /* ** Release a openCnt structure previously allocated by findLockInfo(). */ static void releaseOpenCnt(struct openCnt *pOpen){ pOpen->nRef--; if( pOpen->nRef==0 ){ sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); sqliteFree(pOpen->aPending); sqliteFree(pOpen); } } /* ** Given a file descriptor, locate lockInfo and openCnt structures that ** describes that file descriptor. Create a new ones if necessary. The ** return values might be unset if an error occurs. ** ** Return the number of errors. */ static int findLockInfo( int fd, /* The file descriptor used in the key */ struct lockInfo **ppLock, /* Return the lockInfo structure here */ struct openCnt **ppOpen /* Return the openCnt structure here */ ){ int rc; struct lockKey key1; struct openKey key2; struct stat statbuf; struct lockInfo *pLock; struct openCnt *pOpen; rc = fstat(fd, &statbuf); if( rc!=0 ) return 1; memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; key1.ino = statbuf.st_ino; #ifdef SQLITE_UNIX_THREADS if( threadsOverrideEachOthersLocks<0 ){ testThreadLockingBehavior(fd); } key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self(); #endif memset(&key2, 0, sizeof(key2)); key2.dev = statbuf.st_dev; key2.ino = statbuf.st_ino; pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1)); if( pLock==0 ){ struct lockInfo *pOld; pLock = sqliteMallocRaw( sizeof(*pLock) ); if( pLock==0 ) return 1; pLock->key = key1; pLock->nRef = 1; pLock->cnt = 0; pLock->locktype = 0; pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock); if( pOld!=0 ){ assert( pOld==pLock ); sqliteFree(pLock); return 1; } }else{ pLock->nRef++; } *ppLock = pLock; pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); if( pOpen==0 ){ struct openCnt *pOld; pOpen = sqliteMallocRaw( sizeof(*pOpen) ); if( pOpen==0 ){ releaseLockInfo(pLock); return 1; } pOpen->key = key2; pOpen->nRef = 1; pOpen->nLock = 0; pOpen->nPending = 0; pOpen->aPending = 0; pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); if( pOld!=0 ){ assert( pOld==pOpen ); sqliteFree(pOpen); releaseLockInfo(pLock); return 1; } }else{ pOpen->nRef++; } *ppOpen = pOpen; return 0; } /* ** Delete the named file */ int sqlite3OsDelete(const char *zFilename){ unlink(zFilename); return SQLITE_OK; } /* ** Return TRUE if the named file exists. */ int sqlite3OsFileExists(const char *zFilename){ return access(zFilename, 0)==0; } /* ** Attempt to open a file for both reading and writing. If that ** fails, try opening it read-only. If the file does not exist, ** try to create it. ** ** On success, a handle for the open file is written to *id ** and *pReadonly is set to 0 if the file was opened for reading and ** writing or 1 if the file was opened read-only. The function returns ** SQLITE_OK. ** ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id and *pReadonly unchanged. */ int sqlite3OsOpenReadWrite( const char *zFilename, OsFile *id, int *pReadonly ){ int rc; assert( !id->isOpen ); id->dirfd = -1; id->h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644); if( id->h<0 ){ #ifdef EISDIR if( errno==EISDIR ){ return SQLITE_CANTOPEN; } #endif id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); if( id->h<0 ){ return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; } sqlite3OsEnterMutex(); rc = findLockInfo(id->h, &id->pLock, &id->pOpen); sqlite3OsLeaveMutex(); if( rc ){ close(id->h); return SQLITE_NOMEM; } id->locktype = 0; id->isOpen = 1; TRACE3("OPEN %-3d %s\n", id->h, zFilename); OpenCounter(+1); return SQLITE_OK; } /* ** Attempt to open a new file for exclusive access by this process. ** The file will be opened for both reading and writing. To avoid ** a potential security problem, we do not allow the file to have ** previously existed. Nor do we allow the file to be a symbolic ** link. ** ** If delFlag is true, then make arrangements to automatically delete ** the file when it is closed. ** ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ int rc; assert( !id->isOpen ); if( access(zFilename, 0)==0 ){ return SQLITE_CANTOPEN; } id->dirfd = -1; id->h = open(zFilename, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600); if( id->h<0 ){ return SQLITE_CANTOPEN; } sqlite3OsEnterMutex(); rc = findLockInfo(id->h, &id->pLock, &id->pOpen); sqlite3OsLeaveMutex(); if( rc ){ close(id->h); unlink(zFilename); return SQLITE_NOMEM; } id->locktype = 0; id->isOpen = 1; if( delFlag ){ unlink(zFilename); } TRACE3("OPEN-EX %-3d %s\n", id->h, zFilename); OpenCounter(+1); return SQLITE_OK; } /* ** Attempt to open a new file for read-only access. ** ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ int rc; assert( !id->isOpen ); id->dirfd = -1; id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); if( id->h<0 ){ return SQLITE_CANTOPEN; } sqlite3OsEnterMutex(); rc = findLockInfo(id->h, &id->pLock, &id->pOpen); sqlite3OsLeaveMutex(); if( rc ){ close(id->h); return SQLITE_NOMEM; } id->locktype = 0; id->isOpen = 1; TRACE3("OPEN-RO %-3d %s\n", id->h, zFilename); OpenCounter(+1); return SQLITE_OK; } /* ** Attempt to open a file descriptor for the directory that contains a ** file. This file descriptor can be used to fsync() the directory ** in order to make sure the creation of a new file is actually written ** to disk. ** ** This routine is only meaningful for Unix. It is a no-op under ** windows since windows does not support hard links. ** ** On success, a handle for a previously open file is at *id is ** updated with the new directory file descriptor and SQLITE_OK is ** returned. ** ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id unchanged. */ int sqlite3OsOpenDirectory( const char *zDirname, OsFile *id ){ if( !id->isOpen ){ /* Do not open the directory if the corresponding file is not already ** open. */ return SQLITE_CANTOPEN; } assert( id->dirfd<0 ); id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0644); if( id->dirfd<0 ){ return SQLITE_CANTOPEN; } TRACE3("OPENDIR %-3d %s\n", id->dirfd, zDirname); return SQLITE_OK; } /* ** If the following global variable points to a string which is the ** name of a directory, then that directory will be used to store ** temporary files. */ char *sqlite3_temp_directory = 0; /* ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ int sqlite3OsTempFileName(char *zBuf){ static const char *azDirs[] = { 0, "/var/tmp", "/usr/tmp", "/tmp", ".", }; |
︙ | ︙ | |||
884 885 886 887 888 889 890 891 892 893 894 | zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; } zBuf[j] = 0; }while( access(zBuf,0)==0 ); return SQLITE_OK; } /* ** Check that a given pathname is a directory and is writable ** */ | > | < < > | | | < | | | | < | | | < < < | < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < | | < | < < < < < < < < | | < | < < > < < < < | < | | | | | < | < < < | | < < < < | < < < | < | | | | | | | < | | | | | > > > > > > > > > > > > > > > > > > | 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 | zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; } zBuf[j] = 0; }while( access(zBuf,0)==0 ); return SQLITE_OK; } #ifndef SQLITE_OMIT_PAGER_PRAGMAS /* ** Check that a given pathname is a directory and is writable ** */ int sqlite3OsIsDirWritable(char *zBuf){ struct stat buf; if( zBuf==0 ) return 0; if( zBuf[0]==0 ) return 0; if( stat(zBuf, &buf) ) return 0; if( !S_ISDIR(buf.st_mode) ) return 0; if( access(zBuf, 07) ) return 0; return 1; } #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ /* ** Read data from a file into a buffer. Return SQLITE_OK if all ** bytes were read successfully and SQLITE_IOERR if anything goes ** wrong. */ int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ int got; assert( id->isOpen ); SimulateIOError(SQLITE_IOERR); TIMER_START; got = read(id->h, pBuf, amt); TIMER_END; TRACE4("READ %-3d %7d %d\n", id->h, last_page, TIMER_ELAPSED); SEEK(0); /* if( got<0 ) got = 0; */ if( got==amt ){ return SQLITE_OK; }else{ return SQLITE_IOERR; } } /* ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. */ int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ int wrote = 0; assert( id->isOpen ); assert( amt>0 ); SimulateIOError(SQLITE_IOERR); SimulateDiskfullError; TIMER_START; while( amt>0 && (wrote = write(id->h, pBuf, amt))>0 ){ amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } TIMER_END; TRACE4("WRITE %-3d %7d %d\n", id->h, last_page, TIMER_ELAPSED); SEEK(0); if( amt>0 ){ return SQLITE_FULL; } return SQLITE_OK; } /* ** Move the read/write pointer in a file. */ int sqlite3OsSeek(OsFile *id, i64 offset){ assert( id->isOpen ); SEEK(offset/1024 + 1); lseek(id->h, offset, SEEK_SET); return SQLITE_OK; } /* ** The fsync() system call does not work as advertised on many ** unix systems. The following procedure is an attempt to make ** it work better. ** ** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful ** for testing when we want to run through the test suite quickly. ** You are strongly advised *not* to deploy with SQLITE_NO_SYNC ** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash ** or power failure will likely corrupt the database file. */ static int full_fsync(int fd){ #ifdef SQLITE_NO_SYNC return SQLITE_OK; #else int rc; #ifdef F_FULLFSYNC rc = fcntl(fd, F_FULLFSYNC, 0); if( rc ) rc = fsync(fd); #else rc = fsync(fd); #endif return rc; #endif } /* ** Make sure all writes to a particular file are committed to disk. ** ** Under Unix, also make sure that the directory entry for the file ** has been created by fsync-ing the directory that contains the file. ** If we do not do this and we encounter a power failure, the directory ** entry for the journal might not exist after we reboot. The next ** SQLite to access the file will not know that the journal exists (because ** the directory entry for the journal was never created) and the transaction ** will not roll back - possibly leading to database corruption. */ int sqlite3OsSync(OsFile *id){ assert( id->isOpen ); SimulateIOError(SQLITE_IOERR); TRACE2("SYNC %-3d\n", id->h); if( full_fsync(id->h) ){ return SQLITE_IOERR; } if( id->dirfd>=0 ){ TRACE2("DIRSYNC %-3d\n", id->dirfd); full_fsync(id->dirfd); close(id->dirfd); /* Only need to sync once, so close the directory */ id->dirfd = -1; /* when we are done. */ } return SQLITE_OK; } /* ** Sync the directory zDirname. This is a no-op on operating systems other ** than UNIX. */ int sqlite3OsSyncDirectory(const char *zDirname){ int fd; int r; SimulateIOError(SQLITE_IOERR); fd = open(zDirname, O_RDONLY|O_BINARY, 0644); TRACE3("DIRSYNC %-3d (%s)\n", fd, zDirname); if( fd<0 ){ return SQLITE_CANTOPEN; } r = fsync(fd); close(fd); return ((r==0)?SQLITE_OK:SQLITE_IOERR); } /* ** Truncate an open file to a specified size */ int sqlite3OsTruncate(OsFile *id, i64 nByte){ assert( id->isOpen ); SimulateIOError(SQLITE_IOERR); return ftruncate(id->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR; } /* ** Determine the current size of a file in bytes */ int sqlite3OsFileSize(OsFile *id, i64 *pSize){ struct stat buf; assert( id->isOpen ); SimulateIOError(SQLITE_IOERR); if( fstat(id->h, &buf)!=0 ){ return SQLITE_IOERR; } *pSize = buf.st_size; return SQLITE_OK; } /* ** This routine checks if there is a RESERVED lock held on the specified ** file by this or any other process. If such a lock is held, return ** non-zero. If the file is unlocked or holds only SHARED locks, then ** return zero. */ int sqlite3OsCheckReservedLock(OsFile *id){ int r = 0; assert( id->isOpen ); sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads */ /* Check if a thread in this process holds such a lock */ if( id->pLock->locktype>SHARED_LOCK ){ r = 1; } /* Otherwise see if some other process holds it. */ if( !r ){ struct flock lock; lock.l_whence = SEEK_SET; lock.l_start = RESERVED_BYTE; lock.l_len = 1; lock.l_type = F_WRLCK; fcntl(id->h, F_GETLK, &lock); if( lock.l_type!=F_UNLCK ){ r = 1; } } sqlite3OsLeaveMutex(); TRACE3("TEST WR-LOCK %d %d\n", id->h, r); return r; } #ifdef SQLITE_DEBUG /* ** Helper function for printing out trace information from debugging ** binaries. This returns the string represetation of the supplied ** integer lock-type. */ static const char * locktypeName(int locktype){ switch( locktype ){ case NO_LOCK: return "NONE"; case SHARED_LOCK: return "SHARED"; case RESERVED_LOCK: return "RESERVED"; case PENDING_LOCK: return "PENDING"; case EXCLUSIVE_LOCK: return "EXCLUSIVE"; } return "ERROR"; } #endif /* ** Lock the file with the lock specified by parameter locktype - one ** of the following: ** ** (1) SHARED_LOCK ** (2) RESERVED_LOCK |
︙ | ︙ | |||
1177 1178 1179 1180 1181 1182 1183 | ** SHARED -> (PENDING) -> EXCLUSIVE ** RESERVED -> (PENDING) -> EXCLUSIVE ** PENDING -> EXCLUSIVE ** ** This routine will only increase a lock. Use the sqlite3OsUnlock() ** routine to lower a locking level. */ | | | 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 | ** SHARED -> (PENDING) -> EXCLUSIVE ** RESERVED -> (PENDING) -> EXCLUSIVE ** PENDING -> EXCLUSIVE ** ** This routine will only increase a lock. Use the sqlite3OsUnlock() ** routine to lower a locking level. */ int sqlite3OsLock(OsFile *id, int locktype){ /* The following describes the implementation of the various locks and ** lock transitions in terms of the POSIX advisory shared and exclusive ** lock primitives (called read-locks and write-locks below, to avoid ** confusion with SQLite lock names). The algorithms are complicated ** slightly in order to be compatible with windows systems simultaneously ** accessing the same database file, in case that is ever required. ** |
︙ | ︙ | |||
1217 1218 1219 1220 1221 1222 1223 | ** ** The reason a single byte cannot be used instead of the 'shared byte ** range' is that some versions of windows do not support read-locks. By ** locking a random byte from a range, concurrent SHARED locks may exist ** even if the locking primitive used is always a write-lock. */ int rc = SQLITE_OK; | < | | | | | | < | | | | < < < < < < < < < | | | | < | | | | < < < | | | | | | | | > > > > | < | | | | < < < | | | | | | < < < | | < < < | | | | < < < | | < | > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < < < < < < < < < | | | < < < | | 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 | ** ** The reason a single byte cannot be used instead of the 'shared byte ** range' is that some versions of windows do not support read-locks. By ** locking a random byte from a range, concurrent SHARED locks may exist ** even if the locking primitive used is always a write-lock. */ int rc = SQLITE_OK; struct lockInfo *pLock = id->pLock; struct flock lock; int s; assert( id->isOpen ); TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", id->h, locktypeName(locktype), locktypeName(id->locktype), locktypeName(pLock->locktype), pLock->cnt ,getpid() ); /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the end_lock: exit path, as ** sqlite3OsEnterMutex() hasn't been called yet. */ if( id->locktype>=locktype ){ TRACE3("LOCK %d %s ok (already held)\n", id->h, locktypeName(locktype)); return SQLITE_OK; } /* Make sure the locking sequence is correct */ assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); assert( locktype!=RESERVED_LOCK || id->locktype==SHARED_LOCK ); /* This mutex is needed because id->pLock is shared across threads */ sqlite3OsEnterMutex(); /* If some thread using this PID has a lock via a different OsFile* ** handle that precludes the requested lock, return BUSY. */ if( (id->locktype!=pLock->locktype && (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK)) ){ rc = SQLITE_BUSY; goto end_lock; } /* If a SHARED lock is requested, and some thread using this PID already ** has a SHARED or RESERVED lock, then increment reference counts and ** return SQLITE_OK. */ if( locktype==SHARED_LOCK && (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){ assert( locktype==SHARED_LOCK ); assert( id->locktype==0 ); assert( pLock->cnt>0 ); id->locktype = SHARED_LOCK; pLock->cnt++; id->pOpen->nLock++; goto end_lock; } lock.l_len = 1L; lock.l_whence = SEEK_SET; /* A PENDING lock is needed before acquiring a SHARED lock and before ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will ** be released. */ if( locktype==SHARED_LOCK || (locktype==EXCLUSIVE_LOCK && id->locktype<PENDING_LOCK) ){ lock.l_type = (locktype==SHARED_LOCK?F_RDLCK:F_WRLCK); lock.l_start = PENDING_BYTE; s = fcntl(id->h, F_SETLK, &lock); if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; goto end_lock; } } /* If control gets to this point, then actually go ahead and make ** operating system calls for the specified lock. */ if( locktype==SHARED_LOCK ){ assert( pLock->cnt==0 ); assert( pLock->locktype==0 ); /* Now get the read-lock */ lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; s = fcntl(id->h, F_SETLK, &lock); /* Drop the temporary PENDING lock */ lock.l_start = PENDING_BYTE; lock.l_len = 1L; lock.l_type = F_UNLCK; fcntl(id->h, F_SETLK, &lock); if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; }else{ id->locktype = SHARED_LOCK; id->pOpen->nLock++; pLock->cnt = 1; } }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){ /* We are trying for an exclusive lock but another thread in this ** same process is still holding a shared lock. */ rc = SQLITE_BUSY; }else{ /* The request was for a RESERVED or EXCLUSIVE lock. It is ** assumed that there is a SHARED or greater lock on the file ** already. */ assert( 0!=id->locktype ); lock.l_type = F_WRLCK; switch( locktype ){ case RESERVED_LOCK: lock.l_start = RESERVED_BYTE; break; case EXCLUSIVE_LOCK: lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; break; default: assert(0); } s = fcntl(id->h, F_SETLK, &lock); if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; } } if( rc==SQLITE_OK ){ id->locktype = locktype; pLock->locktype = locktype; }else if( locktype==EXCLUSIVE_LOCK ){ id->locktype = PENDING_LOCK; pLock->locktype = PENDING_LOCK; } end_lock: sqlite3OsLeaveMutex(); TRACE4("LOCK %d %s %s\n", id->h, locktypeName(locktype), rc==SQLITE_OK ? "ok" : "failed"); return rc; } /* ** Lower the locking level on file descriptor id to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. ** ** It is not possible for this routine to fail if the second argument ** is NO_LOCK. If the second argument is SHARED_LOCK, this routine ** might return SQLITE_IOERR instead of SQLITE_OK. */ int sqlite3OsUnlock(OsFile *id, int locktype){ struct lockInfo *pLock; struct flock lock; int rc = SQLITE_OK; assert( id->isOpen ); TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", id->h, locktype, id->locktype, id->pLock->locktype, id->pLock->cnt, getpid()); assert( locktype<=SHARED_LOCK ); if( id->locktype<=locktype ){ return SQLITE_OK; } sqlite3OsEnterMutex(); pLock = id->pLock; assert( pLock->cnt!=0 ); if( id->locktype>SHARED_LOCK ){ assert( pLock->locktype==id->locktype ); if( locktype==SHARED_LOCK ){ lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; if( fcntl(id->h, F_SETLK, &lock)!=0 ){ /* This should never happen */ rc = SQLITE_IOERR; } } lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = PENDING_BYTE; lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); fcntl(id->h, F_SETLK, &lock); pLock->locktype = SHARED_LOCK; } if( locktype==NO_LOCK ){ struct openCnt *pOpen; /* Decrement the shared lock counter. Release the lock using an ** OS call only when all threads in this same process have released ** the lock. */ pLock->cnt--; if( pLock->cnt==0 ){ lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = lock.l_len = 0L; fcntl(id->h, F_SETLK, &lock); pLock->locktype = NO_LOCK; } /* Decrement the count of locks against this same file. When the ** count reaches zero, close any other file descriptors whose close ** was deferred because of outstanding locks. */ pOpen = id->pOpen; pOpen->nLock--; assert( pOpen->nLock>=0 ); if( pOpen->nLock==0 && pOpen->nPending>0 ){ int i; for(i=0; i<pOpen->nPending; i++){ close(pOpen->aPending[i]); } sqliteFree(pOpen->aPending); pOpen->nPending = 0; pOpen->aPending = 0; } } sqlite3OsLeaveMutex(); id->locktype = locktype; return rc; } /* ** Close a file. */ int sqlite3OsClose(OsFile *id){ if( !id->isOpen ) return SQLITE_OK; sqlite3OsUnlock(id, NO_LOCK); if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; sqlite3OsEnterMutex(); if( id->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file ** descriptor to pOpen->aPending. It will be automatically closed when ** the last lock is cleared. */ int *aNew; struct openCnt *pOpen = id->pOpen; pOpen->nPending++; aNew = sqliteRealloc( pOpen->aPending, pOpen->nPending*sizeof(int) ); if( aNew==0 ){ /* If a malloc fails, just leak the file descriptor */ }else{ pOpen->aPending = aNew; pOpen->aPending[pOpen->nPending-1] = id->h; } }else{ /* There are no outstanding locks so we can close the file immediately */ close(id->h); } releaseLockInfo(id->pLock); releaseOpenCnt(id->pOpen); sqlite3OsLeaveMutex(); id->isOpen = 0; TRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); return SQLITE_OK; } /* ** Get information to seed the random number generator. The seed ** is written into the buffer zBuf[256]. The calling function must ** supply a sufficiently large buffer. */ int sqlite3OsRandomSeed(char *zBuf){ /* We have to initialize zBuf to prevent valgrind from reporting ** errors. The reports issued by valgrind are incorrect - we would ** prefer that the randomness be increased by making use of the ** uninitialized space in zBuf - but valgrind errors tend to worry ** some users. Rather than argue, it seems easier just to initialize ** the whole array and silence valgrind, even if that means less randomness ** in the random seed. ** ** When testing, initializing zBuf[] to zero is all we do. That means ** that we always use the same random number sequence.* This makes the ** tests repeatable. */ memset(zBuf, 0, 256); #if !defined(SQLITE_TEST) { int pid, fd; fd = open("/dev/urandom", O_RDONLY); if( fd<0 ){ time((time_t*)zBuf); pid = getpid(); memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid)); }else{ read(fd, zBuf, 256); close(fd); } } #endif return SQLITE_OK; } /* ** Sleep for a little while. Return the amount of time slept. */ int sqlite3OsSleep(int ms){ #if defined(HAVE_USLEEP) && HAVE_USLEEP usleep(ms*1000); return ms; #else sleep((ms+999)/1000); return 1000*((ms+999)/1000); #endif |
︙ | ︙ | |||
1673 1674 1675 1676 1677 1678 1679 | /* ** The following pair of routine implement mutual exclusion for ** multi-threaded processes. Only a single thread is allowed to ** executed code that is surrounded by EnterMutex() and LeaveMutex(). ** ** SQLite uses only a single Mutex. There is not much critical ** code and what little there is executes quickly and without blocking. | < < | | < < < < < | < < < < < < < < < < < < < < < < < < < | | < < < < | < < < < < < < < < < < < < < < < | < < < < < | < < < < < | < < < < < < < < < < < < | < < < < < | < < < < < | < < < < | < < | | < | < < < < < < < > > > > > > > > > > > > > > > > > > > > | 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 | /* ** The following pair of routine implement mutual exclusion for ** multi-threaded processes. Only a single thread is allowed to ** executed code that is surrounded by EnterMutex() and LeaveMutex(). ** ** SQLite uses only a single Mutex. There is not much critical ** code and what little there is executes quickly and without blocking. */ void sqlite3OsEnterMutex(){ #ifdef SQLITE_UNIX_THREADS pthread_mutex_lock(&mutex); #endif assert( !inMutex ); inMutex = 1; } void sqlite3OsLeaveMutex(){ assert( inMutex ); inMutex = 0; #ifdef SQLITE_UNIX_THREADS pthread_mutex_unlock(&mutex); #endif } /* ** Turn a relative pathname into a full pathname. Return a pointer ** to the full pathname stored in space obtained from sqliteMalloc(). ** The calling function is responsible for freeing this space once it ** is no longer needed. */ char *sqlite3OsFullPathname(const char *zRelative){ char *zFull = 0; if( zRelative[0]=='/' ){ sqlite3SetString(&zFull, zRelative, (char*)0); }else{ char zBuf[5000]; sqlite3SetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative, (char*)0); } return zFull; } /* ** The following variable, if set to a non-zero value, becomes the result ** returned from sqlite3OsCurrentTime(). This is used for testing. */ #ifdef SQLITE_TEST int sqlite3_current_time = 0; #endif /* ** Find the current time (in Universal Coordinated Time). Write the ** current time and date as a Julian Day number into *prNow and ** return 0. Return 1 if the time and date cannot be found. */ int sqlite3OsCurrentTime(double *prNow){ time_t t; time(&t); *prNow = t/86400.0 + 2440587.5; #ifdef SQLITE_TEST if( sqlite3_current_time ){ *prNow = sqlite3_current_time/86400.0 + 2440587.5; } #endif return 0; } #if 0 /* NOT USED */ /* ** Find the time that the file was last modified. Write the ** modification time and date as a Julian Day number into *prNow and ** return SQLITE_OK. Return SQLITE_ERROR if the modification ** time cannot be found. */ int sqlite3OsFileModTime(OsFile *id, double *prNow){ int rc; struct stat statbuf; if( fstat(id->h, &statbuf)==0 ){ *prNow = statbuf.st_mtime/86400.0 + 2440587.5; rc = SQLITE_OK; }else{ rc = SQLITE_ERROR; } return rc; } #endif /* NOT USED */ #endif /* OS_UNIX */ |
Added SQLite.Interop/src/os_unix.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | /* ** 2004 May 22 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This header file defined OS-specific features for Unix. */ #ifndef _SQLITE_OS_UNIX_H_ #define _SQLITE_OS_UNIX_H_ /* ** Helpful hint: To get this to compile on HP/UX, add -D_INCLUDE_POSIX_SOURCE ** to the compiler command line. */ /* ** These #defines should enable >2GB file support on Posix if the ** underlying operating system supports it. If the OS lacks ** large file support, or if the OS is windows, these should be no-ops. ** ** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch ** on the compiler command line. This is necessary if you are compiling ** on a recent machine (ex: RedHat 7.2) but you want your code to work ** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 ** without this option, LFS is enable. But LFS does not exist in the kernel ** in RedHat 6.0, so the code won't work. Hence, for maximum binary ** portability you should omit LFS. ** ** Similar is true for MacOS. LFS is only supported on MacOS 9 and later. */ #ifndef SQLITE_DISABLE_LFS # define _LARGE_FILE 1 # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 # endif # define _LARGEFILE_SOURCE 1 #endif /* ** standard include files. */ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> /* ** The OsFile structure is a operating-system independing representation ** of an open file handle. It is defined differently for each architecture. ** ** This is the definition for Unix. ** ** OsFile.locktype takes one of the values SHARED_LOCK, RESERVED_LOCK, ** PENDING_LOCK or EXCLUSIVE_LOCK. */ typedef struct OsFile OsFile; struct OsFile { struct Pager *pPager; /* The pager that owns this OsFile. Might be 0 */ struct openCnt *pOpen; /* Info about all open fd's on this inode */ struct lockInfo *pLock; /* Info about locks on this inode */ int h; /* The file descriptor */ unsigned char locktype; /* The type of lock held on this fd */ unsigned char isOpen; /* True if needs to be closed */ int dirfd; /* File descriptor for the directory */ }; /* ** Maximum number of characters in a temporary file name */ #define SQLITE_TEMPNAME_SIZE 200 /* ** Minimum interval supported by sqlite3OsSleep(). */ #if defined(HAVE_USLEEP) && HAVE_USLEEP # define SQLITE_MIN_SLEEP_MS 1 #else # define SQLITE_MIN_SLEEP_MS 1000 #endif #endif /* _SQLITE_OS_UNIX_H_ */ |
Changes to SQLite.Interop/src/os_win.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | */ #include "sqliteInt.h" #include "os.h" #if OS_WIN /* This file is used for windows only */ #include <winbase.h> | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < | < < | < < < < < < < < < | < | < < < < < | | < < | < | | | > > > > > > > > > < < < < < < < < < < | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | < | | | | < < | < < | < < < < < < < | < < < < < < < > > | | | | | | | | < < | | | < < | | | | < < | < < < < < < < < < < < < < < | | | | | | | | < < | | | < < | | | | < | > | < < < < < < < < < < | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | */ #include "sqliteInt.h" #include "os.h" #if OS_WIN /* This file is used for windows only */ #include <winbase.h> /* ** Macros used to determine whether or not to use threads. */ #if defined(THREADSAFE) && THREADSAFE # define SQLITE_W32_THREADS 1 #endif /* ** Include code that is common to all os_*.c files */ #include "os_common.h" /* ** Delete the named file */ int sqlite3OsDelete(const char *zFilename){ DeleteFileA(zFilename); TRACE2("DELETE \"%s\"\n", zFilename); return SQLITE_OK; } /* ** Return TRUE if the named file exists. */ int sqlite3OsFileExists(const char *zFilename){ return GetFileAttributesA(zFilename) != 0xffffffff; } /* ** Attempt to open a file for both reading and writing. If that ** fails, try opening it read-only. If the file does not exist, ** try to create it. ** ** On success, a handle for the open file is written to *id ** and *pReadonly is set to 0 if the file was opened for reading and ** writing or 1 if the file was opened read-only. The function returns ** SQLITE_OK. ** ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id and *pReadonly unchanged. */ int sqlite3OsOpenReadWrite( const char *zFilename, OsFile *id, int *pReadonly ){ HANDLE h; assert( !id->isOpen ); h = CreateFileA(zFilename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ h = CreateFileA(zFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; } id->h = h; id->locktype = NO_LOCK; id->sharedLockByte = 0; id->isOpen = 1; OpenCounter(+1); TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); return SQLITE_OK; } /* ** Attempt to open a new file for exclusive access by this process. ** The file will be opened for both reading and writing. To avoid ** a potential security problem, we do not allow the file to have ** previously existed. Nor do we allow the file to be a symbolic ** link. ** ** If delFlag is true, then make arrangements to automatically delete ** the file when it is closed. ** ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ HANDLE h; int fileflags; assert( !id->isOpen ); if( delFlag ){ fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_DELETE_ON_CLOSE; }else{ fileflags = FILE_FLAG_RANDOM_ACCESS; } h = CreateFileA(zFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, fileflags, NULL ); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } id->h = h; id->locktype = NO_LOCK; id->sharedLockByte = 0; id->isOpen = 1; OpenCounter(+1); TRACE3("OPEN EX %d \"%s\"\n", h, zFilename); return SQLITE_OK; } /* ** Attempt to open a new file for read-only access. ** ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ HANDLE h; assert( !id->isOpen ); h = CreateFileA(zFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } id->h = h; id->locktype = NO_LOCK; id->sharedLockByte = 0; id->isOpen = 1; OpenCounter(+1); TRACE3("OPEN RO %d \"%s\"\n", h, zFilename); return SQLITE_OK; } /* ** Attempt to open a file descriptor for the directory that contains a ** file. This file descriptor can be used to fsync() the directory ** in order to make sure the creation of a new file is actually written ** to disk. ** ** This routine is only meaningful for Unix. It is a no-op under ** windows since windows does not support hard links. ** ** On success, a handle for a previously open file is at *id is ** updated with the new directory file descriptor and SQLITE_OK is ** returned. ** ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id unchanged. */ int sqlite3OsOpenDirectory( const char *zDirname, OsFile *id ){ return SQLITE_OK; } /* ** If the following global variable points to a string which is the ** name of a directory, then that directory will be used to store ** temporary files. */ char *sqlite3_temp_directory = 0; /* ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ int sqlite3OsTempFileName(char *zBuf){ static char zChars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; int i, j; char zTempPath[SQLITE_TEMPNAME_SIZE]; if( sqlite3_temp_directory ){ strncpy(zTempPath, sqlite3_temp_directory, SQLITE_TEMPNAME_SIZE-30); zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; }else{ GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath); } for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} zTempPath[i] = 0; for(;;){ sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath); |
︙ | ︙ | |||
799 800 801 802 803 804 805 | TRACE2("TEMP FILENAME: %s\n", zBuf); return SQLITE_OK; } /* ** Close a file. */ | | < | | | < < < < < < < < | | | | | | | | | < < < < < < < < | | < < < | | < < < | | | | | | | | | | | | | | > > > > > > > > < < > > | > > > > > > > | | | | | < | | < < | < < < < < < < < | 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 | TRACE2("TEMP FILENAME: %s\n", zBuf); return SQLITE_OK; } /* ** Close a file. */ int sqlite3OsClose(OsFile *id){ if( id->isOpen ){ TRACE2("CLOSE %d\n", id->h); CloseHandle(id->h); OpenCounter(-1); id->isOpen = 0; } return SQLITE_OK; } /* ** Read data from a file into a buffer. Return SQLITE_OK if all ** bytes were read successfully and SQLITE_IOERR if anything goes ** wrong. */ int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ DWORD got; assert( id->isOpen ); SimulateIOError(SQLITE_IOERR); TRACE3("READ %d lock=%d\n", id->h, id->locktype); if( !ReadFile(id->h, pBuf, amt, &got, 0) ){ got = 0; } if( got==(DWORD)amt ){ return SQLITE_OK; }else{ return SQLITE_IOERR; } } /* ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. */ int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ int rc = 0; DWORD wrote; assert( id->isOpen ); SimulateIOError(SQLITE_IOERR); SimulateDiskfullError; TRACE3("WRITE %d lock=%d\n", id->h, id->locktype); assert( amt>0 ); while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){ amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } if( !rc || amt>(int)wrote ){ return SQLITE_FULL; } return SQLITE_OK; } /* ** Move the read/write pointer in a file. */ int sqlite3OsSeek(OsFile *id, i64 offset){ LONG upperBits = offset>>32; LONG lowerBits = offset & 0xffffffff; DWORD rc; assert( id->isOpen ); SEEK(offset/1024 + 1); rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN); TRACE3("SEEK %d %lld\n", id->h, offset); return SQLITE_OK; } /* ** Make sure all writes to a particular file are committed to disk. */ int sqlite3OsSync(OsFile *id){ assert( id->isOpen ); TRACE3("SYNC %d lock=%d\n", id->h, id->locktype); if( FlushFileBuffers(id->h) ){ return SQLITE_OK; }else{ return SQLITE_IOERR; } } /* ** Sync the directory zDirname. This is a no-op on operating systems other ** than UNIX. */ int sqlite3OsSyncDirectory(const char *zDirname){ SimulateIOError(SQLITE_IOERR); return SQLITE_OK; } /* ** Truncate an open file to a specified size */ int sqlite3OsTruncate(OsFile *id, i64 nByte){ LONG upperBits = nByte>>32; assert( id->isOpen ); TRACE3("TRUNCATE %d %lld\n", id->h, nByte); SimulateIOError(SQLITE_IOERR); SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN); SetEndOfFile(id->h); return SQLITE_OK; } /* ** Determine the current size of a file in bytes */ int sqlite3OsFileSize(OsFile *id, i64 *pSize){ DWORD upperBits, lowerBits; assert( id->isOpen ); SimulateIOError(SQLITE_IOERR); lowerBits = GetFileSize(id->h, &upperBits); *pSize = (((i64)upperBits)<<32) + lowerBits; return SQLITE_OK; } /* ** Return true (non-zero) if we are running under WinNT, Win2K or WinXP. ** Return false (zero) for Win95, Win98, or WinME. ** ** Here is an interesting observation: Win95, Win98, and WinME lack ** the LockFileEx() API. But we can still statically link against that ** API as long as we don't call it win running Win95/98/ME. A call to ** this routine is used to determine if the host is Win95/98/ME or ** WinNT/2K/XP so that we will know whether or not we can safely call ** the LockFileEx() API. */ static int isNT(void){ static int osType = 0; /* 0=unknown 1=win95 2=winNT */ if( osType==0 ){ OSVERSIONINFO sInfo; sInfo.dwOSVersionInfoSize = sizeof(sInfo); GetVersionEx(&sInfo); osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; } return osType==2; } /* ** Acquire a reader lock. ** Different API routines are called depending on whether or not this ** is Win95 or WinNT. */ static int getReadLock(OsFile *id){ int res; if( isNT() ){ OVERLAPPED ovlp; ovlp.Offset = SHARED_FIRST; ovlp.OffsetHigh = 0; ovlp.hEvent = 0; res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY, 0, SHARED_SIZE,0,&ovlp); }else{ int lk; sqlite3Randomness(sizeof(lk), &lk); id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0); } return res; } /* ** Undo a readlock */ static int unlockReadLock(OsFile *id){ int res; if( isNT() ){ res = UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); }else{ res = UnlockFile(id->h, SHARED_FIRST + id->sharedLockByte, 0, 1, 0); } return res; } #ifndef SQLITE_OMIT_PAGER_PRAGMAS /* ** Check that a given pathname is a directory and is writable ** */ int sqlite3OsIsDirWritable(char *zBuf){ int fileAttr; if(! zBuf ) return 0; if(! isNT() && strlen(zBuf) > MAX_PATH ) return 0; fileAttr = GetFileAttributesA(zBuf); if( fileAttr == 0xffffffff ) return 0; if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){ return 0; } return 1; } #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ |
︙ | ︙ | |||
1027 1028 1029 1030 1031 1032 1033 | ** ** UNLOCKED -> SHARED ** SHARED -> RESERVED ** SHARED -> (PENDING) -> EXCLUSIVE ** RESERVED -> (PENDING) -> EXCLUSIVE ** PENDING -> EXCLUSIVE ** | | | < | | | | | | | | | | | | | | | | | | | | < | | | | | | | < | | | | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | > > > > > > > > | > > | < | < < < < < < | | > > > > | > > > | > > > > | < < < | < < < | | > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 | ** ** UNLOCKED -> SHARED ** SHARED -> RESERVED ** SHARED -> (PENDING) -> EXCLUSIVE ** RESERVED -> (PENDING) -> EXCLUSIVE ** PENDING -> EXCLUSIVE ** ** This routine will only increase a lock. The sqlite3OsUnlock() routine ** erases all locks at once and returns us immediately to locking level 0. ** It is not possible to lower the locking level one step at a time. You ** must go straight to locking level 0. */ int sqlite3OsLock(OsFile *id, int locktype){ int rc = SQLITE_OK; /* Return code from subroutines */ int res = 1; /* Result of a windows lock call */ int newLocktype; /* Set id->locktype to this value before exiting */ int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ assert( id->isOpen ); TRACE5("LOCK %d %d was %d(%d)\n", id->h, locktype, id->locktype, id->sharedLockByte); /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the end_lock: exit path, as ** sqlite3OsEnterMutex() hasn't been called yet. */ if( id->locktype>=locktype ){ return SQLITE_OK; } /* Make sure the locking sequence is correct */ assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); assert( locktype!=RESERVED_LOCK || id->locktype==SHARED_LOCK ); /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of ** the PENDING_LOCK byte is temporary. */ newLocktype = id->locktype; if( id->locktype==NO_LOCK || (locktype==EXCLUSIVE_LOCK && id->locktype==RESERVED_LOCK) ){ int cnt = 3; while( cnt-->0 && (res = LockFile(id->h, PENDING_BYTE, 0, 1, 0))==0 ){ /* Try 3 times to get the pending lock. The pending lock might be ** held by another reader process who will release it momentarily. */ TRACE2("could not get a PENDING lock. cnt=%d\n", cnt); Sleep(1); } gotPendingLock = res; } /* Acquire a shared lock */ if( locktype==SHARED_LOCK && res ){ assert( id->locktype==NO_LOCK ); res = getReadLock(id); if( res ){ newLocktype = SHARED_LOCK; } } /* Acquire a RESERVED lock */ if( locktype==RESERVED_LOCK && res ){ assert( id->locktype==SHARED_LOCK ); res = LockFile(id->h, RESERVED_BYTE, 0, 1, 0); if( res ){ newLocktype = RESERVED_LOCK; } } /* Acquire a PENDING lock */ if( locktype==EXCLUSIVE_LOCK && res ){ newLocktype = PENDING_LOCK; gotPendingLock = 0; } /* Acquire an EXCLUSIVE lock */ if( locktype==EXCLUSIVE_LOCK && res ){ assert( id->locktype>=SHARED_LOCK ); res = unlockReadLock(id); TRACE2("unreadlock = %d\n", res); res = LockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); if( res ){ newLocktype = EXCLUSIVE_LOCK; }else{ TRACE2("error-code = %d\n", GetLastError()); } } /* If we are holding a PENDING lock that ought to be released, then ** release it now. */ if( gotPendingLock && locktype==SHARED_LOCK ){ UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); } /* Update the state of the lock has held in the file descriptor then ** return the appropriate result code. */ if( res ){ rc = SQLITE_OK; }else{ TRACE4("LOCK FAILED %d trying for %d but got %d\n", id->h, locktype, newLocktype); rc = SQLITE_BUSY; } id->locktype = newLocktype; return rc; } /* ** This routine checks if there is a RESERVED lock held on the specified ** file by this or any other process. If such a lock is held, return ** non-zero, otherwise zero. */ int sqlite3OsCheckReservedLock(OsFile *id){ int rc; assert( id->isOpen ); if( id->locktype>=RESERVED_LOCK ){ rc = 1; TRACE3("TEST WR-LOCK %d %d (local)\n", id->h, rc); }else{ rc = LockFile(id->h, RESERVED_BYTE, 0, 1, 0); if( rc ){ UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); } rc = !rc; TRACE3("TEST WR-LOCK %d %d (remote)\n", id->h, rc); } return rc; } /* ** Lower the locking level on file descriptor id to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. ** ** It is not possible for this routine to fail if the second argument ** is NO_LOCK. If the second argument is SHARED_LOCK then this routine ** might return SQLITE_IOERR; */ int sqlite3OsUnlock(OsFile *id, int locktype){ int type; int rc = SQLITE_OK; assert( id->isOpen ); assert( locktype<=SHARED_LOCK ); TRACE5("UNLOCK %d to %d was %d(%d)\n", id->h, locktype, id->locktype, id->sharedLockByte); type = id->locktype; if( type>=EXCLUSIVE_LOCK ){ UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); if( locktype==SHARED_LOCK && !getReadLock(id) ){ /* This should never happen. We should always be able to ** reacquire the read lock */ rc = SQLITE_IOERR; } } if( type>=RESERVED_LOCK ){ UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); } if( locktype==NO_LOCK && type>=SHARED_LOCK ){ unlockReadLock(id); } if( type>=PENDING_LOCK ){ UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); } id->locktype = locktype; return rc; } /* ** Get information to seed the random number generator. The seed ** is written into the buffer zBuf[256]. The calling function must ** supply a sufficiently large buffer. */ int sqlite3OsRandomSeed(char *zBuf){ /* We have to initialize zBuf to prevent valgrind from reporting ** errors. The reports issued by valgrind are incorrect - we would ** prefer that the randomness be increased by making use of the ** uninitialized space in zBuf - but valgrind errors tend to worry ** some users. Rather than argue, it seems easier just to initialize ** the whole array and silence valgrind, even if that means less randomness ** in the random seed. ** ** When testing, initializing zBuf[] to zero is all we do. That means ** that we always use the same random number sequence.* This makes the ** tests repeatable. */ memset(zBuf, 0, 256); GetSystemTime((LPSYSTEMTIME)zBuf); return SQLITE_OK; } /* ** Sleep for a little while. Return the amount of time slept. */ int sqlite3OsSleep(int ms){ Sleep(ms); return ms; } /* ** Static variables used for thread synchronization */ static int inMutex = 0; #ifdef SQLITE_W32_THREADS static CRITICAL_SECTION cs; #endif /* ** The following pair of routine implement mutual exclusion for ** multi-threaded processes. Only a single thread is allowed to ** executed code that is surrounded by EnterMutex() and LeaveMutex(). ** ** SQLite uses only a single Mutex. There is not much critical ** code and what little there is executes quickly and without blocking. */ void sqlite3OsEnterMutex(){ #ifdef SQLITE_W32_THREADS static int isInit = 0; while( !isInit ){ static long lock = 0; if( InterlockedIncrement(&lock)==1 ){ InitializeCriticalSection(&cs); isInit = 1; }else{ Sleep(1); } } EnterCriticalSection(&cs); #endif assert( !inMutex ); inMutex = 1; } void sqlite3OsLeaveMutex(){ assert( inMutex ); inMutex = 0; #ifdef SQLITE_W32_THREADS LeaveCriticalSection(&cs); #endif } /* ** Turn a relative pathname into a full pathname. Return a pointer ** to the full pathname stored in space obtained from sqliteMalloc(). ** The calling function is responsible for freeing this space once it ** is no longer needed. */ char *sqlite3OsFullPathname(const char *zRelative){ char *zNotUsed; char *zFull; int nByte; nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1; zFull = sqliteMalloc( nByte ); if( zFull==0 ) return 0; GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed); return zFull; } /* ** The following variable, if set to a non-zero value, becomes the result ** returned from sqlite3OsCurrentTime(). This is used for testing. */ #ifdef SQLITE_TEST int sqlite3_current_time = 0; #endif /* ** Find the current time (in Universal Coordinated Time). Write the ** current time and date as a Julian Day number into *prNow and ** return 0. Return 1 if the time and date cannot be found. */ int sqlite3OsCurrentTime(double *prNow){ FILETIME ft; /* FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). */ double now; GetSystemTimeAsFileTime( &ft ); now = ((double)ft.dwHighDateTime) * 4294967296.0; *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5; #ifdef SQLITE_TEST if( sqlite3_current_time ){ *prNow = sqlite3_current_time/86400.0 + 2440587.5; } #endif return 0; } /* ** Find the time that the file was last modified. Write the ** modification time and date as a Julian Day number into *prNow and ** return SQLITE_OK. Return SQLITE_ERROR if the modification ** time cannot be found. */ int sqlite3OsFileModTime(OsFile *id, double *prMTime){ int rc; FILETIME ft; /* FILETIME structure is a 64-bit value representing the number of ** 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). */ if( GetFileTime(id->h, 0, 0, &ft) ){ double t; t = ((double)ft.dwHighDateTime) * 4294967296.0; *prMTime = (t + ft.dwLowDateTime)/864000000000.0 + 2305813.5; rc = SQLITE_OK; }else{ rc = SQLITE_ERROR; } return rc; } #endif /* OS_WIN */ |
Added SQLite.Interop/src/os_win.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | /* ** 2004 May 22 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This header file defines OS-specific features for Win32 */ #ifndef _SQLITE_OS_WIN_H_ #define _SQLITE_OS_WIN_H_ #include <windows.h> #include <winbase.h> /* ** The OsFile structure is a operating-system independing representation ** of an open file handle. It is defined differently for each architecture. ** ** This is the definition for Win32. */ typedef struct OsFile OsFile; struct OsFile { HANDLE h; /* Handle for accessing the file */ unsigned char locktype; /* Type of lock currently held on this file */ unsigned char isOpen; /* True if needs to be closed */ short sharedLockByte; /* Randomly chosen byte used as a shared lock */ }; #define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) #define SQLITE_MIN_SLEEP_MS 1 #endif /* _SQLITE_OS_WIN_H_ */ |
Changes to SQLite.Interop/src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** | | < | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.1 2005/03/01 16:04:31 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include "pager.h" #include <assert.h> #include <string.h> /* |
︙ | ︙ | |||
42 43 44 45 46 47 48 | #define TRACE3(X,Y,Z) #define TRACE4(X,Y,Z,W) #define TRACE5(X,Y,Z,W,V) #endif /* ** The following two macros are used within the TRACEX() macros above | | > > > > > > | | > | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | #define TRACE3(X,Y,Z) #define TRACE4(X,Y,Z,W) #define TRACE5(X,Y,Z,W,V) #endif /* ** The following two macros are used within the TRACEX() macros above ** to print out file-descriptors. They are required so that tracing ** can be turned on when using both the regular os_unix.c and os_test.c ** backends. ** ** PAGERID() takes a pointer to a Pager struct as it's argument. The ** associated file-descriptor is returned. FILEHANDLEID() takes an OsFile ** struct as it's argument. */ #ifdef OS_TEST #define PAGERID(p) (p->fd->fd.h) #define FILEHANDLEID(fd) (fd->fd.h) #else #define PAGERID(p) (p->fd.h) #define FILEHANDLEID(fd) (fd.h) #endif /* ** The page cache as a whole is always in one of the following ** states: ** ** PAGER_UNLOCK The page cache is not currently reading or ** writing the database file. There is no |
︙ | ︙ | |||
161 162 163 164 165 166 167 | u8 needSync; /* Sync journal before writing this page */ u8 alwaysRollback; /* Disable dont_rollback() for this page */ short int nRef; /* Number of users of this page */ PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */ #ifdef SQLITE_CHECK_PAGES u32 pageHash; #endif | | | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | u8 needSync; /* Sync journal before writing this page */ u8 alwaysRollback; /* Disable dont_rollback() for this page */ short int nRef; /* Number of users of this page */ PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */ #ifdef SQLITE_CHECK_PAGES u32 pageHash; #endif /* pPager->psAligned bytes of page data follow this header */ /* Pager.nExtra bytes of local data follow the page data */ }; /* ** For an in-memory only database, some extra information is recorded about ** each page so that changes can be rolled back. (Journal files are not ** used for in-memory databases.) The following information is added to |
︙ | ︙ | |||
197 198 199 200 201 202 203 | /* ** Convert a pointer to a PgHdr into a pointer to its data ** and back again. */ #define PGHDR_TO_DATA(P) ((void*)(&(P)[1])) #define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1]) | | | | < | < < < < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > > > | < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < | < > | | | | < | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | /* ** Convert a pointer to a PgHdr into a pointer to its data ** and back again. */ #define PGHDR_TO_DATA(P) ((void*)(&(P)[1])) #define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1]) #define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->psAligned]) #define PGHDR_TO_HIST(P,PGR) \ ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->psAligned+(PGR)->nExtra]) /* ** How big to make the hash table used for locating in-memory pages ** by page number. */ #define N_PG_HASH 2048 /* ** Hash a page number */ #define pager_hash(PN) ((PN)&(N_PG_HASH-1)) /* ** A open page cache is an instance of the following structure. */ struct Pager { char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ char *zDirectory; /* Directory hold database and journal files */ OsFile fd, jfd; /* File descriptors for database and journal */ OsFile stfd; /* File descriptor for the statement subjournal*/ int dbSize; /* Number of pages in the file */ int origDbSize; /* dbSize before the current change */ int stmtSize; /* Size of database (in pages) at stmt_begin() */ i64 stmtJSize; /* Size of journal at stmt_begin() */ int nRec; /* Number of pages written to the journal */ u32 cksumInit; /* Quasi-random value added to every checksum */ int stmtNRec; /* Number of records in stmt subjournal */ int nExtra; /* Add this many bytes to each in-memory page */ void (*xDestructor)(void*,int); /* Call this routine when freeing pages */ void (*xReiniter)(void*,int); /* Call this routine when reloading pages */ int pageSize; /* Number of bytes in a page */ int psAligned; /* pageSize rounded up to a multiple of 8 */ int nPage; /* Total number of in-memory pages */ int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */ int mxPage; /* Maximum number of pages to hold in cache */ int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */ int nRead,nWrite; /* Database pages read/written */ void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void *pCodecArg; /* First argument to xCodec() */ u8 journalOpen; /* True if journal file descriptors is valid */ u8 journalStarted; /* True if header of journal is synced */ u8 useJournal; /* Use a rollback journal on this file */ u8 noReadlock; /* Do not bother to obtain readlocks */ u8 stmtOpen; /* True if the statement subjournal is open */ u8 stmtInUse; /* True we are in a statement subtransaction */ u8 stmtAutoopen; /* Open stmt journal when main journal is opened*/ u8 noSync; /* Do not sync the journal if true */ u8 fullSync; /* Do extra syncs of the journal for robustness */ u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */ u8 errMask; /* One of several kinds of errors */ u8 tempFile; /* zFilename is a temporary file */ u8 readOnly; /* True for a read-only database */ u8 needSync; /* True if an fsync() is needed on the journal */ u8 dirtyCache; /* True if cached pages have changed */ u8 alwaysRollback; /* Disable dont_rollback() for all pages */ u8 memDb; /* True to inhibit all file I/O */ u8 *aInJournal; /* One bit for each page in the database file */ u8 *aInStmt; /* One bit for each page in the database */ u8 setMaster; /* True if a m-j name has been written to jrnl */ BusyHandler *pBusyHandler; /* Pointer to sqlite.busyHandler */ PgHdr *pFirst, *pLast; /* List of free pages */ PgHdr *pFirstSynced; /* First free page with PgHdr.needSync==0 */ PgHdr *pAll; /* List of all pages */ PgHdr *pStmt; /* List of pages in the statement subjournal */ i64 journalOff; /* Current byte offset in the journal file */ i64 journalHdr; /* Byte offset to previous journal header */ i64 stmtHdrOff; /* First journal header written this statement */ i64 stmtCksum; /* cksumInit when statement was started */ int sectorSize; /* Assumed sector size during rollback */ PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number to PgHdr */ }; /* ** These are bits that can be set in Pager.errMask. */ #define PAGER_ERR_FULL 0x01 /* a write() failed */ #define PAGER_ERR_MEM 0x02 /* malloc() failed */ #define PAGER_ERR_LOCK 0x04 /* error in the locking protocol */ #define PAGER_ERR_CORRUPT 0x08 /* database or journal corruption */ #define PAGER_ERR_DISK 0x10 /* general disk I/O error - bad hard drive? */ /* ** Journal files begin with the following magic string. The data ** was obtained from /dev/random. It is used only as a sanity check. ** ** Since version 2.8.0, the journal format contains additional sanity ** checking information. If the power fails while the journal is begin |
︙ | ︙ | |||
402 403 404 405 406 407 408 | ** Read a 32-bit integer from the given file descriptor. Store the integer ** that is read in *pRes. Return SQLITE_OK if everything worked, or an ** error code is something goes wrong. ** ** All values are stored on disk as big-endian. */ static int read32bits(OsFile *fd, u32 *pRes){ | | > | > > | > < < < < < < < < < < > > > | > > > | | < < < < < < | | < < | > | | | < | < | 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 | ** Read a 32-bit integer from the given file descriptor. Store the integer ** that is read in *pRes. Return SQLITE_OK if everything worked, or an ** error code is something goes wrong. ** ** All values are stored on disk as big-endian. */ static int read32bits(OsFile *fd, u32 *pRes){ u32 res; int rc; rc = sqlite3OsRead(fd, &res, sizeof(res)); if( rc==SQLITE_OK ){ unsigned char ac[4]; memcpy(ac, &res, 4); res = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; } *pRes = res; return rc; } /* ** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK ** on success or an error code is something goes wrong. */ static int write32bits(OsFile *fd, u32 val){ unsigned char ac[4]; ac[0] = (val>>24) & 0xff; ac[1] = (val>>16) & 0xff; ac[2] = (val>>8) & 0xff; ac[3] = val & 0xff; return sqlite3OsWrite(fd, ac, 4); } /* ** Write the 32-bit integer 'val' into the page identified by page header ** 'p' at offset 'offset'. */ static void store32bits(u32 val, PgHdr *p, int offset){ unsigned char *ac; ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; ac[0] = (val>>24) & 0xff; ac[1] = (val>>16) & 0xff; ac[2] = (val>>8) & 0xff; ac[3] = val & 0xff; } /* ** Read a 32-bit integer at offset 'offset' from the page identified by ** page header 'p'. */ static u32 retrieve32bits(PgHdr *p, int offset){ unsigned char *ac; ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; return (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; } /* ** Convert the bits in the pPager->errMask into an approprate ** return code. */ static int pager_errcode(Pager *pPager){ int rc = SQLITE_OK; if( pPager->errMask & PAGER_ERR_LOCK ) rc = SQLITE_PROTOCOL; if( pPager->errMask & PAGER_ERR_DISK ) rc = SQLITE_IOERR; if( pPager->errMask & PAGER_ERR_FULL ) rc = SQLITE_FULL; if( pPager->errMask & PAGER_ERR_MEM ) rc = SQLITE_NOMEM; if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT; return rc; } #ifdef SQLITE_CHECK_PAGES /* ** Return a 32-bit hash of the page data for pPage. */ |
︙ | ︙ | |||
496 497 498 499 500 501 502 | ** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES ** is defined, and NDEBUG is not defined, an assert() statement checks ** that the page is either dirty or still matches the calculated page-hash. */ #define CHECK_PAGE(x) checkPage(x) static void checkPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; | | | 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 | ** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES ** is defined, and NDEBUG is not defined, an assert() statement checks ** that the page is either dirty or still matches the calculated page-hash. */ #define CHECK_PAGE(x) checkPage(x) static void checkPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; assert( !pPg->pageHash || pPager->errMask || MEMDB || pPg->dirty || pPg->pageHash==pager_pagehash(pPg) ); } #else #define CHECK_PAGE(x) #endif |
︙ | ︙ | |||
597 598 599 600 601 602 603 | if( c ){ offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager); } assert( offset%JOURNAL_HDR_SZ(pPager)==0 ); assert( offset>=c ); assert( (offset-c)<JOURNAL_HDR_SZ(pPager) ); pPager->journalOff = offset; | | < | > > | | > > | | | > > | | > > | | < > | < | < | 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 | if( c ){ offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager); } assert( offset%JOURNAL_HDR_SZ(pPager)==0 ); assert( offset>=c ); assert( (offset-c)<JOURNAL_HDR_SZ(pPager) ); pPager->journalOff = offset; return sqlite3OsSeek(&pPager->jfd, pPager->journalOff); } /* ** The journal file must be open when this routine is called. A journal ** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the ** current location. ** ** The format for the journal header is as follows: ** - 8 bytes: Magic identifying journal format. ** - 4 bytes: Number of records in journal, or -1 no-sync mode is on. ** - 4 bytes: Random number used for page hash. ** - 4 bytes: Initial database page count. ** - 4 bytes: Sector size used by the process that wrote this journal. ** ** Followed by (JOURNAL_HDR_SZ - 24) bytes of unused space. */ static int writeJournalHdr(Pager *pPager){ int rc = seekJournalHdr(pPager); if( rc ) return rc; pPager->journalHdr = pPager->journalOff; if( pPager->stmtHdrOff==0 ){ pPager->stmtHdrOff = pPager->journalHdr; } pPager->journalOff += JOURNAL_HDR_SZ(pPager); /* FIX ME: ** ** Possibly for a pager not in no-sync mode, the journal magic should not ** be written until nRec is filled in as part of next syncJournal(). ** ** Actually maybe the whole journal header should be delayed until that ** point. Think about this. */ rc = sqlite3OsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); if( rc==SQLITE_OK ){ /* The nRec Field. 0xFFFFFFFF for no-sync journals. */ rc = write32bits(&pPager->jfd, pPager->noSync ? 0xffffffff : 0); } if( rc==SQLITE_OK ){ /* The random check-hash initialiser */ sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); rc = write32bits(&pPager->jfd, pPager->cksumInit); } if( rc==SQLITE_OK ){ /* The initial database size */ rc = write32bits(&pPager->jfd, pPager->dbSize); } if( rc==SQLITE_OK ){ /* The assumed sector size for this process */ rc = write32bits(&pPager->jfd, pPager->sectorSize); } /* The journal header has been written successfully. Seek the journal ** file descriptor to the end of the journal header sector. */ if( rc==SQLITE_OK ){ sqlite3OsSeek(&pPager->jfd, pPager->journalOff-1); rc = sqlite3OsWrite(&pPager->jfd, "\000", 1); } return rc; } /* ** The journal file must be open when this is called. A journal header file ** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal |
︙ | ︙ | |||
690 691 692 693 694 695 696 | rc = seekJournalHdr(pPager); if( rc ) return rc; if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){ return SQLITE_DONE; } | | | | | | | < < < | < | | > > | > > | | < | | 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 | rc = seekJournalHdr(pPager); if( rc ) return rc; if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){ return SQLITE_DONE; } rc = sqlite3OsRead(&pPager->jfd, aMagic, sizeof(aMagic)); if( rc ) return rc; if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ return SQLITE_DONE; } rc = read32bits(&pPager->jfd, pNRec); if( rc ) return rc; rc = read32bits(&pPager->jfd, &pPager->cksumInit); if( rc ) return rc; rc = read32bits(&pPager->jfd, pDbSize); if( rc ) return rc; /* Update the assumed sector-size to match the value used by ** the process that created this journal. If this journal was ** created by a process other than this one, then this routine ** is being called from within pager_playback(). The local value ** of Pager.sectorSize is restored at the end of that routine. */ rc = read32bits(&pPager->jfd, (u32 *)&pPager->sectorSize); if( rc ) return rc; pPager->journalOff += JOURNAL_HDR_SZ(pPager); rc = sqlite3OsSeek(&pPager->jfd, pPager->journalOff); return rc; } /* ** Write the supplied master journal name into the journal file for pager ** pPager at the current location. The master journal name must be the last ** thing written to a journal file. If the pager is in full-sync mode, the ** journal file descriptor is advanced to the next sector boundary before ** anything is written. The format is: ** ** + 4 bytes: PAGER_MJ_PGNO. ** + N bytes: length of master journal name. ** + 4 bytes: N ** + 4 bytes: Master journal name checksum. ** + 8 bytes: aJournalMagic[]. ** ** The master journal page checksum is the sum of the bytes in the master ** journal name. */ static int writeMasterJournal(Pager *pPager, const char *zMaster){ int rc; int len; int i; u32 cksum = 0; if( !zMaster || pPager->setMaster) return SQLITE_OK; pPager->setMaster = 1; len = strlen(zMaster); for(i=0; i<len; i++){ cksum += zMaster[i]; } /* If in full-sync mode, advance to the next disk sector before writing ** the master journal name. This is in case the previous page written to ** the journal has already been synced. */ if( pPager->fullSync ){ rc = seekJournalHdr(pPager); if( rc!=SQLITE_OK ) return rc; } pPager->journalOff += (len+20); rc = write32bits(&pPager->jfd, PAGER_MJ_PGNO(pPager)); if( rc!=SQLITE_OK ) return rc; rc = sqlite3OsWrite(&pPager->jfd, zMaster, len); if( rc!=SQLITE_OK ) return rc; rc = write32bits(&pPager->jfd, len); if( rc!=SQLITE_OK ) return rc; rc = write32bits(&pPager->jfd, cksum); if( rc!=SQLITE_OK ) return rc; rc = sqlite3OsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); pPager->needSync = 1; return rc; } /* ** Add or remove a page from the list of all pages that are in the ** statement journal. ** |
︙ | ︙ | |||
838 839 840 841 842 843 844 | ** Unlock the database and clear the in-memory cache. This routine ** sets the state of the pager back to what it was when it was first ** opened. Any outstanding pages are invalidated and subsequent attempts ** to access those pages will likely result in a coredump. */ static void pager_reset(Pager *pPager){ PgHdr *pPg, *pNext; | < | | 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 | ** Unlock the database and clear the in-memory cache. This routine ** sets the state of the pager back to what it was when it was first ** opened. Any outstanding pages are invalidated and subsequent attempts ** to access those pages will likely result in a coredump. */ static void pager_reset(Pager *pPager){ PgHdr *pPg, *pNext; for(pPg=pPager->pAll; pPg; pPg=pNext){ pNext = pPg->pNextAll; sqliteFree(pPg); } pPager->pFirst = 0; pPager->pFirstSynced = 0; pPager->pLast = 0; pPager->pAll = 0; memset(pPager->aHash, 0, sizeof(pPager->aHash)); pPager->nPage = 0; if( pPager->state>=PAGER_RESERVED ){ sqlite3pager_rollback(pPager); } sqlite3OsUnlock(&pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; pPager->dbSize = -1; pPager->nRef = 0; assert( pPager->journalOpen==0 ); } /* |
︙ | ︙ | |||
898 899 900 901 902 903 904 | #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif } pPager->dirtyCache = 0; pPager->nRec = 0; }else{ | < | | 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 | #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif } pPager->dirtyCache = 0; pPager->nRec = 0; }else{ assert( pPager->dirtyCache==0 || pPager->useJournal==0 ); } rc = sqlite3OsUnlock(&pPager->fd, SHARED_LOCK); pPager->state = PAGER_SHARED; pPager->origDbSize = 0; pPager->setMaster = 0; return rc; } /* |
︙ | ︙ | |||
928 929 930 931 932 933 934 | ** though fast and simple, catches the mostly likely kind of corruption. ** ** FIX ME: Consider adding every 200th (or so) byte of the data to the ** checksum. That way if a single page spans 3 or more disk sectors and ** only the middle sector is corrupt, we will still have a reasonable ** chance of failing the checksum and thus detecting the problem. */ | | | 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 | ** though fast and simple, catches the mostly likely kind of corruption. ** ** FIX ME: Consider adding every 200th (or so) byte of the data to the ** checksum. That way if a single page spans 3 or more disk sectors and ** only the middle sector is corrupt, we will still have a reasonable ** chance of failing the checksum and thus detecting the problem. */ static u32 pager_cksum(Pager *pPager, Pgno pgno, const char *aData){ u32 cksum = pPager->cksumInit; int i = pPager->pageSize-200; while( i>0 ){ cksum += aData[i]; i -= 200; } return cksum; |
︙ | ︙ | |||
952 953 954 955 956 957 958 | */ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ int rc; PgHdr *pPg; /* An existing page in the cache */ Pgno pgno; /* The page number of a page in journal */ u32 cksum; /* Checksum used for sanity checking */ u8 aData[SQLITE_MAX_PAGE_SIZE]; /* Temp storage for a page */ | < < < < < < | 930 931 932 933 934 935 936 937 938 939 940 941 942 943 | */ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ int rc; PgHdr *pPg; /* An existing page in the cache */ Pgno pgno; /* The page number of a page in journal */ u32 cksum; /* Checksum used for sanity checking */ u8 aData[SQLITE_MAX_PAGE_SIZE]; /* Temp storage for a page */ rc = read32bits(jfd, &pgno); if( rc!=SQLITE_OK ) return rc; rc = sqlite3OsRead(jfd, &aData, pPager->pageSize); if( rc!=SQLITE_OK ) return rc; pPager->journalOff += pPager->pageSize + 4; |
︙ | ︙ | |||
993 994 995 996 997 998 999 | /* If the pager is in RESERVED state, then there must be a copy of this ** page in the pager cache. In this case just update the pager cache, ** not the database file. The page is left marked dirty in this case. ** ** If in EXCLUSIVE state, then we update the pager cache if it exists ** and the main file. The page is then marked not dirty. | < < < < < < < < < < < < < | | | < | < < > > > | > | > | | | > | | 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 | /* If the pager is in RESERVED state, then there must be a copy of this ** page in the pager cache. In this case just update the pager cache, ** not the database file. The page is left marked dirty in this case. ** ** If in EXCLUSIVE state, then we update the pager cache if it exists ** and the main file. The page is then marked not dirty. */ pPg = pager_lookup(pPager, pgno); assert( pPager->state>=PAGER_EXCLUSIVE || pPg ); TRACE3("PLAYBACK %d page %d\n", PAGERID(pPager), pgno); if( pPager->state>=PAGER_EXCLUSIVE ){ sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize); rc = sqlite3OsWrite(&pPager->fd, aData, pPager->pageSize); } if( pPg ){ /* No page should ever be explicitly rolled back that is in use, except ** for page 1 which is held in use in order to keep the lock on the ** database active. However such a page may be rolled back as a result ** of an internal error resulting in an automatic call to ** sqlite3pager_rollback(). */ void *pData; /* assert( pPg->nRef==0 || pPg->pgno==1 ); */ pData = PGHDR_TO_DATA(pPg); memcpy(pData, aData, pPager->pageSize); if( pPager->xDestructor ){ /*** FIX ME: Should this be xReinit? ***/ pPager->xDestructor(pData, pPager->pageSize); } if( pPager->state>=PAGER_EXCLUSIVE ){ pPg->dirty = 0; pPg->needSync = 0; #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif } CODEC(pPager, pData, pPg->pgno, 3); } return rc; } /* ** Parameter zMaster is the name of a master journal file. A single journal ** file that referred to the master journal file has just been rolled back. ** This routine checks if it is possible to delete the master journal file, ** and does so if it is. ** ** The master journal file contains the names of all child journals. ** To tell if a master journal can be deleted, check to each of the ** children. If all children are either missing or do not refer to ** a different master journal, then this master journal can be deleted. */ static int pager_delmaster(const char *zMaster){ int rc; int master_open = 0; OsFile master; char *zMasterJournal = 0; /* Contents of master journal file */ i64 nMasterJournal; /* Size of master journal file */ /* Open the master journal file exclusively in case some other process ** is running this routine also. Not that it makes too much difference. */ memset(&master, 0, sizeof(master)); rc = sqlite3OsOpenReadOnly(zMaster, &master); if( rc!=SQLITE_OK ) goto delmaster_out; master_open = 1; rc = sqlite3OsFileSize(&master, &nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; if( nMasterJournal>0 ){ char *zJournal; char *zMasterPtr = 0; /* Load the entire master journal file into space obtained from ** sqliteMalloc() and pointed to by zMasterJournal. */ zMasterJournal = (char *)sqliteMalloc(nMasterJournal); if( !zMasterJournal ){ rc = SQLITE_NOMEM; goto delmaster_out; } rc = sqlite3OsRead(&master, zMasterJournal, nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; zJournal = zMasterJournal; while( (zJournal-zMasterJournal)<nMasterJournal ){ if( sqlite3OsFileExists(zJournal) ){ /* One of the journals pointed to by the master journal exists. ** Open it and check if it points at the master journal. If ** so, return without deleting the master journal file. */ OsFile journal; int c; memset(&journal, 0, sizeof(journal)); rc = sqlite3OsOpenReadOnly(zJournal, &journal); if( rc!=SQLITE_OK ){ goto delmaster_out; } rc = readMasterJournal(&journal, &zMasterPtr); sqlite3OsClose(&journal); if( rc!=SQLITE_OK ){ goto delmaster_out; } c = zMasterPtr!=0 && strcmp(zMasterPtr, zMaster)==0; sqliteFree(zMasterPtr); |
︙ | ︙ | |||
1141 1142 1143 1144 1145 1146 1147 | static int pager_reload_cache(Pager *pPager){ PgHdr *pPg; int rc = SQLITE_OK; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ char zBuf[SQLITE_MAX_PAGE_SIZE]; if( !pPg->dirty ) continue; if( (int)pPg->pgno <= pPager->origDbSize ){ | | < | < | 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 | static int pager_reload_cache(Pager *pPager){ PgHdr *pPg; int rc = SQLITE_OK; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ char zBuf[SQLITE_MAX_PAGE_SIZE]; if( !pPg->dirty ) continue; if( (int)pPg->pgno <= pPager->origDbSize ){ sqlite3OsSeek(&pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1)); rc = sqlite3OsRead(&pPager->fd, zBuf, pPager->pageSize); TRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno); if( rc ) break; CODEC(pPager, zBuf, pPg->pgno, 2); }else{ memset(zBuf, 0, pPager->pageSize); } if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), pPager->pageSize) ){ |
︙ | ︙ | |||
1174 1175 1176 1177 1178 1179 1180 | /* ** Truncate the main file of the given pager to the number of pages ** indicated. */ static int pager_truncate(Pager *pPager, int nPage){ assert( pPager->state>=PAGER_EXCLUSIVE ); | | | 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 | /* ** Truncate the main file of the given pager to the number of pages ** indicated. */ static int pager_truncate(Pager *pPager, int nPage){ assert( pPager->state>=PAGER_EXCLUSIVE ); return sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(i64)nPage); } /* ** Playback the journal and thus restore the database file to ** the state it was in before we started making changes. ** ** The journal file format is as follows: |
︙ | ︙ | |||
1242 1243 1244 1245 1246 1247 1248 | int rc; /* Result code of a subroutine */ char *zMaster = 0; /* Name of master journal file if any */ /* Figure out how many records are in the journal. Abort early if ** the journal is empty. */ assert( pPager->journalOpen ); | | | | | 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 | int rc; /* Result code of a subroutine */ char *zMaster = 0; /* Name of master journal file if any */ /* Figure out how many records are in the journal. Abort early if ** the journal is empty. */ assert( pPager->journalOpen ); rc = sqlite3OsFileSize(&pPager->jfd, &szJ); if( rc!=SQLITE_OK ){ goto end_playback; } /* Read the master journal name from the journal, if it is present. ** If a master journal file name is specified, but the file is not ** present on disk, then the journal is not hot and does not need to be ** played back. */ rc = readMasterJournal(&pPager->jfd, &zMaster); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK || (zMaster && !sqlite3OsFileExists(zMaster)) ){ sqliteFree(zMaster); zMaster = 0; if( rc==SQLITE_DONE ) rc = SQLITE_OK; goto end_playback; } sqlite3OsSeek(&pPager->jfd, 0); pPager->journalOff = 0; /* This loop terminates either when the readJournalHdr() call returns ** SQLITE_DONE or an IO error occurs. */ while( 1 ){ /* Read the next journal header from the journal file. If there are |
︙ | ︙ | |||
1303 1304 1305 1306 1307 1308 1309 | rc = pager_truncate(pPager, mxPg); if( rc!=SQLITE_OK ){ goto end_playback; } pPager->dbSize = mxPg; } | | | | 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 | rc = pager_truncate(pPager, mxPg); if( rc!=SQLITE_OK ){ goto end_playback; } pPager->dbSize = mxPg; } /* rc = sqlite3OsSeek(&pPager->jfd, JOURNAL_HDR_SZ(pPager)); */ if( rc!=SQLITE_OK ) goto end_playback; /* Copy original pages out of the journal and back into the database file. */ for(i=0; i<nRec; i++){ rc = pager_playback_one_page(pPager, &pPager->jfd, 1); if( rc!=SQLITE_OK ){ if( rc==SQLITE_DONE ){ rc = SQLITE_OK; pPager->journalOff = szJ; break; }else{ goto end_playback; |
︙ | ︙ | |||
1376 1377 1378 1379 1380 1381 1382 | int i; /* Loop counter */ int rc; szJ = pPager->journalOff; #ifndef NDEBUG { i64 os_szJ; | | | 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 | int i; /* Loop counter */ int rc; szJ = pPager->journalOff; #ifndef NDEBUG { i64 os_szJ; rc = sqlite3OsFileSize(&pPager->jfd, &os_szJ); if( rc!=SQLITE_OK ) return rc; assert( szJ==os_szJ ); } #endif /* Set hdrOff to be the offset to the first journal header written ** this statement transaction, or the end of the file if no journal |
︙ | ︙ | |||
1402 1403 1404 1405 1406 1407 1408 | rc = pager_truncate(pPager, pPager->stmtSize); } pPager->dbSize = pPager->stmtSize; /* Figure out how many records are in the statement journal. */ assert( pPager->stmtInUse && pPager->journalOpen ); | | | | | | > | > > > > > > > > > > > > > > | 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 | rc = pager_truncate(pPager, pPager->stmtSize); } pPager->dbSize = pPager->stmtSize; /* Figure out how many records are in the statement journal. */ assert( pPager->stmtInUse && pPager->journalOpen ); sqlite3OsSeek(&pPager->stfd, 0); nRec = pPager->stmtNRec; /* Copy original pages out of the statement journal and back into the ** database file. Note that the statement journal omits checksums from ** each record since power-failure recovery is not important to statement ** journals. */ for(i=nRec-1; i>=0; i--){ rc = pager_playback_one_page(pPager, &pPager->stfd, 0); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; } /* Now roll some pages back from the transaction journal. Pager.stmtJSize ** was the size of the journal file when this statement was started, so ** everything after that needs to be rolled back, either into the ** database, the memory cache, or both. ** ** If it is not zero, then Pager.stmtHdrOff is the offset to the start ** of the first journal header written during this statement transaction. */ rc = sqlite3OsSeek(&pPager->jfd, pPager->stmtJSize); if( rc!=SQLITE_OK ){ goto end_stmt_playback; } pPager->journalOff = pPager->stmtJSize; pPager->cksumInit = pPager->stmtCksum; assert( JOURNAL_HDR_SZ(pPager)<(pPager->pageSize+8) ); while( pPager->journalOff <= (hdrOff-(pPager->pageSize+8)) ){ rc = pager_playback_one_page(pPager, &pPager->jfd, 1); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; } while( pPager->journalOff < szJ ){ u32 nRec; u32 dummy; rc = readJournalHdr(pPager, szJ, &nRec, &dummy); if( rc!=SQLITE_OK ){ assert( rc!=SQLITE_DONE ); goto end_stmt_playback; } if( nRec==0 ){ nRec = (szJ - pPager->journalOff) / (pPager->pageSize+8); } for(i=nRec-1; i>=0 && pPager->journalOff < szJ; i--){ rc = pager_playback_one_page(pPager, &pPager->jfd, 1); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; } } pPager->journalOff = szJ; end_stmt_playback: if( rc!=SQLITE_OK ){ pPager->errMask |= PAGER_ERR_CORRUPT; rc = SQLITE_CORRUPT; /* bkpt-CORRUPT */ }else{ pPager->journalOff = szJ; /* pager_reload_cache(pPager); */ } return rc; } /* ** Change the maximum number of in-memory pages that are allowed. ** ** The maximum number is the absolute value of the mxPage parameter. ** If mxPage is negative, the noSync flag is also set. noSync bypasses ** calls to sqlite3OsSync(). The pager runs much faster with noSync on, ** but if the operating system crashes or there is an abrupt power ** failure, the database file might be left in an inconsistent and ** unrepairable state. */ void sqlite3pager_set_cachesize(Pager *pPager, int mxPage){ if( mxPage>=0 ){ pPager->noSync = pPager->tempFile; if( pPager->noSync ) pPager->needSync = 0; }else{ pPager->noSync = 1; mxPage = -mxPage; } if( mxPage>10 ){ pPager->mxPage = mxPage; }else{ pPager->mxPage = 10; } } |
︙ | ︙ | |||
1513 1514 1515 1516 1517 1518 1519 | pPager->noSync = level==1 || pPager->tempFile; pPager->fullSync = level==3 && !pPager->tempFile; if( pPager->noSync ) pPager->needSync = 0; } #endif /* | < < < < < < < | | | < | | 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 | pPager->noSync = level==1 || pPager->tempFile; pPager->fullSync = level==3 && !pPager->tempFile; if( pPager->noSync ) pPager->needSync = 0; } #endif /* ** Open a temporary file. Write the name of the file into zName ** (zName must be at least SQLITE_TEMPNAME_SIZE bytes long.) Write ** the file descriptor into *fd. Return SQLITE_OK on success or some ** other error code if we fail. ** ** The OS will automatically delete the temporary file when it is ** closed. */ static int sqlite3pager_opentemp(char *zFile, OsFile *fd){ int cnt = 8; int rc; do{ cnt--; sqlite3OsTempFileName(zFile); rc = sqlite3OsOpenExclusive(zFile, fd, 1); }while( cnt>0 && rc!=SQLITE_OK && rc!=SQLITE_NOMEM ); return rc; } /* ** Create a new page cache and put a pointer to the page cache in *ppPager. ** The file to be cached need not exist. The file is not locked until |
︙ | ︙ | |||
1560 1561 1562 1563 1564 1565 1566 | */ int sqlite3pager_open( Pager **ppPager, /* Return the Pager structure here */ const char *zFilename, /* Name of the database file to open */ int nExtra, /* Extra bytes append to each in-memory page */ int flags /* flags controlling this file */ ){ | | | < < < < < < < > | < < < < < > > > > | < < < < > > | > > | | < | < < < < < < < | < < > > > | | | | > | | | < < | | | | | | | | < < < < < < < | 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 | */ int sqlite3pager_open( Pager **ppPager, /* Return the Pager structure here */ const char *zFilename, /* Name of the database file to open */ int nExtra, /* Extra bytes append to each in-memory page */ int flags /* flags controlling this file */ ){ Pager *pPager; char *zFullPathname = 0; int nameLen; OsFile fd; int rc = SQLITE_OK; int i; int tempFile = 0; int memDb = 0; int readOnly = 0; int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; int noReadlock = (flags & PAGER_NO_READLOCK)!=0; char zTemp[SQLITE_TEMPNAME_SIZE]; *ppPager = 0; memset(&fd, 0, sizeof(fd)); if( sqlite3_malloc_failed ){ return SQLITE_NOMEM; } if( zFilename && zFilename[0] ){ #ifndef SQLITE_OMIT_MEMORYDB if( strcmp(zFilename,":memory:")==0 ){ memDb = 1; zFullPathname = sqliteStrDup(""); rc = SQLITE_OK; }else #endif { zFullPathname = sqlite3OsFullPathname(zFilename); if( zFullPathname ){ rc = sqlite3OsOpenReadWrite(zFullPathname, &fd, &readOnly); } } }else{ rc = sqlite3pager_opentemp(zTemp, &fd); zFilename = zTemp; zFullPathname = sqlite3OsFullPathname(zFilename); if( rc==SQLITE_OK ){ tempFile = 1; } } if( !zFullPathname ){ sqlite3OsClose(&fd); return SQLITE_NOMEM; } if( rc!=SQLITE_OK ){ sqlite3OsClose(&fd); sqliteFree(zFullPathname); return rc; } nameLen = strlen(zFullPathname); pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 ); if( pPager==0 ){ sqlite3OsClose(&fd); sqliteFree(zFullPathname); return SQLITE_NOMEM; } TRACE3("OPEN %d %s\n", FILEHANDLEID(fd), zFullPathname); pPager->zFilename = (char*)&pPager[1]; pPager->zDirectory = &pPager->zFilename[nameLen+1]; pPager->zJournal = &pPager->zDirectory[nameLen+1]; strcpy(pPager->zFilename, zFullPathname); strcpy(pPager->zDirectory, zFullPathname); for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){} if( i>0 ) pPager->zDirectory[i-1] = 0; strcpy(pPager->zJournal, zFullPathname); sqliteFree(zFullPathname); strcpy(&pPager->zJournal[nameLen], "-journal"); pPager->fd = fd; #if OS_UNIX pPager->fd.pPager = pPager; #endif pPager->journalOpen = 0; pPager->useJournal = useJournal && !memDb; pPager->noReadlock = noReadlock && readOnly; pPager->stmtOpen = 0; pPager->stmtInUse = 0; pPager->nRef = 0; pPager->dbSize = memDb-1; pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE; pPager->psAligned = FORCE_ALIGNMENT(pPager->pageSize); pPager->stmtSize = 0; pPager->stmtJSize = 0; pPager->nPage = 0; pPager->mxPage = 100; pPager->state = PAGER_UNLOCK; pPager->errMask = 0; pPager->tempFile = tempFile; pPager->memDb = memDb; pPager->readOnly = readOnly; pPager->needSync = 0; pPager->noSync = pPager->tempFile || !useJournal; pPager->fullSync = (pPager->noSync?0:1); pPager->pFirst = 0; pPager->pFirstSynced = 0; pPager->pLast = 0; pPager->nExtra = FORCE_ALIGNMENT(nExtra); pPager->sectorSize = PAGER_SECTOR_SIZE; pPager->pBusyHandler = 0; memset(pPager->aHash, 0, sizeof(pPager->aHash)); *ppPager = pPager; return SQLITE_OK; } /* ** Set the busy handler function. */ void sqlite3pager_set_busyhandler(Pager *pPager, BusyHandler *pBusyHandler){ |
︙ | ︙ | |||
1716 1717 1718 1719 1720 1721 1722 | ** page data. */ void sqlite3pager_set_reiniter(Pager *pPager, void (*xReinit)(void*,int)){ pPager->xReiniter = xReinit; } /* | | < | > | < | < < < | < < < < < < < < < < < < < < < < < | < < < < < < < < < | < < < < < < | | < | < < < < < | < > | | | | | < < | > | | | < < < < | 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 | ** page data. */ void sqlite3pager_set_reiniter(Pager *pPager, void (*xReinit)(void*,int)){ pPager->xReiniter = xReinit; } /* ** Set the page size. ** ** The page size must only be changed when the cache is empty. */ void sqlite3pager_set_pagesize(Pager *pPager, int pageSize){ assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE ); pPager->pageSize = pageSize; pPager->psAligned = FORCE_ALIGNMENT(pageSize); } /* ** Read the first N bytes from the beginning of the file into memory ** that pDest points to. No error checking is done. */ void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){ memset(pDest, 0, N); if( MEMDB==0 ){ sqlite3OsSeek(&pPager->fd, 0); sqlite3OsRead(&pPager->fd, pDest, N); } } /* ** Return the total number of pages in the disk file associated with ** pPager. */ int sqlite3pager_pagecount(Pager *pPager){ i64 n; assert( pPager!=0 ); if( pPager->dbSize>=0 ){ return pPager->dbSize; } if( sqlite3OsFileSize(&pPager->fd, &n)!=SQLITE_OK ){ pPager->errMask |= PAGER_ERR_DISK; return 0; } n /= pPager->pageSize; if( !MEMDB && n==PENDING_BYTE/pPager->pageSize ){ n++; } if( pPager->state!=PAGER_UNLOCK ){ pPager->dbSize = n; } return n; } /* ** Forward declaration */ |
︙ | ︙ | |||
1907 1908 1909 1910 1911 1912 1913 | } #else #define memoryTruncate(p) #endif /* ** Try to obtain a lock on a file. Invoke the busy callback if the lock | | > | | > > > > | | | 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 | } #else #define memoryTruncate(p) #endif /* ** Try to obtain a lock on a file. Invoke the busy callback if the lock ** is currently not available. Repeate until the busy callback returns ** false or until the lock succeeds. ** ** Return SQLITE_OK on success and an error code if we cannot obtain ** the lock. */ static int pager_wait_on_lock(Pager *pPager, int locktype){ int rc; assert( PAGER_SHARED==SHARED_LOCK ); assert( PAGER_RESERVED==RESERVED_LOCK ); assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK ); if( pPager->state>=locktype ){ rc = SQLITE_OK; }else{ int busy = 1; do { rc = sqlite3OsLock(&pPager->fd, locktype); }while( rc==SQLITE_BUSY && pPager->pBusyHandler && pPager->pBusyHandler->xFunc && pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++) ); if( rc==SQLITE_OK ){ pPager->state = locktype; } } return rc; } /* ** Truncate the file to the number of pages specified. */ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ int rc; sqlite3pager_pagecount(pPager); if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); return rc; } if( nPage>=(unsigned)pPager->dbSize ){ return SQLITE_OK; } if( MEMDB ){ pPager->dbSize = nPage; |
︙ | ︙ | |||
1975 1976 1977 1978 1979 1980 1981 | ** Shutdown the page cache. Free all memory and close all files. ** ** If a transaction was in progress when this routine is called, that ** transaction is rolled back. All outstanding pages are invalidated ** and their memory is freed. Any attempt to use a page associated ** with this page cache after this function returns will likely ** result in a coredump. | < < < < < < < < < > > > | > > | > | | | | 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 | ** Shutdown the page cache. Free all memory and close all files. ** ** If a transaction was in progress when this routine is called, that ** transaction is rolled back. All outstanding pages are invalidated ** and their memory is freed. Any attempt to use a page associated ** with this page cache after this function returns will likely ** result in a coredump. */ int sqlite3pager_close(Pager *pPager){ PgHdr *pPg, *pNext; switch( pPager->state ){ case PAGER_RESERVED: case PAGER_SYNCED: case PAGER_EXCLUSIVE: { /* We ignore any IO errors that occur during the rollback ** operation. So disable IO error simulation so that testing ** works more easily. */ #if defined(SQLITE_TEST) && (defined(OS_UNIX) || defined(OS_WIN)) extern int sqlite3_io_error_pending; int ioerr_cnt = sqlite3_io_error_pending; sqlite3_io_error_pending = -1; #endif sqlite3pager_rollback(pPager); #if defined(SQLITE_TEST) && (defined(OS_UNIX) || defined(OS_WIN)) sqlite3_io_error_pending = ioerr_cnt; #endif if( !MEMDB ){ sqlite3OsUnlock(&pPager->fd, NO_LOCK); } assert( pPager->journalOpen==0 ); break; } case PAGER_SHARED: { if( !MEMDB ){ sqlite3OsUnlock(&pPager->fd, NO_LOCK); } break; } default: { /* Do nothing */ break; } |
︙ | ︙ | |||
2028 2029 2030 2031 2032 2033 2034 | assert( !pHist->pStmt ); } #endif pNext = pPg->pNextAll; sqliteFree(pPg); } TRACE2("CLOSE %d\n", PAGERID(pPager)); | < < | < < | < < < < < < < < < < < < < < < < < < < < < | 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 | assert( !pHist->pStmt ); } #endif pNext = pPg->pNextAll; sqliteFree(pPg); } TRACE2("CLOSE %d\n", PAGERID(pPager)); sqlite3OsClose(&pPager->fd); assert( pPager->journalOpen==0 ); /* Temp files are automatically deleted by the OS ** if( pPager->tempFile ){ ** sqlite3OsDelete(pPager->zFilename); ** } */ sqliteFree(pPager); return SQLITE_OK; } /* ** Return the page number for the given page data. */ |
︙ | ︙ | |||
2166 2167 2168 2169 2170 2171 2172 | ** was turned off after the transaction was started. Ticket #615 */ #ifndef NDEBUG { /* Make sure the pPager->nRec counter we are keeping agrees ** with the nRec computed from the size of the journal file. */ i64 jSz; | | | < | < | | < | | 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 | ** was turned off after the transaction was started. Ticket #615 */ #ifndef NDEBUG { /* Make sure the pPager->nRec counter we are keeping agrees ** with the nRec computed from the size of the journal file. */ i64 jSz; rc = sqlite3OsFileSize(&pPager->jfd, &jSz); if( rc!=0 ) return rc; assert( pPager->journalOff==jSz ); } #endif { /* Write the nRec value into the journal file header. If in ** full-synchronous mode, sync the journal first. This ensures that ** all data has really hit the disk before nRec is updated to mark ** it as a candidate for rollback. */ if( pPager->fullSync ){ TRACE2("SYNC journal of %d\n", PAGERID(pPager)); rc = sqlite3OsSync(&pPager->jfd); if( rc!=0 ) return rc; } sqlite3OsSeek(&pPager->jfd, pPager->journalHdr + sizeof(aJournalMagic)); rc = write32bits(&pPager->jfd, pPager->nRec); if( rc ) return rc; sqlite3OsSeek(&pPager->jfd, pPager->journalOff); } TRACE2("SYNC journal of %d\n", PAGERID(pPager)); rc = sqlite3OsSync(&pPager->jfd); if( rc!=0 ) return rc; pPager->journalStarted = 1; } pPager->needSync = 0; /* Erase the needSync flag from every page. */ |
︙ | ︙ | |||
2257 2258 2259 2260 2261 2262 2263 | rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ return rc; } while( pList ){ assert( pList->dirty ); | | < | < | | 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 | rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ return rc; } while( pList ){ assert( pList->dirty ); sqlite3OsSeek(&pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize); /* If there are dirty pages in the page cache with page numbers greater ** than Pager.dbSize, this means sqlite3pager_truncate() was called to ** make the file smaller (presumably by auto-vacuum code). Do not write ** any such pages to the file. */ if( pList->pgno<=pPager->dbSize ){ CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); TRACE3("STORE %d page %d\n", PAGERID(pPager), pList->pgno); rc = sqlite3OsWrite(&pPager->fd, PGHDR_TO_DATA(pList), pPager->pageSize); CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0); pPager->nWrite++; } #ifndef NDEBUG else{ TRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno); } #endif if( rc ) return rc; |
︙ | ︙ | |||
2304 2305 2306 2307 2308 2309 2310 | p->pDirty = pList; pList = p; } } return pList; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 | p->pDirty = pList; pList = p; } } return pList; } /* ** Acquire a page. ** ** A read lock on the disk file is obtained when the first page is acquired. ** This read lock is dropped when the last page is released. ** ** A _get works for any page number greater than 0. If the database |
︙ | ︙ | |||
2513 2514 2515 2516 2517 2518 2519 | ** just returns 0. This routine acquires a read-lock the first time it ** has to go to disk, and could also playback an old journal if necessary. ** Since _lookup() never goes to disk, it never has to deal with locks ** or journal files. */ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ PgHdr *pPg; | | | | | | | | > > > | | | | | | | > > > > > > > > > > > > > > > > > > > > > | > > > > > > > | > > > > > > | > | > > > > > | | > | | > | > > > > > > > > > > > > > > > > > | 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 | ** just returns 0. This routine acquires a read-lock the first time it ** has to go to disk, and could also playback an old journal if necessary. ** Since _lookup() never goes to disk, it never has to deal with locks ** or journal files. */ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ PgHdr *pPg; int rc, n; /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page ** number greater than this, or zero, is requested. */ if( pgno>PAGER_MAX_PGNO || pgno==0 ){ return SQLITE_CORRUPT; } /* Make sure we have not hit any critical errors. */ assert( pPager!=0 ); *ppPage = 0; if( pPager->errMask & ~(PAGER_ERR_FULL) ){ return pager_errcode(pPager); } /* If this is the first page accessed, then get a SHARED lock ** on the database file. */ if( pPager->nRef==0 && !MEMDB ){ if( !pPager->noReadlock ){ rc = pager_wait_on_lock(pPager, SHARED_LOCK); if( rc!=SQLITE_OK ){ return rc; } } /* If a journal file exists, and there is no RESERVED lock on the ** database file, then it either needs to be played back or deleted. */ if( pPager->useJournal && sqlite3OsFileExists(pPager->zJournal) && !sqlite3OsCheckReservedLock(&pPager->fd) ){ int rc; /* Get an EXCLUSIVE lock on the database file. At this point it is ** important that a RESERVED lock is not obtained on the way to the ** EXCLUSIVE lock. If it were, another process might open the ** database file, detect the RESERVED lock, and conclude that the ** database is safe to read while this process is still rolling it ** back. ** ** Because the intermediate RESERVED lock is not requested, the ** second process will get to this point in the code and fail to ** obtain it's own EXCLUSIVE lock on the database file. */ rc = sqlite3OsLock(&pPager->fd, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ sqlite3OsUnlock(&pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; return rc; } pPager->state = PAGER_EXCLUSIVE; /* Open the journal for reading only. Return SQLITE_BUSY if ** we are unable to open the journal file. ** ** The journal file does not need to be locked itself. The ** journal file is never open unless the main database file holds ** a write lock, so there is never any chance of two or more ** processes opening the journal at the same time. */ rc = sqlite3OsOpenReadOnly(pPager->zJournal, &pPager->jfd); if( rc!=SQLITE_OK ){ sqlite3OsUnlock(&pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; return SQLITE_BUSY; } pPager->journalOpen = 1; pPager->journalStarted = 0; pPager->journalOff = 0; pPager->setMaster = 0; pPager->journalHdr = 0; /* Playback and delete the journal. Drop the database write ** lock and reacquire the read lock. */ rc = pager_playback(pPager); if( rc!=SQLITE_OK ){ return rc; } } pPg = 0; }else{ /* Search for page in cache */ pPg = pager_lookup(pPager, pgno); if( MEMDB && pPager->state==PAGER_UNLOCK ){ pPager->state = PAGER_SHARED; } } if( pPg==0 ){ /* The requested page is not in the page cache. */ int h; pPager->nMiss++; if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || MEMDB ){ /* Create a new page */ pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->psAligned + sizeof(u32) + pPager->nExtra + MEMDB*sizeof(PgHistory) ); if( pPg==0 ){ if( !MEMDB ){ pager_unwritelock(pPager); } pPager->errMask |= PAGER_ERR_MEM; return SQLITE_NOMEM; } memset(pPg, 0, sizeof(*pPg)); if( MEMDB ){ memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory)); } pPg->pPager = pPager; pPg->pNextAll = pPager->pAll; pPager->pAll = pPg; pPager->nPage++; }else{ /* Find a page to recycle. Try to locate a page that does not ** require us to do an fsync() on the journal. */ pPg = pPager->pFirstSynced; /* If we could not find a page that does not require an fsync() ** on the journal file then fsync the journal file. This is a ** very slow operation, so we work hard to avoid it. But sometimes ** it can't be helped. */ if( pPg==0 ){ int rc = syncJournal(pPager); if( rc!=0 ){ sqlite3pager_rollback(pPager); return SQLITE_IOERR; } if( pPager->fullSync ){ /* If in full-sync mode, write a new journal header into the ** journal file. This is done to avoid ever modifying a journal ** header that is involved in the rollback of pages that have ** already been written to the database (in case the header is ** trashed when the nRec field is updated). */ pPager->nRec = 0; assert( pPager->journalOff > 0 ); rc = writeJournalHdr(pPager); if( rc!=0 ){ sqlite3pager_rollback(pPager); return SQLITE_IOERR; } } pPg = pPager->pFirst; } assert( pPg->nRef==0 ); /* Write the page to the database file if it is dirty. */ if( pPg->dirty ){ assert( pPg->needSync==0 ); pPg->pDirty = 0; rc = pager_write_pagelist( pPg ); if( rc!=SQLITE_OK ){ sqlite3pager_rollback(pPager); return SQLITE_IOERR; } } assert( pPg->dirty==0 ); /* If the page we are recycling is marked as alwaysRollback, then ** set the global alwaysRollback flag, thus disabling the ** sqlite_dont_rollback() optimization for the rest of this transaction. ** It is necessary to do this because the page marked alwaysRollback ** might be reloaded at a later time but at that point we won't remember ** that is was marked alwaysRollback. This means that all pages must ** be marked as alwaysRollback from here on out. */ if( pPg->alwaysRollback ){ pPager->alwaysRollback = 1; } /* Unlink the old page from the free list and the hash table */ unlinkPage(pPg); pPager->nOvfl++; } pPg->pgno = pgno; if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){ sqlite3CheckMemory(pPager->aInJournal, pgno/8); assert( pPager->journalOpen ); pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0; pPg->needSync = 0; |
︙ | ︙ | |||
2663 2664 2665 2666 2667 2668 2669 | if( pPg->pNextHash ){ assert( pPg->pNextHash->pPrevHash==0 ); pPg->pNextHash->pPrevHash = pPg; } if( pPager->nExtra>0 ){ memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); } | > | | | | < | < < | | < | | | 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 | if( pPg->pNextHash ){ assert( pPg->pNextHash->pPrevHash==0 ); pPg->pNextHash->pPrevHash = pPg; } if( pPager->nExtra>0 ){ memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); } n = sqlite3pager_pagecount(pPager); if( pPager->errMask!=0 ){ sqlite3pager_unref(PGHDR_TO_DATA(pPg)); rc = pager_errcode(pPager); return rc; } if( n<(int)pgno ){ memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); }else{ int rc; assert( MEMDB==0 ); sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize); rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize); TRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno); CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); if( rc!=SQLITE_OK ){ i64 fileSize; if( sqlite3OsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK || fileSize>=pgno*pPager->pageSize ){ sqlite3pager_unref(PGHDR_TO_DATA(pPg)); return rc; }else{ memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); } }else{ pPager->nRead++; } } #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif }else{ /* The requested page is in the page cache. */ pPager->nHit++; page_ref(pPg); } *ppPage = PGHDR_TO_DATA(pPg); return SQLITE_OK; } /* |
︙ | ︙ | |||
2722 2723 2724 2725 2726 2727 2728 | ** has ever happened. */ void *sqlite3pager_lookup(Pager *pPager, Pgno pgno){ PgHdr *pPg; assert( pPager!=0 ); assert( pgno!=0 ); | | | 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 | ** has ever happened. */ void *sqlite3pager_lookup(Pager *pPager, Pgno pgno){ PgHdr *pPg; assert( pPager!=0 ); assert( pgno!=0 ); if( pPager->errMask & ~(PAGER_ERR_FULL) ){ return 0; } pPg = pager_lookup(pPager, pgno); if( pPg==0 ) return 0; page_ref(pPg); return PGHDR_TO_DATA(pPg); } |
︙ | ︙ | |||
2797 2798 2799 2800 2801 2802 2803 | */ static int pager_open_journal(Pager *pPager){ int rc; assert( !MEMDB ); assert( pPager->state>=PAGER_RESERVED ); assert( pPager->journalOpen==0 ); assert( pPager->useJournal ); | < | < < < | | | | | < < < < < < < < | | < | 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 | */ static int pager_open_journal(Pager *pPager){ int rc; assert( !MEMDB ); assert( pPager->state>=PAGER_RESERVED ); assert( pPager->journalOpen==0 ); assert( pPager->useJournal ); sqlite3pager_pagecount(pPager); pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); if( pPager->aInJournal==0 ){ rc = SQLITE_NOMEM; goto failed_to_open_journal; } rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile); pPager->journalOff = 0; pPager->setMaster = 0; pPager->journalHdr = 0; if( rc!=SQLITE_OK ){ goto failed_to_open_journal; } sqlite3OsOpenDirectory(pPager->zDirectory, &pPager->jfd); pPager->journalOpen = 1; pPager->journalStarted = 0; pPager->needSync = 0; pPager->alwaysRollback = 0; pPager->nRec = 0; if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); return rc; } pPager->origDbSize = pPager->dbSize; rc = writeJournalHdr(pPager); if( pPager->stmtAutoopen && rc==SQLITE_OK ){ rc = sqlite3pager_stmt_begin(pPager); } if( rc!=SQLITE_OK ){ rc = pager_unwritelock(pPager); if( rc==SQLITE_OK ){ rc = SQLITE_FULL; } } return rc; failed_to_open_journal: sqliteFree(pPager->aInJournal); pPager->aInJournal = 0; sqlite3OsUnlock(&pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; return rc; } /* ** Acquire a write-lock on the database. The lock is removed when ** the any of the following happen: ** |
︙ | ︙ | |||
2895 2896 2897 2898 2899 2900 2901 | assert( pPager->state!=PAGER_UNLOCK ); if( pPager->state==PAGER_SHARED ){ assert( pPager->aInJournal==0 ); if( MEMDB ){ pPager->state = PAGER_EXCLUSIVE; pPager->origDbSize = pPager->dbSize; }else{ | > > > | > | 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 | assert( pPager->state!=PAGER_UNLOCK ); if( pPager->state==PAGER_SHARED ){ assert( pPager->aInJournal==0 ); if( MEMDB ){ pPager->state = PAGER_EXCLUSIVE; pPager->origDbSize = pPager->dbSize; }else{ if( SQLITE_BUSY_RESERVED_LOCK || exFlag ){ rc = pager_wait_on_lock(pPager, RESERVED_LOCK); }else{ rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK); } if( rc==SQLITE_OK ){ pPager->state = PAGER_RESERVED; if( exFlag ){ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); } } if( rc!=SQLITE_OK ){ |
︙ | ︙ | |||
2939 2940 2941 2942 2943 2944 2945 | int sqlite3pager_write(void *pData){ PgHdr *pPg = DATA_TO_PGHDR(pData); Pager *pPager = pPg->pPager; int rc = SQLITE_OK; /* Check for errors */ | | | | 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 | int sqlite3pager_write(void *pData){ PgHdr *pPg = DATA_TO_PGHDR(pData); Pager *pPager = pPg->pPager; int rc = SQLITE_OK; /* Check for errors */ if( pPager->errMask ){ return pager_errcode(pPager); } if( pPager->readOnly ){ return SQLITE_PERM; } assert( !pPager->setMaster ); |
︙ | ︙ | |||
2996 2997 2998 2999 3000 3001 3002 | assert( pHist->pOrig==0 ); pHist->pOrig = sqliteMallocRaw( pPager->pageSize ); if( pHist->pOrig ){ memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize); } }else{ u32 cksum; | < < < < | | < < | 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 | assert( pHist->pOrig==0 ); pHist->pOrig = sqliteMallocRaw( pPager->pageSize ); if( pHist->pOrig ){ memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize); } }else{ u32 cksum; CODEC(pPager, pData, pPg->pgno, 7); cksum = pager_cksum(pPager, pPg->pgno, pData); saved = *(u32*)PGHDR_TO_EXTRA(pPg, pPager); store32bits(cksum, pPg, pPager->pageSize); szPg = pPager->pageSize+8; store32bits(pPg->pgno, pPg, -4); rc = sqlite3OsWrite(&pPager->jfd, &((char*)pData)[-4], szPg); pPager->journalOff += szPg; TRACE4("JOURNAL %d page %d needSync=%d\n", PAGERID(pPager), pPg->pgno, pPg->needSync); CODEC(pPager, pData, pPg->pgno, 0); *(u32*)PGHDR_TO_EXTRA(pPg, pPager) = saved; if( rc!=SQLITE_OK ){ sqlite3pager_rollback(pPager); pPager->errMask |= PAGER_ERR_FULL; return rc; } pPager->nRec++; assert( pPager->aInJournal!=0 ); pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); pPg->needSync = !pPager->noSync; if( pPager->stmtInUse ){ |
︙ | ︙ | |||
3057 3058 3059 3060 3061 3062 3063 | if( pHist->pStmt ){ memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize); } TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); }else{ store32bits(pPg->pgno, pPg, -4); CODEC(pPager, pData, pPg->pgno, 7); | | < | < < | 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 | if( pHist->pStmt ){ memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize); } TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); }else{ store32bits(pPg->pgno, pPg, -4); CODEC(pPager, pData, pPg->pgno, 7); rc = sqlite3OsWrite(&pPager->stfd,((char*)pData)-4, pPager->pageSize+4); TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); CODEC(pPager, pData, pPg->pgno, 0); if( rc!=SQLITE_OK ){ sqlite3pager_rollback(pPager); pPager->errMask |= PAGER_ERR_FULL; return rc; } pPager->stmtNRec++; assert( pPager->aInStmt!=0 ); pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); } page_add_to_stmt_list(pPg); |
︙ | ︙ | |||
3149 3150 3151 3152 3153 3154 3155 | void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){ PgHdr *pPg; if( MEMDB ) return; pPg = pager_lookup(pPager, pgno); pPg->alwaysRollback = 1; | | | 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 | void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){ PgHdr *pPg; if( MEMDB ) return; pPg = pager_lookup(pPager, pgno); pPg->alwaysRollback = 1; if( pPg && pPg->dirty ){ if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){ /* If this pages is the last page in the file and the file has grown ** during the current transaction, then do NOT mark the page as clean. ** When the database file grows, we must make sure that the last page ** gets written at least once so that the disk file will be the correct ** size. If you do not write this page and the size of the file ** on the disk ends up being too small, that can lead to database |
︙ | ︙ | |||
3225 3226 3227 3228 3229 3230 3231 | ** and an error code is returned. If the commit worked, SQLITE_OK ** is returned. */ int sqlite3pager_commit(Pager *pPager){ int rc; PgHdr *pPg; | | | | | 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 | ** and an error code is returned. If the commit worked, SQLITE_OK ** is returned. */ int sqlite3pager_commit(Pager *pPager){ int rc; PgHdr *pPg; if( pPager->errMask==PAGER_ERR_FULL ){ rc = sqlite3pager_rollback(pPager); if( rc==SQLITE_OK ){ rc = SQLITE_FULL; } return rc; } if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); return rc; } if( pPager->state<PAGER_RESERVED ){ return SQLITE_ERROR; } TRACE2("COMMIT %d\n", PAGERID(pPager)); if( MEMDB ){ |
︙ | ︙ | |||
3344 3345 3346 3347 3348 3349 3350 | if( !pPager->dirtyCache || !pPager->journalOpen ){ rc = pager_unwritelock(pPager); pPager->dbSize = -1; return rc; } | | | | | | 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 | if( !pPager->dirtyCache || !pPager->journalOpen ){ rc = pager_unwritelock(pPager); pPager->dbSize = -1; return rc; } if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){ if( pPager->state>=PAGER_EXCLUSIVE ){ pager_playback(pPager); } return pager_errcode(pPager); } if( pPager->state==PAGER_RESERVED ){ int rc2; rc = pager_reload_cache(pPager); rc2 = pager_unwritelock(pPager); if( rc==SQLITE_OK ){ rc = rc2; } }else{ rc = pager_playback(pPager); } if( rc!=SQLITE_OK ){ rc = SQLITE_CORRUPT; /* bkpt-CORRUPT */ pPager->errMask |= PAGER_ERR_CORRUPT; } pPager->dbSize = -1; return rc; } /* ** Return TRUE if the database file is opened read-only. Return FALSE |
︙ | ︙ | |||
3386 3387 3388 3389 3390 3391 3392 | int *sqlite3pager_stats(Pager *pPager){ static int a[11]; a[0] = pPager->nRef; a[1] = pPager->nPage; a[2] = pPager->mxPage; a[3] = pPager->dbSize; a[4] = pPager->state; | | < < | 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 | int *sqlite3pager_stats(Pager *pPager){ static int a[11]; a[0] = pPager->nRef; a[1] = pPager->nPage; a[2] = pPager->mxPage; a[3] = pPager->dbSize; a[4] = pPager->state; a[5] = pPager->errMask; a[6] = pPager->nHit; a[7] = pPager->nMiss; a[8] = pPager->nOvfl; a[9] = pPager->nRead; a[10] = pPager->nWrite; return a; } /* ** Set the statement rollback point. ** ** This routine should be called with the transaction journal already |
︙ | ︙ | |||
3422 3423 3424 3425 3426 3427 3428 | if( !pPager->journalOpen ){ pPager->stmtAutoopen = 1; return SQLITE_OK; } assert( pPager->journalOpen ); pPager->aInStmt = sqliteMalloc( pPager->dbSize/8 + 1 ); if( pPager->aInStmt==0 ){ | | | | 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 | if( !pPager->journalOpen ){ pPager->stmtAutoopen = 1; return SQLITE_OK; } assert( pPager->journalOpen ); pPager->aInStmt = sqliteMalloc( pPager->dbSize/8 + 1 ); if( pPager->aInStmt==0 ){ sqlite3OsLock(&pPager->fd, SHARED_LOCK); return SQLITE_NOMEM; } #ifndef NDEBUG rc = sqlite3OsFileSize(&pPager->jfd, &pPager->stmtJSize); if( rc ) goto stmt_begin_failed; assert( pPager->stmtJSize == pPager->journalOff ); #endif pPager->stmtJSize = pPager->journalOff; pPager->stmtSize = pPager->dbSize; pPager->stmtHdrOff = 0; pPager->stmtCksum = pPager->cksumInit; |
︙ | ︙ | |||
3459 3460 3461 3462 3463 3464 3465 | ** Commit a statement. */ int sqlite3pager_stmt_commit(Pager *pPager){ if( pPager->stmtInUse ){ PgHdr *pPg, *pNext; TRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); if( !MEMDB ){ | | | | 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 | ** Commit a statement. */ int sqlite3pager_stmt_commit(Pager *pPager){ if( pPager->stmtInUse ){ PgHdr *pPg, *pNext; TRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); if( !MEMDB ){ sqlite3OsSeek(&pPager->stfd, 0); /* sqlite3OsTruncate(&pPager->stfd, 0); */ sqliteFree( pPager->aInStmt ); pPager->aInStmt = 0; } for(pPg=pPager->pStmt; pPg; pPg=pNext){ pNext = pPg->pNextStmt; assert( pPg->inStmt ); pPg->inStmt = 0; |
︙ | ︙ | |||
3535 3536 3537 3538 3539 3540 3541 | /* ** Return the full pathname of the journal file. */ const char *sqlite3pager_journalname(Pager *pPager){ return pPager->zJournal; } | < < < < < < < < | 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 | /* ** Return the full pathname of the journal file. */ const char *sqlite3pager_journalname(Pager *pPager){ return pPager->zJournal; } /* ** Set the codec for this pager */ void sqlite3pager_set_codec( Pager *pPager, void (*xCodec)(void*,void*,Pgno,int), void *pCodecArg |
︙ | ︙ | |||
3631 3632 3633 3634 3635 3636 3637 | if( nTrunc!=0 ){ /* If this transaction has made the database smaller, then all pages ** being discarded by the truncation must be written to the journal ** file. */ Pgno i; void *pPage; | < | | 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 | if( nTrunc!=0 ){ /* If this transaction has made the database smaller, then all pages ** being discarded by the truncation must be written to the journal ** file. */ Pgno i; void *pPage; for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){ if( !(pPager->aInJournal[i/8] & (1<<(i&7))) ){ rc = sqlite3pager_get(pPager, i, &pPage); if( rc!=SQLITE_OK ) goto sync_exit; rc = sqlite3pager_write(pPage); sqlite3pager_unref(pPage); if( rc!=SQLITE_OK ) goto sync_exit; } } |
︙ | ︙ | |||
3663 3664 3665 3666 3667 3668 3669 | /* Write all dirty pages to the database file */ pPg = pager_get_all_dirty_pages(pPager); rc = pager_write_pagelist(pPg); if( rc!=SQLITE_OK ) goto sync_exit; /* Sync the database file. */ if( !pPager->noSync ){ | | | 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 | /* Write all dirty pages to the database file */ pPg = pager_get_all_dirty_pages(pPager); rc = pager_write_pagelist(pPg); if( rc!=SQLITE_OK ) goto sync_exit; /* Sync the database file. */ if( !pPager->noSync ){ rc = sqlite3OsSync(&pPager->fd); } pPager->state = PAGER_SYNCED; } sync_exit: return rc; |
︙ | ︙ | |||
3686 3687 3688 3689 3690 3691 3692 | ** by this routine. The same applies to the page pData refers to on entry to ** this routine. ** ** References to the page refered to by pData remain valid. Updating any ** meta-data associated with page pData (i.e. data stored in the nExtra bytes ** allocated along with the page) is the responsibility of the caller. ** | | | < < > | 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 | ** by this routine. The same applies to the page pData refers to on entry to ** this routine. ** ** References to the page refered to by pData remain valid. Updating any ** meta-data associated with page pData (i.e. data stored in the nExtra bytes ** allocated along with the page) is the responsibility of the caller. ** ** A transaction must be active when this routine is called, however it is ** illegal to call this routine if a statment transaction is active. */ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ PgHdr *pPg = DATA_TO_PGHDR(pData); PgHdr *pPgOld; int h; Pgno needSyncPgno = 0; assert( !pPager->stmtInUse ); assert( pPg->nRef>0 ); TRACE5("MOVE %d page %d (needSync=%d) moves to %d\n", PAGERID(pPager), pPg->pgno, pPg->needSync, pgno); if( pPg->needSync ){ needSyncPgno = pPg->pgno; |
︙ | ︙ | |||
3777 3778 3779 3780 3781 3782 3783 | #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) /* ** Return the current state of the file lock for the given pager. ** The return value is one of NO_LOCK, SHARED_LOCK, RESERVED_LOCK, ** PENDING_LOCK, or EXCLUSIVE_LOCK. */ int sqlite3pager_lockstate(Pager *pPager){ | > > > | > < < | 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 | #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) /* ** Return the current state of the file lock for the given pager. ** The return value is one of NO_LOCK, SHARED_LOCK, RESERVED_LOCK, ** PENDING_LOCK, or EXCLUSIVE_LOCK. */ int sqlite3pager_lockstate(Pager *pPager){ #ifdef OS_TEST return pPager->fd->fd.locktype; #else return pPager->fd.locktype; #endif } #endif #ifdef SQLITE_DEBUG /* ** Print a listing of all referenced pages and their ref count. */ void sqlite3pager_refdump(Pager *pPager){ PgHdr *pPg; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ if( pPg->nRef<=0 ) continue; sqlite3DebugPrintf("PAGE %3d addr=%p nRef=%d\n", pPg->pgno, PGHDR_TO_DATA(pPg), pPg->nRef); } } #endif |
Changes to SQLite.Interop/src/pager.h.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite page cache ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** | | < < < | | | < < | < > | < | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite page cache ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** ** @(#) $Id: pager.h,v 1.1 2005/03/01 16:04:31 rmsimpson Exp $ */ /* ** The default size of a database page. */ #ifndef SQLITE_DEFAULT_PAGE_SIZE # define SQLITE_DEFAULT_PAGE_SIZE 1024 #endif /* Maximum page size. The upper bound on this value is 65536 (a limit ** imposed by the 2-byte size of cell array pointers.) The ** maximum page size determines the amount of stack space allocated ** by many of the routines in pager.c and btree.c On embedded architectures ** or any machine where memory and especially stack memory is limited, ** one may wish to chose a smaller value for the maximum page size. */ #ifndef SQLITE_MAX_PAGE_SIZE # define SQLITE_MAX_PAGE_SIZE 8192 #endif /* ** Maximum number of pages in one database. */ #define SQLITE_MAX_PAGE 1073741823 |
︙ | ︙ | |||
70 71 72 73 74 75 76 | ** routines: */ int sqlite3pager_open(Pager **ppPager, const char *zFilename, int nExtra, int flags); void sqlite3pager_set_busyhandler(Pager*, BusyHandler *pBusyHandler); void sqlite3pager_set_destructor(Pager*, void(*)(void*,int)); void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int)); | | | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | ** routines: */ int sqlite3pager_open(Pager **ppPager, const char *zFilename, int nExtra, int flags); void sqlite3pager_set_busyhandler(Pager*, BusyHandler *pBusyHandler); void sqlite3pager_set_destructor(Pager*, void(*)(void*,int)); void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int)); void sqlite3pager_set_pagesize(Pager*, int); void sqlite3pager_read_fileheader(Pager*, int, unsigned char*); void sqlite3pager_set_cachesize(Pager*, int); int sqlite3pager_close(Pager *pPager); int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage); void *sqlite3pager_lookup(Pager *pPager, Pgno pgno); int sqlite3pager_ref(void*); int sqlite3pager_unref(void*); |
︙ | ︙ | |||
99 100 101 102 103 104 105 | void sqlite3pager_dont_rollback(void*); void sqlite3pager_dont_write(Pager*, Pgno); int *sqlite3pager_stats(Pager*); void sqlite3pager_set_safety_level(Pager*,int); const char *sqlite3pager_filename(Pager*); const char *sqlite3pager_dirname(Pager*); const char *sqlite3pager_journalname(Pager*); | < < < < < | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | void sqlite3pager_dont_rollback(void*); void sqlite3pager_dont_write(Pager*, Pgno); int *sqlite3pager_stats(Pager*); void sqlite3pager_set_safety_level(Pager*,int); const char *sqlite3pager_filename(Pager*); const char *sqlite3pager_dirname(Pager*); const char *sqlite3pager_journalname(Pager*); int sqlite3pager_rename(Pager*, const char *zNewName); void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*); int sqlite3pager_movepage(Pager*,void*,Pgno); #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) int sqlite3pager_lockstate(Pager*); #endif #ifdef SQLITE_TEST void sqlite3pager_refdump(Pager*); int pager3_refinfo_enable; #endif |
Changes to SQLite.Interop/src/parse.c.
1 2 3 4 5 6 | /* Driver template for the LEMON parser generator. ** The author disclaims copyright to this source code. */ /* First off, code is include which follows the "include" declaration ** in the input file. */ #include <stdio.h> | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | /* Driver template for the LEMON parser generator. ** The author disclaims copyright to this source code. */ /* First off, code is include which follows the "include" declaration ** in the input file. */ #include <stdio.h> #line 33 "parse.y" #include "sqliteInt.h" #include "parse.h" /* ** An instance of this structure holds information about the ** LIMIT clause of a SELECT statement. */ struct LimitVal { Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */ Expr *pOffset; /* The OFFSET expression. NULL if there is none */ }; /* ** An instance of this structure is used to store the LIKE, ** GLOB, NOT LIKE, and NOT GLOB operators. */ struct LikeOp { int opcode; /* Either TK_GLOB or TK_LIKE */ int not; /* True if the NOT keyword is present */ }; /* ** An instance of the following structure describes the event of a ** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, ** TK_DELETE, or TK_INSTEAD. If the event is of the form ** |
︙ | ︙ | |||
89 90 91 92 93 94 95 | ** sqlite3ParserARG_FETCH Code to extract %extra_argument from yypParser ** YYNSTATE the combined number of states. ** YYNRULE the number of rules in the grammar ** YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. */ #define YYCODETYPE unsigned char | | > > > | | | < | | < | > | | < < | | | | | | | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | ** sqlite3ParserARG_FETCH Code to extract %extra_argument from yypParser ** YYNSTATE the combined number of states. ** YYNRULE the number of rules in the grammar ** YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. */ #define YYCODETYPE unsigned char #define YYNOCODE 239 #define YYACTIONTYPE unsigned short int #define sqlite3ParserTOKENTYPE Token typedef union { sqlite3ParserTOKENTYPE yy0; struct AttachKey yy40; int yy60; struct TrigEvent yy62; struct {int value; int mask;} yy243; struct LikeOp yy258; ExprList* yy266; IdList* yy272; Select* yy331; struct LimitVal yy348; Token yy406; SrcList* yy427; Expr* yy454; TriggerStep* yy455; int yy477; } YYMINORTYPE; #define YYSTACKDEPTH 100 #define sqlite3ParserARG_SDECL Parse *pParse; #define sqlite3ParserARG_PDECL ,Parse *pParse #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse #define sqlite3ParserARG_STORE yypParser->pParse = pParse #define YYNSTATE 564 #define YYNRULE 305 #define YYERRORSYMBOL 141 #define YYERRSYMDT yy477 #define YYFALLBACK 1 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2) #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) #define YY_ERROR_ACTION (YYNSTATE+YYNRULE) /* Next are that tables used to determine what action to take based on the ** current state and lookahead token. These tables are used to implement |
︙ | ︙ | |||
171 172 173 174 175 176 177 | ** yy_shift_ofst[] For each state, the offset into yy_action for ** shifting terminals. ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. */ static const YYACTIONTYPE yy_action[] = { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > < < < < < < < < < | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > > < < < < < < < < < < < < < < | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > > > > > > > | | | | < | | > | | | < | | | < < | | | | < | | | > | > | | > > | | | < | | > | | | < < < < < < < < < | | | > | | | | | > > > > > > | > > | | | | | > > > > > > > > > > > | | < < | < < < < < < < < < | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > > | > > > | > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | < | | | | | | | | | | | | | | | | | | | > > > > > > > > > < < < < < < < < < | | | | | | | | | | > > > > > > > > > > > > > > > > > > > | < | | | | | | | | | | | | | | > > > > > > > > > > > > > > | > > | > > > > | | | | | | | | | | | > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > | < < | | | | | < < < | | | < | | | | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | > > > > | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 | ** yy_shift_ofst[] For each state, the offset into yy_action for ** shifting terminals. ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. */ static const YYACTIONTYPE yy_action[] = { /* 0 */ 263, 261, 261, 154, 124, 126, 128, 130, 132, 134, /* 10 */ 136, 138, 140, 142, 350, 567, 145, 641, 261, 369, /* 20 */ 144, 114, 116, 112, 118, 7, 124, 126, 128, 130, /* 30 */ 132, 134, 136, 138, 140, 142, 136, 138, 140, 142, /* 40 */ 110, 94, 146, 157, 162, 167, 156, 161, 120, 122, /* 50 */ 114, 116, 112, 118, 9, 124, 126, 128, 130, 132, /* 60 */ 134, 136, 138, 140, 142, 574, 223, 262, 262, 124, /* 70 */ 126, 128, 130, 132, 134, 136, 138, 140, 142, 13, /* 80 */ 96, 145, 13, 2, 262, 144, 4, 78, 371, 92, /* 90 */ 10, 373, 380, 385, 132, 134, 136, 138, 140, 142, /* 100 */ 75, 3, 562, 388, 296, 110, 94, 146, 157, 162, /* 110 */ 167, 156, 161, 120, 122, 114, 116, 112, 118, 77, /* 120 */ 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, /* 130 */ 145, 65, 573, 13, 144, 11, 371, 66, 292, 373, /* 140 */ 380, 385, 870, 1, 563, 14, 15, 4, 14, 15, /* 150 */ 172, 388, 51, 665, 110, 94, 146, 157, 162, 167, /* 160 */ 156, 161, 120, 122, 114, 116, 112, 118, 72, 124, /* 170 */ 126, 128, 130, 132, 134, 136, 138, 140, 142, 51, /* 180 */ 37, 341, 40, 59, 67, 69, 305, 336, 107, 106, /* 190 */ 108, 847, 572, 34, 338, 96, 366, 349, 13, 14, /* 200 */ 15, 371, 12, 145, 373, 380, 385, 144, 564, 40, /* 210 */ 59, 67, 69, 305, 336, 75, 388, 3, 562, 190, /* 220 */ 345, 338, 44, 45, 95, 460, 802, 110, 94, 146, /* 230 */ 157, 162, 167, 156, 161, 120, 122, 114, 116, 112, /* 240 */ 118, 575, 124, 126, 128, 130, 132, 134, 136, 138, /* 250 */ 140, 142, 20, 48, 800, 364, 362, 101, 102, 367, /* 260 */ 499, 295, 49, 596, 14, 15, 191, 32, 33, 27, /* 270 */ 148, 403, 96, 50, 147, 534, 46, 145, 494, 466, /* 280 */ 456, 144, 580, 279, 36, 340, 47, 399, 309, 81, /* 290 */ 368, 401, 75, 335, 398, 505, 176, 501, 150, 151, /* 300 */ 197, 110, 94, 146, 157, 162, 167, 156, 161, 120, /* 310 */ 122, 114, 116, 112, 118, 77, 124, 126, 128, 130, /* 320 */ 132, 134, 136, 138, 140, 142, 149, 280, 258, 169, /* 330 */ 96, 39, 281, 13, 298, 367, 96, 175, 22, 335, /* 340 */ 28, 145, 188, 402, 33, 144, 217, 6, 5, 171, /* 350 */ 75, 173, 174, 25, 176, 581, 75, 57, 58, 507, /* 360 */ 235, 351, 356, 357, 265, 110, 94, 146, 157, 162, /* 370 */ 167, 156, 161, 120, 122, 114, 116, 112, 118, 503, /* 380 */ 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, /* 390 */ 457, 77, 243, 294, 48, 227, 236, 293, 297, 14, /* 400 */ 15, 288, 96, 49, 217, 152, 222, 163, 168, 278, /* 410 */ 24, 13, 687, 13, 50, 145, 518, 201, 152, 144, /* 420 */ 163, 168, 75, 358, 582, 171, 176, 173, 174, 263, /* 430 */ 171, 261, 173, 174, 354, 356, 357, 588, 211, 110, /* 440 */ 94, 146, 157, 162, 167, 156, 161, 120, 122, 114, /* 450 */ 116, 112, 118, 654, 124, 126, 128, 130, 132, 134, /* 460 */ 136, 138, 140, 142, 303, 13, 688, 96, 250, 817, /* 470 */ 96, 16, 17, 18, 246, 81, 216, 14, 15, 14, /* 480 */ 15, 145, 13, 406, 435, 144, 13, 75, 487, 387, /* 490 */ 75, 493, 248, 258, 235, 660, 358, 262, 310, 852, /* 500 */ 171, 26, 173, 174, 253, 110, 94, 146, 157, 162, /* 510 */ 167, 156, 161, 120, 122, 114, 116, 112, 118, 397, /* 520 */ 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, /* 530 */ 229, 14, 15, 489, 250, 152, 252, 163, 168, 171, /* 540 */ 839, 173, 174, 360, 361, 96, 145, 533, 14, 15, /* 550 */ 144, 866, 14, 15, 801, 442, 312, 275, 255, 453, /* 560 */ 850, 338, 251, 535, 536, 75, 662, 247, 13, 493, /* 570 */ 110, 94, 146, 157, 162, 167, 156, 161, 120, 122, /* 580 */ 114, 116, 112, 118, 845, 124, 126, 128, 130, 132, /* 590 */ 134, 136, 138, 140, 142, 726, 96, 171, 96, 173, /* 600 */ 174, 171, 252, 173, 174, 152, 583, 163, 168, 42, /* 610 */ 720, 525, 96, 145, 441, 271, 75, 144, 75, 170, /* 620 */ 302, 640, 91, 31, 358, 313, 320, 322, 251, 432, /* 630 */ 434, 433, 75, 844, 14, 15, 176, 110, 94, 146, /* 640 */ 157, 162, 167, 156, 161, 120, 122, 114, 116, 112, /* 650 */ 118, 77, 124, 126, 128, 130, 132, 134, 136, 138, /* 660 */ 140, 142, 171, 96, 173, 174, 331, 52, 171, 96, /* 670 */ 173, 174, 96, 195, 213, 207, 29, 348, 145, 54, /* 680 */ 310, 318, 144, 75, 455, 342, 217, 93, 83, 75, /* 690 */ 30, 452, 75, 109, 587, 286, 111, 171, 265, 173, /* 700 */ 174, 319, 110, 94, 146, 157, 162, 167, 156, 161, /* 710 */ 120, 122, 114, 116, 112, 118, 77, 124, 126, 128, /* 720 */ 130, 132, 134, 136, 138, 140, 142, 244, 96, 187, /* 730 */ 96, 96, 810, 331, 214, 266, 215, 35, 312, 96, /* 740 */ 96, 479, 328, 145, 623, 38, 327, 144, 75, 455, /* 750 */ 75, 75, 113, 689, 115, 117, 315, 461, 426, 75, /* 760 */ 75, 77, 463, 119, 121, 407, 325, 110, 165, 146, /* 770 */ 157, 162, 167, 156, 161, 120, 122, 114, 116, 112, /* 780 */ 118, 77, 124, 126, 128, 130, 132, 134, 136, 138, /* 790 */ 140, 142, 42, 96, 96, 96, 96, 824, 273, 159, /* 800 */ 415, 96, 410, 272, 96, 273, 479, 41, 145, 332, /* 810 */ 537, 43, 144, 75, 75, 75, 75, 123, 125, 127, /* 820 */ 129, 75, 465, 64, 75, 131, 53, 463, 133, 158, /* 830 */ 317, 316, 265, 94, 146, 157, 162, 167, 156, 161, /* 840 */ 120, 122, 114, 116, 112, 118, 219, 124, 126, 128, /* 850 */ 130, 132, 134, 136, 138, 140, 142, 96, 689, 96, /* 860 */ 96, 532, 96, 331, 299, 96, 215, 96, 96, 283, /* 870 */ 96, 261, 219, 96, 145, 96, 840, 75, 144, 75, /* 880 */ 75, 135, 75, 137, 139, 75, 141, 75, 75, 143, /* 890 */ 75, 153, 155, 75, 164, 75, 376, 166, 56, 178, /* 900 */ 146, 157, 162, 167, 156, 161, 120, 122, 114, 116, /* 910 */ 112, 118, 652, 124, 126, 128, 130, 132, 134, 136, /* 920 */ 138, 140, 142, 76, 96, 96, 96, 71, 438, 364, /* 930 */ 362, 437, 96, 96, 96, 96, 331, 262, 233, 332, /* 940 */ 96, 55, 331, 439, 75, 75, 75, 331, 180, 182, /* 950 */ 184, 199, 75, 75, 75, 75, 196, 198, 208, 210, /* 960 */ 75, 107, 106, 108, 212, 720, 326, 177, 327, 382, /* 970 */ 430, 431, 107, 106, 108, 391, 548, 61, 96, 96, /* 980 */ 449, 471, 458, 45, 183, 181, 300, 96, 476, 352, /* 990 */ 96, 353, 179, 73, 74, 343, 346, 95, 75, 75, /* 1000 */ 290, 96, 224, 240, 345, 275, 42, 75, 95, 76, /* 1010 */ 75, 245, 332, 71, 277, 383, 275, 327, 332, 96, /* 1020 */ 75, 75, 404, 332, 287, 386, 96, 392, 421, 327, /* 1030 */ 101, 102, 103, 104, 105, 185, 189, 199, 96, 75, /* 1040 */ 96, 101, 102, 427, 414, 60, 75, 107, 106, 108, /* 1050 */ 474, 470, 486, 177, 77, 450, 421, 327, 75, 484, /* 1060 */ 75, 273, 478, 436, 491, 492, 423, 490, 421, 421, /* 1070 */ 183, 181, 421, 421, 483, 421, 77, 421, 179, 73, /* 1080 */ 74, 476, 244, 95, 77, 81, 526, 860, 490, 421, /* 1090 */ 689, 522, 62, 64, 500, 70, 597, 63, 523, 68, /* 1100 */ 598, 76, 81, 79, 81, 71, 502, 504, 84, 80, /* 1110 */ 506, 510, 244, 514, 239, 520, 101, 102, 103, 104, /* 1120 */ 105, 185, 189, 77, 546, 241, 82, 558, 86, 199, /* 1130 */ 85, 225, 90, 87, 97, 88, 99, 142, 89, 107, /* 1140 */ 106, 108, 160, 98, 516, 177, 100, 218, 666, 667, /* 1150 */ 668, 186, 209, 193, 192, 194, 200, 204, 203, 202, /* 1160 */ 206, 205, 183, 181, 219, 220, 221, 226, 228, 232, /* 1170 */ 179, 73, 74, 230, 233, 95, 234, 231, 237, 242, /* 1180 */ 238, 215, 260, 249, 257, 276, 267, 254, 256, 259, /* 1190 */ 264, 269, 270, 76, 274, 282, 301, 71, 219, 268, /* 1200 */ 285, 291, 284, 306, 324, 307, 311, 308, 101, 102, /* 1210 */ 103, 104, 105, 185, 189, 803, 355, 329, 375, 304, /* 1220 */ 314, 199, 321, 337, 330, 365, 334, 372, 309, 333, /* 1230 */ 323, 107, 106, 108, 344, 339, 347, 177, 374, 378, /* 1240 */ 400, 359, 370, 377, 381, 379, 384, 389, 363, 390, /* 1250 */ 393, 394, 396, 54, 183, 181, 289, 408, 395, 409, /* 1260 */ 411, 413, 179, 73, 74, 412, 416, 95, 417, 420, /* 1270 */ 428, 422, 832, 429, 443, 440, 444, 837, 838, 76, /* 1280 */ 446, 445, 448, 71, 451, 808, 809, 459, 454, 447, /* 1290 */ 418, 727, 728, 831, 464, 462, 846, 457, 469, 419, /* 1300 */ 101, 102, 103, 104, 105, 185, 189, 199, 467, 468, /* 1310 */ 472, 473, 475, 424, 848, 477, 480, 107, 106, 108, /* 1320 */ 425, 482, 488, 177, 485, 849, 481, 495, 496, 851, /* 1330 */ 659, 661, 816, 858, 497, 509, 511, 719, 513, 515, /* 1340 */ 183, 181, 722, 517, 725, 519, 521, 524, 179, 73, /* 1350 */ 74, 818, 528, 95, 530, 819, 820, 531, 538, 821, /* 1360 */ 8, 822, 539, 823, 549, 19, 21, 23, 405, 541, /* 1370 */ 542, 544, 543, 859, 547, 861, 862, 865, 545, 540, /* 1380 */ 551, 867, 557, 555, 552, 550, 101, 102, 103, 104, /* 1390 */ 105, 185, 189, 554, 560, 559, 561, 868, 529, 545, /* 1400 */ 460, 545, 545, 545, 545, 527, 545, 553, 545, 545, /* 1410 */ 545, 545, 556, 545, 545, 545, 545, 545, 545, 545, /* 1420 */ 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, /* 1430 */ 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, /* 1440 */ 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, /* 1450 */ 545, 545, 545, 508, 512, 456, 545, 545, 545, 498, /* 1460 */ 545, 545, 545, 545, 81, }; static const YYCODETYPE yy_lookahead[] = { /* 0 */ 24, 26, 26, 78, 79, 80, 81, 82, 83, 84, /* 10 */ 85, 86, 87, 88, 22, 9, 40, 23, 26, 25, /* 20 */ 44, 74, 75, 76, 77, 9, 79, 80, 81, 82, /* 30 */ 83, 84, 85, 86, 87, 88, 85, 86, 87, 88, /* 40 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, /* 50 */ 74, 75, 76, 77, 148, 79, 80, 81, 82, 83, /* 60 */ 84, 85, 86, 87, 88, 9, 25, 92, 92, 79, /* 70 */ 80, 81, 82, 83, 84, 85, 86, 87, 88, 26, /* 80 */ 150, 40, 26, 144, 92, 44, 147, 157, 94, 48, /* 90 */ 149, 97, 98, 99, 83, 84, 85, 86, 87, 88, /* 100 */ 170, 9, 10, 109, 174, 64, 65, 66, 67, 68, /* 110 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 189, /* 120 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, /* 130 */ 40, 29, 9, 26, 44, 12, 94, 35, 85, 97, /* 140 */ 98, 99, 142, 143, 144, 92, 93, 147, 92, 93, /* 150 */ 112, 109, 66, 115, 64, 65, 66, 67, 68, 69, /* 160 */ 70, 71, 72, 73, 74, 75, 76, 77, 22, 79, /* 170 */ 80, 81, 82, 83, 84, 85, 86, 87, 88, 66, /* 180 */ 94, 95, 96, 97, 98, 99, 100, 101, 60, 61, /* 190 */ 62, 17, 9, 160, 108, 150, 163, 164, 26, 92, /* 200 */ 93, 94, 150, 40, 97, 98, 99, 44, 0, 96, /* 210 */ 97, 98, 99, 100, 101, 170, 109, 9, 10, 174, /* 220 */ 92, 108, 186, 187, 96, 51, 136, 64, 65, 66, /* 230 */ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, /* 240 */ 77, 9, 79, 80, 81, 82, 83, 84, 85, 86, /* 250 */ 87, 88, 149, 18, 17, 83, 84, 129, 130, 150, /* 260 */ 20, 23, 27, 117, 92, 93, 221, 158, 159, 22, /* 270 */ 40, 24, 150, 38, 44, 103, 41, 40, 104, 105, /* 280 */ 106, 44, 9, 157, 168, 169, 51, 177, 178, 115, /* 290 */ 181, 182, 170, 177, 184, 55, 174, 57, 68, 69, /* 300 */ 137, 64, 65, 66, 67, 68, 69, 70, 71, 72, /* 310 */ 73, 74, 75, 76, 77, 189, 79, 80, 81, 82, /* 320 */ 83, 84, 85, 86, 87, 88, 96, 201, 202, 22, /* 330 */ 150, 169, 206, 26, 212, 150, 150, 23, 149, 177, /* 340 */ 155, 40, 23, 158, 159, 44, 224, 145, 146, 111, /* 350 */ 170, 113, 114, 151, 174, 9, 170, 13, 14, 157, /* 360 */ 174, 165, 166, 167, 163, 64, 65, 66, 67, 68, /* 370 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 139, /* 380 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, /* 390 */ 64, 189, 212, 112, 18, 209, 210, 116, 23, 92, /* 400 */ 93, 200, 150, 27, 224, 217, 218, 219, 220, 22, /* 410 */ 149, 26, 23, 26, 38, 40, 214, 41, 217, 44, /* 420 */ 219, 220, 170, 227, 9, 111, 174, 113, 114, 24, /* 430 */ 111, 26, 113, 114, 165, 166, 167, 9, 137, 64, /* 440 */ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, /* 450 */ 75, 76, 77, 127, 79, 80, 81, 82, 83, 84, /* 460 */ 85, 86, 87, 88, 23, 26, 23, 150, 25, 9, /* 470 */ 150, 13, 14, 15, 25, 115, 224, 92, 93, 92, /* 480 */ 93, 40, 26, 153, 47, 44, 26, 170, 128, 171, /* 490 */ 170, 174, 201, 202, 174, 9, 227, 92, 45, 9, /* 500 */ 111, 152, 113, 114, 119, 64, 65, 66, 67, 68, /* 510 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 66, /* 520 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, /* 530 */ 210, 92, 93, 216, 25, 217, 93, 219, 220, 111, /* 540 */ 103, 113, 114, 129, 130, 150, 40, 150, 92, 93, /* 550 */ 44, 9, 92, 93, 17, 225, 103, 150, 119, 229, /* 560 */ 9, 108, 119, 166, 167, 170, 9, 118, 26, 174, /* 570 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, /* 580 */ 74, 75, 76, 77, 11, 79, 80, 81, 82, 83, /* 590 */ 84, 85, 86, 87, 88, 9, 150, 111, 150, 113, /* 600 */ 114, 111, 93, 113, 114, 217, 9, 219, 220, 103, /* 610 */ 9, 216, 150, 40, 21, 208, 170, 44, 170, 157, /* 620 */ 174, 23, 174, 25, 227, 104, 105, 106, 119, 104, /* 630 */ 105, 106, 170, 11, 92, 93, 174, 64, 65, 66, /* 640 */ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, /* 650 */ 77, 189, 79, 80, 81, 82, 83, 84, 85, 86, /* 660 */ 87, 88, 111, 150, 113, 114, 150, 96, 111, 150, /* 670 */ 113, 114, 150, 136, 212, 138, 156, 162, 40, 108, /* 680 */ 45, 32, 44, 170, 157, 170, 224, 174, 192, 170, /* 690 */ 23, 98, 170, 174, 9, 199, 174, 111, 163, 113, /* 700 */ 114, 52, 64, 65, 66, 67, 68, 69, 70, 71, /* 710 */ 72, 73, 74, 75, 76, 77, 189, 79, 80, 81, /* 720 */ 82, 83, 84, 85, 86, 87, 88, 126, 150, 157, /* 730 */ 150, 150, 139, 150, 23, 200, 25, 161, 103, 150, /* 740 */ 150, 214, 226, 40, 23, 150, 25, 44, 170, 157, /* 750 */ 170, 170, 174, 24, 174, 174, 107, 230, 136, 170, /* 760 */ 170, 189, 235, 174, 174, 20, 183, 64, 65, 66, /* 770 */ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, /* 780 */ 77, 189, 79, 80, 81, 82, 83, 84, 85, 86, /* 790 */ 87, 88, 103, 150, 150, 150, 150, 9, 25, 66, /* 800 */ 55, 150, 57, 23, 150, 25, 214, 171, 40, 226, /* 810 */ 22, 33, 44, 170, 170, 170, 170, 174, 174, 174, /* 820 */ 174, 170, 230, 102, 170, 174, 171, 235, 174, 96, /* 830 */ 95, 96, 163, 65, 66, 67, 68, 69, 70, 71, /* 840 */ 72, 73, 74, 75, 76, 77, 117, 79, 80, 81, /* 850 */ 82, 83, 84, 85, 86, 87, 88, 150, 103, 150, /* 860 */ 150, 73, 150, 150, 23, 150, 25, 150, 150, 200, /* 870 */ 150, 26, 117, 150, 40, 150, 103, 170, 44, 170, /* 880 */ 170, 174, 170, 174, 174, 170, 174, 170, 170, 174, /* 890 */ 170, 174, 174, 170, 174, 170, 183, 174, 42, 174, /* 900 */ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, /* 910 */ 76, 77, 9, 79, 80, 81, 82, 83, 84, 85, /* 920 */ 86, 87, 88, 22, 150, 150, 150, 26, 28, 83, /* 930 */ 84, 31, 150, 150, 150, 150, 150, 92, 26, 226, /* 940 */ 150, 180, 150, 43, 170, 170, 170, 150, 174, 174, /* 950 */ 174, 50, 170, 170, 170, 170, 174, 174, 174, 174, /* 960 */ 170, 60, 61, 62, 174, 9, 23, 66, 25, 183, /* 970 */ 53, 54, 60, 61, 62, 183, 131, 172, 150, 150, /* 980 */ 183, 25, 186, 187, 83, 84, 85, 150, 150, 23, /* 990 */ 150, 25, 91, 92, 93, 83, 84, 96, 170, 170, /* 1000 */ 150, 150, 174, 174, 92, 150, 103, 170, 96, 22, /* 1010 */ 170, 174, 226, 26, 174, 23, 150, 25, 226, 150, /* 1020 */ 170, 170, 157, 226, 174, 174, 150, 23, 150, 25, /* 1030 */ 129, 130, 131, 132, 133, 134, 135, 50, 150, 170, /* 1040 */ 150, 129, 130, 174, 157, 46, 170, 60, 61, 62, /* 1050 */ 174, 213, 157, 66, 189, 23, 150, 25, 170, 23, /* 1060 */ 170, 25, 174, 208, 174, 23, 188, 25, 150, 150, /* 1070 */ 83, 84, 150, 150, 208, 150, 189, 150, 91, 92, /* 1080 */ 93, 150, 126, 96, 189, 115, 23, 9, 25, 150, /* 1090 */ 9, 157, 171, 102, 188, 22, 117, 173, 128, 171, /* 1100 */ 117, 22, 115, 190, 115, 26, 188, 188, 193, 189, /* 1110 */ 188, 188, 126, 188, 124, 188, 129, 130, 131, 132, /* 1120 */ 133, 134, 135, 189, 46, 123, 191, 188, 195, 50, /* 1130 */ 194, 121, 125, 196, 117, 197, 117, 88, 198, 60, /* 1140 */ 61, 62, 96, 150, 213, 66, 150, 150, 115, 115, /* 1150 */ 115, 22, 136, 223, 222, 17, 22, 25, 187, 23, /* 1160 */ 23, 150, 83, 84, 117, 150, 154, 122, 25, 101, /* 1170 */ 91, 92, 93, 211, 26, 96, 162, 172, 211, 122, /* 1180 */ 172, 25, 154, 203, 119, 103, 204, 150, 150, 150, /* 1190 */ 150, 120, 22, 22, 150, 23, 23, 26, 117, 205, /* 1200 */ 205, 117, 204, 150, 22, 175, 150, 176, 129, 130, /* 1210 */ 131, 132, 133, 134, 135, 136, 23, 211, 22, 171, /* 1220 */ 179, 50, 179, 162, 172, 163, 172, 150, 178, 211, /* 1230 */ 179, 60, 61, 62, 170, 180, 170, 66, 46, 23, /* 1240 */ 182, 228, 182, 173, 22, 171, 171, 46, 228, 22, /* 1250 */ 100, 150, 176, 108, 83, 84, 85, 150, 175, 154, /* 1260 */ 150, 24, 91, 92, 93, 154, 150, 96, 154, 103, /* 1270 */ 39, 154, 11, 37, 139, 47, 150, 103, 103, 22, /* 1280 */ 103, 154, 22, 26, 171, 9, 139, 185, 11, 150, /* 1290 */ 231, 127, 127, 9, 9, 17, 17, 64, 107, 232, /* 1300 */ 129, 130, 131, 132, 133, 134, 135, 50, 185, 150, /* 1310 */ 150, 73, 194, 233, 9, 73, 127, 60, 61, 62, /* 1320 */ 234, 22, 22, 66, 215, 9, 150, 118, 150, 9, /* 1330 */ 9, 9, 9, 9, 194, 118, 194, 9, 185, 107, /* 1340 */ 83, 84, 9, 194, 9, 127, 215, 22, 91, 92, /* 1350 */ 93, 9, 150, 96, 150, 9, 9, 154, 150, 9, /* 1360 */ 11, 9, 23, 9, 34, 16, 17, 18, 19, 236, /* 1370 */ 163, 150, 24, 9, 163, 9, 9, 9, 237, 30, /* 1380 */ 236, 9, 20, 154, 150, 36, 129, 130, 131, 132, /* 1390 */ 133, 134, 135, 150, 140, 59, 150, 9, 49, 238, /* 1400 */ 51, 238, 238, 238, 238, 56, 238, 58, 238, 238, /* 1410 */ 238, 238, 63, 238, 238, 238, 238, 238, 238, 238, /* 1420 */ 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, /* 1430 */ 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, /* 1440 */ 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, /* 1450 */ 238, 238, 238, 104, 105, 106, 238, 238, 238, 110, /* 1460 */ 238, 238, 238, 238, 115, }; #define YY_SHIFT_USE_DFLT (-76) static const short yy_shift_ofst[] = { /* 0 */ 92, 208, -76, -76, 1349, 6, 16, -76, 458, 123, /* 10 */ 183, 56, 232, -76, -76, -76, -76, -76, -76, 123, /* 20 */ 273, 123, 346, 123, 415, 247, 597, 456, 598, 667, /* 30 */ 685, 107, -76, -25, -76, 86, -76, 456, 113, -76, /* 40 */ 689, -76, 778, 235, -76, -76, -76, -76, -76, -76, /* 50 */ -76, 571, 689, -76, 856, -76, 344, -76, -76, 999, /* 60 */ 102, 689, 991, -76, -76, -76, -76, 689, -76, 1073, /* 70 */ 1257, 146, 901, 979, 983, -76, 987, -76, 238, 989, /* 80 */ -76, 281, -76, 449, 986, 1002, 990, 1010, 1007, -76, /* 90 */ 1257, 41, 1257, 638, 1257, -76, 1017, 456, 1019, 456, /* 100 */ -76, -76, -76, -76, -76, -76, -76, -76, -76, 834, /* 110 */ 1257, 768, 1257, -10, 1257, -10, 1257, -10, 1257, -10, /* 120 */ 1257, -53, 1257, -53, 1257, 11, 1257, 11, 1257, 11, /* 130 */ 1257, 11, 1257, -49, 1257, -49, 1257, 1049, 1257, 1049, /* 140 */ 1257, 1049, 1257, -76, -76, -76, 230, -76, -76, -76, /* 150 */ -76, -76, 1257, -75, 1257, -10, -76, 733, -76, 1046, /* 160 */ -76, -76, -76, 1257, 703, 1257, -53, -76, 307, 987, /* 170 */ 314, 38, 1033, 1034, 1035, -76, 638, 1257, 834, 1257, /* 180 */ -76, 1257, -76, 1257, -76, 1129, 989, 319, -76, 1079, /* 190 */ 90, 1016, 537, 1138, -76, 1257, 163, 1257, 638, 1134, /* 200 */ 376, 1136, -76, 1132, 456, 1137, -76, 1257, 237, 1257, /* 210 */ 301, 1257, 638, 711, -76, 1257, -76, -76, 1047, 456, /* 220 */ -76, -76, -76, 1257, 638, 1045, 1257, 1143, 1257, 1068, /* 230 */ 102, -76, 1148, -76, -76, 638, 1068, 102, -76, 1257, /* 240 */ 638, 1057, 1257, 1156, 1257, 638, -76, -76, 509, -76, /* 250 */ -76, -76, 385, -76, 439, -76, 1065, -76, 387, 1047, /* 260 */ 405, -76, -76, 456, -76, -76, 1082, 1071, -76, 1170, /* 270 */ 456, 780, -76, 456, -76, -76, 1257, 638, 989, 389, /* 280 */ 443, 1172, 405, 1082, 1071, -76, 1171, -24, -76, -76, /* 290 */ 1084, 53, -76, -76, -76, -76, 375, -76, 841, -76, /* 300 */ 1173, -76, 441, 689, -76, 456, 1182, -76, 635, -76, /* 310 */ 456, -76, 521, 649, -76, 735, -76, -76, -76, -76, /* 320 */ 649, -76, 649, -76, 456, 943, -76, 456, 1068, 102, /* 330 */ -76, -76, 1068, 102, -76, -76, 1148, -76, 856, -76, /* 340 */ -76, 912, -76, 128, -76, -76, 128, -76, -76, -8, /* 350 */ 846, 966, -76, 846, 1193, -76, -76, -76, 414, -76, /* 360 */ -76, -76, 414, -76, -76, -76, -76, -76, -6, 42, /* 370 */ -76, 456, -76, 1192, 1196, 456, 721, 1216, 689, -76, /* 380 */ 1222, 456, 992, 689, -76, 1257, 506, -76, 1201, 1227, /* 390 */ 456, 1004, 1150, 456, 1182, -76, 453, 1145, -76, -76, /* 400 */ -76, -76, -76, 989, 428, 593, 745, 456, 1047, -76, /* 410 */ 456, 729, 1237, 989, 486, 456, 1047, 900, 525, 1166, /* 420 */ 456, 1047, -76, 1231, 622, 1261, 1257, 573, 1236, 917, /* 430 */ -76, -76, 1174, 1175, 437, 456, 773, -76, -76, 1228, /* 440 */ -76, -76, 1135, 456, 755, 1177, 456, 1260, 456, 1032, /* 450 */ 903, 1276, 1147, 1277, 174, 490, 326, 235, -76, 1164, /* 460 */ 1165, 1278, 1284, 1285, 174, 1279, 1233, 456, 1191, 456, /* 470 */ 956, 456, 1238, 1257, 638, 1305, 1242, 1257, 638, 1189, /* 480 */ 456, 1299, 456, 1036, -76, 360, 551, 1300, 1257, 1042, /* 490 */ 1257, 638, 1316, 638, 1209, 456, 601, 1320, 240, 456, /* 500 */ 1321, 456, 1322, 456, 1323, 456, 1324, 557, 1217, 456, /* 510 */ 601, 1328, 1233, 456, 1232, 456, 956, 1333, 1218, 456, /* 520 */ 1299, 970, 586, 1325, 1257, 1063, 1335, 460, 1342, 456, /* 530 */ 1047, 788, 172, 1346, 1347, 1350, 1352, 456, 1339, 1354, /* 540 */ 1330, -25, 1348, 456, 1078, 1364, 845, 1366, 1367, -76, /* 550 */ 1330, 456, 1368, 542, 1081, 1372, 1362, 456, 1336, 1254, /* 560 */ 456, 1388, -76, -76, }; #define YY_REDUCE_USE_DFLT (-95) static const short yy_reduce_ofst[] = { /* 0 */ 0, -61, -95, -95, 202, -95, -95, -95, -94, -59, /* 10 */ -95, 52, -95, -95, -95, -95, -95, -95, -95, 103, /* 20 */ -95, 189, -95, 261, -95, 349, -95, 185, 520, -95, /* 30 */ -95, 109, -95, 33, 576, 116, -95, 595, 162, -95, /* 40 */ 636, -95, -95, 36, -95, -95, -95, -95, -95, -95, /* 50 */ -95, -95, 655, -95, 761, -95, -95, -95, -95, -95, /* 60 */ 805, 921, 924, -95, -95, -95, -95, 928, -95, -95, /* 70 */ 446, -95, 122, -95, -95, -95, -70, -95, 913, 920, /* 80 */ -95, 935, 496, 915, 936, 933, 937, 938, 940, -95, /* 90 */ 448, 388, 513, 388, 519, -95, -95, 993, -95, 996, /* 100 */ -95, -95, -95, -95, -95, -95, -95, -95, -95, 388, /* 110 */ 522, 388, 578, 388, 580, 388, 581, 388, 589, 388, /* 120 */ 590, 388, 643, 388, 644, 388, 645, 388, 646, 388, /* 130 */ 651, 388, 654, 388, 707, 388, 709, 388, 710, 388, /* 140 */ 712, 388, 715, 388, -95, -95, -95, -95, -95, -95, /* 150 */ -95, -95, 717, 188, 718, 388, -95, -95, -95, -95, /* 160 */ -95, -95, -95, 720, 388, 723, 388, -95, 997, 462, /* 170 */ 913, -95, -95, -95, -95, -95, 388, 725, 388, 774, /* 180 */ 388, 775, 388, 776, 388, -95, 572, 913, -95, 45, /* 190 */ 388, 932, 930, -95, -95, 782, 388, 783, 388, -95, /* 200 */ 971, -95, -95, -95, 1011, -95, -95, 784, 388, 785, /* 210 */ 388, 790, 388, -95, -95, 252, -95, -95, 1012, 1015, /* 220 */ -95, -95, -95, 828, 388, -95, 186, -95, 320, 962, /* 230 */ 1005, -95, 1014, -95, -95, 388, 967, 1008, -95, 829, /* 240 */ 388, -95, 180, -95, 837, 388, -95, 291, 980, -95, /* 250 */ -95, -95, 1037, -95, 1038, -95, -95, -95, 1039, 1028, /* 260 */ 535, -95, -95, 1040, -95, -95, 982, 994, -95, -95, /* 270 */ 407, -95, -95, 1044, -95, -95, 840, 388, 126, 913, /* 280 */ 980, -95, 669, 998, 995, -95, 850, 201, -95, -95, /* 290 */ -95, 993, -95, -95, -95, -95, 388, -95, -95, -95, /* 300 */ -95, -95, 388, 1048, -95, 1053, 1030, 1031, 1050, -95, /* 310 */ 1056, -95, -95, 1041, -95, -95, -95, -95, -95, -95, /* 320 */ 1043, -95, 1051, -95, 583, -95, -95, 516, 1006, 1052, /* 330 */ -95, -95, 1018, 1054, -95, -95, 1061, -95, 1055, -95, /* 340 */ -95, 515, -95, 1064, -95, -95, 1066, -95, -95, 1062, /* 350 */ 196, -95, -95, 269, -95, -95, -95, -95, 1013, -95, /* 360 */ -95, -95, 1020, -95, -95, -95, -95, -95, 1058, 1060, /* 370 */ -95, 1077, -95, -95, -95, 713, 1070, -95, 1074, -95, /* 380 */ -95, 786, -95, 1075, -95, 851, 318, -95, -95, -95, /* 390 */ 792, -95, -95, 1101, 1083, 1076, 110, -95, -95, -95, /* 400 */ -95, -95, -95, 865, 913, 330, -95, 1107, 1105, -95, /* 410 */ 1110, 1111, -95, 887, 913, 1116, 1114, 1059, 1067, -95, /* 420 */ 878, 1117, -95, 1080, 1086, -95, 869, 388, -95, -95, /* 430 */ -95, -95, -95, -95, -95, 855, -95, -95, -95, -95, /* 440 */ -95, -95, -95, 1126, 1127, -95, 1139, -95, 797, -95, /* 450 */ 1113, -95, -95, -95, 527, 913, 1102, 796, -95, -95, /* 460 */ -95, -95, -95, -95, 592, -95, 1123, 1159, -95, 838, /* 470 */ 1118, 1160, -95, 876, 388, -95, -95, 888, 388, -95, /* 480 */ 1176, 1109, 866, -95, -95, 895, 913, -95, 317, -95, /* 490 */ 890, 388, -95, 388, -95, 1178, 1140, -95, -95, 906, /* 500 */ -95, 918, -95, 919, -95, 922, -95, 913, -95, 923, /* 510 */ 1142, -95, 1153, 925, -95, 931, 1149, -95, -95, 927, /* 520 */ 1131, 934, 913, -95, 395, -95, -95, 1202, -95, 1204, /* 530 */ 1203, -95, 397, -95, -95, -95, -95, 1208, -95, -95, /* 540 */ 1133, 1207, -95, 1221, 1141, -95, 1211, -95, -95, -95, /* 550 */ 1144, 1234, -95, 1243, 1229, -95, -95, 939, -95, -95, /* 560 */ 1246, -95, -95, -95, }; static const YYACTIONTYPE yy_default[] = { /* 0 */ 570, 570, 565, 568, 869, 869, 869, 569, 576, 869, /* 10 */ 869, 869, 869, 596, 597, 598, 577, 578, 579, 869, /* 20 */ 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, /* 30 */ 869, 869, 589, 599, 608, 591, 607, 869, 869, 609, /* 40 */ 652, 615, 869, 869, 653, 656, 657, 658, 855, 856, /* 50 */ 857, 869, 652, 616, 637, 635, 869, 638, 639, 869, /* 60 */ 708, 652, 623, 617, 624, 706, 707, 652, 618, 869, /* 70 */ 869, 738, 807, 744, 739, 735, 869, 663, 869, 869, /* 80 */ 664, 672, 674, 681, 720, 711, 713, 701, 715, 669, /* 90 */ 869, 716, 869, 717, 869, 737, 869, 869, 740, 869, /* 100 */ 741, 742, 743, 745, 746, 747, 750, 751, 752, 753, /* 110 */ 869, 754, 869, 755, 869, 756, 869, 757, 869, 758, /* 120 */ 869, 759, 869, 760, 869, 761, 869, 762, 869, 763, /* 130 */ 869, 764, 869, 765, 869, 766, 869, 767, 869, 768, /* 140 */ 869, 769, 869, 770, 771, 772, 869, 773, 774, 781, /* 150 */ 788, 791, 869, 776, 869, 775, 778, 869, 779, 869, /* 160 */ 782, 780, 787, 869, 869, 869, 789, 790, 869, 807, /* 170 */ 869, 869, 869, 869, 869, 794, 806, 869, 783, 869, /* 180 */ 784, 869, 785, 869, 786, 869, 869, 869, 796, 869, /* 190 */ 869, 869, 869, 869, 797, 869, 869, 869, 798, 869, /* 200 */ 869, 869, 853, 869, 869, 869, 854, 869, 869, 869, /* 210 */ 869, 869, 799, 869, 792, 807, 804, 805, 689, 869, /* 220 */ 690, 795, 777, 869, 718, 869, 869, 702, 869, 709, /* 230 */ 708, 703, 869, 593, 710, 705, 709, 708, 704, 869, /* 240 */ 714, 869, 807, 712, 869, 721, 673, 684, 682, 683, /* 250 */ 692, 693, 869, 694, 869, 695, 869, 696, 869, 689, /* 260 */ 680, 594, 595, 869, 678, 679, 698, 700, 685, 869, /* 270 */ 869, 869, 699, 869, 733, 734, 869, 697, 684, 869, /* 280 */ 869, 869, 680, 698, 700, 686, 869, 680, 675, 676, /* 290 */ 869, 869, 677, 670, 671, 793, 869, 736, 869, 748, /* 300 */ 869, 749, 869, 652, 619, 869, 811, 625, 620, 626, /* 310 */ 869, 627, 869, 869, 628, 869, 631, 632, 633, 634, /* 320 */ 869, 629, 869, 630, 869, 869, 812, 869, 709, 708, /* 330 */ 813, 815, 709, 708, 814, 621, 869, 622, 637, 636, /* 340 */ 610, 869, 611, 869, 612, 744, 869, 613, 614, 600, /* 350 */ 830, 869, 601, 830, 869, 602, 605, 606, 869, 825, /* 360 */ 827, 828, 869, 826, 829, 604, 603, 592, 869, 869, /* 370 */ 642, 869, 645, 869, 869, 869, 869, 869, 652, 646, /* 380 */ 869, 869, 869, 652, 647, 869, 652, 648, 869, 869, /* 390 */ 869, 869, 869, 869, 811, 625, 650, 869, 649, 651, /* 400 */ 643, 644, 590, 869, 869, 586, 869, 869, 689, 584, /* 410 */ 869, 869, 869, 869, 869, 869, 689, 836, 869, 869, /* 420 */ 869, 689, 691, 841, 869, 869, 869, 869, 869, 869, /* 430 */ 842, 843, 869, 869, 869, 869, 869, 833, 834, 869, /* 440 */ 835, 585, 869, 869, 869, 869, 869, 869, 869, 869, /* 450 */ 869, 869, 869, 869, 869, 869, 869, 869, 655, 869, /* 460 */ 869, 869, 869, 869, 869, 869, 654, 869, 869, 869, /* 470 */ 869, 869, 869, 869, 723, 869, 869, 869, 724, 869, /* 480 */ 869, 731, 869, 869, 732, 869, 869, 869, 869, 869, /* 490 */ 869, 729, 869, 730, 869, 869, 869, 869, 869, 869, /* 500 */ 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, /* 510 */ 869, 869, 654, 869, 869, 869, 869, 869, 869, 869, /* 520 */ 731, 869, 869, 869, 869, 869, 869, 869, 869, 869, /* 530 */ 689, 869, 830, 869, 869, 869, 869, 869, 869, 869, /* 540 */ 864, 869, 869, 869, 869, 869, 869, 869, 869, 863, /* 550 */ 864, 869, 869, 869, 869, 869, 869, 869, 869, 869, /* 560 */ 869, 869, 571, 566, }; #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0])) /* The next table maps tokens into fallback tokens. If a construct ** like the following: ** ** %fallback ID X Y Z. ** ** appears in the grammer, then ID becomes a fallback token for X, Y, ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser ** but it does not parse, the type of the token is changed to ID and ** the parse is retried before an error is thrown. */ #ifdef YYFALLBACK static const YYCODETYPE yyFallback[] = { 0, /* $ => nothing */ 0, /* END_OF_FILE => nothing */ 0, /* ILLEGAL => nothing */ 0, /* SPACE => nothing */ 0, /* UNCLOSED_STRING => nothing */ 0, /* COMMENT => nothing */ 0, /* FUNCTION => nothing */ 0, /* COLUMN => nothing */ 0, /* AGG_FUNCTION => nothing */ 0, /* SEMI => nothing */ 26, /* EXPLAIN => ID */ 26, /* BEGIN => ID */ 0, /* TRANSACTION => nothing */ 26, /* DEFERRED => ID */ 26, /* IMMEDIATE => ID */ 26, /* EXCLUSIVE => ID */ 0, /* COMMIT => nothing */ 26, /* END => ID */ 0, /* ROLLBACK => nothing */ 0, /* CREATE => nothing */ 0, /* TABLE => nothing */ 26, /* TEMP => ID */ 0, /* LP => nothing */ 0, /* RP => nothing */ 0, /* AS => nothing */ 0, /* COMMA => nothing */ 0, /* ID => nothing */ 26, /* ABORT => ID */ 26, /* AFTER => ID */ 26, /* ASC => ID */ 26, /* ATTACH => ID */ 26, /* BEFORE => ID */ 26, /* CASCADE => ID */ 26, /* CONFLICT => ID */ 26, /* DATABASE => ID */ 26, /* DESC => ID */ 26, /* DETACH => ID */ 26, /* EACH => ID */ 26, /* FAIL => ID */ 26, /* FOR => ID */ 26, /* GLOB => ID */ 26, /* IGNORE => ID */ 26, /* INITIALLY => ID */ 26, /* INSTEAD => ID */ 26, /* LIKE => ID */ 26, /* MATCH => ID */ 26, /* KEY => ID */ 26, /* OF => ID */ 26, /* OFFSET => ID */ 26, /* PRAGMA => ID */ 26, /* RAISE => ID */ 26, /* REPLACE => ID */ 26, /* RESTRICT => ID */ 26, /* ROW => ID */ 26, /* STATEMENT => ID */ 26, /* TRIGGER => ID */ 26, /* VACUUM => ID */ 26, /* VIEW => ID */ 26, /* REINDEX => ID */ 26, /* RENAME => ID */ 26, /* CDATE => ID */ 26, /* CTIME => ID */ 26, /* CTIMESTAMP => ID */ 26, /* ALTER => ID */ 0, /* OR => nothing */ 0, /* AND => nothing */ 0, /* NOT => nothing */ 0, /* IS => nothing */ 0, /* BETWEEN => nothing */ 0, /* IN => nothing */ 0, /* ISNULL => nothing */ 0, /* NOTNULL => nothing */ 0, /* NE => nothing */ 0, /* EQ => nothing */ |
︙ | ︙ | |||
684 685 686 687 688 689 690 | 0, /* INSERT => nothing */ 0, /* SET => nothing */ 0, /* DEFERRABLE => nothing */ 0, /* FOREIGN => nothing */ 0, /* DROP => nothing */ 0, /* UNION => nothing */ 0, /* ALL => nothing */ | < > > < < < | 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 | 0, /* INSERT => nothing */ 0, /* SET => nothing */ 0, /* DEFERRABLE => nothing */ 0, /* FOREIGN => nothing */ 0, /* DROP => nothing */ 0, /* UNION => nothing */ 0, /* ALL => nothing */ 0, /* INTERSECT => nothing */ 0, /* EXCEPT => nothing */ 0, /* SELECT => nothing */ 0, /* DISTINCT => nothing */ 0, /* DOT => nothing */ 0, /* FROM => nothing */ 0, /* JOIN => nothing */ 0, /* USING => nothing */ 0, /* ORDER => nothing */ 0, /* BY => nothing */ 0, /* GROUP => nothing */ 0, /* HAVING => nothing */ 0, /* LIMIT => nothing */ 0, /* WHERE => nothing */ 0, /* INTO => nothing */ 0, /* VALUES => nothing */ 0, /* INTEGER => nothing */ 0, /* FLOAT => nothing */ 0, /* BLOB => nothing */ 0, /* REGISTER => nothing */ 0, /* VARIABLE => nothing */ 0, /* EXISTS => nothing */ 0, /* CASE => nothing */ 0, /* WHEN => nothing */ 0, /* THEN => nothing */ 0, /* ELSE => nothing */ 0, /* INDEX => nothing */ 0, /* TO => nothing */ }; #endif /* YYFALLBACK */ /* The following structure represents a single element of the ** parser's stack. Information stored includes: ** ** + The state number for the parser at this level of the stack. |
︙ | ︙ | |||
784 785 786 787 788 789 790 | } #endif /* NDEBUG */ #ifndef NDEBUG /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ static const char *const yyTokenName[] = { | > > | < | | | | < | | | | | | | | > | | | | | > | | | | | | | | | | | | | < | | | | | | | | | | < | | | | | | | | | | | | | < | > | | | | | | < | | | | | < < | | | | | | | | | | > | | | | | < | | | | | | | | | | | < | | | | | | | | | | | | | > > > > | < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | > > > | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > > | > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | | | | | < < | < < < < | 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 | } #endif /* NDEBUG */ #ifndef NDEBUG /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ static const char *const yyTokenName[] = { "$", "END_OF_FILE", "ILLEGAL", "SPACE", "UNCLOSED_STRING", "COMMENT", "FUNCTION", "COLUMN", "AGG_FUNCTION", "SEMI", "EXPLAIN", "BEGIN", "TRANSACTION", "DEFERRED", "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END", "ROLLBACK", "CREATE", "TABLE", "TEMP", "LP", "RP", "AS", "COMMA", "ID", "ABORT", "AFTER", "ASC", "ATTACH", "BEFORE", "CASCADE", "CONFLICT", "DATABASE", "DESC", "DETACH", "EACH", "FAIL", "FOR", "GLOB", "IGNORE", "INITIALLY", "INSTEAD", "LIKE", "MATCH", "KEY", "OF", "OFFSET", "PRAGMA", "RAISE", "REPLACE", "RESTRICT", "ROW", "STATEMENT", "TRIGGER", "VACUUM", "VIEW", "REINDEX", "RENAME", "CDATE", "CTIME", "CTIMESTAMP", "ALTER", "OR", "AND", "NOT", "IS", "BETWEEN", "IN", "ISNULL", "NOTNULL", "NE", "EQ", "GT", "LE", "LT", "GE", "ESCAPE", "BITAND", "BITOR", "LSHIFT", "RSHIFT", "PLUS", "MINUS", "STAR", "SLASH", "REM", "CONCAT", "UMINUS", "UPLUS", "BITNOT", "STRING", "JOIN_KW", "CONSTRAINT", "DEFAULT", "NULL", "PRIMARY", "UNIQUE", "CHECK", "REFERENCES", "COLLATE", "AUTOINCR", "ON", "DELETE", "UPDATE", "INSERT", "SET", "DEFERRABLE", "FOREIGN", "DROP", "UNION", "ALL", "INTERSECT", "EXCEPT", "SELECT", "DISTINCT", "DOT", "FROM", "JOIN", "USING", "ORDER", "BY", "GROUP", "HAVING", "LIMIT", "WHERE", "INTO", "VALUES", "INTEGER", "FLOAT", "BLOB", "REGISTER", "VARIABLE", "EXISTS", "CASE", "WHEN", "THEN", "ELSE", "INDEX", "TO", "error", "input", "cmdlist", "ecmd", "cmdx", "cmd", "explain", "transtype", "trans_opt", "nm", "create_table", "create_table_args", "temp", "dbnm", "columnlist", "conslist_opt", "select", "column", "columnid", "type", "carglist", "id", "ids", "typename", "signed", "plus_num", "minus_num", "carg", "ccons", "term", "onconf", "sortorder", "autoinc", "expr", "idxlist_opt", "refargs", "defer_subclause", "refarg", "refact", "init_deferred_pred_opt", "conslist", "tcons", "idxlist", "defer_subclause_opt", "orconf", "resolvetype", "raisetype", "fullname", "oneselect", "multiselect_op", "distinct", "selcollist", "from", "where_opt", "groupby_opt", "having_opt", "orderby_opt", "limit_opt", "sclp", "as", "seltablist", "stl_prefix", "joinop", "on_opt", "using_opt", "seltablist_paren", "joinop2", "inscollist", "sortlist", "sortitem", "collate", "exprlist", "setlist", "insert_cmd", "inscollist_opt", "itemlist", "likeop", "escape", "between_op", "in_op", "case_operand", "case_exprlist", "case_else", "expritem", "uniqueflag", "idxitem", "plus_opt", "number", "trigger_decl", "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause", "when_clause", "trigger_cmd", "database_kw_opt", "key_opt", }; #endif /* NDEBUG */ #ifndef NDEBUG /* For tracing reduce actions, the names of all rules are required. */ static const char *const yyRuleName[] = { /* 0 */ "input ::= cmdlist", /* 1 */ "cmdlist ::= cmdlist ecmd", /* 2 */ "cmdlist ::= ecmd", /* 3 */ "cmdx ::= cmd", /* 4 */ "ecmd ::= SEMI", /* 5 */ "ecmd ::= explain cmdx SEMI", /* 6 */ "explain ::=", /* 7 */ "explain ::= EXPLAIN", /* 8 */ "cmd ::= BEGIN transtype trans_opt", /* 9 */ "trans_opt ::=", /* 10 */ "trans_opt ::= TRANSACTION", /* 11 */ "trans_opt ::= TRANSACTION nm", /* 12 */ "transtype ::=", /* 13 */ "transtype ::= DEFERRED", /* 14 */ "transtype ::= IMMEDIATE", /* 15 */ "transtype ::= EXCLUSIVE", /* 16 */ "cmd ::= COMMIT trans_opt", /* 17 */ "cmd ::= END trans_opt", /* 18 */ "cmd ::= ROLLBACK trans_opt", /* 19 */ "cmd ::= create_table create_table_args", /* 20 */ "create_table ::= CREATE temp TABLE nm dbnm", /* 21 */ "temp ::= TEMP", /* 22 */ "temp ::=", /* 23 */ "create_table_args ::= LP columnlist conslist_opt RP", /* 24 */ "create_table_args ::= AS select", /* 25 */ "columnlist ::= columnlist COMMA column", /* 26 */ "columnlist ::= column", /* 27 */ "column ::= columnid type carglist", /* 28 */ "columnid ::= nm", /* 29 */ "id ::= ID", /* 30 */ "ids ::= ID", /* 31 */ "ids ::= STRING", /* 32 */ "nm ::= ID", /* 33 */ "nm ::= STRING", /* 34 */ "nm ::= JOIN_KW", /* 35 */ "type ::=", /* 36 */ "type ::= typename", /* 37 */ "type ::= typename LP signed RP", /* 38 */ "type ::= typename LP signed COMMA signed RP", /* 39 */ "typename ::= ids", /* 40 */ "typename ::= typename ids", /* 41 */ "signed ::= plus_num", /* 42 */ "signed ::= minus_num", /* 43 */ "carglist ::= carglist carg", /* 44 */ "carglist ::=", /* 45 */ "carg ::= CONSTRAINT nm ccons", /* 46 */ "carg ::= ccons", /* 47 */ "carg ::= DEFAULT term", /* 48 */ "carg ::= DEFAULT PLUS term", /* 49 */ "carg ::= DEFAULT MINUS term", /* 50 */ "carg ::= DEFAULT id", /* 51 */ "ccons ::= NULL onconf", /* 52 */ "ccons ::= NOT NULL onconf", /* 53 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", /* 54 */ "ccons ::= UNIQUE onconf", /* 55 */ "ccons ::= CHECK LP expr RP onconf", /* 56 */ "ccons ::= REFERENCES nm idxlist_opt refargs", /* 57 */ "ccons ::= defer_subclause", /* 58 */ "ccons ::= COLLATE id", /* 59 */ "autoinc ::=", /* 60 */ "autoinc ::= AUTOINCR", /* 61 */ "refargs ::=", /* 62 */ "refargs ::= refargs refarg", /* 63 */ "refarg ::= MATCH nm", /* 64 */ "refarg ::= ON DELETE refact", /* 65 */ "refarg ::= ON UPDATE refact", /* 66 */ "refarg ::= ON INSERT refact", /* 67 */ "refact ::= SET NULL", /* 68 */ "refact ::= SET DEFAULT", /* 69 */ "refact ::= CASCADE", /* 70 */ "refact ::= RESTRICT", /* 71 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", /* 72 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", /* 73 */ "init_deferred_pred_opt ::=", /* 74 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", /* 75 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", /* 76 */ "conslist_opt ::=", /* 77 */ "conslist_opt ::= COMMA conslist", /* 78 */ "conslist ::= conslist COMMA tcons", /* 79 */ "conslist ::= conslist tcons", /* 80 */ "conslist ::= tcons", /* 81 */ "tcons ::= CONSTRAINT nm", /* 82 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf", /* 83 */ "tcons ::= UNIQUE LP idxlist RP onconf", /* 84 */ "tcons ::= CHECK expr onconf", /* 85 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt", /* 86 */ "defer_subclause_opt ::=", /* 87 */ "defer_subclause_opt ::= defer_subclause", /* 88 */ "onconf ::=", /* 89 */ "onconf ::= ON CONFLICT resolvetype", /* 90 */ "orconf ::=", /* 91 */ "orconf ::= OR resolvetype", /* 92 */ "resolvetype ::= raisetype", /* 93 */ "resolvetype ::= IGNORE", /* 94 */ "resolvetype ::= REPLACE", /* 95 */ "cmd ::= DROP TABLE fullname", /* 96 */ "cmd ::= CREATE temp VIEW nm dbnm AS select", /* 97 */ "cmd ::= DROP VIEW fullname", /* 98 */ "cmd ::= select", /* 99 */ "select ::= oneselect", /* 100 */ "select ::= select multiselect_op oneselect", /* 101 */ "multiselect_op ::= UNION", /* 102 */ "multiselect_op ::= UNION ALL", /* 103 */ "multiselect_op ::= INTERSECT", /* 104 */ "multiselect_op ::= EXCEPT", /* 105 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", /* 106 */ "distinct ::= DISTINCT", /* 107 */ "distinct ::= ALL", /* 108 */ "distinct ::=", /* 109 */ "sclp ::= selcollist COMMA", /* 110 */ "sclp ::=", /* 111 */ "selcollist ::= sclp expr as", /* 112 */ "selcollist ::= sclp STAR", /* 113 */ "selcollist ::= sclp nm DOT STAR", /* 114 */ "as ::= AS nm", /* 115 */ "as ::= ids", /* 116 */ "as ::=", /* 117 */ "from ::=", /* 118 */ "from ::= FROM seltablist", /* 119 */ "stl_prefix ::= seltablist joinop", /* 120 */ "stl_prefix ::=", /* 121 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt", /* 122 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt", /* 123 */ "seltablist_paren ::= select", /* 124 */ "seltablist_paren ::= seltablist", /* 125 */ "dbnm ::=", /* 126 */ "dbnm ::= DOT nm", /* 127 */ "fullname ::= nm dbnm", /* 128 */ "joinop ::= COMMA", /* 129 */ "joinop ::= JOIN", /* 130 */ "joinop ::= JOIN_KW JOIN", /* 131 */ "joinop ::= JOIN_KW nm JOIN", /* 132 */ "joinop ::= JOIN_KW nm nm JOIN", /* 133 */ "on_opt ::= ON expr", /* 134 */ "on_opt ::=", /* 135 */ "using_opt ::= USING LP inscollist RP", /* 136 */ "using_opt ::=", /* 137 */ "orderby_opt ::=", /* 138 */ "orderby_opt ::= ORDER BY sortlist", /* 139 */ "sortlist ::= sortlist COMMA sortitem collate sortorder", /* 140 */ "sortlist ::= sortitem collate sortorder", /* 141 */ "sortitem ::= expr", /* 142 */ "sortorder ::= ASC", /* 143 */ "sortorder ::= DESC", /* 144 */ "sortorder ::=", /* 145 */ "collate ::=", /* 146 */ "collate ::= COLLATE id", /* 147 */ "groupby_opt ::=", /* 148 */ "groupby_opt ::= GROUP BY exprlist", /* 149 */ "having_opt ::=", /* 150 */ "having_opt ::= HAVING expr", /* 151 */ "limit_opt ::=", /* 152 */ "limit_opt ::= LIMIT expr", /* 153 */ "limit_opt ::= LIMIT expr OFFSET expr", /* 154 */ "limit_opt ::= LIMIT expr COMMA expr", /* 155 */ "cmd ::= DELETE FROM fullname where_opt", /* 156 */ "where_opt ::=", /* 157 */ "where_opt ::= WHERE expr", /* 158 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt", /* 159 */ "setlist ::= setlist COMMA nm EQ expr", /* 160 */ "setlist ::= nm EQ expr", /* 161 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP", /* 162 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select", /* 163 */ "insert_cmd ::= INSERT orconf", /* 164 */ "insert_cmd ::= REPLACE", /* 165 */ "itemlist ::= itemlist COMMA expr", /* 166 */ "itemlist ::= expr", /* 167 */ "inscollist_opt ::=", /* 168 */ "inscollist_opt ::= LP inscollist RP", /* 169 */ "inscollist ::= inscollist COMMA nm", /* 170 */ "inscollist ::= nm", /* 171 */ "expr ::= term", /* 172 */ "expr ::= LP expr RP", /* 173 */ "term ::= NULL", /* 174 */ "expr ::= ID", /* 175 */ "expr ::= JOIN_KW", /* 176 */ "expr ::= nm DOT nm", /* 177 */ "expr ::= nm DOT nm DOT nm", /* 178 */ "term ::= INTEGER", /* 179 */ "term ::= FLOAT", /* 180 */ "term ::= STRING", /* 181 */ "expr ::= BLOB", /* 182 */ "expr ::= REGISTER", /* 183 */ "expr ::= VARIABLE", /* 184 */ "expr ::= ID LP exprlist RP", /* 185 */ "expr ::= ID LP STAR RP", /* 186 */ "term ::= CTIME", /* 187 */ "term ::= CDATE", /* 188 */ "term ::= CTIMESTAMP", /* 189 */ "expr ::= expr AND expr", /* 190 */ "expr ::= expr OR expr", /* 191 */ "expr ::= expr LT expr", /* 192 */ "expr ::= expr GT expr", /* 193 */ "expr ::= expr LE expr", /* 194 */ "expr ::= expr GE expr", /* 195 */ "expr ::= expr NE expr", /* 196 */ "expr ::= expr EQ expr", /* 197 */ "expr ::= expr BITAND expr", /* 198 */ "expr ::= expr BITOR expr", /* 199 */ "expr ::= expr LSHIFT expr", /* 200 */ "expr ::= expr RSHIFT expr", /* 201 */ "expr ::= expr PLUS expr", /* 202 */ "expr ::= expr MINUS expr", /* 203 */ "expr ::= expr STAR expr", /* 204 */ "expr ::= expr SLASH expr", /* 205 */ "expr ::= expr REM expr", /* 206 */ "expr ::= expr CONCAT expr", /* 207 */ "likeop ::= LIKE", /* 208 */ "likeop ::= GLOB", /* 209 */ "likeop ::= NOT LIKE", /* 210 */ "likeop ::= NOT GLOB", /* 211 */ "escape ::= ESCAPE expr", /* 212 */ "escape ::=", /* 213 */ "expr ::= expr likeop expr escape", /* 214 */ "expr ::= expr ISNULL", /* 215 */ "expr ::= expr IS NULL", /* 216 */ "expr ::= expr NOTNULL", /* 217 */ "expr ::= expr NOT NULL", /* 218 */ "expr ::= expr IS NOT NULL", /* 219 */ "expr ::= NOT expr", /* 220 */ "expr ::= BITNOT expr", /* 221 */ "expr ::= MINUS expr", /* 222 */ "expr ::= PLUS expr", /* 223 */ "between_op ::= BETWEEN", /* 224 */ "between_op ::= NOT BETWEEN", /* 225 */ "expr ::= expr between_op expr AND expr", /* 226 */ "in_op ::= IN", /* 227 */ "in_op ::= NOT IN", /* 228 */ "expr ::= expr in_op LP exprlist RP", /* 229 */ "expr ::= LP select RP", /* 230 */ "expr ::= expr in_op LP select RP", /* 231 */ "expr ::= expr in_op nm dbnm", /* 232 */ "expr ::= EXISTS LP select RP", /* 233 */ "expr ::= CASE case_operand case_exprlist case_else END", /* 234 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", /* 235 */ "case_exprlist ::= WHEN expr THEN expr", /* 236 */ "case_else ::= ELSE expr", /* 237 */ "case_else ::=", /* 238 */ "case_operand ::= expr", /* 239 */ "case_operand ::=", /* 240 */ "exprlist ::= exprlist COMMA expritem", /* 241 */ "exprlist ::= expritem", /* 242 */ "expritem ::= expr", /* 243 */ "expritem ::=", /* 244 */ "cmd ::= CREATE uniqueflag INDEX nm dbnm ON nm LP idxlist RP onconf", /* 245 */ "uniqueflag ::= UNIQUE", /* 246 */ "uniqueflag ::=", /* 247 */ "idxlist_opt ::=", /* 248 */ "idxlist_opt ::= LP idxlist RP", /* 249 */ "idxlist ::= idxlist COMMA idxitem collate sortorder", /* 250 */ "idxlist ::= idxitem collate sortorder", /* 251 */ "idxitem ::= nm", /* 252 */ "cmd ::= DROP INDEX fullname", /* 253 */ "cmd ::= VACUUM", /* 254 */ "cmd ::= VACUUM nm", /* 255 */ "cmd ::= PRAGMA nm dbnm EQ nm", /* 256 */ "cmd ::= PRAGMA nm dbnm EQ ON", /* 257 */ "cmd ::= PRAGMA nm dbnm EQ plus_num", /* 258 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", /* 259 */ "cmd ::= PRAGMA nm dbnm LP nm RP", /* 260 */ "cmd ::= PRAGMA nm dbnm", /* 261 */ "plus_num ::= plus_opt number", /* 262 */ "minus_num ::= MINUS number", /* 263 */ "number ::= INTEGER", /* 264 */ "number ::= FLOAT", /* 265 */ "plus_opt ::= PLUS", /* 266 */ "plus_opt ::=", /* 267 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END", /* 268 */ "trigger_decl ::= temp TRIGGER nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", /* 269 */ "trigger_time ::= BEFORE", /* 270 */ "trigger_time ::= AFTER", /* 271 */ "trigger_time ::= INSTEAD OF", /* 272 */ "trigger_time ::=", /* 273 */ "trigger_event ::= DELETE", /* 274 */ "trigger_event ::= INSERT", /* 275 */ "trigger_event ::= UPDATE", /* 276 */ "trigger_event ::= UPDATE OF inscollist", /* 277 */ "foreach_clause ::=", /* 278 */ "foreach_clause ::= FOR EACH ROW", /* 279 */ "foreach_clause ::= FOR EACH STATEMENT", /* 280 */ "when_clause ::=", /* 281 */ "when_clause ::= WHEN expr", /* 282 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list", /* 283 */ "trigger_cmd_list ::=", /* 284 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", /* 285 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", /* 286 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", /* 287 */ "trigger_cmd ::= DELETE FROM nm where_opt", /* 288 */ "trigger_cmd ::= select", /* 289 */ "expr ::= RAISE LP IGNORE RP", /* 290 */ "expr ::= RAISE LP raisetype COMMA nm RP", /* 291 */ "raisetype ::= ROLLBACK", /* 292 */ "raisetype ::= ABORT", /* 293 */ "raisetype ::= FAIL", /* 294 */ "cmd ::= DROP TRIGGER fullname", /* 295 */ "cmd ::= ATTACH database_kw_opt ids AS nm key_opt", /* 296 */ "key_opt ::=", /* 297 */ "key_opt ::= KEY ids", /* 298 */ "key_opt ::= KEY BLOB", /* 299 */ "database_kw_opt ::= DATABASE", /* 300 */ "database_kw_opt ::=", /* 301 */ "cmd ::= DETACH database_kw_opt nm", /* 302 */ "cmd ::= REINDEX", /* 303 */ "cmd ::= REINDEX nm dbnm", /* 304 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", }; #endif /* NDEBUG */ /* ** This function returns the symbolic name associated with a token ** value. */ |
︙ | ︙ | |||
1203 1204 1205 1206 1207 1208 1209 | ** reduce or during error processing or when a parser is ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those ** which appear on the RHS of the rule, but which are not used ** inside the C code. */ | | | | | | | | | | | | | | < < < < | | | | | < < < < < < < < < < < < < < | < < < < < > > > > > > | > > > > > > > > > > > > > < | > | | | | | | | | | | | | | | | | < < < < < | 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 | ** reduce or during error processing or when a parser is ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those ** which appear on the RHS of the rule, but which are not used ** inside the C code. */ case 157: case 189: case 206: #line 325 "parse.y" {sqlite3SelectDelete((yypminor->yy331));} #line 1315 "parse.c" break; case 170: case 174: case 194: case 196: case 204: case 210: case 224: #line 584 "parse.y" {sqlite3ExprDelete((yypminor->yy454));} #line 1326 "parse.c" break; case 175: case 183: case 192: case 195: case 197: case 199: case 209: case 212: case 213: case 216: case 222: #line 796 "parse.y" {sqlite3ExprListDelete((yypminor->yy266));} #line 1341 "parse.c" break; case 188: case 193: case 201: case 202: #line 454 "parse.y" {sqlite3SrcListDelete((yypminor->yy427));} #line 1349 "parse.c" break; case 198: #line 516 "parse.y" { sqlite3ExprDelete((yypminor->yy348).pLimit); sqlite3ExprDelete((yypminor->yy348).pOffset); } #line 1357 "parse.c" break; case 205: case 208: case 215: #line 472 "parse.y" {sqlite3IdListDelete((yypminor->yy272));} #line 1364 "parse.c" break; case 230: case 235: #line 889 "parse.y" {sqlite3DeleteTriggerStep((yypminor->yy455));} #line 1370 "parse.c" break; case 232: #line 873 "parse.y" {sqlite3IdListDelete((yypminor->yy62).b);} #line 1375 "parse.c" break; default: break; /* If no destructor action specified: do nothing */ } } /* ** Pop the parser's stack once. |
︙ | ︙ | |||
1346 1347 1348 1349 1350 1351 1352 | static int yy_find_shift_action( yyParser *pParser, /* The parser */ int iLookAhead /* The look-ahead token */ ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; | > | > | 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 | static int yy_find_shift_action( yyParser *pParser, /* The parser */ int iLookAhead /* The look-ahead token */ ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */ i = yy_shift_ofst[stateno]; if( i==YY_SHIFT_USE_DFLT ){ return yy_default[stateno]; } if( iLookAhead==YYNOCODE ){ return YY_NO_ACTION; } i += iLookAhead; if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ |
︙ | ︙ | |||
1388 1389 1390 1391 1392 1393 1394 | static int yy_find_reduce_action( int stateno, /* Current state number */ int iLookAhead /* The look-ahead token */ ){ int i; /* int stateno = pParser->yystack[pParser->yyidx].stateno; */ | | | | 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 | static int yy_find_reduce_action( int stateno, /* Current state number */ int iLookAhead /* The look-ahead token */ ){ int i; /* int stateno = pParser->yystack[pParser->yyidx].stateno; */ i = yy_reduce_ofst[stateno]; if( i==YY_REDUCE_USE_DFLT ){ return yy_default[stateno]; } if( iLookAhead==YYNOCODE ){ return YY_NO_ACTION; } i += iLookAhead; if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ |
︙ | ︙ | |||
1451 1452 1453 1454 1455 1456 1457 | /* The following table contains information about every rule that ** is used during the reduce. */ static const struct { YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ unsigned char nrhs; /* Number of right-hand side symbols in the rule */ } yyRuleInfo[] = { | | | | | | | | | | < | | | | | | | | | | | < | < | | < < | | | > < < < < < < < < < < | > > | | > > | | | > > > | > > | > | | | | | | | | | | | | < < < < | < < < < < | | | < < | > > | | | | > > | > > | | | | | < | > > | | | | > > | | | | | | | < < | < < | | | < | | < | | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > | | | > | | | | > > | | > | | > > | | < | | < | | | > > | | | | | | | | | | | | > | | | > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | | | > | | | | | < | < | > > > | | | | | | | | | | | | | < < < | < < < > > > > > > | | | | | | | | | | | | | > | | | | < < < | | | | > | | | | > > > | | | | | | | | | | | | | > | | | | | < < | < < < < | 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 | /* The following table contains information about every rule that ** is used during the reduce. */ static const struct { YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ unsigned char nrhs; /* Number of right-hand side symbols in the rule */ } yyRuleInfo[] = { { 142, 1 }, { 143, 2 }, { 143, 1 }, { 145, 1 }, { 144, 1 }, { 144, 3 }, { 147, 0 }, { 147, 1 }, { 146, 3 }, { 149, 0 }, { 149, 1 }, { 149, 2 }, { 148, 0 }, { 148, 1 }, { 148, 1 }, { 148, 1 }, { 146, 2 }, { 146, 2 }, { 146, 2 }, { 146, 2 }, { 151, 5 }, { 153, 1 }, { 153, 0 }, { 152, 4 }, { 152, 2 }, { 155, 3 }, { 155, 1 }, { 158, 3 }, { 159, 1 }, { 162, 1 }, { 163, 1 }, { 163, 1 }, { 150, 1 }, { 150, 1 }, { 150, 1 }, { 160, 0 }, { 160, 1 }, { 160, 4 }, { 160, 6 }, { 164, 1 }, { 164, 2 }, { 165, 1 }, { 165, 1 }, { 161, 2 }, { 161, 0 }, { 168, 3 }, { 168, 1 }, { 168, 2 }, { 168, 3 }, { 168, 3 }, { 168, 2 }, { 169, 2 }, { 169, 3 }, { 169, 5 }, { 169, 2 }, { 169, 5 }, { 169, 4 }, { 169, 1 }, { 169, 2 }, { 173, 0 }, { 173, 1 }, { 176, 0 }, { 176, 2 }, { 178, 2 }, { 178, 3 }, { 178, 3 }, { 178, 3 }, { 179, 2 }, { 179, 2 }, { 179, 1 }, { 179, 1 }, { 177, 3 }, { 177, 2 }, { 180, 0 }, { 180, 2 }, { 180, 2 }, { 156, 0 }, { 156, 2 }, { 181, 3 }, { 181, 2 }, { 181, 1 }, { 182, 2 }, { 182, 7 }, { 182, 5 }, { 182, 3 }, { 182, 10 }, { 184, 0 }, { 184, 1 }, { 171, 0 }, { 171, 3 }, { 185, 0 }, { 185, 2 }, { 186, 1 }, { 186, 1 }, { 186, 1 }, { 146, 3 }, { 146, 7 }, { 146, 3 }, { 146, 1 }, { 157, 1 }, { 157, 3 }, { 190, 1 }, { 190, 2 }, { 190, 1 }, { 190, 1 }, { 189, 9 }, { 191, 1 }, { 191, 1 }, { 191, 0 }, { 199, 2 }, { 199, 0 }, { 192, 3 }, { 192, 2 }, { 192, 4 }, { 200, 2 }, { 200, 1 }, { 200, 0 }, { 193, 0 }, { 193, 2 }, { 202, 2 }, { 202, 0 }, { 201, 6 }, { 201, 7 }, { 206, 1 }, { 206, 1 }, { 154, 0 }, { 154, 2 }, { 188, 2 }, { 203, 1 }, { 203, 1 }, { 203, 2 }, { 203, 3 }, { 203, 4 }, { 204, 2 }, { 204, 0 }, { 205, 4 }, { 205, 0 }, { 197, 0 }, { 197, 3 }, { 209, 5 }, { 209, 3 }, { 210, 1 }, { 172, 1 }, { 172, 1 }, { 172, 0 }, { 211, 0 }, { 211, 2 }, { 195, 0 }, { 195, 3 }, { 196, 0 }, { 196, 2 }, { 198, 0 }, { 198, 2 }, { 198, 4 }, { 198, 4 }, { 146, 4 }, { 194, 0 }, { 194, 2 }, { 146, 6 }, { 213, 5 }, { 213, 3 }, { 146, 8 }, { 146, 5 }, { 214, 2 }, { 214, 1 }, { 216, 3 }, { 216, 1 }, { 215, 0 }, { 215, 3 }, { 208, 3 }, { 208, 1 }, { 174, 1 }, { 174, 3 }, { 170, 1 }, { 174, 1 }, { 174, 1 }, { 174, 3 }, { 174, 5 }, { 170, 1 }, { 170, 1 }, { 170, 1 }, { 174, 1 }, { 174, 1 }, { 174, 1 }, { 174, 4 }, { 174, 4 }, { 170, 1 }, { 170, 1 }, { 170, 1 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 174, 3 }, { 217, 1 }, { 217, 1 }, { 217, 2 }, { 217, 2 }, { 218, 2 }, { 218, 0 }, { 174, 4 }, { 174, 2 }, { 174, 3 }, { 174, 2 }, { 174, 3 }, { 174, 4 }, { 174, 2 }, { 174, 2 }, { 174, 2 }, { 174, 2 }, { 219, 1 }, { 219, 2 }, { 174, 5 }, { 220, 1 }, { 220, 2 }, { 174, 5 }, { 174, 3 }, { 174, 5 }, { 174, 4 }, { 174, 4 }, { 174, 5 }, { 222, 5 }, { 222, 4 }, { 223, 2 }, { 223, 0 }, { 221, 1 }, { 221, 0 }, { 212, 3 }, { 212, 1 }, { 224, 1 }, { 224, 0 }, { 146, 11 }, { 225, 1 }, { 225, 0 }, { 175, 0 }, { 175, 3 }, { 183, 5 }, { 183, 3 }, { 226, 1 }, { 146, 3 }, { 146, 1 }, { 146, 2 }, { 146, 5 }, { 146, 5 }, { 146, 5 }, { 146, 5 }, { 146, 6 }, { 146, 3 }, { 166, 2 }, { 167, 2 }, { 228, 1 }, { 228, 1 }, { 227, 1 }, { 227, 0 }, { 146, 5 }, { 229, 10 }, { 231, 1 }, { 231, 1 }, { 231, 2 }, { 231, 0 }, { 232, 1 }, { 232, 1 }, { 232, 1 }, { 232, 3 }, { 233, 0 }, { 233, 3 }, { 233, 3 }, { 234, 0 }, { 234, 2 }, { 230, 3 }, { 230, 0 }, { 235, 6 }, { 235, 8 }, { 235, 5 }, { 235, 4 }, { 235, 1 }, { 174, 4 }, { 174, 6 }, { 187, 1 }, { 187, 1 }, { 187, 1 }, { 146, 3 }, { 146, 6 }, { 237, 0 }, { 237, 2 }, { 237, 2 }, { 236, 1 }, { 236, 0 }, { 146, 3 }, { 146, 1 }, { 146, 3 }, { 146, 6 }, }; static void yy_accept(yyParser*); /* Forward Declaration */ /* ** Perform a reduce action and the shift that must immediately ** follow the reduce. |
︙ | ︙ | |||
1795 1796 1797 1798 1799 1800 1801 | ** case 0: ** #line <lineno> <grammarfile> ** { ... } // User supplied code ** #line <lineno> <thisfile> ** break; */ case 3: | | | | | | | | | | | | | | > > > > > | | | < < < < < < < < < | | | | | | | | | > > > > > > > > > > | < | | | | | < | | | | | > > > > > > < < < < < < < < < < < | < < < < < < < | | | | | < | < < | > > < < < < < < < | < | | | | | | | | | > > > > | > > > > | | | | | < | | < < < | | < | < < | | | < | < < | | | | | | | | | | > | | | | < | > | < < < < | > | | | | | > > > > > > > > > > | < | < < | | > > > > > | | < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < < < < < < < | < < < < | < < < < < < | < < | | | | | | < < < < < | | | | | | | | > > | > | > | > > > > > | | | > | > > > > > < | | | < | < > > > | | > | > | < | < < < < < | > | > | | < | < | | | | > > | > > | | | < < | < | > > > > > > | > | > > > > > > > > | | | > > > > > > > > > > > > > > | < | < | | | | | | | < < < < < < < < | | | | < < < | | | | | < < < < < < < < < < < < < < < | | | | | | | | | > | > > > > > > > > > > | | | > > > > > > > > | > > > > | | | < | | | | | | < | < < < < < < < < < < | | < < < < < < < < < < < < < < < < | < | < | > > > > > | | | | | | > > > > > > > > | | | > > > > > > | | | > | | | < < < < | < < < < < < < < | | | | < < < < < | | | < | > > | > | < | > > | > | | | | | | < < | < | | | < < | < | | > > > > | | | | | | | | | | | | | < < < < < | | < < < < < | | | | | | | | | | | | | | | | | | > | | | > | | | < | | | > > > > | | | | > > > > | | | > | | | | < < < < < < < < < < < < < < < < < < | | | | | | | | | | | > > > > > > > > > > > > > > | < < < < < | | < | | | | | | > < < < < < < < < < < | < | < < | < < < < < < < < < > > > > > > > > > | | | | | | | | | | | | | < < < | < < > > > > | < < < | | | | > | > | < < < < < | | < < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | < < < | | < < | > > > > > > | | | | | | | < < < | > > > > > | | | | | | < < < < > | < > > > | | | | | | | | < | | > > > > > | > | | | | < | | < < < < | | | | | > | < | | < | | < | | | | | | < | | < | | | | > | | | | | | | | | | < < | | < < < < < < | | | > > > > > > > > > > | | | | < < | < < < < < < | | | | | | < | | | > > | < < | | < > | > | | < | | | | < < < < | | < | < | | > | | | | | | | | | < | < < | | | < | < < | | < | | | | | > > | > > > | | | > > | > | | | | | | | | < < < < < < | | | | | | | > > | | | | | | | | > | < < | < | | | | | | | | | | | | | | | > | > > | | | | | | | | | | | < < | < < | | | < < | < < | | | | | | | | | | | > | > | | | > | > | | | | | | | | | | | | | | | > | > | | | | | | | | | | | | | | | | | | | | > > > > | < | | | | | | 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 | ** case 0: ** #line <lineno> <grammarfile> ** { ... } // User supplied code ** #line <lineno> <thisfile> ** break; */ case 3: #line 84 "parse.y" { sqlite3FinishCoding(pParse); } #line 1907 "parse.c" break; case 6: #line 87 "parse.y" { sqlite3BeginParse(pParse, 0); } #line 1912 "parse.c" break; case 7: #line 89 "parse.y" { sqlite3BeginParse(pParse, 1); } #line 1917 "parse.c" break; case 8: #line 95 "parse.y" {sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy60);} #line 1922 "parse.c" break; case 12: #line 100 "parse.y" {yygotominor.yy60 = TK_DEFERRED;} #line 1927 "parse.c" break; case 13: case 14: case 15: case 101: case 103: case 104: #line 101 "parse.y" {yygotominor.yy60 = yymsp[0].major;} #line 1937 "parse.c" break; case 16: case 17: #line 104 "parse.y" {sqlite3CommitTransaction(pParse);} #line 1943 "parse.c" break; case 18: #line 106 "parse.y" {sqlite3RollbackTransaction(pParse);} #line 1948 "parse.c" break; case 20: #line 111 "parse.y" { sqlite3StartTable(pParse,&yymsp[-4].minor.yy0,&yymsp[-1].minor.yy406,&yymsp[0].minor.yy406,yymsp[-3].minor.yy60,0); } #line 1955 "parse.c" break; case 21: case 60: case 74: case 106: case 224: case 227: #line 115 "parse.y" {yygotominor.yy60 = 1;} #line 1965 "parse.c" break; case 22: case 59: case 73: case 75: case 86: case 107: case 108: case 223: case 226: #line 116 "parse.y" {yygotominor.yy60 = 0;} #line 1978 "parse.c" break; case 23: #line 117 "parse.y" { sqlite3EndTable(pParse,&yymsp[0].minor.yy0,0); } #line 1985 "parse.c" break; case 24: #line 120 "parse.y" { sqlite3EndTable(pParse,0,yymsp[0].minor.yy331); sqlite3SelectDelete(yymsp[0].minor.yy331); } #line 1993 "parse.c" break; case 28: #line 132 "parse.y" {sqlite3AddColumn(pParse,&yymsp[0].minor.yy406);} #line 1998 "parse.c" break; case 29: case 30: case 31: case 32: case 33: case 34: case 263: case 264: #line 138 "parse.y" {yygotominor.yy406 = yymsp[0].minor.yy0;} #line 2010 "parse.c" break; case 36: #line 193 "parse.y" {sqlite3AddColumnType(pParse,&yymsp[0].minor.yy406,&yymsp[0].minor.yy406);} #line 2015 "parse.c" break; case 37: #line 194 "parse.y" {sqlite3AddColumnType(pParse,&yymsp[-3].minor.yy406,&yymsp[0].minor.yy0);} #line 2020 "parse.c" break; case 38: #line 196 "parse.y" {sqlite3AddColumnType(pParse,&yymsp[-5].minor.yy406,&yymsp[0].minor.yy0);} #line 2025 "parse.c" break; case 39: case 114: case 115: case 126: case 146: case 251: case 261: case 262: #line 198 "parse.y" {yygotominor.yy406 = yymsp[0].minor.yy406;} #line 2037 "parse.c" break; case 40: #line 199 "parse.y" {yygotominor.yy406.z=yymsp[-1].minor.yy406.z; yygotominor.yy406.n=yymsp[0].minor.yy406.n+(yymsp[0].minor.yy406.z-yymsp[-1].minor.yy406.z);} #line 2042 "parse.c" break; case 41: #line 201 "parse.y" { yygotominor.yy60 = atoi(yymsp[0].minor.yy406.z); } #line 2047 "parse.c" break; case 42: #line 202 "parse.y" { yygotominor.yy60 = -atoi(yymsp[0].minor.yy406.z); } #line 2052 "parse.c" break; case 47: case 48: #line 207 "parse.y" {sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454);} #line 2058 "parse.c" break; case 49: #line 209 "parse.y" { Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy454, 0, 0); sqlite3AddDefaultValue(pParse,p); } #line 2066 "parse.c" break; case 50: #line 213 "parse.y" { Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy406); sqlite3AddDefaultValue(pParse,p); } #line 2074 "parse.c" break; case 52: #line 222 "parse.y" {sqlite3AddNotNull(pParse, yymsp[0].minor.yy60);} #line 2079 "parse.c" break; case 53: #line 224 "parse.y" {sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy60,yymsp[0].minor.yy60);} #line 2084 "parse.c" break; case 54: #line 225 "parse.y" {sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy60,0,0);} #line 2089 "parse.c" break; case 56: #line 228 "parse.y" {sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy406,yymsp[-1].minor.yy266,yymsp[0].minor.yy60);} #line 2094 "parse.c" break; case 57: #line 229 "parse.y" {sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy60);} #line 2099 "parse.c" break; case 58: #line 230 "parse.y" {sqlite3AddCollateType(pParse, yymsp[0].minor.yy406.z, yymsp[0].minor.yy406.n);} #line 2104 "parse.c" break; case 61: #line 243 "parse.y" { yygotominor.yy60 = OE_Restrict * 0x010101; } #line 2109 "parse.c" break; case 62: #line 244 "parse.y" { yygotominor.yy60 = (yymsp[-1].minor.yy60 & yymsp[0].minor.yy243.mask) | yymsp[0].minor.yy243.value; } #line 2114 "parse.c" break; case 63: #line 246 "parse.y" { yygotominor.yy243.value = 0; yygotominor.yy243.mask = 0x000000; } #line 2119 "parse.c" break; case 64: #line 247 "parse.y" { yygotominor.yy243.value = yymsp[0].minor.yy60; yygotominor.yy243.mask = 0x0000ff; } #line 2124 "parse.c" break; case 65: #line 248 "parse.y" { yygotominor.yy243.value = yymsp[0].minor.yy60<<8; yygotominor.yy243.mask = 0x00ff00; } #line 2129 "parse.c" break; case 66: #line 249 "parse.y" { yygotominor.yy243.value = yymsp[0].minor.yy60<<16; yygotominor.yy243.mask = 0xff0000; } #line 2134 "parse.c" break; case 67: #line 251 "parse.y" { yygotominor.yy60 = OE_SetNull; } #line 2139 "parse.c" break; case 68: #line 252 "parse.y" { yygotominor.yy60 = OE_SetDflt; } #line 2144 "parse.c" break; case 69: #line 253 "parse.y" { yygotominor.yy60 = OE_Cascade; } #line 2149 "parse.c" break; case 70: #line 254 "parse.y" { yygotominor.yy60 = OE_Restrict; } #line 2154 "parse.c" break; case 71: case 72: case 87: case 89: case 91: case 92: case 163: #line 256 "parse.y" {yygotominor.yy60 = yymsp[0].minor.yy60;} #line 2165 "parse.c" break; case 82: #line 273 "parse.y" {sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy266,yymsp[0].minor.yy60,yymsp[-2].minor.yy60);} #line 2170 "parse.c" break; case 83: #line 275 "parse.y" {sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy266,yymsp[0].minor.yy60,0,0);} #line 2175 "parse.c" break; case 85: #line 278 "parse.y" { sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy266, &yymsp[-3].minor.yy406, yymsp[-2].minor.yy266, yymsp[-1].minor.yy60); sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy60); } #line 2183 "parse.c" break; case 88: case 90: #line 292 "parse.y" {yygotominor.yy60 = OE_Default;} #line 2189 "parse.c" break; case 93: #line 297 "parse.y" {yygotominor.yy60 = OE_Ignore;} #line 2194 "parse.c" break; case 94: case 164: #line 298 "parse.y" {yygotominor.yy60 = OE_Replace;} #line 2200 "parse.c" break; case 95: #line 302 "parse.y" { sqlite3DropTable(pParse, yymsp[0].minor.yy427, 0); } #line 2207 "parse.c" break; case 96: #line 309 "parse.y" { sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy406, &yymsp[-2].minor.yy406, yymsp[0].minor.yy331, yymsp[-5].minor.yy60); } #line 2214 "parse.c" break; case 97: #line 312 "parse.y" { sqlite3DropTable(pParse, yymsp[0].minor.yy427, 1); } #line 2221 "parse.c" break; case 98: #line 319 "parse.y" { sqlite3Select(pParse, yymsp[0].minor.yy331, SRT_Callback, 0, 0, 0, 0, 0); sqlite3SelectDelete(yymsp[0].minor.yy331); } #line 2229 "parse.c" break; case 99: case 123: #line 329 "parse.y" {yygotominor.yy331 = yymsp[0].minor.yy331;} #line 2235 "parse.c" break; case 100: #line 331 "parse.y" { if( yymsp[0].minor.yy331 ){ yymsp[0].minor.yy331->op = yymsp[-1].minor.yy60; yymsp[0].minor.yy331->pPrior = yymsp[-2].minor.yy331; } yygotominor.yy331 = yymsp[0].minor.yy331; } #line 2246 "parse.c" break; case 102: #line 340 "parse.y" {yygotominor.yy60 = TK_ALL;} #line 2251 "parse.c" break; case 105: #line 345 "parse.y" { yygotominor.yy331 = sqlite3SelectNew(yymsp[-6].minor.yy266,yymsp[-5].minor.yy427,yymsp[-4].minor.yy454,yymsp[-3].minor.yy266,yymsp[-2].minor.yy454,yymsp[-1].minor.yy266,yymsp[-7].minor.yy60,yymsp[0].minor.yy348.pLimit,yymsp[0].minor.yy348.pOffset); } #line 2258 "parse.c" break; case 109: case 248: #line 366 "parse.y" {yygotominor.yy266 = yymsp[-1].minor.yy266;} #line 2264 "parse.c" break; case 110: case 137: case 147: case 247: #line 367 "parse.y" {yygotominor.yy266 = 0;} #line 2272 "parse.c" break; case 111: #line 368 "parse.y" { yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-2].minor.yy266,yymsp[-1].minor.yy454,yymsp[0].minor.yy406.n?&yymsp[0].minor.yy406:0); } #line 2279 "parse.c" break; case 112: #line 371 "parse.y" { yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-1].minor.yy266, sqlite3Expr(TK_ALL, 0, 0, 0), 0); } #line 2286 "parse.c" break; case 113: #line 374 "parse.y" { Expr *pRight = sqlite3Expr(TK_ALL, 0, 0, 0); Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy406); yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-3].minor.yy266, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0); } #line 2295 "parse.c" break; case 116: #line 386 "parse.y" {yygotominor.yy406.n = 0;} #line 2300 "parse.c" break; case 117: #line 398 "parse.y" {yygotominor.yy427 = sqliteMalloc(sizeof(*yygotominor.yy427));} #line 2305 "parse.c" break; case 118: #line 399 "parse.y" {yygotominor.yy427 = yymsp[0].minor.yy427;} #line 2310 "parse.c" break; case 119: #line 404 "parse.y" { yygotominor.yy427 = yymsp[-1].minor.yy427; if( yygotominor.yy427 && yygotominor.yy427->nSrc>0 ) yygotominor.yy427->a[yygotominor.yy427->nSrc-1].jointype = yymsp[0].minor.yy60; } #line 2318 "parse.c" break; case 120: #line 408 "parse.y" {yygotominor.yy427 = 0;} #line 2323 "parse.c" break; case 121: #line 409 "parse.y" { yygotominor.yy427 = sqlite3SrcListAppend(yymsp[-5].minor.yy427,&yymsp[-4].minor.yy406,&yymsp[-3].minor.yy406); if( yymsp[-2].minor.yy406.n ) sqlite3SrcListAddAlias(yygotominor.yy427,&yymsp[-2].minor.yy406); if( yymsp[-1].minor.yy454 ){ if( yygotominor.yy427 && yygotominor.yy427->nSrc>1 ){ yygotominor.yy427->a[yygotominor.yy427->nSrc-2].pOn = yymsp[-1].minor.yy454; } else { sqlite3ExprDelete(yymsp[-1].minor.yy454); } } if( yymsp[0].minor.yy272 ){ if( yygotominor.yy427 && yygotominor.yy427->nSrc>1 ){ yygotominor.yy427->a[yygotominor.yy427->nSrc-2].pUsing = yymsp[0].minor.yy272; } else { sqlite3IdListDelete(yymsp[0].minor.yy272); } } } #line 2339 "parse.c" break; case 122: #line 423 "parse.y" { yygotominor.yy427 = sqlite3SrcListAppend(yymsp[-6].minor.yy427,0,0); yygotominor.yy427->a[yygotominor.yy427->nSrc-1].pSelect = yymsp[-4].minor.yy331; if( yymsp[-2].minor.yy406.n ) sqlite3SrcListAddAlias(yygotominor.yy427,&yymsp[-2].minor.yy406); if( yymsp[-1].minor.yy454 ){ if( yygotominor.yy427 && yygotominor.yy427->nSrc>1 ){ yygotominor.yy427->a[yygotominor.yy427->nSrc-2].pOn = yymsp[-1].minor.yy454; } else { sqlite3ExprDelete(yymsp[-1].minor.yy454); } } if( yymsp[0].minor.yy272 ){ if( yygotominor.yy427 && yygotominor.yy427->nSrc>1 ){ yygotominor.yy427->a[yygotominor.yy427->nSrc-2].pUsing = yymsp[0].minor.yy272; } else { sqlite3IdListDelete(yymsp[0].minor.yy272); } } } #line 2356 "parse.c" break; case 124: #line 444 "parse.y" { yygotominor.yy331 = sqlite3SelectNew(0,yymsp[0].minor.yy427,0,0,0,0,0,0,0); } #line 2363 "parse.c" break; case 125: #line 450 "parse.y" {yygotominor.yy406.z=0; yygotominor.yy406.n=0;} #line 2368 "parse.c" break; case 127: #line 455 "parse.y" {yygotominor.yy427 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy406,&yymsp[0].minor.yy406);} #line 2373 "parse.c" break; case 128: case 129: #line 459 "parse.y" { yygotominor.yy60 = JT_INNER; } #line 2379 "parse.c" break; case 130: #line 461 "parse.y" { yygotominor.yy60 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } #line 2384 "parse.c" break; case 131: #line 462 "parse.y" { yygotominor.yy60 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy406,0); } #line 2389 "parse.c" break; case 132: #line 464 "parse.y" { yygotominor.yy60 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy406,&yymsp[-1].minor.yy406); } #line 2394 "parse.c" break; case 133: case 141: case 150: case 157: case 171: case 211: case 236: case 238: case 242: #line 468 "parse.y" {yygotominor.yy454 = yymsp[0].minor.yy454;} #line 2407 "parse.c" break; case 134: case 149: case 156: case 212: case 237: case 239: case 243: #line 469 "parse.y" {yygotominor.yy454 = 0;} #line 2418 "parse.c" break; case 135: case 168: #line 473 "parse.y" {yygotominor.yy272 = yymsp[-1].minor.yy272;} #line 2424 "parse.c" break; case 136: case 167: #line 474 "parse.y" {yygotominor.yy272 = 0;} #line 2430 "parse.c" break; case 138: case 148: #line 485 "parse.y" {yygotominor.yy266 = yymsp[0].minor.yy266;} #line 2436 "parse.c" break; case 139: #line 486 "parse.y" { yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-4].minor.yy266,yymsp[-2].minor.yy454,yymsp[-1].minor.yy406.n>0?&yymsp[-1].minor.yy406:0); if( yygotominor.yy266 ) yygotominor.yy266->a[yygotominor.yy266->nExpr-1].sortOrder = yymsp[0].minor.yy60; } #line 2444 "parse.c" break; case 140: #line 490 "parse.y" { yygotominor.yy266 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy454,yymsp[-1].minor.yy406.n>0?&yymsp[-1].minor.yy406:0); if( yygotominor.yy266 && yygotominor.yy266->a ) yygotominor.yy266->a[0].sortOrder = yymsp[0].minor.yy60; } #line 2452 "parse.c" break; case 142: case 144: #line 499 "parse.y" {yygotominor.yy60 = SQLITE_SO_ASC;} #line 2458 "parse.c" break; case 143: #line 500 "parse.y" {yygotominor.yy60 = SQLITE_SO_DESC;} #line 2463 "parse.c" break; case 145: #line 502 "parse.y" {yygotominor.yy406.z = 0; yygotominor.yy406.n = 0;} #line 2468 "parse.c" break; case 151: #line 520 "parse.y" {yygotominor.yy348.pLimit = 0; yygotominor.yy348.pOffset = 0;} #line 2473 "parse.c" break; case 152: #line 521 "parse.y" {yygotominor.yy348.pLimit = yymsp[0].minor.yy454; yygotominor.yy348.pOffset = 0;} #line 2478 "parse.c" break; case 153: #line 523 "parse.y" {yygotominor.yy348.pLimit = yymsp[-2].minor.yy454; yygotominor.yy348.pOffset = yymsp[0].minor.yy454;} #line 2483 "parse.c" break; case 154: #line 525 "parse.y" {yygotominor.yy348.pOffset = yymsp[-2].minor.yy454; yygotominor.yy348.pLimit = yymsp[0].minor.yy454;} #line 2488 "parse.c" break; case 155: #line 529 "parse.y" {sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy427,yymsp[0].minor.yy454);} #line 2493 "parse.c" break; case 158: #line 543 "parse.y" {sqlite3Update(pParse,yymsp[-3].minor.yy427,yymsp[-1].minor.yy266,yymsp[0].minor.yy454,yymsp[-4].minor.yy60);} #line 2498 "parse.c" break; case 159: #line 546 "parse.y" {yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-4].minor.yy266,yymsp[0].minor.yy454,&yymsp[-2].minor.yy406);} #line 2503 "parse.c" break; case 160: #line 547 "parse.y" {yygotominor.yy266 = sqlite3ExprListAppend(0,yymsp[0].minor.yy454,&yymsp[-2].minor.yy406);} #line 2508 "parse.c" break; case 161: #line 553 "parse.y" {sqlite3Insert(pParse, yymsp[-5].minor.yy427, yymsp[-1].minor.yy266, 0, yymsp[-4].minor.yy272, yymsp[-7].minor.yy60);} #line 2513 "parse.c" break; case 162: #line 555 "parse.y" {sqlite3Insert(pParse, yymsp[-2].minor.yy427, 0, yymsp[0].minor.yy331, yymsp[-1].minor.yy272, yymsp[-4].minor.yy60);} #line 2518 "parse.c" break; case 165: case 240: #line 565 "parse.y" {yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-2].minor.yy266,yymsp[0].minor.yy454,0);} #line 2524 "parse.c" break; case 166: case 241: #line 566 "parse.y" {yygotominor.yy266 = sqlite3ExprListAppend(0,yymsp[0].minor.yy454,0);} #line 2530 "parse.c" break; case 169: #line 575 "parse.y" {yygotominor.yy272 = sqlite3IdListAppend(yymsp[-2].minor.yy272,&yymsp[0].minor.yy406);} #line 2535 "parse.c" break; case 170: #line 576 "parse.y" {yygotominor.yy272 = sqlite3IdListAppend(0,&yymsp[0].minor.yy406);} #line 2540 "parse.c" break; case 172: #line 587 "parse.y" {yygotominor.yy454 = yymsp[-1].minor.yy454; sqlite3ExprSpan(yygotominor.yy454,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } #line 2545 "parse.c" break; case 173: case 178: case 179: case 180: case 181: #line 588 "parse.y" {yygotominor.yy454 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);} #line 2554 "parse.c" break; case 174: case 175: #line 589 "parse.y" {yygotominor.yy454 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);} #line 2560 "parse.c" break; case 176: #line 591 "parse.y" { Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy406); Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy406); yygotominor.yy454 = sqlite3Expr(TK_DOT, temp1, temp2, 0); } #line 2569 "parse.c" break; case 177: #line 596 "parse.y" { Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy406); Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy406); Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy406); Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0); yygotominor.yy454 = sqlite3Expr(TK_DOT, temp1, temp4, 0); } #line 2580 "parse.c" break; case 182: #line 607 "parse.y" {yygotominor.yy454 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);} #line 2585 "parse.c" break; case 183: #line 608 "parse.y" { Token *pToken = &yymsp[0].minor.yy0; Expr *pExpr = yygotominor.yy454 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); sqlite3ExprAssignVarNumber(pParse, pExpr); } #line 2594 "parse.c" break; case 184: #line 613 "parse.y" { yygotominor.yy454 = sqlite3ExprFunction(yymsp[-1].minor.yy266, &yymsp[-3].minor.yy0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } #line 2602 "parse.c" break; case 185: #line 617 "parse.y" { yygotominor.yy454 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } #line 2610 "parse.c" break; case 186: case 187: case 188: #line 621 "parse.y" {yygotominor.yy454 = sqlite3Expr(yymsp[0].major,0,0,0);} #line 2617 "parse.c" break; case 189: case 190: case 191: case 192: case 193: case 194: case 195: case 196: case 197: case 198: case 199: case 200: case 201: case 202: case 203: case 204: case 205: case 206: #line 624 "parse.y" {yygotominor.yy454 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy454, yymsp[0].minor.yy454, 0);} #line 2639 "parse.c" break; case 207: #line 643 "parse.y" {yygotominor.yy258.opcode = TK_LIKE; yygotominor.yy258.not = 0;} #line 2644 "parse.c" break; case 208: #line 644 "parse.y" {yygotominor.yy258.opcode = TK_GLOB; yygotominor.yy258.not = 0;} #line 2649 "parse.c" break; case 209: #line 645 "parse.y" {yygotominor.yy258.opcode = TK_LIKE; yygotominor.yy258.not = 1;} #line 2654 "parse.c" break; case 210: #line 646 "parse.y" {yygotominor.yy258.opcode = TK_GLOB; yygotominor.yy258.not = 1;} #line 2659 "parse.c" break; case 213: #line 650 "parse.y" { ExprList *pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy454, 0); pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy454, 0); if( yymsp[0].minor.yy454 ){ pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy454, 0); } yygotominor.yy454 = sqlite3ExprFunction(pList, 0); if( yygotominor.yy454 ) yygotominor.yy454->op = yymsp[-2].minor.yy258.opcode; if( yymsp[-2].minor.yy258.not ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0); sqlite3ExprSpan(yygotominor.yy454, &yymsp[-3].minor.yy454->span, &yymsp[-1].minor.yy454->span); } #line 2674 "parse.c" break; case 214: #line 662 "parse.y" { yygotominor.yy454 = sqlite3Expr(TK_ISNULL, yymsp[-1].minor.yy454, 0, 0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy454->span,&yymsp[0].minor.yy0); } #line 2682 "parse.c" break; case 215: #line 666 "parse.y" { yygotominor.yy454 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy454, 0, 0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-2].minor.yy454->span,&yymsp[0].minor.yy0); } #line 2690 "parse.c" break; case 216: #line 670 "parse.y" { yygotominor.yy454 = sqlite3Expr(TK_NOTNULL, yymsp[-1].minor.yy454, 0, 0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy454->span,&yymsp[0].minor.yy0); } #line 2698 "parse.c" break; case 217: #line 674 "parse.y" { yygotominor.yy454 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy454, 0, 0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-2].minor.yy454->span,&yymsp[0].minor.yy0); } #line 2706 "parse.c" break; case 218: #line 678 "parse.y" { yygotominor.yy454 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy454, 0, 0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-3].minor.yy454->span,&yymsp[0].minor.yy0); } #line 2714 "parse.c" break; case 219: case 220: #line 682 "parse.y" { yygotominor.yy454 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy454, 0, 0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy454->span); } #line 2723 "parse.c" break; case 221: #line 690 "parse.y" { yygotominor.yy454 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy454, 0, 0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy454->span); } #line 2731 "parse.c" break; case 222: #line 694 "parse.y" { yygotominor.yy454 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy454, 0, 0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy454->span); } #line 2739 "parse.c" break; case 225: #line 701 "parse.y" { ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy454, 0); pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy454, 0); yygotominor.yy454 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy454, 0, 0); if( yygotominor.yy454 ) yygotominor.yy454->pList = pList; if( yymsp[-3].minor.yy60 ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-4].minor.yy454->span,&yymsp[0].minor.yy454->span); } #line 2751 "parse.c" break; case 228: #line 713 "parse.y" { yygotominor.yy454 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy454, 0, 0); if( yygotominor.yy454 ) yygotominor.yy454->pList = yymsp[-1].minor.yy266; if( yymsp[-3].minor.yy60 ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-4].minor.yy454->span,&yymsp[0].minor.yy0); } #line 2761 "parse.c" break; case 229: #line 719 "parse.y" { yygotominor.yy454 = sqlite3Expr(TK_SELECT, 0, 0, 0); if( yygotominor.yy454 ) yygotominor.yy454->pSelect = yymsp[-1].minor.yy331; sqlite3ExprSpan(yygotominor.yy454,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } #line 2770 "parse.c" break; case 230: #line 724 "parse.y" { yygotominor.yy454 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy454, 0, 0); if( yygotominor.yy454 ) yygotominor.yy454->pSelect = yymsp[-1].minor.yy331; if( yymsp[-3].minor.yy60 ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-4].minor.yy454->span,&yymsp[0].minor.yy0); } #line 2780 "parse.c" break; case 231: #line 730 "parse.y" { SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy406,&yymsp[0].minor.yy406); yygotominor.yy454 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy454, 0, 0); if( yygotominor.yy454 ) yygotominor.yy454->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0); if( yymsp[-2].minor.yy60 ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0); sqlite3ExprSpan(yygotominor.yy454,&yymsp[-3].minor.yy454->span,yymsp[0].minor.yy406.z?&yymsp[0].minor.yy406:&yymsp[-1].minor.yy406); } #line 2791 "parse.c" break; case 232: #line 737 "parse.y" { Expr *p = yygotominor.yy454 = sqlite3Expr(TK_EXISTS, 0, 0, 0); if( p ){ p->pSelect = yymsp[-1].minor.yy331; sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } } #line 2802 "parse.c" break; case 233: #line 747 "parse.y" { yygotominor.yy454 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy454, yymsp[-1].minor.yy454, 0); if( yygotominor.yy454 ) yygotominor.yy454->pList = yymsp[-2].minor.yy266; sqlite3ExprSpan(yygotominor.yy454, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); } #line 2811 "parse.c" break; case 234: #line 754 "parse.y" { yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-4].minor.yy266, yymsp[-2].minor.yy454, 0); yygotominor.yy266 = sqlite3ExprListAppend(yygotominor.yy266, yymsp[0].minor.yy454, 0); } #line 2819 "parse.c" break; case 235: #line 758 "parse.y" { yygotominor.yy266 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy454, 0); yygotominor.yy266 = sqlite3ExprListAppend(yygotominor.yy266, yymsp[0].minor.yy454, 0); } #line 2827 "parse.c" break; case 244: #line 783 "parse.y" { if( yymsp[-9].minor.yy60!=OE_None ) yymsp[-9].minor.yy60 = yymsp[0].minor.yy60; if( yymsp[-9].minor.yy60==OE_Default) yymsp[-9].minor.yy60 = OE_Abort; sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy406, &yymsp[-6].minor.yy406, sqlite3SrcListAppend(0,&yymsp[-4].minor.yy406,0),yymsp[-2].minor.yy266,yymsp[-9].minor.yy60, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0); } #line 2836 "parse.c" break; case 245: case 292: #line 790 "parse.y" {yygotominor.yy60 = OE_Abort;} #line 2842 "parse.c" break; case 246: #line 791 "parse.y" {yygotominor.yy60 = OE_None;} #line 2847 "parse.c" break; case 249: #line 801 "parse.y" { Expr *p = 0; if( yymsp[-1].minor.yy406.n>0 ){ p = sqlite3Expr(TK_COLUMN, 0, 0, 0); if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy406.z, yymsp[-1].minor.yy406.n); } yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-4].minor.yy266, p, &yymsp[-2].minor.yy406); } #line 2859 "parse.c" break; case 250: #line 809 "parse.y" { Expr *p = 0; if( yymsp[-1].minor.yy406.n>0 ){ p = sqlite3Expr(TK_COLUMN, 0, 0, 0); if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy406.z, yymsp[-1].minor.yy406.n); } yygotominor.yy266 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy406); } #line 2871 "parse.c" break; case 252: #line 822 "parse.y" {sqlite3DropIndex(pParse, yymsp[0].minor.yy427);} #line 2876 "parse.c" break; case 253: case 254: #line 826 "parse.y" {sqlite3Vacuum(pParse,0);} #line 2882 "parse.c" break; case 255: case 257: #line 832 "parse.y" {sqlite3Pragma(pParse,&yymsp[-3].minor.yy406,&yymsp[-2].minor.yy406,&yymsp[0].minor.yy406,0);} #line 2888 "parse.c" break; case 256: #line 833 "parse.y" {sqlite3Pragma(pParse,&yymsp[-3].minor.yy406,&yymsp[-2].minor.yy406,&yymsp[0].minor.yy0,0);} #line 2893 "parse.c" break; case 258: #line 835 "parse.y" { sqlite3Pragma(pParse,&yymsp[-3].minor.yy406,&yymsp[-2].minor.yy406,&yymsp[0].minor.yy406,1); } #line 2900 "parse.c" break; case 259: #line 838 "parse.y" {sqlite3Pragma(pParse,&yymsp[-4].minor.yy406,&yymsp[-3].minor.yy406,&yymsp[-1].minor.yy406,0);} #line 2905 "parse.c" break; case 260: #line 839 "parse.y" {sqlite3Pragma(pParse,&yymsp[-1].minor.yy406,&yymsp[0].minor.yy406,0,0);} #line 2910 "parse.c" break; case 267: #line 852 "parse.y" { Token all; all.z = yymsp[-3].minor.yy406.z; all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy406.z) + yymsp[0].minor.yy0.n; sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy455, &all); } #line 2920 "parse.c" break; case 268: #line 861 "parse.y" { sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy406, &yymsp[-6].minor.yy406, yymsp[-5].minor.yy60, yymsp[-4].minor.yy62.a, yymsp[-4].minor.yy62.b, yymsp[-2].minor.yy427, yymsp[-1].minor.yy60, yymsp[0].minor.yy454, yymsp[-9].minor.yy60); yygotominor.yy406 = (yymsp[-6].minor.yy406.n==0?yymsp[-7].minor.yy406:yymsp[-6].minor.yy406); } #line 2928 "parse.c" break; case 269: case 272: #line 867 "parse.y" { yygotominor.yy60 = TK_BEFORE; } #line 2934 "parse.c" break; case 270: #line 868 "parse.y" { yygotominor.yy60 = TK_AFTER; } #line 2939 "parse.c" break; case 271: #line 869 "parse.y" { yygotominor.yy60 = TK_INSTEAD;} #line 2944 "parse.c" break; case 273: case 274: case 275: #line 874 "parse.y" {yygotominor.yy62.a = yymsp[0].major; yygotominor.yy62.b = 0;} #line 2951 "parse.c" break; case 276: #line 877 "parse.y" {yygotominor.yy62.a = TK_UPDATE; yygotominor.yy62.b = yymsp[0].minor.yy272;} #line 2956 "parse.c" break; case 277: case 278: #line 880 "parse.y" { yygotominor.yy60 = TK_ROW; } #line 2962 "parse.c" break; case 279: #line 882 "parse.y" { yygotominor.yy60 = TK_STATEMENT; } #line 2967 "parse.c" break; case 280: #line 885 "parse.y" { yygotominor.yy454 = 0; } #line 2972 "parse.c" break; case 281: #line 886 "parse.y" { yygotominor.yy454 = yymsp[0].minor.yy454; } #line 2977 "parse.c" break; case 282: #line 890 "parse.y" { yymsp[-2].minor.yy455->pNext = yymsp[0].minor.yy455; yygotominor.yy455 = yymsp[-2].minor.yy455; } #line 2985 "parse.c" break; case 283: #line 894 "parse.y" { yygotominor.yy455 = 0; } #line 2990 "parse.c" break; case 284: #line 900 "parse.y" { yygotominor.yy455 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy406, yymsp[-1].minor.yy266, yymsp[0].minor.yy454, yymsp[-4].minor.yy60); } #line 2995 "parse.c" break; case 285: #line 905 "parse.y" {yygotominor.yy455 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy406, yymsp[-4].minor.yy272, yymsp[-1].minor.yy266, 0, yymsp[-7].minor.yy60);} #line 3000 "parse.c" break; case 286: #line 908 "parse.y" {yygotominor.yy455 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy406, yymsp[-1].minor.yy272, 0, yymsp[0].minor.yy331, yymsp[-4].minor.yy60);} #line 3005 "parse.c" break; case 287: #line 912 "parse.y" {yygotominor.yy455 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy406, yymsp[0].minor.yy454);} #line 3010 "parse.c" break; case 288: #line 915 "parse.y" {yygotominor.yy455 = sqlite3TriggerSelectStep(yymsp[0].minor.yy331); } #line 3015 "parse.c" break; case 289: #line 918 "parse.y" { yygotominor.yy454 = sqlite3Expr(TK_RAISE, 0, 0, 0); yygotominor.yy454->iColumn = OE_Ignore; sqlite3ExprSpan(yygotominor.yy454, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); } #line 3024 "parse.c" break; case 290: #line 923 "parse.y" { yygotominor.yy454 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy406); yygotominor.yy454->iColumn = yymsp[-3].minor.yy60; sqlite3ExprSpan(yygotominor.yy454, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); } #line 3033 "parse.c" break; case 291: #line 931 "parse.y" {yygotominor.yy60 = OE_Rollback;} #line 3038 "parse.c" break; case 293: #line 933 "parse.y" {yygotominor.yy60 = OE_Fail;} #line 3043 "parse.c" break; case 294: #line 938 "parse.y" { sqlite3DropTrigger(pParse,yymsp[0].minor.yy427); } #line 3050 "parse.c" break; case 295: #line 944 "parse.y" { sqlite3Attach(pParse, &yymsp[-3].minor.yy406, &yymsp[-1].minor.yy406, yymsp[0].minor.yy40.type, &yymsp[0].minor.yy40.key); } #line 3057 "parse.c" break; case 296: #line 948 "parse.y" { yygotominor.yy40.type = 0; } #line 3062 "parse.c" break; case 297: #line 949 "parse.y" { yygotominor.yy40.type=1; yygotominor.yy40.key = yymsp[0].minor.yy406; } #line 3067 "parse.c" break; case 298: #line 950 "parse.y" { yygotominor.yy40.type=2; yygotominor.yy40.key = yymsp[0].minor.yy0; } #line 3072 "parse.c" break; case 301: #line 956 "parse.y" { sqlite3Detach(pParse, &yymsp[0].minor.yy406); } #line 3079 "parse.c" break; case 302: #line 962 "parse.y" {sqlite3Reindex(pParse, 0, 0);} #line 3084 "parse.c" break; case 303: #line 963 "parse.y" {sqlite3Reindex(pParse, &yymsp[-1].minor.yy406, &yymsp[0].minor.yy406);} #line 3089 "parse.c" break; case 304: #line 968 "parse.y" { sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy427,&yymsp[0].minor.yy406); } #line 3096 "parse.c" break; }; yygoto = yyRuleInfo[yyruleno].lhs; yysize = yyRuleInfo[yyruleno].nrhs; yypParser->yyidx -= yysize; yyact = yy_find_reduce_action(yymsp[-yysize].stateno,yygoto); if( yyact < YYNSTATE ){ |
︙ | ︙ | |||
3120 3121 3122 3123 3124 3125 3126 | static void yy_syntax_error( yyParser *yypParser, /* The parser */ int yymajor, /* The major type of the error token */ YYMINORTYPE yyminor /* The minor type of the error token */ ){ sqlite3ParserARG_FETCH; #define TOKEN (yyminor.yy0) | | | | 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 | static void yy_syntax_error( yyParser *yypParser, /* The parser */ int yymajor, /* The major type of the error token */ YYMINORTYPE yyminor /* The minor type of the error token */ ){ sqlite3ParserARG_FETCH; #define TOKEN (yyminor.yy0) #line 23 "parse.y" if( pParse->zErrMsg==0 ){ if( TOKEN.z[0] ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); }else{ sqlite3ErrorMsg(pParse, "incomplete SQL statement"); } } #line 3163 "parse.c" sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } /* ** The following is executed when the parser accepts */ static void yy_accept( |
︙ | ︙ | |||
3185 3186 3187 3188 3189 3190 3191 | int yyendofinput; /* True if we are at the end of input */ int yyerrorhit = 0; /* True if yymajor has invoked an error */ yyParser *yypParser; /* The parser */ /* (re)initialize the parser, if necessary */ yypParser = (yyParser*)yyp; if( yypParser->yyidx<0 ){ | | | 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 | int yyendofinput; /* True if we are at the end of input */ int yyerrorhit = 0; /* True if yymajor has invoked an error */ yyParser *yypParser; /* The parser */ /* (re)initialize the parser, if necessary */ yypParser = (yyParser*)yyp; if( yypParser->yyidx<0 ){ if( yymajor==0 ) return; yypParser->yyidx = 0; yypParser->yyerrcnt = -1; yypParser->yystack[0].stateno = 0; yypParser->yystack[0].major = 0; } yyminorunion.yy0 = yyminor; yyendofinput = (yymajor==0); |
︙ | ︙ |
Changes to SQLite.Interop/src/parse.h.
|
| > > > > > > > > | | < < | | | | | | | | | | < < < | | | | | | | | < | | | | < | | | | | | | > | | | | | | | | | | | | | | | | | | > > | | > | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | > | | | | | < | < < < < < < < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | #define TK_END_OF_FILE 1 #define TK_ILLEGAL 2 #define TK_SPACE 3 #define TK_UNCLOSED_STRING 4 #define TK_COMMENT 5 #define TK_FUNCTION 6 #define TK_COLUMN 7 #define TK_AGG_FUNCTION 8 #define TK_SEMI 9 #define TK_EXPLAIN 10 #define TK_BEGIN 11 #define TK_TRANSACTION 12 #define TK_DEFERRED 13 #define TK_IMMEDIATE 14 #define TK_EXCLUSIVE 15 #define TK_COMMIT 16 #define TK_END 17 #define TK_ROLLBACK 18 #define TK_CREATE 19 #define TK_TABLE 20 #define TK_TEMP 21 #define TK_LP 22 #define TK_RP 23 #define TK_AS 24 #define TK_COMMA 25 #define TK_ID 26 #define TK_ABORT 27 #define TK_AFTER 28 #define TK_ASC 29 #define TK_ATTACH 30 #define TK_BEFORE 31 #define TK_CASCADE 32 #define TK_CONFLICT 33 #define TK_DATABASE 34 #define TK_DESC 35 #define TK_DETACH 36 #define TK_EACH 37 #define TK_FAIL 38 #define TK_FOR 39 #define TK_GLOB 40 #define TK_IGNORE 41 #define TK_INITIALLY 42 #define TK_INSTEAD 43 #define TK_LIKE 44 #define TK_MATCH 45 #define TK_KEY 46 #define TK_OF 47 #define TK_OFFSET 48 #define TK_PRAGMA 49 #define TK_RAISE 50 #define TK_REPLACE 51 #define TK_RESTRICT 52 #define TK_ROW 53 #define TK_STATEMENT 54 #define TK_TRIGGER 55 #define TK_VACUUM 56 #define TK_VIEW 57 #define TK_REINDEX 58 #define TK_RENAME 59 #define TK_CDATE 60 #define TK_CTIME 61 #define TK_CTIMESTAMP 62 #define TK_ALTER 63 #define TK_OR 64 #define TK_AND 65 #define TK_NOT 66 #define TK_IS 67 #define TK_BETWEEN 68 #define TK_IN 69 #define TK_ISNULL 70 #define TK_NOTNULL 71 #define TK_NE 72 #define TK_EQ 73 #define TK_GT 74 #define TK_LE 75 #define TK_LT 76 #define TK_GE 77 #define TK_ESCAPE 78 #define TK_BITAND 79 #define TK_BITOR 80 #define TK_LSHIFT 81 #define TK_RSHIFT 82 #define TK_PLUS 83 #define TK_MINUS 84 #define TK_STAR 85 #define TK_SLASH 86 #define TK_REM 87 #define TK_CONCAT 88 #define TK_UMINUS 89 #define TK_UPLUS 90 #define TK_BITNOT 91 #define TK_STRING 92 #define TK_JOIN_KW 93 #define TK_CONSTRAINT 94 #define TK_DEFAULT 95 #define TK_NULL 96 #define TK_PRIMARY 97 #define TK_UNIQUE 98 #define TK_CHECK 99 #define TK_REFERENCES 100 #define TK_COLLATE 101 #define TK_AUTOINCR 102 #define TK_ON 103 #define TK_DELETE 104 #define TK_UPDATE 105 #define TK_INSERT 106 #define TK_SET 107 #define TK_DEFERRABLE 108 #define TK_FOREIGN 109 #define TK_DROP 110 #define TK_UNION 111 #define TK_ALL 112 #define TK_INTERSECT 113 #define TK_EXCEPT 114 #define TK_SELECT 115 #define TK_DISTINCT 116 #define TK_DOT 117 #define TK_FROM 118 #define TK_JOIN 119 #define TK_USING 120 #define TK_ORDER 121 #define TK_BY 122 #define TK_GROUP 123 #define TK_HAVING 124 #define TK_LIMIT 125 #define TK_WHERE 126 #define TK_INTO 127 #define TK_VALUES 128 #define TK_INTEGER 129 #define TK_FLOAT 130 #define TK_BLOB 131 #define TK_REGISTER 132 #define TK_VARIABLE 133 #define TK_EXISTS 134 #define TK_CASE 135 #define TK_WHEN 136 #define TK_THEN 137 #define TK_ELSE 138 #define TK_INDEX 139 #define TK_TO 140 |
Changes to SQLite.Interop/src/pragma.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2003 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | /* ** 2003 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** ** $Id: pragma.c,v 1.1 2005/03/01 16:04:34 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* Ignore this whole file if pragmas are disabled */ #ifndef SQLITE_OMIT_PRAGMA #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) # include "pager.h" # include "btree.h" #endif /* ** Interpret the given string as a safety level. Return 0 for OFF, ** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or ** unrecognized string argument. ** ** Note that the values returned are one less that the values that ** should be passed into sqlite3BtreeSetSafetyLevel(). The is done ** to support legacy SQL code. The safety level used to be boolean ** and older scripts may have used numbers 0 for OFF and 1 for ON. */ static int getSafetyLevel(const u8 *z){ /* 123456789 123456789 */ static const char zText[] = "onoffalseyestruefull"; static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4}; static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2}; int i, n; if( isdigit(*z) ){ |
︙ | ︙ | |||
54 55 56 57 58 59 60 | } return 1; } /* ** Interpret the given string as a boolean value. */ | | < < < < | < < < < < < < < < | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | } return 1; } /* ** Interpret the given string as a boolean value. */ static int getBoolean(const u8 *z){ return getSafetyLevel(z)&1; } #ifndef SQLITE_OMIT_PAGER_PRAGMAS /* ** Interpret the given string as a temp db location. Return 1 for file ** backed temporary databases, 2 for the Red-Black tree in memory database ** and 0 to use the compile-time default. */ static int getTempStore(const char *z){ if( z[0]>='0' && z[0]<='2' ){ return z[0] - '0'; }else if( sqlite3StrICmp(z, "file")==0 ){ return 1; }else if( sqlite3StrICmp(z, "memory")==0 ){ return 2; }else{ return 0; } } /* ** Invalidate temp storage, either when the temp storage is changed ** from default, or when 'file' and the temp_store_directory has changed */ static int invalidateTempStorage(Parse *pParse){ sqlite3 *db = pParse->db; if( db->aDb[1].pBt!=0 ){ if( db->flags & SQLITE_InTrans ){ sqlite3ErrorMsg(pParse, "temporary storage cannot be changed " "from within a transaction"); return SQLITE_ERROR; } sqlite3BtreeClose(db->aDb[1].pBt); db->aDb[1].pBt = 0; sqlite3ResetInternalSchema(db, 0); } return SQLITE_OK; } /* ** If the TEMP database is open, close it and mark the database schema ** as needing reloading. This must be done when using the TEMP_STORE ** or DEFAULT_TEMP_STORE pragmas. */ static int changeTempStorage(Parse *pParse, const char *zStorageType){ int ts = getTempStore(zStorageType); sqlite3 *db = pParse->db; if( db->temp_store==ts ) return SQLITE_OK; if( invalidateTempStorage( pParse ) != SQLITE_OK ){ return SQLITE_ERROR; } db->temp_store = ts; return SQLITE_OK; } #endif /* ** Generate code to return a single integer value. */ static void returnSingleInt(Parse *pParse, const char *zLabel, int value){ Vdbe *v = sqlite3GetVdbe(pParse); sqlite3VdbeAddOp(v, OP_Integer, value, 0); if( pParse->explain==0 ){ sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, zLabel, P3_STATIC); } sqlite3VdbeAddOp(v, OP_Callback, 1, 0); } /* ** Check to see if zRight and zLeft refer to a pragma that queries ** or changes one of the flags in db->flags. Return 1 if so and 0 if not. ** Also, implement the pragma. */ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ static const struct sPragmaType { const char *zName; /* Name of the pragma */ int mask; /* Mask for the db->flags value */ } aPragma[] = { { "vdbe_trace", SQLITE_VdbeTrace }, { "sql_trace", SQLITE_SqlTrace }, { "vdbe_listing", SQLITE_VdbeListing }, { "full_column_names", SQLITE_FullColNames }, { "short_column_names", SQLITE_ShortColNames }, { "count_changes", SQLITE_CountRows }, { "empty_result_callbacks", SQLITE_NullCallback }, /* The following is VERY experimental */ { "writable_schema", SQLITE_WriteSchema }, { "omit_readlock", SQLITE_NoReadlock }, }; int i; const struct sPragmaType *p; for(i=0, p=aPragma; i<sizeof(aPragma)/sizeof(aPragma[0]); i++, p++){ if( sqlite3StrICmp(zLeft, p->zName)==0 ){ sqlite3 *db = pParse->db; Vdbe *v; |
︙ | ︙ | |||
186 187 188 189 190 191 192 | sqlite3VdbeAddOp(v, OP_Expire, 0, 0); } return 1; } } return 0; } | < | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | sqlite3VdbeAddOp(v, OP_Expire, 0, 0); } return 1; } } return 0; } /* ** Process a pragma statement. ** ** Pragmas are of this form: ** ** PRAGMA [database.]id [= value] |
︙ | ︙ | |||
284 285 286 287 288 289 290 | sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3VdbeAddOp(v, OP_Integer, size, 0); sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 2); addr = sqlite3VdbeAddOp(v, OP_Integer, 0, 0); sqlite3VdbeAddOp(v, OP_Ge, 0, addr+3); sqlite3VdbeAddOp(v, OP_Negative, 0, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 2); | | | | 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3VdbeAddOp(v, OP_Integer, size, 0); sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 2); addr = sqlite3VdbeAddOp(v, OP_Integer, 0, 0); sqlite3VdbeAddOp(v, OP_Ge, 0, addr+3); sqlite3VdbeAddOp(v, OP_Negative, 0, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 2); pDb->cache_size = size; sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size); } }else /* ** PRAGMA [database.]page_size ** PRAGMA [database.]page_size=N ** |
︙ | ︙ | |||
346 347 348 349 350 351 352 | ** cache size stored on the disk so the cache size will revert ** to its default value when the database is closed and reopened. ** N should be a positive integer. */ if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ if( sqlite3ReadSchema(pParse) ) goto pragma_out; if( !zRight ){ | | | | | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | ** cache size stored on the disk so the cache size will revert ** to its default value when the database is closed and reopened. ** N should be a positive integer. */ if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ if( sqlite3ReadSchema(pParse) ) goto pragma_out; if( !zRight ){ returnSingleInt(pParse, "cache_size", pDb->cache_size); }else{ int size = atoi(zRight); if( size<0 ) size = -size; pDb->cache_size = size; sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size); } }else /* ** PRAGMA temp_store ** PRAGMA temp_store = "default"|"memory"|"file" ** |
︙ | ︙ | |||
438 439 440 441 442 443 444 | pDb->safety_level = getSafetyLevel(zRight)+1; sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level); } } }else #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ | < < | 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | pDb->safety_level = getSafetyLevel(zRight)+1; sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level); } } }else #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ if( flagPragma(pParse, zLeft, zRight) ){ /* The flagPragma() subroutine also generates any necessary code ** there is nothing more to do here */ }else #ifndef SQLITE_OMIT_SCHEMA_PRAGMAS /* ** PRAGMA table_info(<table>) ** ** Return a single row for each column of the named table. The columns of ** the returned data set are: |
︙ | ︙ | |||
587 588 589 590 591 592 593 | sqlite3VdbeSetColName(v, 1, "seq", P3_STATIC); sqlite3VdbeSetColName(v, 2, "table", P3_STATIC); sqlite3VdbeSetColName(v, 3, "from", P3_STATIC); sqlite3VdbeSetColName(v, 4, "to", P3_STATIC); while(pFK){ int j; for(j=0; j<pFK->nCol; j++){ | < | < | | | | < < < < < < < < < < > > > > > > > > | < < < < | > | < | > | | | | | | > | | | | | | | | | | | | | | | 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 | sqlite3VdbeSetColName(v, 1, "seq", P3_STATIC); sqlite3VdbeSetColName(v, 2, "table", P3_STATIC); sqlite3VdbeSetColName(v, 3, "from", P3_STATIC); sqlite3VdbeSetColName(v, 4, "to", P3_STATIC); while(pFK){ int j; for(j=0; j<pFK->nCol; j++){ sqlite3VdbeAddOp(v, OP_Integer, i, 0); sqlite3VdbeAddOp(v, OP_Integer, j, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, pFK->zTo, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[pFK->aCol[j].iFrom].zName, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, pFK->aCol[j].zCol, 0); sqlite3VdbeAddOp(v, OP_Callback, 5, 0); } ++i; pFK = pFK->pNextFrom; } } } }else #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ #ifndef NDEBUG if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ extern void sqlite3ParserTrace(FILE*, char *); if( getBoolean(zRight) ){ sqlite3ParserTrace(stdout, "parser: "); }else{ sqlite3ParserTrace(0, 0); } }else #endif #ifndef SQLITE_OMIT_INTEGRITY_CHECK if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){ int i, j, addr; /* Code that initializes the integrity check program. Set the ** error count 0 */ static const VdbeOpList initCode[] = { { OP_Integer, 0, 0, 0}, { OP_MemStore, 0, 1, 0}, }; /* Code that appears at the end of the integrity check. If no error ** messages have been generated, output OK. Otherwise output the ** error message */ static const VdbeOpList endCode[] = { { OP_MemLoad, 0, 0, 0}, { OP_Integer, 0, 0, 0}, { OP_Ne, 0, 0, 0}, /* 2 */ { OP_String8, 0, 0, "ok"}, { OP_Callback, 1, 0, 0}, }; /* Initialize the VDBE program */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, "integrity_check", P3_STATIC); sqlite3VdbeAddOpList(v, ArraySize(initCode), initCode); /* Do an integrity check on each database file */ for(i=0; i<db->nDb; i++){ HashElem *x; int cnt = 0; sqlite3CodeVerifySchema(pParse, i); /* Do an integrity check of the B-Tree */ for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; sqlite3VdbeAddOp(v, OP_Integer, pTab->tnum, 0); cnt++; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( sqlite3CheckIndexCollSeq(pParse, pIdx) ) goto pragma_out; sqlite3VdbeAddOp(v, OP_Integer, pIdx->tnum, 0); cnt++; } } assert( cnt>0 ); sqlite3VdbeAddOp(v, OP_IntegrityCk, cnt, i); sqlite3VdbeAddOp(v, OP_Dup, 0, 1); addr = sqlite3VdbeOp3(v, OP_String8, 0, 0, "ok", P3_STATIC); sqlite3VdbeAddOp(v, OP_Eq, 0, addr+6); sqlite3VdbeOp3(v, OP_String8, 0, 0, sqlite3MPrintf("*** in database %s ***\n", db->aDb[i].zName), P3_DYNAMIC); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); sqlite3VdbeAddOp(v, OP_Concat, 0, 1); sqlite3VdbeAddOp(v, OP_Callback, 1, 0); /* Make sure all the indices are constructed correctly. */ sqlite3CodeVerifySchema(pParse, i); for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; int loopTop; if( pTab->pIndex==0 ) continue; sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); sqlite3VdbeAddOp(v, OP_Integer, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, 1, 1); loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0); sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int jmp2; static const VdbeOpList idxErr[] = { { OP_MemIncr, 0, 0, 0}, { OP_String8, 0, 0, "rowid "}, { OP_Recno, 1, 0, 0}, { OP_String8, 0, 0, " missing from index "}, { OP_String8, 0, 0, 0}, /* 4 */ { OP_Concat, 2, 0, 0}, { OP_Callback, 1, 0, 0}, }; sqlite3GenerateIndexKey(v, pIdx, 1); jmp2 = sqlite3VdbeAddOp(v, OP_Found, j+2, 0); addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr); sqlite3VdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC); sqlite3VdbeChangeP2(v, jmp2, sqlite3VdbeCurrentAddr(v)); } sqlite3VdbeAddOp(v, OP_Next, 1, loopTop+1); sqlite3VdbeChangeP2(v, loopTop, sqlite3VdbeCurrentAddr(v)); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ static const VdbeOpList cntIdx[] = { { OP_Integer, 0, 0, 0}, { OP_MemStore, 2, 1, 0}, { OP_Rewind, 0, 0, 0}, /* 2 */ { OP_MemIncr, 2, 0, 0}, { OP_Next, 0, 0, 0}, /* 4 */ { OP_MemLoad, 1, 0, 0}, { OP_MemLoad, 2, 0, 0}, { OP_Eq, 0, 0, 0}, /* 7 */ { OP_MemIncr, 0, 0, 0}, { OP_String8, 0, 0, "wrong # of entries in index "}, { OP_String8, 0, 0, 0}, /* 10 */ { OP_Concat, 0, 0, 0}, { OP_Callback, 1, 0, 0}, }; if( pIdx->tnum==0 ) continue; addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx); sqlite3VdbeChangeP1(v, addr+2, j+2); sqlite3VdbeChangeP2(v, addr+2, addr+5); sqlite3VdbeChangeP1(v, addr+4, j+2); sqlite3VdbeChangeP2(v, addr+4, addr+3); sqlite3VdbeChangeP2(v, addr+7, addr+ArraySize(cntIdx)); sqlite3VdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC); } } } addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode); sqlite3VdbeChangeP2(v, addr+2, addr+ArraySize(endCode)); }else #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ #ifndef SQLITE_OMIT_UTF16 /* ** PRAGMA encoding ** PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be" |
︙ | ︙ | |||
793 794 795 796 797 798 799 | encnames[6].enc = encnames[7].enc = SQLITE_UTF16NATIVE; if( !zRight ){ /* "PRAGMA encoding" */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, "encoding", P3_STATIC); sqlite3VdbeAddOp(v, OP_String8, 0, 0); for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ | | | < < < | | 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 | encnames[6].enc = encnames[7].enc = SQLITE_UTF16NATIVE; if( !zRight ){ /* "PRAGMA encoding" */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, "encoding", P3_STATIC); sqlite3VdbeAddOp(v, OP_String8, 0, 0); for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ if( pEnc->enc==pParse->db->enc ){ sqlite3VdbeChangeP3(v, -1, pEnc->zName, P3_STATIC); break; } } sqlite3VdbeAddOp(v, OP_Callback, 1, 0); }else{ /* "PRAGMA encoding = XXX" */ /* Only change the value of sqlite.enc if the database handle is not ** initialized. If the main database exists, the new sqlite.enc value ** will be overwritten when the schema is next loaded. If it does not ** already exists, it will be created to use the new encoding value. */ if( !(pParse->db->flags&SQLITE_Initialized) ){ for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ pParse->db->enc = pEnc->enc; break; } } if( !pEnc->zName ){ sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); } } |
︙ | ︙ | |||
902 903 904 905 906 907 908 | sqlite3VdbeSetNumCols(v, 2); sqlite3VdbeSetColName(v, 0, "database", P3_STATIC); sqlite3VdbeSetColName(v, 1, "status", P3_STATIC); for(i=0; i<db->nDb; i++){ Btree *pBt; Pager *pPager; if( db->aDb[i].zName==0 ) continue; | | | | < < < < < < < < < < < < < < < < < | | 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | sqlite3VdbeSetNumCols(v, 2); sqlite3VdbeSetColName(v, 0, "database", P3_STATIC); sqlite3VdbeSetColName(v, 1, "status", P3_STATIC); for(i=0; i<db->nDb; i++){ Btree *pBt; Pager *pPager; if( db->aDb[i].zName==0 ) continue; sqlite3VdbeOp3(v, OP_String, 0, 0, db->aDb[i].zName, P3_STATIC); pBt = db->aDb[i].pBt; if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){ sqlite3VdbeOp3(v, OP_String, 0, 0, "closed", P3_STATIC); }else{ int j = sqlite3pager_lockstate(pPager); sqlite3VdbeOp3(v, OP_String, 0, 0, (j>=0 && j<=4) ? azLockName[j] : "unknown", P3_STATIC); } sqlite3VdbeAddOp(v, OP_Callback, 2, 0); } }else #endif {} if( v ){ /* Code an OP_Expire at the end of each PRAGMA program to cause ** the VDBE implementing the pragma to expire. Most (all?) pragmas ** are only valid for a single execution. */ sqlite3VdbeAddOp(v, OP_Expire, 1, 0); } pragma_out: sqliteFree(zLeft); sqliteFree(zRight); } #endif /* SQLITE_OMIT_PRAGMA */ |
Deleted SQLite.Interop/src/prepare.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to SQLite.Interop/src/printf.c.
︙ | ︙ | |||
107 108 109 110 111 112 113 | ** most frequently used conversion types first. */ static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; static const char aPrefix[] = "-x0\000X0"; static const et_info fmtinfo[] = { { 'd', 10, 1, etRADIX, 0, 0 }, { 's', 0, 4, etSTRING, 0, 0 }, | < < > < | | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | ** most frequently used conversion types first. */ static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; static const char aPrefix[] = "-x0\000X0"; static const et_info fmtinfo[] = { { 'd', 10, 1, etRADIX, 0, 0 }, { 's', 0, 4, etSTRING, 0, 0 }, { 'z', 0, 6, etDYNSTRING, 0, 0 }, { 'q', 0, 4, etSQLESCAPE, 0, 0 }, { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, { 'c', 0, 0, etCHARX, 0, 0 }, { 'o', 8, 0, etRADIX, 0, 2 }, { 'u', 10, 0, etRADIX, 0, 0 }, { 'x', 16, 0, etRADIX, 16, 1 }, { 'X', 16, 0, etRADIX, 0, 4 }, { 'f', 0, 1, etFLOAT, 0, 0 }, { 'e', 0, 1, etEXP, 30, 0 }, { 'E', 0, 1, etEXP, 14, 0 }, { 'g', 0, 1, etGENERIC, 30, 0 }, { 'G', 0, 1, etGENERIC, 14, 0 }, { 'i', 10, 1, etRADIX, 0, 0 }, { 'n', 0, 0, etSIZE, 0, 0 }, { '%', 0, 0, etPERCENT, 0, 0 }, { 'p', 16, 0, etPOINTER, 0, 1 }, { 'T', 0, 2, etTOKEN, 0, 0 }, { 'S', 0, 2, etSRCLIST, 0, 0 }, }; #define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0])) /* ** If NOFLOATINGPOINT is defined, then none of the floating point ** conversions will work. */ #ifndef etNOFLOATINGPOINT /* ** "*val" is a double such that 0.1 <= *val < 10.0 ** Return the ascii code for the leading digit of *val, then ** multiply "*val" by 10.0 to renormalize. ** ** Example: ** input: *val = 3.14159 |
︙ | ︙ | |||
159 160 161 162 163 164 165 | if( (*cnt)++ >= 16 ) return '0'; digit = (int)*val; d = digit; digit += '0'; *val = (*val - d)*10.0; return digit; } | | < < < < < < < < | | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | if( (*cnt)++ >= 16 ) return '0'; digit = (int)*val; d = digit; digit += '0'; *val = (*val - d)*10.0; return digit; } #endif #define etBUFSIZE 1000 /* Size of the output buffer */ /* ** The root program. All variations call this core. ** ** INPUTS: ** func This is a pointer to a function taking three arguments ** 1. A pointer to anything. Same as the "arg" parameter. |
︙ | ︙ | |||
216 217 218 219 220 221 222 | int idx; /* A general purpose loop counter */ int count; /* Total number of characters output */ int width; /* Width of the current field */ etByte flag_leftjustify; /* True if "-" flag is present */ etByte flag_plussign; /* True if "+" flag is present */ etByte flag_blanksign; /* True if " " flag is present */ etByte flag_alternateform; /* True if "#" flag is present */ | < < | | | 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | int idx; /* A general purpose loop counter */ int count; /* Total number of characters output */ int width; /* Width of the current field */ etByte flag_leftjustify; /* True if "-" flag is present */ etByte flag_plussign; /* True if "+" flag is present */ etByte flag_blanksign; /* True if " " flag is present */ etByte flag_alternateform; /* True if "#" flag is present */ etByte flag_zeropad; /* True if field width constant starts with zero */ etByte flag_long; /* True if "l" flag is present */ etByte flag_longlong; /* True if the "ll" flag is present */ UINT64_TYPE longvalue; /* Value for integer types */ LONGDOUBLE_TYPE realvalue; /* Value for real types */ const et_info *infop; /* Pointer to the appropriate info structure */ char buf[etBUFSIZE]; /* Conversion buffer */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ etByte errorflag = 0; /* True if an error is encountered */ etByte xtype; /* Conversion paradigm */ char *zExtra; /* Extra memory used for etTCLESCAPE conversions */ static const char spaces[] = " "; #define etSPACESIZE (sizeof(spaces)-1) #ifndef etNOFLOATINGPOINT int exp; /* exponent of real numbers */ double rounder; /* Used for rounding floating point values */ etByte flag_dp; /* True if decimal point should be shown */ etByte flag_rtz; /* True if trailing zeros should be removed */ etByte flag_exp; /* True to force display of the exponent */ int nsd; /* Number of significant digits returned */ #endif |
︙ | ︙ | |||
262 263 264 265 266 267 268 | errorflag = 1; (*func)(arg,"%",1); count++; break; } /* Find out what flags are present */ flag_leftjustify = flag_plussign = flag_blanksign = | | < | | | | < | | | | 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | errorflag = 1; (*func)(arg,"%",1); count++; break; } /* Find out what flags are present */ flag_leftjustify = flag_plussign = flag_blanksign = flag_alternateform = flag_zeropad = 0; do{ switch( c ){ case '-': flag_leftjustify = 1; c = 0; break; case '+': flag_plussign = 1; c = 0; break; case ' ': flag_blanksign = 1; c = 0; break; case '#': flag_alternateform = 1; c = 0; break; case '0': flag_zeropad = 1; c = 0; break; default: break; } }while( c==0 && (c=(*++fmt))!=0 ); /* Get the field width */ width = 0; if( c=='*' ){ width = va_arg(ap,int); if( width<0 ){ flag_leftjustify = 1; width = -width; |
︙ | ︙ | |||
346 347 348 349 350 351 352 | precision = etBUFSIZE-40; } /* ** At this point, variables are initialized as follows: ** ** flag_alternateform TRUE if a '#' is present. | < | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | precision = etBUFSIZE-40; } /* ** At this point, variables are initialized as follows: ** ** flag_alternateform TRUE if a '#' is present. ** flag_plussign TRUE if a '+' is present. ** flag_leftjustify TRUE if a '-' is present or if the ** field width was negative. ** flag_zeropad TRUE if the width began with 0. ** flag_long TRUE if the letter 'l' (ell) prefixed ** the conversion character. ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed |
︙ | ︙ | |||
423 424 425 426 427 428 429 | } length = &buf[etBUFSIZE-1]-bufpt; break; case etFLOAT: case etEXP: case etGENERIC: realvalue = va_arg(ap,double); | | | | > | < | 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 | } length = &buf[etBUFSIZE-1]-bufpt; break; case etFLOAT: case etEXP: case etGENERIC: realvalue = va_arg(ap,double); #ifndef etNOFLOATINGPOINT if( precision<0 ) precision = 6; /* Set default precision */ if( precision>etBUFSIZE-10 ) precision = etBUFSIZE-10; if( realvalue<0.0 ){ realvalue = -realvalue; prefix = '-'; }else{ if( flag_plussign ) prefix = '+'; else if( flag_blanksign ) prefix = ' '; else prefix = 0; } if( infop->type==etGENERIC && precision>0 ) precision--; rounder = 0.0; #if 0 /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */ for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1); #else /* It makes more sense to use 0.5 */ for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1); #endif if( infop->type==etFLOAT ) realvalue += rounder; /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ exp = 0; if( realvalue>0.0 ){ while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; } while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; } while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; } while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; } if( exp>350 || exp<-350 ){ bufpt = "NaN"; length = 3; |
︙ | ︙ | |||
478 479 480 481 482 483 484 | }else{ precision = precision - exp; xtype = etFLOAT; } }else{ flag_rtz = 0; } | > | < | < < > > | < | < < < < | < < | < < | < < < < < | | | < | > > > | | < > > > > > > > > | | < | < < < < | < < < > | | < | < | < | | | | | | | < | | 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 | }else{ precision = precision - exp; xtype = etFLOAT; } }else{ flag_rtz = 0; } /* ** The "exp+precision" test causes output to be of type etEXP if ** the precision is too large to fit in buf[]. */ nsd = 0; if( xtype==etFLOAT && exp+precision<etBUFSIZE-30 ){ flag_dp = (precision>0 || flag_alternateform); if( prefix ) *(bufpt++) = prefix; /* Sign */ if( exp<0 ) *(bufpt++) = '0'; /* Digits before "." */ else for(; exp>=0; exp--) *(bufpt++) = et_getdigit(&realvalue,&nsd); if( flag_dp ) *(bufpt++) = '.'; /* The decimal point */ for(exp++; exp<0 && precision>0; precision--, exp++){ *(bufpt++) = '0'; } while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd); *(bufpt--) = 0; /* Null terminate */ if( flag_rtz && flag_dp ){ /* Remove trailing zeros and "." */ while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0; if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0; } bufpt++; /* point to next free slot */ }else{ /* etEXP or etGENERIC */ flag_dp = (precision>0 || flag_alternateform); if( prefix ) *(bufpt++) = prefix; /* Sign */ *(bufpt++) = et_getdigit(&realvalue,&nsd); /* First digit */ if( flag_dp ) *(bufpt++) = '.'; /* Decimal point */ while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd); bufpt--; /* point to last digit */ if( flag_rtz && flag_dp ){ /* Remove tail zeros */ while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0; if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0; } bufpt++; /* point to next free slot */ if( exp || flag_exp ){ *(bufpt++) = aDigits[infop->charset]; if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */ else { *(bufpt++) = '+'; } if( exp>=100 ){ *(bufpt++) = (exp/100)+'0'; /* 100's digit */ exp %= 100; } *(bufpt++) = exp/10+'0'; /* 10's digit */ *(bufpt++) = exp%10+'0'; /* 1's digit */ } } /* The converted number is in buf[] and zero terminated. Output it. ** Note that the number is in the usual order, not reversed as with ** integer conversions. */ length = bufpt-buf; bufpt = buf; /* Special case: Add leading zeros if the flag_zeropad flag is |
︙ | ︙ | |||
591 592 593 594 595 596 597 | }else if( xtype==etDYNSTRING ){ zExtra = bufpt; } length = strlen(bufpt); if( precision>=0 && precision<length ) length = precision; break; case etSQLESCAPE: | | > | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 | }else if( xtype==etDYNSTRING ){ zExtra = bufpt; } length = strlen(bufpt); if( precision>=0 && precision<length ) length = precision; break; case etSQLESCAPE: case etSQLESCAPE2: { int i, j, n, c, isnull; int needQuote; char *arg = va_arg(ap,char*); isnull = arg==0; if( isnull ) arg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); for(i=n=0; (c=arg[i])!=0; i++){ if( c=='\'' ) n++; } needQuote = !isnull && xtype==etSQLESCAPE2; n += i + 1 + needQuote*2; if( n>etBUFSIZE ){ bufpt = zExtra = sqliteMalloc( n ); if( bufpt==0 ) return -1; }else{ bufpt = buf; } j = 0; if( needQuote ) bufpt[j++] = '\''; for(i=0; (c=arg[i])!=0; i++){ bufpt[j++] = c; if( c=='\'' ) bufpt[j++] = c; } if( needQuote ) bufpt[j++] = '\''; bufpt[j] = 0; length = j; if( precision>=0 && precision<length ) length = precision; } break; case etTOKEN: { Token *pToken = va_arg(ap, Token*); if( pToken && pToken->z ){ (*func)(arg, pToken->z, pToken->n); } length = width = 0; break; } case etSRCLIST: { SrcList *pSrc = va_arg(ap, SrcList*); int k = va_arg(ap, int); |
︙ | ︙ | |||
724 725 726 727 728 729 730 | pM->nAlloc = pM->nChar + nNewChar*2 + 1; if( pM->zText==pM->zBase ){ pM->zText = pM->xRealloc(0, pM->nAlloc); if( pM->zText && pM->nChar ){ memcpy(pM->zText, pM->zBase, pM->nChar); } }else{ | < | < < < | 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 | pM->nAlloc = pM->nChar + nNewChar*2 + 1; if( pM->zText==pM->zBase ){ pM->zText = pM->xRealloc(0, pM->nAlloc); if( pM->zText && pM->nChar ){ memcpy(pM->zText, pM->zBase, pM->nChar); } }else{ pM->zText = pM->xRealloc(pM->zText, pM->nAlloc); } } } if( pM->zText ){ if( nNewChar>0 ){ memcpy(&pM->zText[pM->nChar], zNewText, nNewChar); pM->nChar += nNewChar; |
︙ | ︙ | |||
766 767 768 769 770 771 772 | if( xRealloc ){ if( sM.zText==sM.zBase ){ sM.zText = xRealloc(0, sM.nChar+1); if( sM.zText ){ memcpy(sM.zText, sM.zBase, sM.nChar+1); } }else if( sM.nAlloc>sM.nChar+10 ){ | | < < < | | | 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 | if( xRealloc ){ if( sM.zText==sM.zBase ){ sM.zText = xRealloc(0, sM.nChar+1); if( sM.zText ){ memcpy(sM.zText, sM.zBase, sM.nChar+1); } }else if( sM.nAlloc>sM.nChar+10 ){ sM.zText = xRealloc(sM.zText, sM.nChar+1); } } return sM.zText; } /* ** Realloc that is a real function, not a macro. */ static void *printf_realloc(void *old, int size){ return sqliteRealloc(old,size); } /* ** Print into memory obtained from sqliteMalloc(). Use the internal ** %-conversion extensions. */ char *sqlite3VMPrintf(const char *zFormat, va_list ap){ char zBase[1000]; return base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap); } /* ** Print into memory obtained from sqliteMalloc(). Use the internal ** %-conversion extensions. */ char *sqlite3MPrintf(const char *zFormat, ...){ va_list ap; char *z; char zBase[1000]; va_start(ap, zFormat); z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap); va_end(ap); return z; } /* |
︙ | ︙ |
Changes to SQLite.Interop/src/random.c.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** This file contains code to implement a pseudo-random number ** generator (PRNG) for SQLite. ** ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** | | | < < < | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | ************************************************************************* ** This file contains code to implement a pseudo-random number ** generator (PRNG) for SQLite. ** ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** ** $Id: random.c,v 1.1 2005/03/01 16:04:34 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" /* ** Get a single 8-bit random value from the RC4 PRNG. The Mutex ** must be held while executing this routine. ** ** Why not just use a library random generator like lrand48() for this? ** Because the OP_NewRecno opcode in the VDBE depends on having a very ** good source of random numbers. The lrand48() library function may ** well be good enough. But maybe not. Or maybe lrand48() has some ** subtle problems on some systems that could cause problems. It is hard ** to know. To minimize the risk of problems due to bad lrand48() ** implementations, SQLite uses this random number generator based ** on RC4, which we know works very well. */ static int randomByte(){ unsigned char t; /* All threads share a single random number generator. ** This structure is the current state of the generator. */ |
︙ | ︙ | |||
94 95 96 97 98 99 100 | unsigned char *zBuf = pBuf; sqlite3OsEnterMutex(); while( N-- ){ *(zBuf++) = randomByte(); } sqlite3OsLeaveMutex(); } | > > > | 91 92 93 94 95 96 97 98 99 100 | unsigned char *zBuf = pBuf; sqlite3OsEnterMutex(); while( N-- ){ *(zBuf++) = randomByte(); } sqlite3OsLeaveMutex(); } |
Changes to SQLite.Interop/src/select.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** | | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** ** $Id: select.c,v 1.1 2005/03/01 16:04:35 rmsimpson Exp $ */ #include "sqliteInt.h" #include "../interop.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. */ Select *sqlite3SelectNew( ExprList *pEList, /* which columns to include in the result */ |
︙ | ︙ | |||
56 57 58 59 60 61 62 | pNew->pOrderBy = pOrderBy; pNew->isDistinct = isDistinct; pNew->op = TK_SELECT; pNew->pLimit = pLimit; pNew->pOffset = pOffset; pNew->iLimit = -1; pNew->iOffset = -1; | < < < < | | | | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | pNew->pOrderBy = pOrderBy; pNew->isDistinct = isDistinct; pNew->op = TK_SELECT; pNew->pLimit = pLimit; pNew->pOffset = pOffset; pNew->iLimit = -1; pNew->iOffset = -1; } return pNew; } /* ** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the ** type of join. Return an integer constant that expresses that type ** in terms of the following bit values: ** ** JT_INNER ** JT_OUTER ** JT_NATURAL ** JT_LEFT ** JT_RIGHT ** ** A full outer join is the combination of JT_LEFT and JT_RIGHT. ** ** If an illegal or unsupported join type is seen, then still return ** a join type, but put an error in the pParse structure. */ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ int jointype = 0; Token *apAll[3]; Token *p; static const struct { const char *zKeyword; u8 nChar; u8 code; } keywords[] = { { "natural", 7, JT_NATURAL }, { "left", 4, JT_LEFT|JT_OUTER }, { "right", 5, JT_RIGHT|JT_OUTER }, { "full", 4, JT_LEFT|JT_RIGHT|JT_OUTER }, { "outer", 5, JT_OUTER }, { "inner", 5, JT_INNER }, { "cross", 5, JT_INNER }, }; int i, j; apAll[0] = pA; apAll[1] = pB; apAll[2] = pC; for(i=0; i<3 && apAll[i]; i++){ p = apAll[i]; for(j=0; j<sizeof(keywords)/sizeof(keywords[0]); j++){ if( p->n==keywords[j].nChar && sqlite3StrNICmp(p->z, keywords[j].zKeyword, p->n)==0 ){ jointype |= keywords[j].code; break; } } if( j>=sizeof(keywords)/sizeof(keywords[0]) ){ jointype |= JT_ERROR; break; |
︙ | ︙ | |||
150 151 152 153 154 155 156 | return -1; } /* ** Set the value of a token to a '\000'-terminated string. */ static void setToken(Token *p, const char *z){ | | | < < < < < < < < < < > | > | | > | > < < < < < < < < < < < < < < < < < | < | | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | return -1; } /* ** Set the value of a token to a '\000'-terminated string. */ static void setToken(Token *p, const char *z){ p->z = z; p->n = strlen(z); p->dyn = 0; } /* ** Add a term to the WHERE expression in *ppExpr that requires the ** zCol column to be equal in the two tables pTab1 and pTab2. */ static void addWhereTerm( const char *zCol, /* Name of the column */ const Table *pTab1, /* First table */ const char *zAlias1, /* Alias for first table. May be NULL */ const Table *pTab2, /* Second table */ const char *zAlias2, /* Alias for second table. May be NULL */ Expr **ppExpr /* Add the equality term to this expression */ ){ Token dummy; Expr *pE1a, *pE1b, *pE1c; Expr *pE2a, *pE2b, *pE2c; Expr *pE; setToken(&dummy, zCol); pE1a = sqlite3Expr(TK_ID, 0, 0, &dummy); pE2a = sqlite3Expr(TK_ID, 0, 0, &dummy); if( zAlias1==0 ){ zAlias1 = pTab1->zName; } setToken(&dummy, zAlias1); pE1b = sqlite3Expr(TK_ID, 0, 0, &dummy); if( zAlias2==0 ){ zAlias2 = pTab2->zName; } setToken(&dummy, zAlias2); pE2b = sqlite3Expr(TK_ID, 0, 0, &dummy); pE1c = sqlite3Expr(TK_DOT, pE1b, pE1a, 0); pE2c = sqlite3Expr(TK_DOT, pE2b, pE2a, 0); pE = sqlite3Expr(TK_EQ, pE1c, pE2c, 0); ExprSetProperty(pE, EP_FromJoin); *ppExpr = sqlite3ExprAnd(*ppExpr, pE); } /* ** Set the EP_FromJoin property on all terms of the given expression. ** ** The EP_FromJoin property is used on terms of an expression to tell ** the LEFT OUTER JOIN processing logic that this term is part of the ** join restriction specified in the ON or USING clause and not a part ** of the more general WHERE clause. These terms are moved over to the ** WHERE clause during join processing but we need to remember that they ** originated in the ON or USING clause. */ static void setJoinExpr(Expr *p){ while( p ){ ExprSetProperty(p, EP_FromJoin); setJoinExpr(p->pLeft); p = p->pRight; } } /* ** This routine processes the join information for a SELECT statement. ** ON and USING clauses are converted into extra terms of the WHERE clause. |
︙ | ︙ | |||
277 278 279 280 281 282 283 | "an ON or USING clause", 0); return 1; } for(j=0; j<pLeftTab->nCol; j++){ char *zName = pLeftTab->aCol[j].zName; if( columnIndex(pRightTab, zName)>=0 ){ addWhereTerm(zName, pLeftTab, pLeft->zAlias, | | < < | | 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | "an ON or USING clause", 0); return 1; } for(j=0; j<pLeftTab->nCol; j++){ char *zName = pLeftTab->aCol[j].zName; if( columnIndex(pRightTab, zName)>=0 ){ addWhereTerm(zName, pLeftTab, pLeft->zAlias, pRightTab, pRight->zAlias, &p->pWhere); } } } /* Disallow both ON and USING clauses in the same join */ if( pLeft->pOn && pLeft->pUsing ){ sqlite3ErrorMsg(pParse, "cannot have both ON and USING " "clauses in the same join"); return 1; } /* Add the ON clause to the end of the WHERE clause, connected by ** an AND operator. */ if( pLeft->pOn ){ setJoinExpr(pLeft->pOn); p->pWhere = sqlite3ExprAnd(p->pWhere, pLeft->pOn); pLeft->pOn = 0; } /* Create extra terms on the WHERE clause for each column named ** in the USING clause. Example: If the two tables to be joined are ** A and B and the USING clause names X, Y, and Z, then add this |
︙ | ︙ | |||
318 319 320 321 322 323 324 | char *zName = pList->a[j].zName; if( columnIndex(pLeftTab, zName)<0 || columnIndex(pRightTab, zName)<0 ){ sqlite3ErrorMsg(pParse, "cannot join using column %s - column " "not present in both tables", zName); return 1; } addWhereTerm(zName, pLeftTab, pLeft->zAlias, | | < | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | char *zName = pList->a[j].zName; if( columnIndex(pLeftTab, zName)<0 || columnIndex(pRightTab, zName)<0 ){ sqlite3ErrorMsg(pParse, "cannot join using column %s - column " "not present in both tables", zName); return 1; } addWhereTerm(zName, pLeftTab, pLeft->zAlias, pRightTab, pRight->zAlias, &p->pWhere); } } } return 0; } /* |
︙ | ︙ | |||
347 348 349 350 351 352 353 | sqliteFree(p); } /* ** Insert code into "v" that will push the record on the top of the ** stack into the sorter. */ | | | | < < < | < < > | < < < < < < < | < < < | | < | | > | | > | | < < | < < < < < < < < < < < < < < < < < < < < < | < | < | | | 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | sqliteFree(p); } /* ** Insert code into "v" that will push the record on the top of the ** stack into the sorter. */ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){ int i; for(i=0; i<pOrderBy->nExpr; i++){ sqlite3ExprCode(pParse, pOrderBy->a[i].pExpr); } sqlite3VdbeAddOp(v, OP_MakeRecord, pOrderBy->nExpr, 0); sqlite3VdbeAddOp(v, OP_SortPut, 0, 0); } /* ** Add code to implement the OFFSET and LIMIT */ static void codeLimiter( Vdbe *v, /* Generate code into this VM */ Select *p, /* The SELECT statement being coded */ int iContinue, /* Jump here to skip the current record */ int iBreak, /* Jump here to end the loop */ int nPop /* Number of times to pop stack when jumping */ ){ if( p->iOffset>=0 ){ int addr = sqlite3VdbeCurrentAddr(v) + 3; if( nPop>0 ) addr++; sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, 0); sqlite3VdbeAddOp(v, OP_IfMemPos, p->iOffset, addr); if( nPop>0 ){ sqlite3VdbeAddOp(v, OP_Pop, nPop, 0); } sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue); VdbeComment((v, "# skip OFFSET records")); } if( p->iLimit>=0 ){ sqlite3VdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak); VdbeComment((v, "# exit when LIMIT reached")); } } /* ** This routine generates the code for the inside of the inner loop ** of a SELECT. ** ** If srcTab and nColumn are both zero, then the pEList expressions ** are evaluated in order to get the data for this row. If nColumn>0 |
︙ | ︙ | |||
456 457 458 459 460 461 462 | assert( pEList!=0 ); /* If there was a LIMIT clause on the SELECT statement, then do the check ** to see if this row should be output. */ hasDistinct = distinct>=0 && pEList && pEList->nExpr>0; if( pOrderBy==0 && !hasDistinct ){ | | > | > > > > > > > > | | > > > | > < < | < | > | | | | < < < < | | < | < | | < < < < < < > | | | < < | | | > > > > > > > > > > | > | > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > > | > > > | > > > > > > > > > > > > > | | > > | | < | | | | | > > | | 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 | assert( pEList!=0 ); /* If there was a LIMIT clause on the SELECT statement, then do the check ** to see if this row should be output. */ hasDistinct = distinct>=0 && pEList && pEList->nExpr>0; if( pOrderBy==0 && !hasDistinct ){ codeLimiter(v, p, iContinue, iBreak, 0); } /* Pull the requested columns. */ if( nColumn>0 ){ for(i=0; i<nColumn; i++){ sqlite3VdbeAddOp(v, OP_Column, srcTab, i); } }else{ nColumn = pEList->nExpr; for(i=0; i<pEList->nExpr; i++){ sqlite3ExprCode(pParse, pEList->a[i].pExpr); } } /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ if( hasDistinct ){ #if NULL_ALWAYS_DISTINCT sqlite3VdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqlite3VdbeCurrentAddr(v)+7); #endif /* Deliberately leave the affinity string off of the following ** OP_MakeRecord */ sqlite3VdbeAddOp(v, OP_MakeRecord, pEList->nExpr * -1, 0); sqlite3VdbeAddOp(v, OP_Distinct, distinct, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue); VdbeComment((v, "# skip indistinct records")); sqlite3VdbeAddOp(v, OP_String8, 0, 0); sqlite3VdbeAddOp(v, OP_PutStrKey, distinct, 0); if( pOrderBy==0 ){ codeLimiter(v, p, iContinue, iBreak, nColumn); } } switch( eDest ){ #ifndef SQLITE_OMIT_COMPOUND_SELECT /* In this mode, write each query result to the key of the temporary ** table iParm. */ case SRT_Union: { sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); sqlite3VdbeAddOp(v, OP_String8, 0, 0); sqlite3VdbeAddOp(v, OP_PutStrKey, iParm, 0); break; } /* Construct a record from the query result, but instead of ** saving that record, use it as a key to delete elements from ** the temporary table iParm. */ case SRT_Except: { int addr; addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3); sqlite3VdbeAddOp(v, OP_Delete, iParm, 0); break; } #endif /* Store the result as data using a unique key. */ case SRT_Table: case SRT_TempTable: { sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); if( pOrderBy ){ pushOntoSorter(pParse, v, pOrderBy); }else{ sqlite3VdbeAddOp(v, OP_NewRecno, iParm, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); sqlite3VdbeAddOp(v, OP_PutIntKey, iParm, 0); } break; } #ifndef SQLITE_OMIT_SUBQUERY /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. */ case SRT_Set: { int addr1 = sqlite3VdbeCurrentAddr(v); int addr2; assert( nColumn==1 ); sqlite3VdbeAddOp(v, OP_NotNull, -1, addr1+3); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); if( pOrderBy ){ pushOntoSorter(pParse, v, pOrderBy); }else{ char aff = (iParm>>16)&0xFF; aff = sqlite3CompareAffinity(pEList->a[0].pExpr, aff); sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &aff, 1); sqlite3VdbeAddOp(v, OP_String8, 0, 0); sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0); } sqlite3VdbeChangeP2(v, addr2, sqlite3VdbeCurrentAddr(v)); break; } /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell and break out ** of the scan loop. */ case SRT_Exists: case SRT_Mem: { assert( nColumn==1 ); if( pOrderBy ){ pushOntoSorter(pParse, v, pOrderBy); }else{ sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); sqlite3VdbeAddOp(v, OP_Goto, 0, iBreak); } break; } #endif /* #ifndef SQLITE_OMIT_SUBQUERY */ /* Send the data to the callback function. */ case SRT_Callback: case SRT_Sorter: { if( pOrderBy ){ sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); pushOntoSorter(pParse, v, pOrderBy); }else{ assert( eDest==SRT_Callback ); sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0); } break; } /* Invoke a subroutine to handle the results. The subroutine itself ** is responsible for popping the results off of the stack. */ case SRT_Subroutine: { if( pOrderBy ){ sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); pushOntoSorter(pParse, v, pOrderBy); }else{ sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm); } break; } #if !defined(SQLITE_OMIT_TRIGGER) /* Discard the results. This is used for SELECT statements inside ** the body of a TRIGGER. The purpose of such selects is to call ** user-defined functions that have side effects. We do not care ** about the actual results of the select. */ default: { assert( eDest==SRT_Discard ); sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); break; } #endif } return 0; } /* ** If the inner loop was generated using a non-null pOrderBy argument, ** then the results were placed in a sorter. After the loop is terminated ** we need to run the sorter and output the results. The following ** routine generates the code needed to do that. */ static void generateSortTail( Parse *pParse, /* The parsing context */ Select *p, /* The SELECT statement */ Vdbe *v, /* Generate code into this VDBE */ int nColumn, /* Number of columns of data */ int eDest, /* Write the sorted results here */ int iParm /* Optional parameter associated with eDest */ ){ int end1 = sqlite3VdbeMakeLabel(v); int end2 = sqlite3VdbeMakeLabel(v); int addr; KeyInfo *pInfo; ExprList *pOrderBy; int nCol, i; sqlite3 *db = pParse->db; if( eDest==SRT_Sorter ) return; pOrderBy = p->pOrderBy; nCol = pOrderBy->nExpr; pInfo = sqliteMalloc( sizeof(*pInfo) + nCol*(sizeof(CollSeq*)+1) ); if( pInfo==0 ) return; pInfo->aSortOrder = (char*)&pInfo->aColl[nCol]; pInfo->nField = nCol; for(i=0; i<nCol; i++){ /* If a collation sequence was specified explicity, then it ** is stored in pOrderBy->a[i].zName. Otherwise, use the default ** collation type for the expression. */ pInfo->aColl[i] = sqlite3ExprCollSeq(pParse, pOrderBy->a[i].pExpr); if( !pInfo->aColl[i] ){ pInfo->aColl[i] = db->pDfltColl; } pInfo->aSortOrder[i] = pOrderBy->a[i].sortOrder; } sqlite3VdbeOp3(v, OP_Sort, 0, 0, (char*)pInfo, P3_KEYINFO_HANDOFF); addr = sqlite3VdbeAddOp(v, OP_SortNext, 0, end1); codeLimiter(v, p, addr, end2, 1); switch( eDest ){ case SRT_Table: case SRT_TempTable: { sqlite3VdbeAddOp(v, OP_NewRecno, iParm, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); sqlite3VdbeAddOp(v, OP_PutIntKey, iParm, 0); break; } #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { assert( nColumn==1 ); sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, "n", P3_STATIC); sqlite3VdbeAddOp(v, OP_String8, 0, 0); sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0); break; } case SRT_Exists: case SRT_Mem: { assert( nColumn==1 ); sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); sqlite3VdbeAddOp(v, OP_Goto, 0, end1); break; } #endif case SRT_Callback: case SRT_Subroutine: { int i; sqlite3VdbeAddOp(v, OP_Integer, p->pEList->nExpr, 0); |
︙ | ︙ | |||
731 732 733 734 735 736 737 | break; } default: { /* Do nothing */ break; } } | < < < < | < < < < < | | | > | 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 | break; } default: { /* Do nothing */ break; } } sqlite3VdbeAddOp(v, OP_Goto, 0, addr); sqlite3VdbeResolveLabel(v, end2); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeResolveLabel(v, end1); sqlite3VdbeAddOp(v, OP_SortReset, 0, 0); } /* ** Return a pointer to a string containing the 'declaration type' of the ** expression pExpr. The string may be treated as static by the caller. ** ** If the declaration type is the exact datatype definition extracted from |
︙ | ︙ | |||
780 781 782 783 784 785 786 | for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); if( j<pTabList->nSrc ){ pTab = pTabList->a[j].pTab; }else{ pNC = pNC->pNext; } } | < < < < < < < < < < < < < < | 685 686 687 688 689 690 691 692 693 694 695 696 697 698 | for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); if( j<pTabList->nSrc ){ pTab = pTabList->a[j].pTab; }else{ pNC = pNC->pNext; } } assert( pTab ); if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); if( iCol<0 ){ zType = "INTEGER"; }else{ zType = pTab->aCol[iCol].zType; |
︙ | ︙ | |||
868 869 870 871 872 873 874 | /* If this is an EXPLAIN, skip this step */ if( pParse->explain ){ return; } #endif assert( v!=0 ); | | < | 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 | /* If this is an EXPLAIN, skip this step */ if( pParse->explain ){ return; } #endif assert( v!=0 ); if( pParse->colNamesSet || v==0 || sqlite3_malloc_failed ) return; pParse->colNamesSet = 1; fullNames = (db->flags & SQLITE_FullColNames)!=0; shortNames = (db->flags & SQLITE_ShortColNames)!=0; sqlite3VdbeSetNumCols(v, pEList->nExpr); for(i=0; i<pEList->nExpr; i++){ Expr *p; p = pEList->a[i].pExpr; |
︙ | ︙ | |||
898 899 900 901 902 903 904 | assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); if( iCol<0 ){ zCol = "rowid"; }else{ zCol = pTab->aCol[iCol].zName; } if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){ | | | | | 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 | assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); if( iCol<0 ){ zCol = "rowid"; }else{ zCol = pTab->aCol[iCol].zName; } if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){ sqlite3VdbeSetColName(v, i, p->span.z, p->span.n); }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){ char *zName = 0; char *zTab; zTab = pTabList->a[j].zAlias; if( fullNames || zTab==0 ) zTab = pTab->zName; sqlite3SetString(&zName, zTab, ".", zCol, 0); sqlite3VdbeSetColName(v, i, zName, P3_DYNAMIC); }else{ sqlite3VdbeSetColName(v, i, zCol, strlen(zCol)); } }else if( p->span.z && p->span.z[0] ){ sqlite3VdbeSetColName(v, i, p->span.z, p->span.n); /* sqlite3VdbeCompressSpace(v, addr); */ }else{ char zName[30]; assert( p->op!=TK_COLUMN || pTabList==0 ); sprintf(zName, "column%d", i+1); sqlite3VdbeSetColName(v, i, zName, 0); } |
︙ | ︙ | |||
964 965 966 967 968 969 970 | if( sqlite3SelectResolve(pParse, pSelect, 0) ){ return 0; } pTab = sqliteMalloc( sizeof(Table) ); if( pTab==0 ){ return 0; } | < < | 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 | if( sqlite3SelectResolve(pParse, pSelect, 0) ){ return 0; } pTab = sqliteMalloc( sizeof(Table) ); if( pTab==0 ){ return 0; } pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0; pEList = pSelect->pEList; pTab->nCol = pEList->nExpr; assert( pTab->nCol>0 ); pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol ); for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){ Expr *p, *pR; char *zType; char *zName; char *zBasename; int cnt; NameContext sNC; /* Get an appropriate name for the column */ p = pEList->a[i].pExpr; assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 ); |
︙ | ︙ | |||
998 999 1000 1001 1002 1003 1004 | /* Use the original text of the column expression as its name */ zName = sqlite3MPrintf("%T", &p->span); }else{ /* If all else fails, make up a name */ zName = sqlite3MPrintf("column%d", i+1); } sqlite3Dequote(zName); | < < < < < < < | | | | 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 | /* Use the original text of the column expression as its name */ zName = sqlite3MPrintf("%T", &p->span); }else{ /* If all else fails, make up a name */ zName = sqlite3MPrintf("column%d", i+1); } sqlite3Dequote(zName); /* Make sure the column name is unique. If the name is not unique, ** append a integer to the name so that it becomes unique. */ zBasename = zName; for(j=cnt=0; j<i; j++){ if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ zName = sqlite3MPrintf("%s:%d", zBasename, ++cnt); j = -1; } } if( zBasename!=zName ){ sqliteFree(zBasename); } pCol->zName = zName; /* Get the typename, type affinity, and collating sequence for the ** column. */ sNC.pSrcList = pSelect->pSrc; zType = sqliteStrDup(columnType(&sNC, p)); pCol->zType = zType; pCol->affinity = sqlite3ExprAffinity(p); pCol->pColl = sqlite3ExprCollSeq(pParse, p); if( !pCol->pColl ){ pCol->pColl = pParse->db->pDfltColl; } } pTab->iPKey = -1; return pTab; } /* |
︙ | ︙ | |||
1070 1071 1072 1073 1074 1075 1076 | static int prepSelectStmt(Parse *pParse, Select *p){ int i, j, k, rc; SrcList *pTabList; ExprList *pEList; Table *pTab; struct SrcList_item *pFrom; | | < < | 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 | static int prepSelectStmt(Parse *pParse, Select *p){ int i, j, k, rc; SrcList *pTabList; ExprList *pEList; Table *pTab; struct SrcList_item *pFrom; if( p==0 || p->pSrc==0 ) return 1; pTabList = p->pSrc; pEList = p->pEList; /* Make sure cursor numbers have been assigned to all entries in ** the FROM clause of the SELECT statement. */ sqlite3SrcListAssignCursors(pParse, p->pSrc); |
︙ | ︙ | |||
1100 1101 1102 1103 1104 1105 1106 | #ifndef SQLITE_OMIT_SUBQUERY /* A sub-query in the FROM clause of a SELECT */ assert( pFrom->pSelect!=0 ); if( pFrom->zAlias==0 ){ pFrom->zAlias = sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect); } | < < < | 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 | #ifndef SQLITE_OMIT_SUBQUERY /* A sub-query in the FROM clause of a SELECT */ assert( pFrom->pSelect!=0 ); if( pFrom->zAlias==0 ){ pFrom->zAlias = sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect); } pFrom->pTab = pTab = sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect); if( pTab==0 ){ return 1; } /* The isTransient flag indicates that the Table structure has been ** dynamically allocated and may be freed at any time. In other words, ** pTab is not pointing to a persistent table structure that defines ** part of the schema. */ pTab->isTransient = 1; #endif }else{ /* An ordinary table or view name in the FROM clause */ pFrom->pTab = pTab = sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase); if( pTab==0 ){ return 1; } #ifndef SQLITE_OMIT_VIEW if( pTab->pSelect ){ /* We reach here if the named table is a really a view */ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ return 1; } /* If pFrom->pSelect!=0 it means we are dealing with a |
︙ | ︙ | |||
1169 1170 1171 1172 1173 1174 1175 | /* ** If we get here it means the result set contains one or more "*" ** operators that need to be expanded. Loop through each expression ** in the result set and expand them one by one. */ struct ExprList_item *a = pEList->a; ExprList *pNew = 0; | < < < < < | < < < | 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 | /* ** If we get here it means the result set contains one or more "*" ** operators that need to be expanded. Loop through each expression ** in the result set and expand them one by one. */ struct ExprList_item *a = pEList->a; ExprList *pNew = 0; for(k=0; k<pEList->nExpr; k++){ Expr *pE = a[k].pExpr; if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){ /* This particular expression does not need to be expanded. */ pNew = sqlite3ExprListAppend(pNew, a[k].pExpr, 0); pNew->a[pNew->nExpr-1].zName = a[k].zName; a[k].pExpr = 0; a[k].zName = 0; }else{ /* This expression is a "*" or a "TABLE.*" and needs to be ** expanded. */ int tableSeen = 0; /* Set to 1 when TABLE matches */ char *zTName; /* text of name of TABLE */ |
︙ | ︙ | |||
1229 1230 1231 1232 1233 1234 1235 | ** using clause from the table on the right. */ continue; } } pRight = sqlite3Expr(TK_ID, 0, 0, 0); if( pRight==0 ) break; setToken(&pRight->token, zName); | | < < < | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 | ** using clause from the table on the right. */ continue; } } pRight = sqlite3Expr(TK_ID, 0, 0, 0); if( pRight==0 ) break; setToken(&pRight->token, zName); if( zTabName && pTabList->nSrc>1 ){ pLeft = sqlite3Expr(TK_ID, 0, 0, 0); pExpr = sqlite3Expr(TK_DOT, pLeft, pRight, 0); if( pExpr==0 ) break; setToken(&pLeft->token, zTabName); setToken(&pExpr->span, sqlite3MPrintf("%s.%s", zTabName, zName)); pExpr->span.dyn = 1; pExpr->token.z = 0; pExpr->token.n = 0; pExpr->token.dyn = 0; }else{ pExpr = pRight; pExpr->span = pExpr->token; } pNew = sqlite3ExprListAppend(pNew, pExpr, &pRight->token); } } if( !tableSeen ){ if( zTName ){ sqlite3ErrorMsg(pParse, "no such table: %s", zTName); }else{ sqlite3ErrorMsg(pParse, "no tables specified"); } rc = 1; } sqliteFree(zTName); } } sqlite3ExprListDelete(pEList); p->pEList = pNew; } return rc; } /* ** This routine recursively unlinks the Select.pSrc.a[].pTab pointers ** in a select structure. It just sets the pointers to NULL. This ** routine is recursive in the sense that if the Select.pSrc.a[].pSelect ** pointer is not NULL, this routine is called recursively on that pointer. ** ** This routine is called on the Select structure that defines a ** VIEW in order to undo any bindings to tables. This is necessary ** because those tables might be DROPed by a subsequent SQL command. ** If the bindings are not removed, then the Select.pSrc->a[].pTab field ** will be left pointing to a deallocated Table structure after the ** DROP and a coredump will occur the next time the VIEW is used. */ #if 0 void sqlite3SelectUnbind(Select *p){ int i; SrcList *pSrc = p->pSrc; struct SrcList_item *pItem; Table *pTab; if( p==0 ) return; for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){ if( (pTab = pItem->pTab)!=0 ){ if( pTab->isTransient ){ sqlite3DeleteTable(0, pTab); } pItem->pTab = 0; if( pItem->pSelect ){ sqlite3SelectUnbind(pItem->pSelect); } } } } #endif #ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** This routine associates entries in an ORDER BY expression list with ** columns in a result. For each ORDER BY expression, the opcode of ** the top-level node is changed to TK_COLUMN and the iColumn value of ** the top-level node is filled in with column number and the iTable ** value of the top-level node is filled with iTable parameter. |
︙ | ︙ | |||
1365 1366 1367 1368 1369 1370 1371 | Vdbe *v = pParse->pVdbe; if( v==0 ){ v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db); } return v; } | < | | | | | < < < < < < | | > | | | | < < < | < < < < < < < < < < < < | | < > > > > > > > > > | | < < < < < < < < < < < | | | < < | > > > > > | > > > > > > > > > > > > > > | > > > > > > | > > > | > > > > > > | > > | 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 | Vdbe *v = pParse->pVdbe; if( v==0 ){ v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db); } return v; } /* ** Compute the iLimit and iOffset fields of the SELECT based on the ** pLimit and pOffset expressions. nLimit and nOffset hold the expressions ** that appear in the original SQL statement after the LIMIT and OFFSET ** keywords. Or NULL if those keywords are omitted. iLimit and iOffset ** are the integer memory register numbers for counters used to compute ** the limit and offset. If there is no limit and/or offset, then ** iLimit and iOffset are negative. ** ** This routine changes the values if iLimit and iOffset only if ** a limit or offset is defined by nLimit and nOffset. iLimit and ** iOffset should have been preset to appropriate default values ** (usually but not always -1) prior to calling this routine. ** Only if nLimit>=0 or nOffset>0 do the limit registers get ** redefined. The UNION ALL operator uses this property to force ** the reuse of the same limit and offset registers across multiple ** SELECT statements. */ static void computeLimitRegisters(Parse *pParse, Select *p){ /* ** "LIMIT -1" always shows all rows. There is some ** contraversy about what the correct behavior should be. ** The current implementation interprets "LIMIT 0" to mean ** no rows. */ if( p->pLimit ){ int iMem = pParse->nMem++; Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return; sqlite3ExprCode(pParse, p->pLimit); sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); sqlite3VdbeAddOp(v, OP_Negative, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1); VdbeComment((v, "# LIMIT counter")); p->iLimit = iMem; } if( p->pOffset ){ int iMem = pParse->nMem++; Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return; sqlite3ExprCode(pParse, p->pOffset); sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); sqlite3VdbeAddOp(v, OP_Negative, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1); VdbeComment((v, "# OFFSET counter")); p->iOffset = iMem; } } /* ** Generate VDBE instructions that will open a transient table that ** will be used for an index or to store keyed results for a compound ** select. In other words, open a transient table that needs a ** KeyInfo structure. The number of columns in the KeyInfo is determined ** by the result set of the SELECT statement in the second argument. ** ** Specifically, this routine is called to open an index table for ** DISTINCT, UNION, INTERSECT and EXCEPT select statements (but not ** UNION ALL). ** ** Make the new table a KeyAsData table if keyAsData is true. ** ** The value returned is the address of the OP_OpenTemp instruction. */ static int openTempIndex(Parse *pParse, Select *p, int iTab, int keyAsData){ KeyInfo *pKeyInfo; int nColumn; sqlite3 *db = pParse->db; int i; Vdbe *v = pParse->pVdbe; int addr; if( prepSelectStmt(pParse, p) ){ return 0; } nColumn = p->pEList->nExpr; pKeyInfo = sqliteMalloc( sizeof(*pKeyInfo)+nColumn*sizeof(CollSeq*) ); if( pKeyInfo==0 ) return 0; pKeyInfo->enc = db->enc; pKeyInfo->nField = nColumn; for(i=0; i<nColumn; i++){ pKeyInfo->aColl[i] = sqlite3ExprCollSeq(pParse, p->pEList->a[i].pExpr); if( !pKeyInfo->aColl[i] ){ pKeyInfo->aColl[i] = db->pDfltColl; } } addr = sqlite3VdbeOp3(v, OP_OpenTemp, iTab, 0, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); if( keyAsData ){ sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1); } return addr; } #ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** Add the address "addr" to the set of all OpenTemp opcode addresses ** that are being accumulated in p->ppOpenTemp. */ static int multiSelectOpenTempAddr(Select *p, int addr){ IdList *pList = *p->ppOpenTemp = sqlite3IdListAppend(*p->ppOpenTemp, 0); if( pList==0 ){ return SQLITE_NOMEM; } pList->a[pList->nId-1].idx = addr; return SQLITE_OK; } #endif /* SQLITE_OMIT_COMPOUND_SELECT */ #ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** Return the appropriate collating sequence for the iCol-th column of ** the result set for the compound-select statement "p". Return NULL if ** the column has no default collating sequence. ** |
︙ | ︙ | |||
1528 1529 1530 1531 1532 1533 1534 1535 | int eDest, /* \___ Store query results as specified */ int iParm, /* / by these two parameters. */ char *aff /* If eDest is SRT_Union, the affinity string */ ){ int rc = SQLITE_OK; /* Success code from a subroutine */ Select *pPrior; /* Another SELECT immediately to our left */ Vdbe *v; /* Generate code to this VDBE */ int nCol; /* Number of columns in the result set */ | > > > < < < < < > > > > > > > > > > > | > | | < | < < < | | < < < < < > | > | | | < | > | < > | < > | > < | 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 | int eDest, /* \___ Store query results as specified */ int iParm, /* / by these two parameters. */ char *aff /* If eDest is SRT_Union, the affinity string */ ){ int rc = SQLITE_OK; /* Success code from a subroutine */ Select *pPrior; /* Another SELECT immediately to our left */ Vdbe *v; /* Generate code to this VDBE */ IdList *pOpenTemp = 0;/* OP_OpenTemp opcodes that need a KeyInfo */ int aAddr[5]; /* Addresses of SetNumColumns operators */ int nAddr = 0; /* Number used */ int nCol; /* Number of columns in the result set */ /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. */ if( p==0 || p->pPrior==0 ){ rc = 1; goto multi_select_end; } pPrior = p->pPrior; if( pPrior->pOrderBy ){ sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before", selectOpName(p->op)); rc = 1; goto multi_select_end; } if( pPrior->pLimit ){ sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before", selectOpName(p->op)); rc = 1; goto multi_select_end; } /* Make sure we have a valid query engine. If not, create a new one. */ v = sqlite3GetVdbe(pParse); if( v==0 ){ rc = 1; goto multi_select_end; } /* If *p this is the right-most select statement, then initialize ** p->ppOpenTemp to point to pOpenTemp. If *p is not the right most ** statement then p->ppOpenTemp will have already been initialized ** by a prior call to this same procedure. Pass along the pOpenTemp ** pointer to pPrior, the next statement to our left. */ if( p->ppOpenTemp==0 ){ p->ppOpenTemp = &pOpenTemp; } pPrior->ppOpenTemp = p->ppOpenTemp; /* Create the destination temporary table if necessary */ if( eDest==SRT_TempTable ){ assert( p->pEList ); sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0); assert( nAddr==0 ); aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, 0); eDest = SRT_Table; } /* Generate code for the left and right SELECT statements. */ switch( p->op ){ case TK_ALL: { if( p->pOrderBy==0 ){ assert( !pPrior->pLimit ); pPrior->pLimit = p->pLimit; pPrior->pOffset = p->pOffset; rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } p->pPrior = 0; p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; p->pLimit = 0; p->pOffset = 0; rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff); p->pPrior = pPrior; if( rc ){ goto multi_select_end; } break; } /* For UNION ALL ... ORDER BY fall through to the next case */ } case TK_EXCEPT: case TK_UNION: { int unionTab; /* Cursor number of the temporary table holding result */ int op = 0; /* One of the SRT_ operations to apply to self */ int priorOp; /* The SRT_ operation to apply to prior selects */ Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */ ExprList *pOrderBy; /* The ORDER BY clause for the right SELECT */ int addr; priorOp = p->op==TK_ALL ? SRT_Table : SRT_Union; if( eDest==priorOp && p->pOrderBy==0 && !p->pLimit && !p->pOffset ){ /* We can reuse a temporary table generated by a SELECT to our ** right. */ unionTab = iParm; }else{ /* We will need to create our own temporary table to hold the ** intermediate results. */ unionTab = pParse->nTab++; if( p->pOrderBy && matchOrderbyToColumn(pParse, p, p->pOrderBy, unionTab, 1) ){ rc = 1; goto multi_select_end; } addr = sqlite3VdbeAddOp(v, OP_OpenTemp, unionTab, 0); if( p->op!=TK_ALL ){ rc = multiSelectOpenTempAddr(p, addr); if( rc!=SQLITE_OK ){ goto multi_select_end; } sqlite3VdbeAddOp(v, OP_KeyAsData, unionTab, 1); } assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, unionTab, 0); assert( p->pEList ); } /* Code the SELECT statements to our left */ assert( !pPrior->pOrderBy ); rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } /* Code the current SELECT statement */ switch( p->op ){ case TK_EXCEPT: op = SRT_Except; break; case TK_UNION: op = SRT_Union; break; case TK_ALL: op = SRT_Table; break; } p->pPrior = 0; pOrderBy = p->pOrderBy; p->pOrderBy = 0; pLimit = p->pLimit; p->pLimit = 0; pOffset = p->pOffset; p->pOffset = 0; rc = sqlite3Select(pParse, p, op, unionTab, 0, 0, 0, aff); p->pPrior = pPrior; p->pOrderBy = pOrderBy; |
︙ | ︙ | |||
1690 1691 1692 1693 1694 1695 1696 | int iCont, iBreak, iStart; assert( p->pEList ); if( eDest==SRT_Callback ){ generateColumnNames(pParse, 0, p->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); | < > | | 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 | int iCont, iBreak, iStart; assert( p->pEList ); if( eDest==SRT_Callback ){ generateColumnNames(pParse, 0, p->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Rewind, unionTab, iBreak); computeLimitRegisters(pParse, p); iStart = sqlite3VdbeCurrentAddr(v); rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, p->pOrderBy, -1, eDest, iParm, iCont, iBreak, 0); if( rc ){ rc = 1; goto multi_select_end; } sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp(v, OP_Next, unionTab, iStart); |
︙ | ︙ | |||
1719 1720 1721 1722 1723 1724 1725 | /* INTERSECT is different from the others since it requires ** two temporary tables. Hence it has its own case. Begin ** by allocating the tables we will need. */ tab1 = pParse->nTab++; tab2 = pParse->nTab++; | | < | | > | < > > > > | > > > > > | < > | 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 | /* INTERSECT is different from the others since it requires ** two temporary tables. Hence it has its own case. Begin ** by allocating the tables we will need. */ tab1 = pParse->nTab++; tab2 = pParse->nTab++; if( p->pOrderBy && matchOrderbyToColumn(pParse,p,p->pOrderBy,tab1,1) ){ rc = 1; goto multi_select_end; } addr = sqlite3VdbeAddOp(v, OP_OpenTemp, tab1, 0); rc = multiSelectOpenTempAddr(p, addr); if( rc!=SQLITE_OK ){ goto multi_select_end; } sqlite3VdbeAddOp(v, OP_KeyAsData, tab1, 1); assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab1, 0); assert( p->pEList ); /* Code the SELECTs to our left into temporary table "tab1". */ rc = sqlite3Select(pParse, pPrior, SRT_Union, tab1, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } /* Code the current SELECT into temporary table "tab2" */ addr = sqlite3VdbeAddOp(v, OP_OpenTemp, tab2, 0); rc = multiSelectOpenTempAddr(p, addr); if( rc!=SQLITE_OK ){ goto multi_select_end; } sqlite3VdbeAddOp(v, OP_KeyAsData, tab2, 1); assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab2, 0); p->pPrior = 0; pLimit = p->pLimit; p->pLimit = 0; pOffset = p->pOffset; p->pOffset = 0; rc = sqlite3Select(pParse, p, SRT_Union, tab2, 0, 0, 0, aff); p->pPrior = pPrior; |
︙ | ︙ | |||
1766 1767 1768 1769 1770 1771 1772 | */ assert( p->pEList ); if( eDest==SRT_Callback ){ generateColumnNames(pParse, 0, p->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); | < > | | | 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 | */ assert( p->pEList ); if( eDest==SRT_Callback ){ generateColumnNames(pParse, 0, p->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Rewind, tab1, iBreak); computeLimitRegisters(pParse, p); iStart = sqlite3VdbeAddOp(v, OP_FullKey, tab1, 0); sqlite3VdbeAddOp(v, OP_NotFound, tab2, iCont); rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, p->pOrderBy, -1, eDest, iParm, iCont, iBreak, 0); if( rc ){ rc = 1; goto multi_select_end; } sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp(v, OP_Next, tab1, iStart); |
︙ | ︙ | |||
1800 1801 1802 1803 1804 1805 1806 | rc = 1; goto multi_select_end; } /* Set the number of columns in temporary tables */ nCol = p->pEList->nExpr; | | > | | < < < | | | | | | | < | < < < < < < < < < < < | < < < | | | | | < | | | | > | | < < < < < < < < > > | > > > > > | 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 | rc = 1; goto multi_select_end; } /* Set the number of columns in temporary tables */ nCol = p->pEList->nExpr; while( nAddr>0 ){ nAddr--; sqlite3VdbeChangeP2(v, aAddr[nAddr], nCol); } /* Compute collating sequences used by either the ORDER BY clause or ** by any temporary tables needed to implement the compound select. ** Attach the KeyInfo structure to all temporary tables. Invoke the ** ORDER BY processing if there is an ORDER BY clause. ** ** This section is run by the right-most SELECT statement only. ** SELECT statements to the left always skip this part. The right-most ** SELECT might also skip this part if it has no ORDER BY clause and ** no temp tables are required. */ if( p->pOrderBy || (pOpenTemp && pOpenTemp->nId>0) ){ int i; /* Loop counter */ KeyInfo *pKeyInfo; /* Collating sequence for the result set */ assert( p->ppOpenTemp == &pOpenTemp ); pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nCol*sizeof(CollSeq*)); if( !pKeyInfo ){ rc = SQLITE_NOMEM; goto multi_select_end; } pKeyInfo->enc = pParse->db->enc; pKeyInfo->nField = nCol; for(i=0; i<nCol; i++){ pKeyInfo->aColl[i] = multiSelectCollSeq(pParse, p, i); if( !pKeyInfo->aColl[i] ){ pKeyInfo->aColl[i] = pParse->db->pDfltColl; } } for(i=0; pOpenTemp && i<pOpenTemp->nId; i++){ int p3type = (i==0?P3_KEYINFO_HANDOFF:P3_KEYINFO); int addr = pOpenTemp->a[i].idx; sqlite3VdbeChangeP3(v, addr, (char *)pKeyInfo, p3type); } if( p->pOrderBy ){ struct ExprList_item *pOrderByTerm = p->pOrderBy->a; for(i=0; i<p->pOrderBy->nExpr; i++, pOrderByTerm++){ Expr *pExpr = pOrderByTerm->pExpr; char *zName = pOrderByTerm->zName; assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol ); /* assert( !pExpr->pColl ); */ if( zName ){ pExpr->pColl = sqlite3LocateCollSeq(pParse, zName, -1); }else{ pExpr->pColl = pKeyInfo->aColl[pExpr->iColumn]; } } generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm); } if( !pOpenTemp ){ /* This happens for UNION ALL ... ORDER BY */ sqliteFree(pKeyInfo); } } multi_select_end: if( pOpenTemp ){ sqlite3IdListDelete(pOpenTemp); } p->ppOpenTemp = 0; return rc; } #endif /* SQLITE_OMIT_COMPOUND_SELECT */ #ifndef SQLITE_OMIT_VIEW /* ** Scan through the expression pExpr. Replace every reference to |
︙ | ︙ | |||
2062 2063 2064 2065 2066 2067 2068 | if( (pSub->pLimit && p->pLimit) || pSub->pOffset || (pSub->pLimit && isAgg) ) return 0; if( pSubSrc->nSrc==0 ) return 0; if( pSub->isDistinct && (pSrc->nSrc>1 || isAgg) ){ return 0; } if( p->isDistinct && subqueryIsAgg ) return 0; | | | 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 | if( (pSub->pLimit && p->pLimit) || pSub->pOffset || (pSub->pLimit && isAgg) ) return 0; if( pSubSrc->nSrc==0 ) return 0; if( pSub->isDistinct && (pSrc->nSrc>1 || isAgg) ){ return 0; } if( p->isDistinct && subqueryIsAgg ) return 0; if( p->pOrderBy && pSub->pOrderBy ) return 0; /* Restriction 3: If the subquery is a join, make sure the subquery is ** not used as the right operand of an outer join. Examples of why this ** is not allowed: ** ** t1 LEFT OUTER JOIN (t2 JOIN t3) ** |
︙ | ︙ | |||
2114 2115 2116 2117 2118 2119 2120 2121 | ** those references with expressions that resolve to the subquery FROM ** elements we are now copying in. */ iParent = pSubitem->iCursor; { int nSubSrc = pSubSrc->nSrc; int jointype = pSubitem->jointype; | > > | > | 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 | ** those references with expressions that resolve to the subquery FROM ** elements we are now copying in. */ iParent = pSubitem->iCursor; { int nSubSrc = pSubSrc->nSrc; int jointype = pSubitem->jointype; Table *pTab = pSubitem->pTab; if( pTab && pTab->isTransient ){ sqlite3DeleteTable(0, pSubitem->pTab); } sqliteFree(pSubitem->zDatabase); sqliteFree(pSubitem->zName); sqliteFree(pSubitem->zAlias); if( nSubSrc>1 ){ int extra = nSubSrc - 1; for(i=1; i<nSubSrc; i++){ pSrc = sqlite3SrcListAppend(pSrc, 0, 0); |
︙ | ︙ | |||
2153 2154 2155 2156 2157 2158 2159 | ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". */ substExprList(p->pEList, iParent, pSub->pEList); pList = p->pEList; for(i=0; i<pList->nExpr; i++){ Expr *pExpr; if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){ | | | 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 | ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". */ substExprList(p->pEList, iParent, pSub->pEList); pList = p->pEList; for(i=0; i<pList->nExpr; i++){ Expr *pExpr; if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){ pList->a[i].zName = sqliteStrNDup(pExpr->span.z, pExpr->span.n); } } if( isAgg ){ substExprList(p->pGroupBy, iParent, pSub->pEList); substExpr(p->pHaving, iParent, pSub->pEList); } if( pSub->pOrderBy ){ |
︙ | ︙ | |||
2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 | Expr *pExpr; int iCol; Table *pTab; Index *pIdx; int base; Vdbe *v; int seekOp; ExprList *pEList, *pList, eList; struct ExprList_item eListItem; SrcList *pSrc; | > < < | | < | < < < | | > < < | < < | | > < < | | | | | | | | 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 | Expr *pExpr; int iCol; Table *pTab; Index *pIdx; int base; Vdbe *v; int seekOp; int cont; ExprList *pEList, *pList, eList; struct ExprList_item eListItem; SrcList *pSrc; /* Check to see if this query is a simple min() or max() query. Return ** zero if it is not. */ if( p->pGroupBy || p->pHaving || p->pWhere ) return 0; pSrc = p->pSrc; if( pSrc->nSrc!=1 ) return 0; pEList = p->pEList; if( pEList->nExpr!=1 ) return 0; pExpr = pEList->a[0].pExpr; if( pExpr->op!=TK_AGG_FUNCTION ) return 0; pList = pExpr->pList; if( pList==0 || pList->nExpr!=1 ) return 0; if( pExpr->token.n!=3 ) return 0; if( sqlite3StrNICmp(pExpr->token.z,"min",3)==0 ){ seekOp = OP_Rewind; }else if( sqlite3StrNICmp(pExpr->token.z,"max",3)==0 ){ seekOp = OP_Last; }else{ return 0; } pExpr = pList->a[0].pExpr; if( pExpr->op!=TK_COLUMN ) return 0; iCol = pExpr->iColumn; pTab = pSrc->a[0].pTab; /* If we get to here, it means the query is of the correct form. ** Check to make sure we have an index and make pIdx point to the ** appropriate index. If the min() or max() is on an INTEGER PRIMARY ** key column, no index is necessary so set pIdx to NULL. If no ** usable index is found, return 0. */ if( iCol<0 ){ pIdx = 0; }else{ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->nColumn>=1 ); if( pIdx->aiColumn[0]==iCol && pIdx->keyInfo.aColl[0]==pColl ) break; } if( pIdx==0 ) return 0; } /* Identify column types if we will be using the callback. This ** step is skipped if the output is going to a table or a memory cell. ** The column names have already been generated in the calling function. */ v = sqlite3GetVdbe(pParse); if( v==0 ) return 0; /* If the output is destined for a temporary table, open that table. */ if( eDest==SRT_TempTable ){ sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, 1); } /* Generating code to find the min or the max. Basically all we have ** to do is find the first or the last entry in the chosen index. If ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first ** or last entry in the main table. */ sqlite3CodeVerifySchema(pParse, pTab->iDb); base = pSrc->a[0].iCursor; computeLimitRegisters(pParse, p); if( pSrc->a[0].pSelect==0 ){ sqlite3OpenTableForReading(v, base, pTab); } cont = sqlite3VdbeMakeLabel(v); if( pIdx==0 ){ sqlite3VdbeAddOp(v, seekOp, base, 0); }else{ /* Even though the cursor used to open the index here is closed ** as soon as a single value has been read from it, allocate it ** using (pParse->nTab++) to prevent the cursor id from being ** reused. This is important for statements of the form ** "INSERT INTO x SELECT max() FROM x". */ int iIdx; iIdx = pParse->nTab++; sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); sqlite3VdbeOp3(v, OP_OpenRead, iIdx, pIdx->tnum, (char*)&pIdx->keyInfo, P3_KEYINFO); if( seekOp==OP_Rewind ){ sqlite3VdbeAddOp(v, OP_String, 0, 0); sqlite3VdbeAddOp(v, OP_MakeRecord, 1, 0); seekOp = OP_MoveGt; } sqlite3VdbeAddOp(v, seekOp, iIdx, 0); sqlite3VdbeAddOp(v, OP_IdxRecno, iIdx, 0); sqlite3VdbeAddOp(v, OP_Close, iIdx, 0); sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); } eList.nExpr = 1; memset(&eListItem, 0, sizeof(eListItem)); eList.a = &eListItem; eList.a[0].pExpr = pExpr; selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont, 0); sqlite3VdbeResolveLabel(v, cont); sqlite3VdbeAddOp(v, OP_Close, base, 0); return 1; } /* ** Analyze and ORDER BY or GROUP BY clause in a SELECT statement. Return |
︙ | ︙ | |||
2410 2411 2412 2413 2414 2415 2416 | Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* The outer name context. May be NULL. */ ){ ExprList *pEList; /* Result set. */ int i; /* For-loop variable used in multiple places */ NameContext sNC; /* Local name-context */ | < | 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 | Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* The outer name context. May be NULL. */ ){ ExprList *pEList; /* Result set. */ int i; /* For-loop variable used in multiple places */ NameContext sNC; /* Local name-context */ /* If this routine has run before, return immediately. */ if( p->isResolved ){ assert( !pOuterNC ); return SQLITE_OK; } p->isResolved = 1; |
︙ | ︙ | |||
2434 2435 2436 2437 2438 2439 2440 | if( prepSelectStmt(pParse, p) ){ return SQLITE_ERROR; } /* Resolve the expressions in the LIMIT and OFFSET clauses. These ** are not allowed to refer to any names, so pass an empty NameContext. */ | < > > > > > > > > > > > > > > > > > > > < | | | < < < < < < < < < < < < < < > | < | | < | | < | | < < | < < < < < < < < | < < < < < < | < < < < | | | > | | < | < | < < > | < < < | > > > | | | < < < | < < < < < < < < < < < < < < < < < < < < < < < < | | < | < < < < < < < < < < < < < | 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 | if( prepSelectStmt(pParse, p) ){ return SQLITE_ERROR; } /* Resolve the expressions in the LIMIT and OFFSET clauses. These ** are not allowed to refer to any names, so pass an empty NameContext. */ sNC.pParse = pParse; sNC.hasAgg = 0; sNC.nErr = 0; sNC.nRef = 0; sNC.pEList = 0; sNC.allowAgg = 0; sNC.pSrcList = 0; sNC.pNext = 0; if( sqlite3ExprResolveNames(&sNC, p->pLimit) || sqlite3ExprResolveNames(&sNC, p->pOffset) ){ return SQLITE_ERROR; } /* Set up the local name-context to pass to ExprResolveNames() to ** resolve the expression-list. */ sNC.allowAgg = 1; sNC.pSrcList = p->pSrc; sNC.pNext = pOuterNC; /* NameContext.nDepth stores the depth of recursion for this query. For ** an outer query (e.g. SELECT * FROM sqlite_master) this is 1. For ** a subquery it is 2. For a subquery of a subquery, 3. And so on. ** Parse.nMaxDepth is the maximum depth for any subquery resolved so ** far. This is used to determine the number of aggregate contexts ** required at runtime. */ sNC.nDepth = (pOuterNC?pOuterNC->nDepth+1:1); if( sNC.nDepth>pParse->nMaxDepth ){ pParse->nMaxDepth = sNC.nDepth; } /* Resolve names in the result set. */ pEList = p->pEList; if( !pEList ) return SQLITE_ERROR; for(i=0; i<pEList->nExpr; i++){ Expr *pX = pEList->a[i].pExpr; if( sqlite3ExprResolveNames(&sNC, pX) ){ return SQLITE_ERROR; } } /* If there are no aggregate functions in the result-set, and no GROUP BY ** expression, do not allow aggregates in any of the other expressions. */ assert( !p->isAgg ); if( p->pGroupBy || sNC.hasAgg ){ p->isAgg = 1; }else{ sNC.allowAgg = 0; } /* If a HAVING clause is present, then there must be a GROUP BY clause. */ if( p->pHaving && !p->pGroupBy ){ sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); return SQLITE_ERROR; } /* Add the expression list to the name-context before parsing the ** other expressions in the SELECT statement. This is so that ** expressions in the WHERE clause (etc.) can refer to expressions by ** aliases in the result set. ** ** Minor point: If this is the case, then the expression will be ** re-evaluated for each reference to it. */ sNC.pEList = p->pEList; if( sqlite3ExprResolveNames(&sNC, p->pWhere) || sqlite3ExprResolveNames(&sNC, p->pHaving) || processOrderGroupBy(&sNC, p->pOrderBy, "ORDER") || processOrderGroupBy(&sNC, p->pGroupBy, "GROUP") ){ return SQLITE_ERROR; } return SQLITE_OK; } /* ** An instance of the following struct is used by sqlite3Select() ** to save aggregate related information from the Parse object ** at the start of each call and to restore it at the end. See ** saveAggregateInfo() and restoreAggregateInfo(). */ struct AggregateInfo { int nAgg; AggExpr *aAgg; }; typedef struct AggregateInfo AggregateInfo; /* ** Copy aggregate related information from the Parse structure ** into the AggregateInfo structure. Zero the aggregate related ** values in the Parse struct. */ static void saveAggregateInfo(Parse *pParse, AggregateInfo *pInfo){ pInfo->aAgg = pParse->aAgg; pInfo->nAgg = pParse->nAgg; pParse->aAgg = 0; pParse->nAgg = 0; } /* ** Copy aggregate related information from the AggregateInfo struct ** back into the Parse structure. The aggregate related information ** currently stored in the Parse structure is deleted. */ static void restoreAggregateInfo(Parse *pParse, AggregateInfo *pInfo){ sqliteFree(pParse->aAgg); pParse->aAgg = pInfo->aAgg; pParse->nAgg = pInfo->nAgg; } /* ** Generate code for the given SELECT statement. ** ** The results are distributed in various ways depending on the ** value of eDest and iParm. ** ** eDest Value Result |
︙ | ︙ | |||
2672 2673 2674 2675 2676 2677 2678 | int eDest, /* How to dispose of the results */ int iParm, /* A parameter used by the eDest disposal method */ Select *pParent, /* Another SELECT for which this is a sub-query */ int parentTab, /* Index in pParent->pSrc of this query */ int *pParentAgg, /* True if pParent uses aggregate functions */ char *aff /* If eDest is SRT_Union, the affinity string */ ){ | | | | < | < | < < < < < < < < < > | | 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 | int eDest, /* How to dispose of the results */ int iParm, /* A parameter used by the eDest disposal method */ Select *pParent, /* Another SELECT for which this is a sub-query */ int parentTab, /* Index in pParent->pSrc of this query */ int *pParentAgg, /* True if pParent uses aggregate functions */ char *aff /* If eDest is SRT_Union, the affinity string */ ){ int i; WhereInfo *pWInfo; Vdbe *v; int isAgg; /* True for select lists like "count(*)" */ ExprList *pEList; /* List of columns to extract. */ SrcList *pTabList; /* List of tables to select from */ Expr *pWhere; /* The WHERE clause. May be NULL */ ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */ ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ Expr *pHaving; /* The HAVING clause. May be NULL */ int isDistinct; /* True if the DISTINCT keyword is present */ int distinct; /* Table to use for the distinct set */ int rc = 1; /* Value to return from this function */ AggregateInfo sAggInfo; if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1; if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; #ifndef SQLITE_OMIT_COMPOUND_SELECT /* If there is are a sequence of queries, do the earlier ones first. */ if( p->pPrior ){ return multiSelect(pParse, p, eDest, iParm, aff); } #endif saveAggregateInfo(pParse, &sAggInfo); pOrderBy = p->pOrderBy; if( eDest==SRT_Union || eDest==SRT_Except || eDest==SRT_Discard ){ p->pOrderBy = 0; } if( sqlite3SelectResolve(pParse, p, 0) ){ goto select_end; } p->pOrderBy = pOrderBy; |
︙ | ︙ | |||
2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 | ** errors before this routine starts. */ if( pParse->nErr>0 ) goto select_end; /* If writing to memory or generating a set ** only a single column may be output. */ #ifndef SQLITE_OMIT_SUBQUERY if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){ sqlite3ErrorMsg(pParse, "only a single result allowed for " "a SELECT that is part of an expression"); goto select_end; } #endif /* ORDER BY is ignored for some destinations. */ | > | > > > | > > > < | | | | | | | 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 | ** errors before this routine starts. */ if( pParse->nErr>0 ) goto select_end; /* If writing to memory or generating a set ** only a single column may be output. */ assert( eDest!=SRT_Exists || pEList->nExpr==1 ); #ifndef SQLITE_OMIT_SUBQUERY if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){ sqlite3ErrorMsg(pParse, "only a single result allowed for " "a SELECT that is part of an expression"); goto select_end; } #endif /* ORDER BY is ignored for some destinations. */ switch( eDest ){ case SRT_Union: case SRT_Except: case SRT_Discard: pOrderBy = 0; break; default: break; } /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto select_end; /* Identify column names if we will be using them in a callback. This ** step is skipped if the output is going to some other destination. */ if( eDest==SRT_Callback ){ generateColumnNames(pParse, pTabList, pEList); } /* Generate code for all sub-queries in the FROM clause */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) for(i=0; i<pTabList->nSrc; i++){ const char *zSavedAuthContext = 0; int needRestoreContext; if( pTabList->a[i].pSelect==0 ) continue; if( pTabList->a[i].zName!=0 ){ zSavedAuthContext = pParse->zAuthContext; pParse->zAuthContext = pTabList->a[i].zName; needRestoreContext = 1; }else{ needRestoreContext = 0; } sqlite3Select(pParse, pTabList->a[i].pSelect, SRT_TempTable, pTabList->a[i].iCursor, p, i, &isAgg, 0); if( needRestoreContext ){ pParse->zAuthContext = zSavedAuthContext; } pTabList = p->pSrc; pWhere = p->pWhere; if( eDest!=SRT_Union && eDest!=SRT_Except && eDest!=SRT_Discard ){ pOrderBy = p->pOrderBy; } pGroupBy = p->pGroupBy; pHaving = p->pHaving; isDistinct = p->isDistinct; } #endif |
︙ | ︙ | |||
2816 2817 2818 2819 2820 2821 2822 | flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){ if( isAgg ) *pParentAgg = 1; goto select_end; } #endif /* If there is an ORDER BY clause, resolve any collation sequences | | < < < < < < < < | | > | < < < < < < < < | | | < | < < < < < < < < < < < < < < < < < | < < < | < < < < | < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | > | | | > > > | | > > | | | | | | < | < < < < < | | > | > > > > > > | < < < | < < < < < < | | | < | > | < < < < | | < | | < > > > > | < < | < < < < < < < > | | < > > | < < < | < < < | < < < < < | < < | < | < > > | < > > | | < < | | < < | > | | < < | < < < < < < < | | < > | < < | > > > < < < < < < | < < < < < < < < < | < < < < > | < < < < | > > | > > | | < < | > | > | | < > | | < | | < < | < < < < < < < < < > | < < | > > | | > > > > > > > | < | < | < > | < < > | < < | < < | | < < < > | > | > | | < | < | | < < | | | < < > | < < | | | | | > > | > | < | 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 | flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){ if( isAgg ) *pParentAgg = 1; goto select_end; } #endif /* If there is an ORDER BY clause, resolve any collation sequences ** names that have been explicitly specified. */ if( pOrderBy ){ for(i=0; i<pOrderBy->nExpr; i++){ if( pOrderBy->a[i].zName ){ pOrderBy->a[i].pExpr->pColl = sqlite3LocateCollSeq(pParse, pOrderBy->a[i].zName, -1); } } if( pParse->nErr ){ goto select_end; } } /* Set the limiter. */ computeLimitRegisters(pParse, p); /* If the output is destined for a temporary table, open that table. */ if( eDest==SRT_TempTable ){ sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, pEList->nExpr); } /* Do an analysis of aggregate expressions. */ if( isAgg || pGroupBy ){ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; sNC.pSrcList = pTabList; assert( pParse->nAgg==0 ); isAgg = 1; for(i=0; i<pEList->nExpr; i++){ if( sqlite3ExprAnalyzeAggregates(&sNC, pEList->a[i].pExpr) ){ goto select_end; } } if( pGroupBy ){ for(i=0; i<pGroupBy->nExpr; i++){ if( sqlite3ExprAnalyzeAggregates(&sNC, pGroupBy->a[i].pExpr) ){ goto select_end; } } } if( pHaving && sqlite3ExprAnalyzeAggregates(&sNC, pHaving) ){ goto select_end; } if( pOrderBy ){ for(i=0; i<pOrderBy->nExpr; i++){ if( sqlite3ExprAnalyzeAggregates(&sNC, pOrderBy->a[i].pExpr) ){ goto select_end; } } } } /* Reset the aggregator */ if( isAgg ){ int addr = sqlite3VdbeAddOp(v, OP_AggReset, (pGroupBy?0:1), pParse->nAgg); for(i=0; i<pParse->nAgg; i++){ FuncDef *pFunc; if( (pFunc = pParse->aAgg[i].pFunc)!=0 && pFunc->xFinalize!=0 ){ sqlite3VdbeOp3(v, OP_AggInit, 0, i, (char*)pFunc, P3_FUNCDEF); } } if( pGroupBy ){ int sz = sizeof(KeyInfo) + pGroupBy->nExpr*sizeof(CollSeq*); KeyInfo *pKey = (KeyInfo *)sqliteMalloc(sz); if( 0==pKey ){ goto select_end; } pKey->enc = pParse->db->enc; pKey->nField = pGroupBy->nExpr; for(i=0; i<pGroupBy->nExpr; i++){ pKey->aColl[i] = sqlite3ExprCollSeq(pParse, pGroupBy->a[i].pExpr); if( !pKey->aColl[i] ){ pKey->aColl[i] = pParse->db->pDfltColl; } } sqlite3VdbeChangeP3(v, addr, (char *)pKey, P3_KEYINFO_HANDOFF); } } /* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists */ if( eDest==SRT_Mem || eDest==SRT_Exists ){ sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_String8 : OP_Integer, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); } /* Open a temporary table to use for the distinct set. */ if( isDistinct ){ distinct = pParse->nTab++; openTempIndex(pParse, p, distinct, 0); }else{ distinct = -1; } /* Begin the database scan */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy ? 0 : &pOrderBy, p->pFetch); if( pWInfo==0 ) goto select_end; /* Use the standard inner loop if we are not dealing with ** aggregates */ if( !isAgg ){ if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest, iParm, pWInfo->iContinue, pWInfo->iBreak, aff) ){ goto select_end; } } /* If we are dealing with aggregates, then do the special aggregate ** processing. */ else{ AggExpr *pAgg; int lbl1 = 0; pParse->fillAgg = 1; if( pGroupBy ){ for(i=0; i<pGroupBy->nExpr; i++){ sqlite3ExprCode(pParse, pGroupBy->a[i].pExpr); } /* No affinity string is attached to the following OP_MakeRecord ** because we do not need to do any coercion of datatypes. */ sqlite3VdbeAddOp(v, OP_MakeRecord, pGroupBy->nExpr, 0); lbl1 = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_AggFocus, 0, lbl1); } for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){ if( pAgg->isAgg ) continue; sqlite3ExprCode(pParse, pAgg->pExpr); sqlite3VdbeAddOp(v, OP_AggSet, 0, i); } pParse->fillAgg = 0; if( lbl1<0 ){ sqlite3VdbeResolveLabel(v, lbl1); } for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){ Expr *pE; int nExpr; FuncDef *pDef; if( !pAgg->isAgg ) continue; assert( pAgg->pFunc!=0 ); assert( pAgg->pFunc->xStep!=0 ); pDef = pAgg->pFunc; pE = pAgg->pExpr; assert( pE!=0 ); assert( pE->op==TK_AGG_FUNCTION ); nExpr = sqlite3ExprCodeExprList(pParse, pE->pList); sqlite3VdbeAddOp(v, OP_Integer, i, 0); if( pDef->needCollSeq ){ CollSeq *pColl = 0; int j; for(j=0; !pColl && j<nExpr; j++){ pColl = sqlite3ExprCollSeq(pParse, pE->pList->a[j].pExpr); } if( !pColl ) pColl = pParse->db->pDfltColl; sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ); } sqlite3VdbeOp3(v, OP_AggFunc, 0, nExpr, (char*)pDef, P3_POINTER); } } /* End the database scan loop. */ sqlite3WhereEnd(pWInfo); /* If we are processing aggregates, we need to set up a second loop ** over all of the aggregate values and process them. */ if( isAgg ){ int endagg = sqlite3VdbeMakeLabel(v); int startagg; startagg = sqlite3VdbeAddOp(v, OP_AggNext, 0, endagg); if( pHaving ){ sqlite3ExprIfFalse(pParse, pHaving, startagg, 1); } if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest, iParm, startagg, endagg, aff) ){ goto select_end; } sqlite3VdbeAddOp(v, OP_Goto, 0, startagg); sqlite3VdbeResolveLabel(v, endagg); sqlite3VdbeAddOp(v, OP_Noop, 0, 0); } /* If there is an ORDER BY clause, then we need to sort the results ** and send them to the callback one by one. */ if( pOrderBy ){ generateSortTail(pParse, p, v, pEList->nExpr, eDest, iParm); } |
︙ | ︙ | |||
3178 3179 3180 3181 3182 3183 3184 | assert( pParent->pSrc->nSrc>parentTab ); assert( pParent->pSrc->a[parentTab].pSelect==p ); sqlite3SelectDelete(p); pParent->pSrc->a[parentTab].pSelect = 0; } #endif | < < < < | < | 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 | assert( pParent->pSrc->nSrc>parentTab ); assert( pParent->pSrc->a[parentTab].pSelect==p ); sqlite3SelectDelete(p); pParent->pSrc->a[parentTab].pSelect = 0; } #endif /* The SELECT was successfully coded. Set the return code to 0 ** to indicate no errors. */ rc = 0; /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. */ select_end: restoreAggregateInfo(pParse, &sAggInfo); return rc; } |
Deleted SQLite.Interop/src/server.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to SQLite.Interop/src/shell.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** ** $Id: shell.c,v 1.1 2005/03/01 16:04:35 rmsimpson Exp $ */ #include <stdlib.h> #include <string.h> #include <stdio.h> #include <assert.h> #include "sqlite3.h" #include <ctype.h> |
︙ | ︙ | |||
77 78 79 80 81 82 83 | static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ /* ** Determines if a string is a number of not. */ | | | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ /* ** Determines if a string is a number of not. */ static int isNumber(const unsigned char *z, int *realnum){ if( *z=='-' || *z=='+' ) z++; if( !isdigit(*z) ){ return 0; } z++; if( realnum ) *realnum = 0; while( isdigit(*z) ){ z++; } |
︙ | ︙ | |||
309 310 311 312 313 314 315 | }else if( c=='\n' ){ fputc('\\', out); fputc('n', out); }else if( c=='\r' ){ fputc('\\', out); fputc('r', out); }else if( !isprint(c) ){ | | | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | }else if( c=='\n' ){ fputc('\\', out); fputc('n', out); }else if( c=='\r' ){ fputc('\\', out); fputc('r', out); }else if( !isprint(c) ){ fprintf(out, "\\%03o", c); }else{ fputc(c, out); } } fputc('"', out); } |
︙ | ︙ | |||
652 653 654 655 656 657 658 | struct callback_data *p = (struct callback_data *)pArg; if( nArg!=3 ) return 1; zTable = azArg[0]; zType = azArg[1]; zSql = azArg[2]; | | < < | < < | | 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 | struct callback_data *p = (struct callback_data *)pArg; if( nArg!=3 ) return 1; zTable = azArg[0]; zType = azArg[1]; zSql = azArg[2]; if( strcasecmp(zTable,"sqlite_sequence")!=0 ){ fprintf(p->out, "%s;\n", zSql); }else{ fprintf(p->out, "DELETE FROM sqlite_sequence;\n"); } if( strcmp(zType, "table")==0 ){ sqlite3_stmt *pTableInfo = 0; char *zSelect = 0; char *zTableInfo = 0; char *zTmp = 0; |
︙ | ︙ | |||
686 687 688 689 690 691 692 | zTmp = appendText(zTmp, zTable, '"'); if( zTmp ){ zSelect = appendText(zSelect, zTmp, '\''); } zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); rc = sqlite3_step(pTableInfo); while( rc==SQLITE_ROW ){ | < | | 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 | zTmp = appendText(zTmp, zTable, '"'); if( zTmp ){ zSelect = appendText(zSelect, zTmp, '\''); } zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); rc = sqlite3_step(pTableInfo); while( rc==SQLITE_ROW ){ zSelect = appendText(zSelect, "quote(", 0); zSelect = appendText(zSelect, sqlite3_column_text(pTableInfo, 1), '"'); rc = sqlite3_step(pTableInfo); if( rc==SQLITE_ROW ){ zSelect = appendText(zSelect, ") || ', ' || ", 0); }else{ zSelect = appendText(zSelect, ") ", 0); } } |
︙ | ︙ | |||
826 827 828 829 830 831 832 | if( c=='n' ){ c = '\n'; }else if( c=='t' ){ c = '\t'; }else if( c=='r' ){ c = '\r'; }else if( c>='0' && c<='7' ){ | | | 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 | if( c=='n' ){ c = '\n'; }else if( c=='t' ){ c = '\t'; }else if( c=='r' ){ c = '\r'; }else if( c>='0' && c<='7' ){ c =- '0'; if( z[i+1]>='0' && z[i+1]<='7' ){ i++; c = (c<<3) + z[i] - '0'; if( z[i+1]>='0' && z[i+1]<='7' ){ i++; c = (c<<3) + z[i] - '0'; } |
︙ | ︙ | |||
985 986 987 988 989 990 991 | ** did an .explain followed by a .width, .mode or .header ** command. */ p->mode = MODE_Column; p->showHeader = 1; memset(p->colWidth,0,ArraySize(p->colWidth)); p->colWidth[0] = 4; | | | | 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 | ** did an .explain followed by a .width, .mode or .header ** command. */ p->mode = MODE_Column; p->showHeader = 1; memset(p->colWidth,0,ArraySize(p->colWidth)); p->colWidth[0] = 4; p->colWidth[1] = 12; p->colWidth[2] = 10; p->colWidth[3] = 10; p->colWidth[4] = 35; }else if (p->explainPrev.valid) { p->explainPrev.valid = 0; p->mode = p->explainPrev.mode; p->showHeader = p->explainPrev.showHeader; memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth)); } }else |
︙ | ︙ | |||
1094 1095 1096 1097 1098 1099 1100 | i++; if( i<nCol ){ azCol[i] = &z[nSep]; z += nSep-1; } } } | < | 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 | i++; if( i<nCol ){ azCol[i] = &z[nSep]; z += nSep-1; } } } if( i+1!=nCol ){ fprintf(stderr,"%s line %d: expected %d columns of data but found %d\n", zFile, lineno, nCol, i+1); zCommit = "ROLLBACK"; break; } for(i=0; i<nCol; i++){ |
︙ | ︙ | |||
1291 1292 1293 1294 1295 1296 1297 | zShellStatic = 0; } }else{ sqlite3_exec(p->db, "SELECT sql FROM " " (SELECT * FROM sqlite_master UNION ALL" " SELECT * FROM sqlite_temp_master) " | | | 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 | zShellStatic = 0; } }else{ sqlite3_exec(p->db, "SELECT sql FROM " " (SELECT * FROM sqlite_master UNION ALL" " SELECT * FROM sqlite_temp_master) " "WHERE type!='meta' AND sql NOTNULL " "ORDER BY substr(type,2,1), name", callback, &data, &zErrMsg ); } if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); sqlite3_free(zErrMsg); |
︙ | ︙ | |||
1335 1336 1337 1338 1339 1340 1341 | char **azResult; int nRow, rc; char *zErrMsg; open_db(p); if( nArg==1 ){ rc = sqlite3_get_table(p->db, "SELECT name FROM sqlite_master " | | | 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 | char **azResult; int nRow, rc; char *zErrMsg; open_db(p); if( nArg==1 ){ rc = sqlite3_get_table(p->db, "SELECT name FROM sqlite_master " "WHERE type IN ('table','view') " "UNION ALL " "SELECT name FROM sqlite_temp_master " "WHERE type IN ('table','view') " "ORDER BY 1", &azResult, &nRow, 0, &zErrMsg ); }else{ |
︙ | ︙ | |||
1699 1700 1701 1702 1703 1704 1705 | #endif } if( i<argc ){ zFirstCmd = argv[i++]; } data.out = stdout; | < < < < < < < | 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 | #endif } if( i<argc ){ zFirstCmd = argv[i++]; } data.out = stdout; /* Go ahead and open the database file if it already exists. If the ** file does not exist, delay opening it. This prevents empty database ** files from being created if a user mistypes the database name argument ** to the sqlite command-line tool. */ if( access(data.zDbFilename, 0)==0 ){ open_db(&data); |
︙ | ︙ |
Changes to SQLite.Interop/src/sqlite3.def.
︙ | ︙ | |||
35 36 37 38 39 40 41 | sqlite3_complete sqlite3_complete16 sqlite3_create_collation sqlite3_create_collation16 sqlite3_create_function sqlite3_create_function16 sqlite3_data_count | < < < < < < < < < < | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | sqlite3_complete sqlite3_complete16 sqlite3_create_collation sqlite3_create_collation16 sqlite3_create_function sqlite3_create_function16 sqlite3_data_count sqlite3_errcode sqlite3_errmsg sqlite3_errmsg16 sqlite3_exec sqlite3_finalize sqlite3_free sqlite3_free_table sqlite3_get_auxdata sqlite3_get_table sqlite3_interrupt sqlite3_last_insert_rowid sqlite3_libversion sqlite3_mprintf sqlite3_open sqlite3_open16 sqlite3_prepare sqlite3_prepare16 sqlite3_progress_handler sqlite3_reset sqlite3_result_blob sqlite3_result_double sqlite3_result_error sqlite3_result_error16 sqlite3_result_int sqlite3_result_int64 sqlite3_result_null sqlite3_result_text sqlite3_result_text16 sqlite3_result_text16be sqlite3_result_text16le sqlite3_result_value sqlite3_set_authorizer sqlite3_set_auxdata sqlite3_snprintf sqlite3_step sqlite3_total_changes sqlite3_trace sqlite3_user_data sqlite3_value_blob sqlite3_value_bytes sqlite3_value_bytes16 sqlite3_value_double sqlite3_value_int sqlite3_value_int64 sqlite3_value_text sqlite3_value_text16 sqlite3_value_text16be sqlite3_value_text16le sqlite3_value_type sqlite3_vmprintf |
Changes to SQLite.Interop/src/sqlite3.h.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** | | | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** ** @(#) $Id: sqlite3.h,v 1.1 2005/03/01 16:04:36 rmsimpson Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ #include <stdarg.h> /* Needed for the definition of va_list */ /* ** Make sure we can call this stuff from C++. */ #ifdef __cplusplus extern "C" { #endif /* ** The version of the SQLite library. */ #ifdef SQLITE_VERSION # undef SQLITE_VERSION #endif #define SQLITE_VERSION "3.1.3" /* ** The format of the version string is "X.Y.Z<trailing string>", where ** X is the major version number, Y is the minor version number and Z ** is the release number. The trailing string is often "alpha" or "beta". ** For example "3.1.1beta". ** ** The SQLITE_VERSION_NUMBER is an integer with the value ** (X*100000 + Y*1000 + Z). For example, for version "3.1.1beta", ** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using ** version 3.1.1 or greater at compile time, programs may use the test ** (SQLITE_VERSION_NUMBER>=3001001). */ #ifdef SQLITE_VERSION_NUMBER # undef SQLITE_VERSION_NUMBER #endif #define SQLITE_VERSION_NUMBER 3001003 /* ** The version string is also compiled into the library so that a program ** can check to make sure that the lib*.a file and the *.h file are from ** the same version. The sqlite3_libversion() function returns a pointer ** to the sqlite3_version variable - useful in DLLs which cannot access ** global variables. |
︙ | ︙ | |||
82 83 84 85 86 87 88 | typedef __int64 sqlite_int64; typedef unsigned __int64 sqlite_uint64; #else typedef long long int sqlite_int64; typedef unsigned long long int sqlite_uint64; #endif | < < < < < < < | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | typedef __int64 sqlite_int64; typedef unsigned __int64 sqlite_uint64; #else typedef long long int sqlite_int64; typedef unsigned long long int sqlite_uint64; #endif /* ** A function to close the database. ** ** Call this function with a pointer to a structure that was previously ** returned from sqlite3_open() and the corresponding database will by closed. ** |
︙ | ︙ | |||
161 162 163 164 165 166 167 | ); /* ** Return values for sqlite3_exec() and sqlite3_step() */ #define SQLITE_OK 0 /* Successful result */ #define SQLITE_ERROR 1 /* SQL error or missing database */ | | | | < | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | ); /* ** Return values for sqlite3_exec() and sqlite3_step() */ #define SQLITE_OK 0 /* Successful result */ #define SQLITE_ERROR 1 /* SQL error or missing database */ #define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */ #define SQLITE_PERM 3 /* Access permission denied */ #define SQLITE_ABORT 4 /* Callback routine requested an abort */ #define SQLITE_BUSY 5 /* The database file is locked */ #define SQLITE_LOCKED 6 /* A table in the database is locked */ #define SQLITE_NOMEM 7 /* A malloc() failed */ #define SQLITE_READONLY 8 /* Attempt to write a readonly database */ #define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ #define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ #define SQLITE_CORRUPT 11 /* The database disk image is malformed */ #define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */ #define SQLITE_FULL 13 /* Insertion failed because database is full */ #define SQLITE_CANTOPEN 14 /* Unable to open the database file */ #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ #define SQLITE_EMPTY 16 /* Database is empty */ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* Too much data for one row of a table */ #define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */ #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ #define SQLITE_FORMAT 24 /* Auxiliary database format error */ #define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ #define SQLITE_NOTADB 26 /* File opened that is not a database file */ #define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ /* ** Each entry in an SQLite table has a unique integer key. (The key is ** the value of the INTEGER PRIMARY KEY column if there is such a column, ** otherwise the key is generated at random. The unique key is always ** available as the ROWID, OID, or _ROWID_ column.) The following routine ** returns the integer key of the most recent insert in the database. |
︙ | ︙ | |||
377 378 379 380 381 382 383 | ** ** For example, so some string variable contains text as follows: ** ** char *zText = "It's a happy day!"; ** ** We can use this text in an SQL statement as follows: ** | < | | | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | ** ** For example, so some string variable contains text as follows: ** ** char *zText = "It's a happy day!"; ** ** We can use this text in an SQL statement as follows: ** ** sqlite3_exec_printf(db, "INSERT INTO table VALUES('%q')", ** callback1, 0, 0, zText); ** ** Because the %q format string is used, the '\'' character in zText ** is escaped and the SQL generated is as follows: ** ** INSERT INTO table1 VALUES('It''s a happy day!') ** ** This is correct. Had we used %s instead of %q, the generated SQL |
︙ | ︙ | |||
457 458 459 460 461 462 463 | #define SQLITE_SELECT 21 /* NULL NULL */ #define SQLITE_TRANSACTION 22 /* NULL NULL */ #define SQLITE_UPDATE 23 /* Table Name Column Name */ #define SQLITE_ATTACH 24 /* Filename NULL */ #define SQLITE_DETACH 25 /* Database Name NULL */ #define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ #define SQLITE_REINDEX 27 /* Index Name NULL */ | < | | | < < < < < < < | 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | #define SQLITE_SELECT 21 /* NULL NULL */ #define SQLITE_TRANSACTION 22 /* NULL NULL */ #define SQLITE_UPDATE 23 /* Table Name Column Name */ #define SQLITE_ATTACH 24 /* Filename NULL */ #define SQLITE_DETACH 25 /* Database Name NULL */ #define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ #define SQLITE_REINDEX 27 /* Index Name NULL */ /* ** The return value of the authorization function should be one of the ** following constants: */ /* #define SQLITE_OK 0 // Allow access (This is actually defined above) */ #define SQLITE_DENY 1 /* Abort the SQL statement with an error */ #define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ /* ** Register a function that is called at every invocation of sqlite3_exec() ** or sqlite3_prepare(). This function can be used (for example) to generate ** a log file of all SQL executed against a database. */ void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); /* ** This routine configures a callback function - the progress callback - that ** is invoked periodically during long running calls to sqlite3_exec(), ** sqlite3_step() and sqlite3_get_table(). An example use for this API is to ** keep a GUI updated during a large query. ** |
︙ | ︙ | |||
701 702 703 704 705 706 707 708 709 710 711 712 713 714 | ** must match exactly. If no parameter with the given name is found, ** return 0. */ int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); /* ** Set all the parameters in the compiled SQL statement to NULL. */ int sqlite3_clear_bindings(sqlite3_stmt*); /* ** Return the number of columns in the result set returned by the compiled ** SQL statement. This routine returns 0 if pStmt is an SQL statement ** that does not return data (for example an UPDATE). | > > | 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 | ** must match exactly. If no parameter with the given name is found, ** return 0. */ int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); /* ** Set all the parameters in the compiled SQL statement to NULL. ** ******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** */ int sqlite3_clear_bindings(sqlite3_stmt*); /* ** Return the number of columns in the result set returned by the compiled ** SQL statement. This routine returns 0 if pStmt is an SQL statement ** that does not return data (for example an UPDATE). |
︙ | ︙ | |||
1015 1016 1017 1018 1019 1020 1021 | ** of the aggregate can use the returned buffer to accumulate data. ** ** The buffer allocated is freed automatically by SQLite. */ void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* | | | | > | 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 | ** of the aggregate can use the returned buffer to accumulate data. ** ** The buffer allocated is freed automatically by SQLite. */ void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* ** The pUserData parameter to the sqlite3_create_function() and ** sqlite3_create_aggregate() routines used to register user functions ** is available to the implementation of the function using this ** call. */ void *sqlite3_user_data(sqlite3_context*); /* ** The following two functions may be used by scalar user functions to ** associate meta-data with argument values. If the same value is passed to ** multiple invocations of the user-function during query execution, under |
︙ | ︙ | |||
1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 | ** Sleep for a little while. The second parameter is the number of ** miliseconds to sleep for. ** ** If the operating system does not support sleep requests with ** milisecond time resolution, then the time will be rounded up to ** the nearest second. The number of miliseconds of sleep actually ** requested from the operating system is returned. */ int sqlite3_sleep(int); /* | > > | > < < < < < < < < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 | ** Sleep for a little while. The second parameter is the number of ** miliseconds to sleep for. ** ** If the operating system does not support sleep requests with ** milisecond time resolution, then the time will be rounded up to ** the nearest second. The number of miliseconds of sleep actually ** requested from the operating system is returned. ** ******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** */ int sqlite3_sleep(int); /* ** Return TRUE (non-zero) of the statement supplied as an argument needs ** to be recompiled. A statement needs to be recompiled whenever the ** execution environment changes in a way that would alter the program ** that sqlite3_prepare() generates. For example, if new functions or ** collating sequences are registered or if an authorizer function is ** added or changed. ** ******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** */ int sqlite3_expired(sqlite3_stmt*); /* ** If the following global variable is made to point to a ** string which is the name of a directory, then all temporary files ** created by SQLite will be placed in that directory. If this variable ** is NULL pointer, then SQLite does a search for an appropriate temporary ** file directory. ** ** Once sqlite3_open() has been called, changing this variable will invalidate the ** current temporary database, if any. */ extern char *sqlite3_temp_directory; #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif |
Changes to SQLite.Interop/src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | < < < < < < < < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.1 2005/03/01 16:04:36 rmsimpson Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** These #defines should enable >2GB file support on Posix if the ** underlying operating system supports it. If the OS lacks ** large file support, or if the OS is windows, these should be no-ops. ** ** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch ** on the compiler command line. This is necessary if you are compiling |
︙ | ︙ | |||
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | # define _LARGE_FILE 1 # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 # endif # define _LARGEFILE_SOURCE 1 #endif #include "sqlite3.h" #include "hash.h" #include "parse.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <stddef.h> | > < < < < < < < < < < < < < < < < < < < < < < < | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | # define _LARGE_FILE 1 # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 # endif # define _LARGEFILE_SOURCE 1 #endif #include "config.h" #include "sqlite3.h" #include "hash.h" #include "parse.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <stddef.h> /* ** The maximum number of in-memory pages to use for the main database ** table and for temporary tables. Internally, the MAX_PAGES and ** TEMP_PAGES macros are used. To override the default values at ** compilation time, the SQLITE_DEFAULT_CACHE_SIZE and ** SQLITE_DEFAULT_TEMP_CACHE_SIZE macros should be set. */ #ifdef SQLITE_DEFAULT_CACHE_SIZE # define MAX_PAGES SQLITE_DEFAULT_CACHE_SIZE #else # define MAX_PAGES 2000 #endif #ifdef SQLITE_DEFAULT_TEMP_CACHE_SIZE # define TEMP_PAGES SQLITE_DEFAULT_TEMP_CACHE_SIZE #else # define TEMP_PAGES 500 #endif /* ** If the following macro is set to 1, then NULL values are considered ** distinct for the SELECT DISTINCT statement and for UNION or EXCEPT ** compound queries. No other SQL database engine (among those tested) ** works this way except for OCELOT. But the SQL92 spec implies that ** this is how things should work. ** |
︙ | ︙ | |||
144 145 146 147 148 149 150 | /* ** The maximum value of a ?nnn wildcard that the parser will accept. */ #define SQLITE_MAX_VARIABLE_NUMBER 999 /* | | | < | > | | | | > > > | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | /* ** The maximum value of a ?nnn wildcard that the parser will accept. */ #define SQLITE_MAX_VARIABLE_NUMBER 999 /* ** When building SQLite for embedded systems where memory is scarce, ** you can define one or more of the following macros to omit extra ** features of the library and thus keep the size of the library to ** a minimum. */ /* #define SQLITE_OMIT_AUTHORIZATION 1 */ /* #define SQLITE_OMIT_MEMORYDB 1 */ /* #define SQLITE_OMIT_VACUUM 1 */ /* #define SQLITE_OMIT_DATETIME_FUNCS 1 */ /* #define SQLITE_OMIT_PROGRESS_CALLBACK 1 */ /* #define SQLITE_OMIT_AUTOVACUUM */ /* #define SQLITE_OMIT_ALTERTABLE */ /* ** Provide a default value for TEMP_STORE in case it is not specified ** on the command-line */ #ifndef TEMP_STORE # define TEMP_STORE 1 |
︙ | ︙ | |||
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | # define UINT8_TYPE unsigned char #endif #ifndef INT8_TYPE # define INT8_TYPE signed char #endif #ifndef LONGDOUBLE_TYPE # define LONGDOUBLE_TYPE long double #endif typedef sqlite_int64 i64; /* 8-byte signed integer */ typedef UINT64_TYPE u64; /* 8-byte unsigned integer */ typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ typedef INT16_TYPE i16; /* 2-byte signed integer */ typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ typedef UINT8_TYPE i8; /* 1-byte signed integer */ /* ** Macros to determine whether the machine is big or little endian, ** evaluated at runtime. */ extern const int sqlite3one; #define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) | > > > > > > > > > > > > > > > > | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | # define UINT8_TYPE unsigned char #endif #ifndef INT8_TYPE # define INT8_TYPE signed char #endif #ifndef LONGDOUBLE_TYPE # define LONGDOUBLE_TYPE long double #endif #ifndef INTPTR_TYPE # if SQLITE_PTR_SZ==4 # define INTPTR_TYPE int # else # define INTPTR_TYPE sqlite_int64 # endif #endif #ifndef UINTPTR_TYPE # if SQLITE_PTR_SZ==4 # define UINTPTR_TYPE unsigned int # else # define UINTPTR_TYPE sqlite_uint64 # endif #endif typedef sqlite_int64 i64; /* 8-byte signed integer */ typedef UINT64_TYPE u64; /* 8-byte unsigned integer */ typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ typedef INT16_TYPE i16; /* 2-byte signed integer */ typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ typedef UINT8_TYPE i8; /* 1-byte signed integer */ typedef INTPTR_TYPE ptr; /* Big enough to hold a pointer */ typedef UINTPTR_TYPE uptr; /* Big enough to hold a pointer */ /* ** Macros to determine whether the machine is big or little endian, ** evaluated at runtime. */ extern const int sqlite3one; #define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) |
︙ | ︙ | |||
231 232 233 234 235 236 237 | ** handle is passed a pointer to sqlite.busyHandler. The busy-handler ** callback is currently invoked only from within pager.c. */ typedef struct BusyHandler BusyHandler; struct BusyHandler { int (*xFunc)(void *,int); /* The busy callback */ void *pArg; /* First arg to busy callback */ | < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < | | | | | | | | | | | | | | | | | | | | | > | < < < < < < < < < < < < < < | > > > > > | | | | < | 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | ** handle is passed a pointer to sqlite.busyHandler. The busy-handler ** callback is currently invoked only from within pager.c. */ typedef struct BusyHandler BusyHandler; struct BusyHandler { int (*xFunc)(void *,int); /* The busy callback */ void *pArg; /* First arg to busy callback */ }; /* ** Defer sourcing vdbe.h and btree.h until after the "u8" and ** "BusyHandler typedefs. */ #include "vdbe.h" #include "btree.h" /* ** This macro casts a pointer to an integer. Useful for doing ** pointer arithmetic. */ #define Addr(X) ((uptr)X) /* ** If memory allocation problems are found, recompile with ** ** -DSQLITE_DEBUG=1 ** ** to enable some sanity checking on malloc() and free(). To ** check for memory leaks, recompile with ** ** -DSQLITE_DEBUG=2 ** ** and a line of text will be written to standard error for ** each malloc() and free(). This output can be analyzed ** by an AWK script to determine if there are any leaks. */ #ifdef SQLITE_MEMDEBUG # define sqliteMalloc(X) sqlite3Malloc_(X,1,__FILE__,__LINE__) # define sqliteMallocRaw(X) sqlite3Malloc_(X,0,__FILE__,__LINE__) # define sqliteFree(X) sqlite3Free_(X,__FILE__,__LINE__) # define sqliteRealloc(X,Y) sqlite3Realloc_(X,Y,__FILE__,__LINE__) # define sqliteStrDup(X) sqlite3StrDup_(X,__FILE__,__LINE__) # define sqliteStrNDup(X,Y) sqlite3StrNDup_(X,Y,__FILE__,__LINE__) #else # define sqliteFree sqlite3FreeX # define sqliteMalloc sqlite3Malloc # define sqliteMallocRaw sqlite3MallocRaw # define sqliteRealloc sqlite3Realloc # define sqliteStrDup sqlite3StrDup # define sqliteStrNDup sqlite3StrNDup #endif /* ** This variable gets set if malloc() ever fails. After it gets set, ** the SQLite library shuts down permanently. */ extern int sqlite3_malloc_failed; /* ** The following global variables are used for testing and debugging ** only. They only work if SQLITE_DEBUG is defined. */ #ifdef SQLITE_MEMDEBUG extern int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */ extern int sqlite3_nFree; /* Number of sqliteFree() calls */ extern int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */ extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */ #endif /* ** Name of the master database table. The master database table ** is a special table that holds the names and attributes of all ** user tables and indices. */ #define MASTER_NAME "sqlite_master" #define TEMP_MASTER_NAME "sqlite_temp_master" /* ** The root-page of the master database table. */ #define MASTER_ROOT 1 /* ** The name of the schema table. */ #define SCHEMA_TABLE(x) (x==1?TEMP_MASTER_NAME:MASTER_NAME) /* ** A convenience macro that returns the number of elements in ** an array. */ #define ArraySize(X) (sizeof(X)/sizeof(X[0])) /* ** Forward references to structures */ typedef struct Column Column; typedef struct Table Table; typedef struct Index Index; typedef struct Instruction Instruction; typedef struct Expr Expr; typedef struct ExprList ExprList; typedef struct Parse Parse; typedef struct Token Token; typedef struct IdList IdList; typedef struct SrcList SrcList; typedef struct WhereInfo WhereInfo; typedef struct WhereLevel WhereLevel; typedef struct Select Select; typedef struct AggExpr AggExpr; typedef struct FuncDef FuncDef; typedef struct Trigger Trigger; typedef struct TriggerStep TriggerStep; typedef struct TriggerStack TriggerStack; typedef struct FKey FKey; typedef struct Db Db; typedef struct AuthContext AuthContext; typedef struct KeyClass KeyClass; typedef struct CollSeq CollSeq; typedef struct KeyInfo KeyInfo; typedef struct NameContext NameContext; typedef struct Fetch Fetch; /* ** Each database file to be accessed by the system is an instance ** of the following structure. There are normally two of these structures ** in the sqlite.aDb[] array. aDb[0] is the main database file and ** aDb[1] is the database file used to hold temporary tables. Additional ** databases may be attached. */ struct Db { char *zName; /* Name of this database */ Btree *pBt; /* The B*Tree structure for this database file */ int schema_cookie; /* Database schema version number for this file */ Hash tblHash; /* All tables indexed by name */ Hash idxHash; /* All (named) indices indexed by name */ Hash trigHash; /* All triggers indexed by name */ Hash aFKey; /* Foreign keys indexed by to-table */ u16 flags; /* Flags associated with this database */ u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ u8 safety_level; /* How aggressive at synching data to disk */ int cache_size; /* Number of pages to use in the cache */ Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ void *pAux; /* Auxiliary data. Usually NULL */ void (*xFreeAux)(void*); /* Routine to free pAux */ }; /* ** These macros can be used to test, set, or clear bits in the ** Db.flags field. */ #define DbHasProperty(D,I,P) (((D)->aDb[I].flags&(P))==(P)) #define DbHasAnyProperty(D,I,P) (((D)->aDb[I].flags&(P))!=0) #define DbSetProperty(D,I,P) (D)->aDb[I].flags|=(P) #define DbClearProperty(D,I,P) (D)->aDb[I].flags&=~(P) /* ** Allowed values for the DB.flags field. ** ** The DB_SchemaLoaded flag is set after the database schema has been ** read into internal hash tables. ** ** DB_UnresetViews means that one or more views have column names that ** have been filled out. If the schema changes, these column names might ** changes and so the view will need to be reset. */ #define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ #define DB_UnresetViews 0x0002 /* Some views have defined column names */ #define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) /* ** Each database is an instance of the following structure. ** ** The sqlite.lastRowid records the last insert rowid generated by an |
︙ | ︙ | |||
457 458 459 460 461 462 463 464 | ** store the most recent error code and, if applicable, string. The ** internal function sqlite3Error() is used to set these variables ** consistently. */ struct sqlite3 { int nDb; /* Number of backends currently in use */ Db *aDb; /* All backends */ int flags; /* Miscellanous flags. See below */ | > < | > > > > > | | < < < < < < < < < < < < < < < | < | | > > > | | | < | < < < > < < < > | < < | < < < < < < | | < < < < < < < < < < < < < < < < < < < < | | | | < < | 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 | ** store the most recent error code and, if applicable, string. The ** internal function sqlite3Error() is used to set these variables ** consistently. */ struct sqlite3 { int nDb; /* Number of backends currently in use */ Db *aDb; /* All backends */ Db aDbStatic[2]; /* Static space for the 2 default backends */ int flags; /* Miscellanous flags. See below */ u8 file_format; /* What file format version is this database? */ u8 temp_store; /* 1: file 2: memory 0: default */ int nTable; /* Number of tables in the database */ BusyHandler busyHandler; /* Busy callback */ void *pCommitArg; /* Argument to xCommitCallback() */ int (*xCommitCallback)(void*);/* Invoked at every commit. */ Hash aFunc; /* All functions that can be in SQL exprs */ Hash aCollSeq; /* All collating sequences */ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ i64 lastRowid; /* ROWID of most recent insert (see above) */ i64 priorNewRowid; /* Last randomly generated ROWID */ int magic; /* Magic number for detect library misuse */ int nChange; /* Value returned by sqlite3_changes() */ int nTotalChange; /* Value returned by sqlite3_total_changes() */ struct sqlite3InitInfo { /* Information used during initialization */ int iDb; /* When back is being initialized */ int newTnum; /* Rootpage of table being initialized */ u8 busy; /* TRUE if currently initializing */ } init; struct Vdbe *pVdbe; /* List of active virtual machines */ int activeVdbeCnt; /* Number of vdbes currently executing */ void (*xTrace)(void*,const char*); /* Trace function */ void *pTraceArg; /* Argument to the trace function */ #ifndef SQLITE_OMIT_AUTHORIZATION int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); /* Access authorization function */ void *pAuthArg; /* 1st argument to the access auth function */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int (*xProgress)(void *); /* The progress callback */ void *pProgressArg; /* Argument to the progress callback */ int nProgressOps; /* Number of opcodes for progress callback */ #endif int errCode; /* Most recent error code (SQLITE_*) */ u8 enc; /* Text encoding for this database. */ u8 autoCommit; /* The auto-commit flag. */ void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); void *pCollNeededArg; sqlite3_value *pValue; /* Value used for transient conversions */ sqlite3_value *pErr; /* Most recent error message */ char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ }; /* ** Possible values for the sqlite.flags and or Db.flags fields. ** ** On sqlite.flags, the SQLITE_InTrans value means that we have ** executed a BEGIN. On Db.flags, SQLITE_InTrans means a statement ** transaction is active on that particular database file. */ #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ #define SQLITE_Initialized 0x00000002 /* True after initialization */ #define SQLITE_Interrupt 0x00000004 /* Cancel current operation */ #define SQLITE_InTrans 0x00000008 /* True if in a transaction */ #define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */ #define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ #define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ #define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */ /* DELETE, or UPDATE and return */ /* the count using a callback. */ #define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ /* result set is empty */ #define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */ #define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */ #define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */ #define SQLITE_NoReadlock 0x00001000 /* Readlocks are omitted when ** accessing read-only databases */ /* ** Possible values for the sqlite.magic field. ** The numbers are obtained at random and have no special meaning, other ** than being distinct from one another. */ #define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ #define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ #define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ #define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ /* ** Each SQL function is defined by an instance of the following ** structure. A pointer to this structure is stored in the sqlite.aFunc ** hash table. When multiple functions have the same name, the hash table ** points to a linked list of these structures. */ struct FuncDef { char *zName; /* SQL name of the function */ int nArg; /* Number of arguments. -1 means unlimited */ u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */ void *pUserData; /* User data parameter */ FuncDef *pNext; /* Next function with same name */ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */ void (*xFinalize)(sqlite3_context*); /* Aggregate finializer */ u8 needCollSeq; /* True if sqlite3GetFuncCollSeq() might be called */ }; /* ** information about each column of an SQL table is held in an instance ** of this structure. */ struct Column { char *zName; /* Name of this column */ Expr *pDflt; /* Default value of this column */ char *zType; /* Data type for this column */ CollSeq *pColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* True if there is a NOT NULL constraint */ u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */ char affinity; /* One of the SQLITE_AFF_... values */ }; /* ** A "Collating Sequence" is defined by an instance of the following ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. ** ** There may two seperate implementations of the collation function, one ** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that ** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine ** native byte order. When a collation sequence is invoked, SQLite selects ** the version that will require the least expensive encoding ** transalations, if any. ** ** The CollSeq.pUser member variable is an extra parameter that passed in ** as the first argument to the UTF-8 comparison function, xCmp. ** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function, ** xCmp16. ** ** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the ** collating sequence is undefined. Indices built on an undefined ** collating sequence may not be read or written. */ struct CollSeq { char *zName; /* Name of the collating sequence, UTF-8 encoded */ u8 enc; /* Text encoding handled by xCmp() */ void *pUser; /* First argument to xCmp() */ int (*xCmp)(void*,int, const void*, int, const void*); }; /* ** A sort order can be either ASC or DESC. */ #define SQLITE_SO_ASC 0 /* Sort in ascending order */ #define SQLITE_SO_DESC 1 /* Sort in ascending order */ /* ** Column affinity types. */ #define SQLITE_AFF_INTEGER 'i' #define SQLITE_AFF_NUMERIC 'n' #define SQLITE_AFF_TEXT 't' #define SQLITE_AFF_NONE 'o' /* ** Each SQL table is represented in memory by an instance of the ** following structure. ** ** Table.zName is the name of the table. The case of the original ** CREATE TABLE statement is stored, but case is not significant for |
︙ | ︙ | |||
696 697 698 699 700 701 702 | int nCol; /* Number of columns in this table */ Column *aCol; /* Information about each column */ int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */ Index *pIndex; /* List of SQL indexes on this table. */ int tnum; /* Root BTree node for this table (see note above) */ Select *pSelect; /* NULL for tables. Points to definition if a view. */ u8 readOnly; /* True if this table should not be written by the user */ | | < < < < < < < < | 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 | int nCol; /* Number of columns in this table */ Column *aCol; /* Information about each column */ int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */ Index *pIndex; /* List of SQL indexes on this table. */ int tnum; /* Root BTree node for this table (see note above) */ Select *pSelect; /* NULL for tables. Points to definition if a view. */ u8 readOnly; /* True if this table should not be written by the user */ u8 iDb; /* Index into sqlite.aDb[] of the backend for this table */ u8 isTransient; /* True if automatically deleted when VDBE finishes */ u8 hasPrimKey; /* True if there exists a primary key */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ u8 autoInc; /* True if the integer primary key is autoincrement */ Trigger *pTrigger; /* List of SQL triggers on this table */ FKey *pFKey; /* Linked list of all foreign keys in this table */ char *zColAff; /* String defining the affinity of each column */ }; /* ** Each foreign key constraint is an instance of the following structure. ** ** A foreign key is associated with two tables. The "from" table is ** the table that contains the REFERENCES clause that creates the foreign |
︙ | ︙ | |||
801 802 803 804 805 806 807 | /* ** An instance of the following structure is passed as the first ** argument to sqlite3VdbeKeyCompare and is used to control the ** comparison of the two index keys. ** ** If the KeyInfo.incrKey value is true and the comparison would | | < | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 | /* ** An instance of the following structure is passed as the first ** argument to sqlite3VdbeKeyCompare and is used to control the ** comparison of the two index keys. ** ** If the KeyInfo.incrKey value is true and the comparison would ** otherwise be equal, then return a result as if the second key larger. */ struct KeyInfo { u8 enc; /* Text encoding - one of the TEXT_Utf* values */ u8 incrKey; /* Increase 2nd key by epsilon before comparison */ int nField; /* Number of entries in aColl[] */ u8 *aSortOrder; /* If defined an aSortOrder[i] is true, sort DESC */ CollSeq *aColl[1]; /* Collating sequence for each term of the key */ |
︙ | ︙ | |||
842 843 844 845 846 847 848 | ** algorithm to employ whenever an attempt is made to insert a non-unique ** element. */ struct Index { char *zName; /* Name of this index */ int nColumn; /* Number of columns in the table used by this index */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */ | < > < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 | ** algorithm to employ whenever an attempt is made to insert a non-unique ** element. */ struct Index { char *zName; /* Name of this index */ int nColumn; /* Number of columns in the table used by this index */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */ Table *pTable; /* The SQL table being indexed */ int tnum; /* Page containing root of this index in database file */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ u8 iDb; /* Index in sqlite.aDb[] of where this index is stored */ char *zColAff; /* String defining the affinity of each column */ Index *pNext; /* The next index associated with the same table */ KeyInfo keyInfo; /* Info on how to order keys. MUST BE LAST */ }; /* ** Each token coming out of the lexer is an instance of ** this structure. Tokens are also used as part of an expression. ** ** Note if Token.z==0 then Token.dyn and Token.n are undefined and ** may contain random values. Do not make any assuptions about Token.dyn ** and Token.n when Token.z==0. */ struct Token { const unsigned char *z; /* Text of the token. Not NULL-terminated! */ unsigned dyn : 1; /* True for malloced memory, false for static */ unsigned n : 31; /* Number of characters in this token */ }; /* ** Each node of an expression in the parse tree is an instance ** of this structure. ** ** Expr.op is the opcode. The integer parser token codes are reused ** as opcodes here. For example, the parser defines TK_GE to be an integer ** code representing the ">=" operator. This same integer code is reused |
︙ | ︙ | |||
952 953 954 955 956 957 958 | ** gives a different answer at different times during statement processing ** then iTable is the address of a subroutine that computes the subquery. ** ** The Expr.pSelect field points to a SELECT statement. The SELECT might ** be the right operand of an IN operator. Or, if a scalar SELECT appears ** in an expression the opcode is TK_SELECT and Expr.pSelect is the only ** operand. | < < < < | < | > | < < | | | | | | < | 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 | ** gives a different answer at different times during statement processing ** then iTable is the address of a subroutine that computes the subquery. ** ** The Expr.pSelect field points to a SELECT statement. The SELECT might ** be the right operand of an IN operator. Or, if a scalar SELECT appears ** in an expression the opcode is TK_SELECT and Expr.pSelect is the only ** operand. */ struct Expr { u8 op; /* Operation performed by this node */ char affinity; /* The affinity of the column or 0 if not a column */ u8 iDb; /* Database referenced by this expression */ u8 flags; /* Various flags. See below */ CollSeq *pColl; /* The collation type of the column or 0 */ Expr *pLeft, *pRight; /* Left and right subnodes */ ExprList *pList; /* A list of expressions used as function arguments ** or in "<expr> IN (<expr-list)" */ Token token; /* An operand token */ Token span; /* Complete text of the expression */ int iTable, iColumn; /* When op==TK_COLUMN, then this expr node means the ** iColumn-th field of the iTable-th table. */ int iAgg; /* When op==TK_COLUMN and pParse->fillAgg==FALSE, pull ** result from the iAgg-th element of the aggregator */ int iAggCtx; /* The value to pass as P1 of OP_AggGet. */ Select *pSelect; /* When the expression is a sub-select. Also the ** right side of "<expr> IN (<select>)" */ }; /* ** The following are the meanings of bits in the Expr.flags field. */ #define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */ #define EP_Agg 0x0002 /* Contains one or more aggregate functions */ #define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x0008 /* Expression contains one or more errors */ #define EP_Not 0x0010 /* Operator preceeded by NOT */ #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ /* ** These macros can be used to test, set, or clear bits in the ** Expr.flags field. */ #define ExprHasProperty(E,P) (((E)->flags&(P))==(P)) #define ExprHasAnyProperty(E,P) (((E)->flags&(P))!=0) |
︙ | ︙ | |||
1010 1011 1012 1013 1014 1015 1016 | ** list of "ID = expr" items in an UPDATE. A list of expressions can ** also be used as the argument to a function, in which case the a.zName ** field is not used. */ struct ExprList { int nExpr; /* Number of expressions on the list */ int nAlloc; /* Number of entries allocated below */ | < | 852 853 854 855 856 857 858 859 860 861 862 863 864 865 | ** list of "ID = expr" items in an UPDATE. A list of expressions can ** also be used as the argument to a function, in which case the a.zName ** field is not used. */ struct ExprList { int nExpr; /* Number of expressions on the list */ int nAlloc; /* Number of entries allocated below */ struct ExprList_item { Expr *pExpr; /* The list of expressions */ char *zName; /* Token associated with this expression */ u8 sortOrder; /* 1 for DESC or 0 for ASC */ u8 isAgg; /* True if this is an aggregate like count(*) */ u8 done; /* A flag to indicate when processing is finished */ } *a; /* One entry for each expression */ |
︙ | ︙ | |||
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 | ** column names after a table name in an INSERT statement. In the statement ** ** INSERT INTO t(a,b,c) ... ** ** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. */ struct IdList { struct IdList_item { char *zName; /* Name of the identifier */ int idx; /* Index in some Table.aCol[] of a column named zName */ } *a; | > > < < | 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 | ** column names after a table name in an INSERT statement. In the statement ** ** INSERT INTO t(a,b,c) ... ** ** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. */ struct IdList { int nId; /* Number of identifiers on the list */ int nAlloc; /* Number of entries allocated for a[] below */ struct IdList_item { char *zName; /* Name of the identifier */ int idx; /* Index in some Table.aCol[] of a column named zName */ } *a; }; /* ** The bitmask datatype defined below is used for various optimizations. */ typedef unsigned int Bitmask; |
︙ | ︙ | |||
1069 1070 1071 1072 1073 1074 1075 | i16 nAlloc; /* Number of entries allocated in a[] below */ struct SrcList_item { char *zDatabase; /* Name of database holding this table */ char *zName; /* Name of the table */ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ Table *pTab; /* An SQL table corresponding to zName */ Select *pSelect; /* A SELECT statement used in place of a table name */ | | | < | | | | | < < | < | | | > | | < | > | | | | 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 | i16 nAlloc; /* Number of entries allocated in a[] below */ struct SrcList_item { char *zDatabase; /* Name of database holding this table */ char *zName; /* Name of the table */ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ Table *pTab; /* An SQL table corresponding to zName */ Select *pSelect; /* A SELECT statement used in place of a table name */ int jointype; /* Type of join between this table and the next */ int iCursor; /* The VDBE cursor number used to access this table */ Expr *pOn; /* The ON clause of a join */ IdList *pUsing; /* The USING clause of a join */ Bitmask colUsed; /* Bit N (1<<N) set if column N or pTab is used */ } a[1]; /* One entry for each identifier on the list */ }; /* ** Permitted values of the SrcList.a.jointype field */ #define JT_INNER 0x0001 /* Any kind of inner or cross join */ #define JT_NATURAL 0x0002 /* True for a "natural" join */ #define JT_LEFT 0x0004 /* Left outer join */ #define JT_RIGHT 0x0008 /* Right outer join */ #define JT_OUTER 0x0010 /* The "OUTER" keyword is present */ #define JT_ERROR 0x0020 /* unknown or unsupported join type */ /* ** For each nested loop in a WHERE clause implementation, the WhereInfo ** structure contains a single instance of this structure. This structure ** is intended to be private the the where.c module and should not be ** access or modified by other modules. */ struct WhereLevel { int iMem; /* Memory cell used by this level */ Index *pIdx; /* Index used. NULL if no index */ int iTabCur; /* The VDBE cursor used to access the table */ int iIdxCur; /* The VDBE cursor used to acesss pIdx */ int score; /* How well this index scored */ int brk; /* Jump here to break out of the loop */ int cont; /* Jump here to continue with the next loop cycle */ int op, p1, p2; /* Opcode used to terminate the loop */ int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */ int top; /* First instruction of interior of the loop */ int inOp, inP1, inP2;/* Opcode used to implement an IN operator */ int bRev; /* Do the scan in the reverse direction */ }; /* ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second ** half does the tail of the WHERE loop. An instance of ** this structure is returned by the first half and passed |
︙ | ︙ | |||
1156 1157 1158 1159 1160 1161 1162 | struct NameContext { Parse *pParse; /* The parser */ SrcList *pSrcList; /* One or more tables used to resolve names */ ExprList *pEList; /* Optional list of named expressions */ int nRef; /* Number of names resolved by this context */ int nErr; /* Number of errors encountered while resolving names */ u8 allowAgg; /* Aggregate functions allowed here */ | | < < < < < < < < < < < < < < < < < | > > > < < < < < < < | | | > > | > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < < < < > | < < > > > > | < > > | < | 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 | struct NameContext { Parse *pParse; /* The parser */ SrcList *pSrcList; /* One or more tables used to resolve names */ ExprList *pEList; /* Optional list of named expressions */ int nRef; /* Number of names resolved by this context */ int nErr; /* Number of errors encountered while resolving names */ u8 allowAgg; /* Aggregate functions allowed here */ u8 hasAgg; int nDepth; /* Depth of subquery recursion. 1 for no recursion */ NameContext *pNext; /* Next outer name context. NULL for outermost */ }; /* ** An instance of the following structure contains all information ** needed to generate code for a single SELECT statement. ** ** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0. ** If there is a LIMIT clause, the parser sets nLimit to the value of the ** limit and nOffset to the value of the offset (or 0 if there is not ** offset). But later on, nLimit and nOffset become the memory locations ** in the VDBE that record the limit and offset counters. */ struct Select { ExprList *pEList; /* The fields of the result */ u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ u8 isDistinct; /* True if the DISTINCT keyword is present */ SrcList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ ExprList *pGroupBy; /* The GROUP BY clause */ Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ Select *pPrior; /* Prior select in a compound select statement */ Expr *pLimit; /* LIMIT expression. NULL means not used. */ Expr *pOffset; /* OFFSET expression. NULL means not used. */ int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ IdList **ppOpenTemp; /* OP_OpenTemp addresses used by multi-selects */ Fetch *pFetch; /* If this stmt is part of a FETCH command */ u8 isResolved; /* True once sqlite3SelectResolve() has run. */ u8 isAgg; /* True if this is an aggregate query */ }; /* ** The results of a select can be distributed in several ways. */ #define SRT_Callback 1 /* Invoke a callback with each row of result */ #define SRT_Mem 2 /* Store result in a memory cell */ #define SRT_Set 3 /* Store result as unique keys in a table */ #define SRT_Union 5 /* Store result as keys in a table */ #define SRT_Except 6 /* Remove result from a UNION table */ #define SRT_Table 7 /* Store result as data with a unique key */ #define SRT_TempTable 8 /* Store result in a trasient table */ #define SRT_Discard 9 /* Do not save the results anywhere */ #define SRT_Sorter 10 /* Store results in the sorter */ #define SRT_Subroutine 11 /* Call a subroutine to handle results */ #define SRT_Exists 12 /* Put 0 or 1 in a memory cell */ /* ** When a SELECT uses aggregate functions (like "count(*)" or "avg(f1)") ** we have to do some additional analysis of expressions. An instance ** of the following structure holds information about a single subexpression ** somewhere in the SELECT statement. An array of these structures holds ** all the information we need to generate code for aggregate ** expressions. ** ** Note that when analyzing a SELECT containing aggregates, both ** non-aggregate field variables and aggregate functions are stored ** in the AggExpr array of the Parser structure. ** ** The pExpr field points to an expression that is part of either the ** field list, the GROUP BY clause, the HAVING clause or the ORDER BY ** clause. The expression will be freed when those clauses are cleaned ** up. Do not try to delete the expression attached to AggExpr.pExpr. ** ** If AggExpr.pExpr==0, that means the expression is "count(*)". */ struct AggExpr { int isAgg; /* if TRUE contains an aggregate function */ Expr *pExpr; /* The expression */ FuncDef *pFunc; /* Information about the aggregate function */ }; /* ** An SQL parser context. A copy of this structure is passed through ** the parser and down into all the parser action routine in order to ** carry around information that is global to the entire parse. ** ** The structure is divided into two parts. When the parser and code ** generate call themselves recursively, the first part of the structure ** is constant but the second part is reset at the beginning and end of ** each recursion. */ struct Parse { sqlite3 *db; /* The main database structure */ int rc; /* Return code from execution */ char *zErrMsg; /* An error message */ Vdbe *pVdbe; /* An engine for executing database bytecode */ u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ u8 nameClash; /* A permanent table name clashes with temp table name */ u8 checkSchema; /* Causes schema cookie check after an error */ u8 nested; /* Number of nested calls to the parser/code generator */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ u32 cookieMask; /* Bitmask of schema verified databases */ int cookieValue[MAX_ATTACHED+2]; /* Values of cookies to verify */ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ u32 writeMask; /* Start a write transaction on these databases */ u8 fillAgg; /* If true, ignore the Expr.iAgg field. Normally false */ /* Above is constant between recursions. Below is reset before and after ** each recursion */ int nVar; /* Number of '?' variables seen in the SQL so far */ int nVarExpr; /* Number of used slots in apVarExpr[] */ int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */ Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */ u8 explain; /* True if the EXPLAIN flag is found on the query */ Token sErrToken; /* The token at which the error occurred */ Token sNameToken; /* Token with unqualified schema object name */ Token sLastToken; /* The last token parsed */ const char *zSql; /* All SQL text */ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ TriggerStack *trigStack; /* Trigger actions being coded */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ int nAgg; /* Number of aggregate expressions */ AggExpr *aAgg; /* An array of aggregate expressions */ int nMaxDepth; /* Maximum depth of subquery recursion */ }; /* ** An instance of the following structure can be declared on a stack and used ** to save the Parse.zAuthContext value so that it can be restored later. */ struct AuthContext { const char *zAuthContext; /* Put saved Parse.zAuthContext here */ Parse *pParse; /* The Parse structure */ }; /* ** Bitfield flags for P2 value in OP_PutIntKey and OP_Delete */ #define OPFLAG_NCHANGE 1 /* Set to update db->nChange */ #define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */ /* * Each trigger present in the database schema is stored as an instance of * struct Trigger. * * Pointers to instances of struct Trigger are stored in two ways. * 1. In the "trigHash" hash table (part of the sqlite3* that represents the * database). This allows Trigger structures to be retrieved by name. * 2. All triggers associated with a single table form a linked list, using the * pNext member of struct Trigger. A pointer to the first element of the * linked list is stored as the "pTrigger" member of the associated * struct Table. * * The "step_list" member points to the first element of a linked list * containing the SQL statements specified as the trigger program. */ struct Trigger { char *name; /* The name of the trigger */ char *table; /* The table or view to which the trigger applies */ u8 iDb; /* Database containing this trigger */ u8 iTabDb; /* Database containing Trigger.table */ u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */ u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ Expr *pWhen; /* The WHEN clause of the expresion (may be NULL) */ IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger, the <column-list> is stored here */ int foreach; /* One of TK_ROW or TK_STATEMENT */ Token nameToken; /* Token containing zName. Use during parsing only */ TriggerStep *step_list; /* Link list of trigger program steps */ Trigger *pNext; /* Next trigger associated with the table */ }; /* ** A trigger is either a BEFORE or an AFTER trigger. The following constants ** determine which. |
︙ | ︙ | |||
1458 1459 1460 1461 1462 1463 1464 | /* * This global flag is set for performance testing of triggers. When it is set * SQLite will perform the overhead of building new and old trigger references * even when no triggers exist */ extern int sqlite3_always_code_trigger_setup; | < < < < < < < < < < < < < | > > > > > > > | | | | | | < > < < < | < < | | | | < | | | < | | > | | < < | 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 | /* * This global flag is set for performance testing of triggers. When it is set * SQLite will perform the overhead of building new and old trigger references * even when no triggers exist */ extern int sqlite3_always_code_trigger_setup; /* ** Internal function prototypes */ int sqlite3StrICmp(const char *, const char *); int sqlite3StrNICmp(const char *, const char *, int); int sqlite3HashNoCase(const char *, int); int sqlite3IsNumber(const char*, int*, u8); int sqlite3Compare(const char *, const char *); int sqlite3SortCompare(const char *, const char *); void sqlite3RealToSortable(double r, char *); #ifdef SQLITE_MEMDEBUG void *sqlite3Malloc_(int,int,char*,int); void sqlite3Free_(void*,char*,int); void *sqlite3Realloc_(void*,int,char*,int); char *sqlite3StrDup_(const char*,char*,int); char *sqlite3StrNDup_(const char*, int,char*,int); void sqlite3CheckMemory(void*,int); #else void *sqlite3Malloc(int); void *sqlite3MallocRaw(int); void sqlite3Free(void*); void *sqlite3Realloc(void*,int); char *sqlite3StrDup(const char*); char *sqlite3StrNDup(const char*, int); # define sqlite3CheckMemory(a,b) #endif void sqlite3FreeX(void*); char *sqlite3MPrintf(const char*, ...); char *sqlite3VMPrintf(const char*, va_list); void sqlite3DebugPrintf(const char*, ...); void *sqlite3TextToPtr(const char*); void sqlite3SetString(char **, const char *, ...); void sqlite3ErrorMsg(Parse*, const char*, ...); void sqlite3Dequote(char*); int sqlite3KeywordCode(const char*, int); int sqlite3RunParser(Parse*, const char*, char **); void sqlite3FinishCoding(Parse*); Expr *sqlite3Expr(int, Expr*, Expr*, const Token*); Expr *sqlite3RegisterExpr(Parse*,Token*); Expr *sqlite3ExprAnd(Expr*, Expr*); void sqlite3ExprSpan(Expr*,Token*,Token*); Expr *sqlite3ExprFunction(ExprList*, Token*); void sqlite3ExprAssignVarNumber(Parse*, Expr*); void sqlite3ExprDelete(Expr*); ExprList *sqlite3ExprListAppend(ExprList*,Expr*,Token*); void sqlite3ExprListDelete(ExprList*); int sqlite3Init(sqlite3*, char**); int sqlite3InitCallback(void*, int, char**, char**); void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); void sqlite3ResetInternalSchema(sqlite3*, int); void sqlite3BeginParse(Parse*,int); void sqlite3RollbackInternalChanges(sqlite3*); void sqlite3CommitInternalChanges(sqlite3*); Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*); void sqlite3OpenMasterTable(Vdbe *v, int); void sqlite3StartTable(Parse*,Token*,Token*,Token*,int,int); void sqlite3AddColumn(Parse*,Token*); void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int); void sqlite3AddColumnType(Parse*,Token*,Token*); void sqlite3AddDefaultValue(Parse*,Expr*); void sqlite3AddCollateType(Parse*, const char*, int); void sqlite3EndTable(Parse*,Token*,Select*); #ifndef SQLITE_OMIT_VIEW void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int); int sqlite3ViewGetColumnNames(Parse*,Table*); #else # define sqlite3ViewGetColumnNames(A,B) 0 #endif void sqlite3DropTable(Parse*, SrcList*, int); void sqlite3DeleteTable(sqlite3*, Table*); void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); IdList *sqlite3IdListAppend(IdList*, Token*); int sqlite3IdListIndex(IdList*,const char*); SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*); void sqlite3SrcListAddAlias(SrcList*, Token*); void sqlite3SrcListAssignCursors(Parse*, SrcList*); void sqlite3IdListDelete(IdList*); void sqlite3SrcListDelete(SrcList*); void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, Token*); void sqlite3DropIndex(Parse*, SrcList*); void sqlite3AddKeyType(Vdbe*, ExprList*); void sqlite3AddIdxKeyType(Vdbe*, Index*); int sqlite3Select(Parse*, Select*, int, int, Select*, int, int*, char *aff); Select *sqlite3SelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*, int,Expr*,Expr*); void sqlite3SelectDelete(Select*); void sqlite3SelectUnbind(Select*); Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTableForReading(Vdbe*, int iCur, Table*); void sqlite3OpenTable(Vdbe*, int iCur, Table*, int); void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, Fetch*); void sqlite3WhereEnd(WhereInfo*); void sqlite3ExprCode(Parse*, Expr*); void sqlite3ExprCodeAndCache(Parse*, Expr*); int sqlite3ExprCodeExprList(Parse*, ExprList*); void sqlite3ExprIfTrue(Parse*, Expr*, int, int); void sqlite3ExprIfFalse(Parse*, Expr*, int, int); void sqlite3NextedParse(Parse*, const char*, ...); Table *sqlite3FindTable(sqlite3*,const char*, const char*); Table *sqlite3LocateTable(Parse*,const char*, const char*); Index *sqlite3FindIndex(sqlite3*,const char*, const char*); void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); void sqlite3Vacuum(Parse*, Token*); int sqlite3RunVacuum(char**, sqlite3*); char *sqlite3NameFromToken(Token*); int sqlite3ExprCheck(Parse*, Expr*, int, int*); int sqlite3ExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); int sqlite3ExprResolveNames(NameContext *, Expr *); int sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); Vdbe *sqlite3GetVdbe(Parse*); void sqlite3Randomness(int, void*); void sqlite3RollbackAll(sqlite3*); void sqlite3CodeVerifySchema(Parse*, int); void sqlite3BeginTransaction(Parse*, int); void sqlite3CommitTransaction(Parse*); void sqlite3RollbackTransaction(Parse*); int sqlite3ExprIsConstant(Expr*); int sqlite3ExprIsInteger(Expr*, int*); int sqlite3IsRowid(const char*); void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int); void sqlite3GenerateRowIndexDelete(sqlite3*, Vdbe*, Table*, int, char*); void sqlite3GenerateIndexKey(Vdbe*, Index*, int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int); void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int); |
︙ | ︙ | |||
1660 1661 1662 1663 1664 1665 1666 | void sqlite3AuthContextPop(AuthContext*); #else # define sqlite3AuthRead(a,b,c) # define sqlite3AuthCheck(a,b,c,d,e) SQLITE_OK # define sqlite3AuthContextPush(a,b,c) # define sqlite3AuthContextPop(a) ((void)(a)) #endif | | | | | 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 | void sqlite3AuthContextPop(AuthContext*); #else # define sqlite3AuthRead(a,b,c) # define sqlite3AuthCheck(a,b,c,d,e) SQLITE_OK # define sqlite3AuthContextPush(a,b,c) # define sqlite3AuthContextPop(a) ((void)(a)) #endif void sqlite3Attach(Parse*, Token*, Token*, int, Token*); void sqlite3Detach(Parse*, Token*); int sqlite3BtreeFactory(const sqlite3 *db, const char *zFilename, int omitJournal, int nCache, Btree **ppBtree); int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*); int sqlite3FixSrcList(DbFixer*, SrcList*); int sqlite3FixSelect(DbFixer*, Select*); int sqlite3FixExpr(DbFixer*, Expr*); int sqlite3FixExprList(DbFixer*, ExprList*); int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); double sqlite3AtoF(const char *z, const char **); char *sqlite3_snprintf(int,char*,const char*,...); int sqlite3GetInt32(const char *, int*); int sqlite3FitsIn64Bits(const char *); int sqlite3utf16ByteLen(const void *pData, int nChar); int sqlite3utf8CharLen(const char *pData, int nByte); int sqlite3ReadUtf8(const unsigned char *); int sqlite3PutVarint(unsigned char *, u64); |
︙ | ︙ | |||
1706 1707 1708 1709 1710 1711 1712 | void sqlite3VdbeSetChanges(sqlite3 *, int); void sqlite3utf16Substr(sqlite3_context *,int,sqlite3_value **); const void *sqlite3ValueText(sqlite3_value*, u8); int sqlite3ValueBytes(sqlite3_value*, u8); void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); void sqlite3ValueFree(sqlite3_value*); | | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 | void sqlite3VdbeSetChanges(sqlite3 *, int); void sqlite3utf16Substr(sqlite3_context *,int,sqlite3_value **); const void *sqlite3ValueText(sqlite3_value*, u8); int sqlite3ValueBytes(sqlite3_value*, u8); void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); void sqlite3ValueFree(sqlite3_value*); sqlite3_value *sqlite3ValueNew(); sqlite3_value *sqlite3GetTransientValue(sqlite3*db); extern const unsigned char sqlite3UpperToLower[]; void sqlite3RootPageMoved(Db*, int, int); void sqlite3Reindex(Parse*, Token*, Token*); void sqlite3AlterFunctions(sqlite3*); void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); int sqlite3GetToken(const unsigned char *, int *); void sqlite3NestedParse(Parse*, const char*, ...); void sqlite3ExpirePreparedStatements(sqlite3*); void sqlite3CodeSubselect(Parse *, Expr *); int sqlite3SelectResolve(Parse *, Select *, NameContext *); #endif |
Changes to SQLite.Interop/src/table.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This file contains the sqlite3_get_table() and sqlite3_free_table() ** interface routines. These are just wrappers around the main ** interface routine of sqlite3_exec(). ** ** These routines are in a separate files so that they will not be linked ** if they are not used. */ | < | < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** This file contains the sqlite3_get_table() and sqlite3_free_table() ** interface routines. These are just wrappers around the main ** interface routine of sqlite3_exec(). ** ** These routines are in a separate files so that they will not be linked ** if they are not used. */ #include <stdlib.h> #include <string.h> #include "sqliteInt.h" /* ** This structure is used to pass data from sqlite3_get_table() through ** to the callback function is uses to build the result. */ typedef struct TabResult { char **azResult; |
︙ | ︙ | |||
191 192 193 194 195 196 197 | azResult--; if( azResult==0 ) return; n = (int)azResult[0]; for(i=1; i<n; i++){ if( azResult[i] ) free(azResult[i]); } free(azResult); } } | < < | 189 190 191 192 193 194 195 | azResult--; if( azResult==0 ) return; n = (int)azResult[0]; for(i=1; i<n; i++){ if( azResult[i] ) free(azResult[i]); } free(azResult); } } |
Changes to SQLite.Interop/src/tclsqlite.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** A TCL Interface to SQLite ** | | < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** A TCL Interface to SQLite ** ** $Id: tclsqlite.c,v 1.1 2005/03/01 16:04:36 rmsimpson Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ #include "sqliteInt.h" #include "hash.h" #include "tcl.h" #include <stdlib.h> #include <string.h> #include <assert.h> #define NUM_PREPARED_STMTS 10 #define MAX_PREPARED_STMTS 100 /* ** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we ** have to do a translation when going between the two. Set the |
︙ | ︙ | |||
49 50 51 52 53 54 55 | /* ** New SQL functions can be created as TCL scripts. Each such function ** is described by an instance of the following structure. */ typedef struct SqlFunc SqlFunc; struct SqlFunc { Tcl_Interp *interp; /* The TCL interpret to execute the function */ | | < < | | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | /* ** New SQL functions can be created as TCL scripts. Each such function ** is described by an instance of the following structure. */ typedef struct SqlFunc SqlFunc; struct SqlFunc { Tcl_Interp *interp; /* The TCL interpret to execute the function */ char *zScript; /* The script to be run */ SqlFunc *pNext; /* Next function on the list of them all */ }; /* ** New collation sequences function can be created as TCL scripts. Each such ** function is described by an instance of the following structure. */ typedef struct SqlCollate SqlCollate; struct SqlCollate { Tcl_Interp *interp; /* The TCL interpret to execute the function */ char *zScript; /* The script to be run */ SqlCollate *pNext; /* Next function on the list of them all */ }; /* ** Prepared statements are cached for faster execution. Each prepared ** statement is described by an instance of the following structure. */ typedef struct SqlPreparedStmt SqlPreparedStmt; |
︙ | ︙ | |||
85 86 87 88 89 90 91 | /* ** There is one instance of this structure for each SQLite database ** that has been opened by the SQLite TCL interface. */ typedef struct SqliteDb SqliteDb; struct SqliteDb { | | | | | | < | | < | < < | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | /* ** There is one instance of this structure for each SQLite database ** that has been opened by the SQLite TCL interface. */ typedef struct SqliteDb SqliteDb; struct SqliteDb { sqlite3 *db; /* The "real" database structure */ Tcl_Interp *interp; /* The interpreter used for this database */ char *zBusy; /* The busy callback routine */ char *zCommit; /* The commit hook callback routine */ char *zTrace; /* The trace callback routine */ char *zProgress; /* The progress callback routine */ char *zAuth; /* The authorization callback routine */ SqlFunc *pFunc; /* List of SQL functions */ SqlCollate *pCollate; /* List of SQL collation functions */ int rc; /* Return code of most recent sqlite3_exec() */ Tcl_Obj *pCollateNeeded; /* Collation needed script */ SqlPreparedStmt *stmtList; /* List of prepared statements*/ SqlPreparedStmt *stmtLast; /* Last statement in the list */ int maxStmt; /* The next maximum number of stmtList */ int nStmt; /* Number of statements in stmtList */ }; /* ** Finalize and free a list of prepared statements */ static void flushStmtCache( SqliteDb *pDb ){ SqlPreparedStmt *pPreStmt; while( pDb->stmtList ){ |
︙ | ︙ | |||
185 186 187 188 189 190 191 | static void DbDeleteCmd(void *db){ SqliteDb *pDb = (SqliteDb*)db; flushStmtCache(pDb); sqlite3_close(pDb->db); while( pDb->pFunc ){ SqlFunc *pFunc = pDb->pFunc; pDb->pFunc = pFunc->pNext; | < < < < < < < < < < < < < < < < > > > > > > | > | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | static void DbDeleteCmd(void *db){ SqliteDb *pDb = (SqliteDb*)db; flushStmtCache(pDb); sqlite3_close(pDb->db); while( pDb->pFunc ){ SqlFunc *pFunc = pDb->pFunc; pDb->pFunc = pFunc->pNext; Tcl_Free((char*)pFunc); } while( pDb->pCollate ){ SqlCollate *pCollate = pDb->pCollate; pDb->pCollate = pCollate->pNext; Tcl_Free((char*)pCollate); } if( pDb->zBusy ){ Tcl_Free(pDb->zBusy); } if( pDb->zTrace ){ Tcl_Free(pDb->zTrace); } if( pDb->zAuth ){ Tcl_Free(pDb->zAuth); } Tcl_Free((char*)pDb); } /* ** This routine is called when a database file is locked while trying ** to execute SQL. */ static int DbBusyHandler(void *cd, int nTries){ SqliteDb *pDb = (SqliteDb*)cd; int rc; char zVal[30]; char *zCmd; Tcl_DString cmd; Tcl_DStringInit(&cmd); Tcl_DStringAppend(&cmd, pDb->zBusy, -1); sprintf(zVal, "%d", nTries); Tcl_DStringAppendElement(&cmd, zVal); zCmd = Tcl_DStringValue(&cmd); rc = Tcl_Eval(pDb->interp, zCmd); Tcl_DStringFree(&cmd); if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ return 0; } return 1; } /* |
︙ | ︙ | |||
268 269 270 271 272 273 274 | Tcl_DStringAppend(&str, pDb->zTrace, -1); Tcl_DStringAppendElement(&str, zSql); Tcl_Eval(pDb->interp, Tcl_DStringValue(&str)); Tcl_DStringFree(&str); Tcl_ResetResult(pDb->interp); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | Tcl_DStringAppend(&str, pDb->zTrace, -1); Tcl_DStringAppendElement(&str, zSql); Tcl_Eval(pDb->interp, Tcl_DStringValue(&str)); Tcl_DStringFree(&str); Tcl_ResetResult(pDb->interp); } /* ** This routine is called when a transaction is committed. The ** TCL script in pDb->zCommit is executed. If it returns non-zero or ** if it throws an exception, the transaction is rolled back instead ** of being committed. */ static int DbCommitHandler(void *cd){ SqliteDb *pDb = (SqliteDb*)cd; int rc; rc = Tcl_Eval(pDb->interp, pDb->zCommit); if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ return 1; } return 0; } static void tclCollateNeeded( void *pCtx, sqlite3 *db, int enc, const char *zName ){ SqliteDb *pDb = (SqliteDb *)pCtx; |
︙ | ︙ | |||
367 368 369 370 371 372 373 | SqlCollate *p = (SqlCollate *)pCtx; Tcl_Obj *pCmd; pCmd = Tcl_NewStringObj(p->zScript, -1); Tcl_IncrRefCount(pCmd); Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA)); Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB)); | | | < < < < < < < < | < < < < < < < < < < | < < < < < < < | | < | < < < < < < < < < < < < < < < < < < < < < < < < | < | < < | | | | < | < < < < < < < < < < < < < < < | < < < < < < < < | < < < < < < < < < < < < < < < < | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | SqlCollate *p = (SqlCollate *)pCtx; Tcl_Obj *pCmd; pCmd = Tcl_NewStringObj(p->zScript, -1); Tcl_IncrRefCount(pCmd); Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA)); Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB)); Tcl_EvalObjEx(p->interp, pCmd, 0); Tcl_DecrRefCount(pCmd); return (atoi(Tcl_GetStringResult(p->interp))); } /* ** This routine is called to evaluate an SQL function implemented ** using TCL script. */ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){ SqlFunc *p = sqlite3_user_data(context); Tcl_DString cmd; int i; int rc; Tcl_DStringInit(&cmd); Tcl_DStringAppend(&cmd, p->zScript, -1); for(i=0; i<argc; i++){ if( SQLITE_NULL==sqlite3_value_type(argv[i]) ){ Tcl_DStringAppendElement(&cmd, ""); }else{ Tcl_DStringAppendElement(&cmd, sqlite3_value_text(argv[i])); } } rc = Tcl_Eval(p->interp, Tcl_DStringValue(&cmd)); if( rc ){ sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); }else{ sqlite3_result_text(context, Tcl_GetStringResult(p->interp), -1, SQLITE_TRANSIENT); } } #ifndef SQLITE_OMIT_AUTHORIZATION /* ** This is the authentication function. It appends the authentication ** type code and the two arguments to zCmd[] then invokes the result |
︙ | ︙ | |||
543 544 545 546 547 548 549 | case SQLITE_SELECT : zCode="SQLITE_SELECT"; break; case SQLITE_TRANSACTION : zCode="SQLITE_TRANSACTION"; break; case SQLITE_UPDATE : zCode="SQLITE_UPDATE"; break; case SQLITE_ATTACH : zCode="SQLITE_ATTACH"; break; case SQLITE_DETACH : zCode="SQLITE_DETACH"; break; case SQLITE_ALTER_TABLE : zCode="SQLITE_ALTER_TABLE"; break; case SQLITE_REINDEX : zCode="SQLITE_REINDEX"; break; | < | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | case SQLITE_SELECT : zCode="SQLITE_SELECT"; break; case SQLITE_TRANSACTION : zCode="SQLITE_TRANSACTION"; break; case SQLITE_UPDATE : zCode="SQLITE_UPDATE"; break; case SQLITE_ATTACH : zCode="SQLITE_ATTACH"; break; case SQLITE_DETACH : zCode="SQLITE_DETACH"; break; case SQLITE_ALTER_TABLE : zCode="SQLITE_ALTER_TABLE"; break; case SQLITE_REINDEX : zCode="SQLITE_REINDEX"; break; default : zCode="????"; break; } Tcl_DStringInit(&str); Tcl_DStringAppend(&str, pDb->zAuth, -1); Tcl_DStringAppendElement(&str, zCode); Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : ""); Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : ""); |
︙ | ︙ | |||
659 660 661 662 663 664 665 | int choice; int rc = TCL_OK; static const char *DB_strs[] = { "authorizer", "busy", "cache", "changes", "close", "collate", "collation_needed", "commit_hook", "complete", "copy", "errorcode", "eval", | | < | | < | < | | < | 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 | int choice; int rc = TCL_OK; static const char *DB_strs[] = { "authorizer", "busy", "cache", "changes", "close", "collate", "collation_needed", "commit_hook", "complete", "copy", "errorcode", "eval", "function", "last_insert_rowid", "onecolumn", "progress", "rekey", "timeout", "total_changes", "trace", "version", 0 }; enum DB_enum { DB_AUTHORIZER, DB_BUSY, DB_CACHE, DB_CHANGES, DB_CLOSE, DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK, DB_COMPLETE, DB_COPY, DB_ERRORCODE, DB_EVAL, DB_FUNCTION, DB_LAST_INSERT_ROWID,DB_ONECOLUMN, DB_PROGRESS, DB_REKEY, DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, DB_VERSION }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); return TCL_ERROR; } |
︙ | ︙ | |||
853 854 855 856 857 858 859 860 861 862 863 864 865 866 | ** ** Shutdown the database */ case DB_CLOSE: { Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0)); break; } /* ** $db collate NAME SCRIPT ** ** Create a new SQL collation function called NAME. Whenever ** that function is called, invoke SCRIPT to evaluate the function. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 | ** ** Shutdown the database */ case DB_CLOSE: { Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0)); break; } /* $db commit_hook ?CALLBACK? ** ** Invoke the given callback just before committing every SQL transaction. ** If the callback throws an exception or returns non-zero, then the ** transaction is aborted. If CALLBACK is an empty string, the callback ** is disabled. */ case DB_COMMIT_HOOK: { if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); return TCL_ERROR; }else if( objc==2 ){ if( pDb->zCommit ){ Tcl_AppendResult(interp, pDb->zCommit, 0); } }else{ char *zCommit; int len; if( pDb->zCommit ){ Tcl_Free(pDb->zCommit); } zCommit = Tcl_GetStringFromObj(objv[2], &len); if( zCommit && len>0 ){ pDb->zCommit = Tcl_Alloc( len + 1 ); strcpy(pDb->zCommit, zCommit); }else{ pDb->zCommit = 0; } if( pDb->zCommit ){ pDb->interp = interp; sqlite3_commit_hook(pDb->db, DbCommitHandler, pDb); }else{ sqlite3_commit_hook(pDb->db, 0, 0); } } break; } /* ** $db collate NAME SCRIPT ** ** Create a new SQL collation function called NAME. Whenever ** that function is called, invoke SCRIPT to evaluate the function. */ |
︙ | ︙ | |||
906 907 908 909 910 911 912 | } pDb->pCollateNeeded = Tcl_DuplicateObj(objv[2]); Tcl_IncrRefCount(pDb->pCollateNeeded); sqlite3_collation_needed(pDb->db, pDb, tclCollateNeeded); break; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 | } pDb->pCollateNeeded = Tcl_DuplicateObj(objv[2]); Tcl_IncrRefCount(pDb->pCollateNeeded); sqlite3_collation_needed(pDb->db, pDb, tclCollateNeeded); break; } /* $db complete SQL ** ** Return TRUE if SQL is a complete SQL statement. Return FALSE if ** additional lines of input are needed. This is similar to the ** built-in "info complete" command of Tcl. */ case DB_COMPLETE: { Tcl_Obj *pResult; int isComplete; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "SQL"); return TCL_ERROR; } isComplete = sqlite3_complete( Tcl_GetStringFromObj(objv[2], 0) ); pResult = Tcl_GetObjResult(interp); Tcl_SetBooleanObj(pResult, isComplete); break; } /* ** $db errorcode ** ** Return the numeric error code that was returned by the most recent ** call to sqlite3_exec(). */ case DB_ERRORCODE: { Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_errcode(pDb->db))); break; } /* ** $db eval $sql ?array? ?{ ...code... }? ** $db onecolumn $sql ** ** The SQL statement in $sql is evaluated. For each row, the values are ** placed in elements of the array named "array" and ...code... is executed. ** If "array" and "code" are omitted, then no callback is every invoked. ** If "array" is an empty string, then the values are placed in variables ** that have the same name as the fields extracted by the query. ** ** The onecolumn method is the equivalent of: ** lindex [$db eval $sql] 0 */ case DB_ONECOLUMN: case DB_EVAL: { char const *zSql; /* Next SQL statement to execute */ char const *zLeft; /* What is left after first stmt in zSql */ sqlite3_stmt *pStmt; /* Compiled SQL statment */ Tcl_Obj *pArray; /* Name of array into which results are written */ Tcl_Obj *pScript; /* Script to run for each result set */ Tcl_Obj **apParm; /* Parameters that need a Tcl_DecrRefCount() */ int nParm; /* Number of entries used in apParm[] */ Tcl_Obj *aParm[10]; /* Static space for apParm[] in the common case */ Tcl_Obj *pRet; /* Value to be returned */ SqlPreparedStmt *pPreStmt; /* Pointer to a prepared statement */ int rc2; if( choice==DB_ONECOLUMN ){ if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "SQL"); return TCL_ERROR; } pRet = 0; }else{ if( objc<3 || objc>5 ){ Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME? ?SCRIPT?"); return TCL_ERROR; } pRet = Tcl_NewObj(); Tcl_IncrRefCount(pRet); } if( objc==3 ){ pArray = pScript = 0; }else if( objc==4 ){ pArray = 0; pScript = objv[3]; }else{ pArray = objv[3]; if( Tcl_GetString(pArray)[0]==0 ) pArray = 0; pScript = objv[4]; } Tcl_IncrRefCount(objv[2]); zSql = Tcl_GetStringFromObj(objv[2], 0); while( rc==TCL_OK && zSql[0] ){ int i; /* Loop counter */ int nVar; /* Number of bind parameters in the pStmt */ int nCol; /* Number of columns in the result set */ Tcl_Obj **apColName = 0; /* Array of column names */ int len; /* String length of zSql */ /* Try to find a SQL statement that has already been compiled and ** which matches the next sequence of SQL. */ pStmt = 0; pPreStmt = pDb->stmtList; len = strlen(zSql); if( pPreStmt && sqlite3_expired(pPreStmt->pStmt) ){ flushStmtCache(pDb); pPreStmt = 0; } for(; pPreStmt; pPreStmt=pPreStmt->pNext){ int n = pPreStmt->nSql; if( len>=n && memcmp(pPreStmt->zSql, zSql, n)==0 && (zSql[n]==0 || zSql[n-1]==';') ){ pStmt = pPreStmt->pStmt; zLeft = &zSql[pPreStmt->nSql]; /* When a prepared statement is found, unlink it from the ** cache list. It will later be added back to the beginning ** of the cache list in order to implement LRU replacement. */ if( pPreStmt->pPrev ){ pPreStmt->pPrev->pNext = pPreStmt->pNext; }else{ pDb->stmtList = pPreStmt->pNext; } if( pPreStmt->pNext ){ pPreStmt->pNext->pPrev = pPreStmt->pPrev; }else{ pDb->stmtLast = pPreStmt->pPrev; } pDb->nStmt--; break; } } /* If no prepared statement was found. Compile the SQL text */ if( pStmt==0 ){ if( SQLITE_OK!=sqlite3_prepare(pDb->db, zSql, -1, &pStmt, &zLeft) ){ Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); rc = TCL_ERROR; break; } if( pStmt==0 ){ if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){ /* A compile-time error in the statement */ Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); rc = TCL_ERROR; break; }else{ /* The statement was a no-op. Continue to the next statement ** in the SQL string. */ zSql = zLeft; continue; } } assert( pPreStmt==0 ); } /* Bind values to parameters that begin with $ or : */ nVar = sqlite3_bind_parameter_count(pStmt); nParm = 0; if( nVar>sizeof(aParm)/sizeof(aParm[0]) ){ apParm = (Tcl_Obj**)Tcl_Alloc(nVar*sizeof(apParm[0])); }else{ apParm = aParm; } for(i=1; i<=nVar; i++){ const char *zVar = sqlite3_bind_parameter_name(pStmt, i); if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':') ){ Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0); if( pVar ){ int n; u8 *data; char *zType = pVar->typePtr ? pVar->typePtr->name : ""; char c = zType[0]; if( c=='b' && strcmp(zType,"bytearray")==0 ){ data = Tcl_GetByteArrayFromObj(pVar, &n); sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC); Tcl_IncrRefCount(pVar); apParm[nParm++] = pVar; }else if( (c=='b' && strcmp(zType,"boolean")==0) || (c=='i' && strcmp(zType,"int")==0) ){ Tcl_GetIntFromObj(interp, pVar, &n); sqlite3_bind_int(pStmt, i, n); }else if( c=='d' && strcmp(zType,"double")==0 ){ double r; Tcl_GetDoubleFromObj(interp, pVar, &r); sqlite3_bind_double(pStmt, i, r); }else{ data = Tcl_GetStringFromObj(pVar, &n); sqlite3_bind_text(pStmt, i, data, n, SQLITE_STATIC); Tcl_IncrRefCount(pVar); apParm[nParm++] = pVar; } }else{ sqlite3_bind_null( pStmt, i ); } } } /* Compute column names */ nCol = sqlite3_column_count(pStmt); if( pScript ){ apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol ); if( apColName==0 ) break; for(i=0; i<nCol; i++){ apColName[i] = dbTextToObj(sqlite3_column_name(pStmt,i)); Tcl_IncrRefCount(apColName[i]); } } /* If results are being stored in an array variable, then create ** the array(*) entry for that array */ if( pArray ){ Tcl_Obj *pColList = Tcl_NewObj(); Tcl_IncrRefCount(pColList); for(i=0; i<nCol; i++){ Tcl_ListObjAppendElement(interp, pColList, apColName[i]); } Tcl_ObjSetVar2(interp, pArray, Tcl_NewStringObj("*",-1), pColList,0); } /* Execute the SQL */ while( rc==TCL_OK && pStmt && SQLITE_ROW==sqlite3_step(pStmt) ){ for(i=0; i<nCol; i++){ Tcl_Obj *pVal; /* Set pVal to contain the i'th column of this row. */ switch( sqlite3_column_type(pStmt, i) ){ case SQLITE_BLOB: { int bytes = sqlite3_column_bytes(pStmt, i); pVal = Tcl_NewByteArrayObj(sqlite3_column_blob(pStmt, i), bytes); break; } case SQLITE_INTEGER: { sqlite_int64 v = sqlite3_column_int64(pStmt, i); if( v>=-2147483647 && v<=2147483647 ){ pVal = Tcl_NewIntObj(v); }else{ pVal = Tcl_NewWideIntObj(v); } break; } case SQLITE_FLOAT: { double r = sqlite3_column_double(pStmt, i); pVal = Tcl_NewDoubleObj(r); break; } default: { pVal = dbTextToObj(sqlite3_column_text(pStmt, i)); break; } } if( pScript ){ if( pArray==0 ){ Tcl_ObjSetVar2(interp, apColName[i], 0, pVal, 0); }else{ Tcl_ObjSetVar2(interp, pArray, apColName[i], pVal, 0); } }else if( choice==DB_ONECOLUMN ){ if( pRet==0 ){ pRet = pVal; Tcl_IncrRefCount(pRet); } rc = TCL_BREAK; }else{ Tcl_ListObjAppendElement(interp, pRet, pVal); } } if( pScript ){ rc = Tcl_EvalObjEx(interp, pScript, 0); if( rc==TCL_CONTINUE ){ rc = TCL_OK; } } } if( rc==TCL_BREAK ){ rc = TCL_OK; } /* Free the column name objects */ if( pScript ){ for(i=0; i<nCol; i++){ Tcl_DecrRefCount(apColName[i]); } Tcl_Free((char*)apColName); } /* Free the bound string and blob parameters */ for(i=0; i<nParm; i++){ Tcl_DecrRefCount(apParm[i]); } if( apParm!=aParm ){ Tcl_Free((char*)apParm); } /* Reset the statement. If the result code is SQLITE_SCHEMA, then ** flush the statement cache and try the statement again. */ rc2 = sqlite3_reset(pStmt); if( SQLITE_SCHEMA==rc2 ){ /* After a schema change, flush the cache and try to run the ** statement again */ flushStmtCache( pDb ); sqlite3_finalize(pStmt); if( pPreStmt ) Tcl_Free((char*)pPreStmt); continue; }else if( SQLITE_OK!=rc2 ){ /* If a run-time error occurs, report the error and stop reading ** the SQL */ Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); sqlite3_finalize(pStmt); rc = TCL_ERROR; if( pPreStmt ) Tcl_Free((char*)pPreStmt); break; }else if( pDb->maxStmt<=0 ){ /* If the cache is turned off, deallocated the statement */ if( pPreStmt ) Tcl_Free((char*)pPreStmt); sqlite3_finalize(pStmt); }else{ /* Everything worked and the cache is operational. ** Create a new SqlPreparedStmt structure if we need one. ** (If we already have one we can just reuse it.) */ if( pPreStmt==0 ){ len = zLeft - zSql; pPreStmt = (SqlPreparedStmt*)Tcl_Alloc( sizeof(*pPreStmt) + len ); if( pPreStmt==0 ) return TCL_ERROR; pPreStmt->pStmt = pStmt; pPreStmt->nSql = len; memcpy(pPreStmt->zSql, zSql, len); pPreStmt->zSql[len] = 0; } /* Add the prepared statement to the beginning of the cache list */ pPreStmt->pNext = pDb->stmtList; pPreStmt->pPrev = 0; if( pDb->stmtList ){ pDb->stmtList->pPrev = pPreStmt; } pDb->stmtList = pPreStmt; if( pDb->stmtLast==0 ){ assert( pDb->nStmt==0 ); pDb->stmtLast = pPreStmt; }else{ assert( pDb->nStmt>0 ); } pDb->nStmt++; /* If we have too many statement in cache, remove the surplus from the ** end of the cache list. */ while( pDb->nStmt>pDb->maxStmt ){ sqlite3_finalize(pDb->stmtLast->pStmt); pDb->stmtLast = pDb->stmtLast->pPrev; Tcl_Free((char*)pDb->stmtLast->pNext); pDb->stmtLast->pNext = 0; pDb->nStmt--; } } /* Proceed to the next statement */ zSql = zLeft; } Tcl_DecrRefCount(objv[2]); if( pRet ){ if( rc==TCL_OK ){ Tcl_SetObjResult(interp, pRet); } Tcl_DecrRefCount(pRet); } break; } /* ** $db function NAME SCRIPT ** ** Create a new SQL function called NAME. Whenever that function is ** called, invoke SCRIPT to evaluate the function. */ case DB_FUNCTION: { SqlFunc *pFunc; char *zName; char *zScript; int nScript; if( objc!=4 ){ Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT"); return TCL_ERROR; } zName = Tcl_GetStringFromObj(objv[2], 0); zScript = Tcl_GetStringFromObj(objv[3], &nScript); pFunc = (SqlFunc*)Tcl_Alloc( sizeof(*pFunc) + nScript + 1 ); if( pFunc==0 ) return TCL_ERROR; pFunc->interp = interp; pFunc->pNext = pDb->pFunc; pFunc->zScript = (char*)&pFunc[1]; pDb->pFunc = pFunc; strcpy(pFunc->zScript, zScript); rc = sqlite3_create_function(pDb->db, zName, -1, SQLITE_UTF8, pFunc, tclSqlFunc, 0, 0); if( rc!=SQLITE_OK ){ rc = TCL_ERROR; Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); }else{ /* Must flush any cached statements */ flushStmtCache( pDb ); } break; } /* ** $db last_insert_rowid ** ** Return an integer which is the ROWID for the most recent insert. */ case DB_LAST_INSERT_ROWID: { Tcl_Obj *pResult; int rowid; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } rowid = sqlite3_last_insert_rowid(pDb->db); pResult = Tcl_GetObjResult(interp); Tcl_SetIntObj(pResult, rowid); break; } /* ** The DB_ONECOLUMN method is implemented together with DB_EVAL. */ /* $db progress ?N CALLBACK? ** ** Invoke the given callback every N virtual machine opcodes while executing ** queries. */ case DB_PROGRESS: { if( objc==2 ){ if( pDb->zProgress ){ Tcl_AppendResult(interp, pDb->zProgress, 0); } }else if( objc==4 ){ char *zProgress; int len; int N; if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){ return TCL_ERROR; }; if( pDb->zProgress ){ Tcl_Free(pDb->zProgress); } zProgress = Tcl_GetStringFromObj(objv[3], &len); if( zProgress && len>0 ){ pDb->zProgress = Tcl_Alloc( len + 1 ); strcpy(pDb->zProgress, zProgress); }else{ pDb->zProgress = 0; } #ifndef SQLITE_OMIT_PROGRESS_CALLBACK if( pDb->zProgress ){ pDb->interp = interp; sqlite3_progress_handler(pDb->db, N, DbProgressHandler, pDb); }else{ sqlite3_progress_handler(pDb->db, 0, 0, 0); } #endif }else{ Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK"); return TCL_ERROR; } break; } /* ** $db rekey KEY ** ** Change the encryption key on the currently open database. */ case DB_REKEY: { int nKey; void *pKey; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "KEY"); return TCL_ERROR; } pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey); #ifdef SQLITE_HAS_CODEC rc = sqlite3_rekey(pDb->db, pKey, nKey); if( rc ){ Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); rc = TCL_ERROR; } #endif break; } /* ** $db timeout MILLESECONDS ** ** Delay for the number of milliseconds specified when a file is locked. */ case DB_TIMEOUT: { int ms; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS"); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR; sqlite3_busy_timeout(pDb->db, ms); break; } /* ** $db total_changes ** ** Return the number of rows that were modified, inserted, or deleted ** since the database handle was created. */ case DB_TOTAL_CHANGES: { Tcl_Obj *pResult; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } pResult = Tcl_GetObjResult(interp); Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db)); break; } /* $db trace ?CALLBACK? ** ** Make arrangements to invoke the CALLBACK routine for each SQL statement ** that is executed. The text of the SQL is appended to CALLBACK before ** it is executed. */ case DB_TRACE: { if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); return TCL_ERROR; }else if( objc==2 ){ if( pDb->zTrace ){ Tcl_AppendResult(interp, pDb->zTrace, 0); } }else{ char *zTrace; int len; if( pDb->zTrace ){ Tcl_Free(pDb->zTrace); } zTrace = Tcl_GetStringFromObj(objv[2], &len); if( zTrace && len>0 ){ pDb->zTrace = Tcl_Alloc( len + 1 ); strcpy(pDb->zTrace, zTrace); }else{ pDb->zTrace = 0; } if( pDb->zTrace ){ pDb->interp = interp; sqlite3_trace(pDb->db, DbTraceHandler, pDb); }else{ sqlite3_trace(pDb->db, 0, 0); } } break; } /* $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR? ** ** Copy data into table from filename, optionally using SEPARATOR ** as column separators. If a column contains a null string, or the ** value of NULLINDICATOR, a NULL is inserted for the column. ** conflict-algorithm is one of the sqlite conflict algorithms: |
︙ | ︙ | |||
1151 1152 1153 1154 1155 1156 1157 | sprintf(zLineNum,"%d",lineno); Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,0); rc = TCL_ERROR; } break; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 | sprintf(zLineNum,"%d",lineno); Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,0); rc = TCL_ERROR; } break; } /* $db version ** ** Return the version string for this database. */ case DB_VERSION: { Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC); break; |
︙ | ︙ | |||
1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 | static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ SqliteDb *p; void *pKey = 0; int nKey = 0; const char *zArg; char *zErrMsg; const char *zFile; if( objc==2 ){ zArg = Tcl_GetStringFromObj(objv[1], 0); if( strcmp(zArg,"-version")==0 ){ Tcl_AppendResult(interp,sqlite3_version,0); return TCL_OK; } if( strcmp(zArg,"-has-codec")==0 ){ | > | 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 | static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ SqliteDb *p; void *pKey = 0; int nKey = 0; const char *zArg; char *zErrMsg; const char *zFile; char zBuf[80]; if( objc==2 ){ zArg = Tcl_GetStringFromObj(objv[1], 0); if( strcmp(zArg,"-version")==0 ){ Tcl_AppendResult(interp,sqlite3_version,0); return TCL_OK; } if( strcmp(zArg,"-has-codec")==0 ){ |
︙ | ︙ | |||
2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 | Tcl_Free((char*)p); free(zErrMsg); return TCL_ERROR; } p->maxStmt = NUM_PREPARED_STMTS; zArg = Tcl_GetStringFromObj(objv[1], 0); Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd); /* If compiled with SQLITE_TEST turned on, then register the "md5sum" ** SQL function. */ #ifdef SQLITE_TEST { extern void Md5_Register(sqlite3*); #ifdef SQLITE_MEMDEBUG int mallocfail = sqlite3_iMallocFail; sqlite3_iMallocFail = 0; #endif Md5_Register(p->db); #ifdef SQLITE_MEMDEBUG sqlite3_iMallocFail = mallocfail; #endif | > > > > > > > > | < < < < < < < < < | | | | | | | | | | | 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 | Tcl_Free((char*)p); free(zErrMsg); return TCL_ERROR; } p->maxStmt = NUM_PREPARED_STMTS; zArg = Tcl_GetStringFromObj(objv[1], 0); Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd); /* The return value is the value of the sqlite* pointer */ sprintf(zBuf, "%p", p->db); if( strncmp(zBuf,"0x",2) ){ sprintf(zBuf, "0x%p", p->db); } Tcl_AppendResult(interp, zBuf, 0); /* If compiled with SQLITE_TEST turned on, then register the "md5sum" ** SQL function. */ #ifdef SQLITE_TEST { extern void Md5_Register(sqlite3*); #ifdef SQLITE_MEMDEBUG int mallocfail = sqlite3_iMallocFail; sqlite3_iMallocFail = 0; #endif Md5_Register(p->db); #ifdef SQLITE_MEMDEBUG sqlite3_iMallocFail = mallocfail; #endif } #endif p->interp = interp; return TCL_OK; } /* ** Provide a dummy Tcl_InitStubs if we are using this as a static ** library. */ #ifndef USE_TCL_STUBS # undef Tcl_InitStubs # define Tcl_InitStubs(a,b,c) #endif /* ** Initialize this module. ** ** This Tcl module contains only a single new Tcl command named "sqlite". ** (Hence there is no namespace. There is no point in using a namespace ** if the extension only supplies one new name!) The "sqlite" command is ** used to open a new SQLite database. See the DbMain() routine above ** for additional information. */ int Sqlite3_Init(Tcl_Interp *interp){ Tcl_InitStubs(interp, "8.4", 0); Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0); Tcl_PkgProvide(interp, "sqlite3", "3.0"); Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0); Tcl_PkgProvide(interp, "sqlite", "3.0"); return TCL_OK; } int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; } int Tclsqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; } #ifndef SQLITE_3_SUFFIX_ONLY int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; } int Tclsqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; } #endif #ifdef TCLSH /***************************************************************************** ** The code that follows is used to build standalone TCL interpreters */ |
︙ | ︙ | |||
2146 2147 2148 2149 2150 2151 2152 | #ifdef SQLITE_TEST { extern int Sqlitetest1_Init(Tcl_Interp*); extern int Sqlitetest2_Init(Tcl_Interp*); extern int Sqlitetest3_Init(Tcl_Interp*); extern int Sqlitetest4_Init(Tcl_Interp*); extern int Sqlitetest5_Init(Tcl_Interp*); | < < < < < < < < < < < | 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 | #ifdef SQLITE_TEST { extern int Sqlitetest1_Init(Tcl_Interp*); extern int Sqlitetest2_Init(Tcl_Interp*); extern int Sqlitetest3_Init(Tcl_Interp*); extern int Sqlitetest4_Init(Tcl_Interp*); extern int Sqlitetest5_Init(Tcl_Interp*); extern int Md5_Init(Tcl_Interp*); Sqlitetest1_Init(interp); Sqlitetest2_Init(interp); Sqlitetest3_Init(interp); Sqlitetest4_Init(interp); Sqlitetest5_Init(interp); Md5_Init(interp); } #endif if( argc>=2 || TCLSH==2 ){ int i; Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY); for(i=3-TCLSH; i<argc; i++){ |
︙ | ︙ |
Changes to SQLite.Interop/src/tokenize.c.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** ** $Id: tokenize.c,v 1.1 2005/03/01 16:04:37 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include <stdlib.h> /* |
︙ | ︙ | |||
34 35 36 37 38 39 40 | ** the #include below. */ #include "keywordhash.h" /* ** If X is a character that can be used in an identifier and | | | | | | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | ** the #include below. */ #include "keywordhash.h" /* ** If X is a character that can be used in an identifier and ** X&0x80==0 then isIdChar[X] will be 1. If X&0x80==0x80 then ** X is always an identifier character. (Hence all UTF-8 ** characters can be part of an identifier). isIdChar[X] will ** be 0 for every character in the lower 128 ASCII characters ** that cannot be used as part of an identifier. ** ** In this implementation, an identifier can be a string of ** alphabetic characters, digits, and "_" plus any character ** with the high-order bit set. The latter rule means that ** any sequence of UTF-8 characters or characters taken from ** an extended ISO8859 character set can form an identifier. ** ** Ticket #1066. the SQL standard does not allow '$' in the ** middle of identfiers. But many SQL implementations do. ** SQLite will allow '$' in identifiers for compatibility. ** But the feature is undocumented. */ static const char isIdChar[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ }; #define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && isIdChar[c-0x20])) /* ** Return the length of the token that begins at z[0]. ** Store the token type in *tokenType before returning. */ static int getToken(const unsigned char *z, int *tokenType){ int i, c; |
︙ | ︙ | |||
179 180 181 182 183 184 185 | *tokenType = TK_BITAND; return 1; } case '~': { *tokenType = TK_BITNOT; return 1; } | | > > > > | < | | < < < | | < < < < < | | < < < | | | | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | *tokenType = TK_BITAND; return 1; } case '~': { *tokenType = TK_BITNOT; return 1; } case '#': { for(i=1; isdigit(z[i]) || (i==1 && z[1]=='-'); i++){} *tokenType = TK_REGISTER; return i; } case '\'': case '"': { int delim = z[0]; for(i=1; (c=z[i])!=0; i++){ if( c==delim ){ if( z[i+1]==delim ){ i++; }else{ break; } } } if( c ) i++; *tokenType = TK_STRING; return i; } case '.': { *tokenType = TK_DOT; return 1; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { *tokenType = TK_INTEGER; for(i=1; isdigit(z[i]); i++){} #ifndef SQLITE_OMIT_FLOATING_POINT if( z[i]=='.' && isdigit(z[i+1]) ){ i += 2; while( isdigit(z[i]) ){ i++; } *tokenType = TK_FLOAT; } if( (z[i]=='e' || z[i]=='E') && ( isdigit(z[i+1]) || ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2])) ) |
︙ | ︙ | |||
243 244 245 246 247 248 249 | return i; } case '?': { *tokenType = TK_VARIABLE; for(i=1; isdigit(z[i]); i++){} return i; } | | | < < < | | | < < < | > > > > | > | > > > > | | < | | | < | | | | | | | | | | | | < | | | | | > > | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | return i; } case '?': { *tokenType = TK_VARIABLE; for(i=1; isdigit(z[i]); i++){} return i; } case ':': { for(i=1; IdChar(z[i]); i++){} *tokenType = i>1 ? TK_VARIABLE : TK_ILLEGAL; return i; } #ifndef SQLITE_OMIT_TCL_VARIABLE case '$': { *tokenType = TK_VARIABLE; if( z[1]=='{' ){ int nBrace = 1; for(i=2; (c=z[i])!=0 && nBrace; i++){ if( c=='{' ){ nBrace++; }else if( c=='}' ){ nBrace--; } } if( c==0 ) *tokenType = TK_ILLEGAL; }else{ int n = 0; for(i=1; (c=z[i])!=0; i++){ if( isalnum(c) || c=='_' ){ n++; }else if( c=='(' && n>0 ){ do{ i++; }while( (c=z[i])!=0 && !isspace(c) && c!=')' ); if( c==')' ){ i++; }else{ *tokenType = TK_ILLEGAL; } break; }else if( c==':' && z[i+1]==':' ){ i++; }else{ break; } } if( n==0 ) *tokenType = TK_ILLEGAL; } return i; } #endif #ifndef SQLITE_OMIT_BLOB_LITERAL case 'x': case 'X': { if( (c=z[1])=='\'' || c=='"' ){ int delim = c; *tokenType = TK_BLOB; for(i=2; (c=z[i])!=0; i++){ if( c==delim ){ |
︙ | ︙ | |||
336 337 338 339 340 341 342 | int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ int nErr = 0; int i; void *pEngine; int tokenType; int lastTokenParsed = -1; sqlite3 *db = pParse->db; | < | > | | | | 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ int nErr = 0; int i; void *pEngine; int tokenType; int lastTokenParsed = -1; sqlite3 *db = pParse->db; extern void *sqlite3ParserAlloc(void*(*)(int)); extern void sqlite3ParserFree(void*, void(*)(void*)); extern int sqlite3Parser(void*, int, Token, Parse*); db->flags &= ~SQLITE_Interrupt; pParse->rc = SQLITE_OK; i = 0; pEngine = sqlite3ParserAlloc((void*(*)(int))malloc); if( pEngine==0 ){ sqlite3SetString(pzErrMsg, "out of memory", (char*)0); return 1; } assert( pParse->sLastToken.dyn==0 ); assert( pParse->pNewTable==0 ); assert( pParse->pNewTrigger==0 ); assert( pParse->nVar==0 ); assert( pParse->nVarExpr==0 ); assert( pParse->nVarExprAlloc==0 ); assert( pParse->apVarExpr==0 ); pParse->zTail = pParse->zSql = zSql; while( sqlite3_malloc_failed==0 && zSql[i]!=0 ){ assert( i>=0 ); pParse->sLastToken.z = &zSql[i]; assert( pParse->sLastToken.dyn==0 ); pParse->sLastToken.n = getToken((unsigned char*)&zSql[i],&tokenType); i += pParse->sLastToken.n; switch( tokenType ){ case TK_SPACE: case TK_COMMENT: { if( (db->flags & SQLITE_Interrupt)!=0 ){ |
︙ | ︙ | |||
403 404 405 406 407 408 409 | if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ if( lastTokenParsed!=TK_SEMI ){ sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse); pParse->zTail = &zSql[i]; } sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); } | | | | > < < < < < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 | if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ if( lastTokenParsed!=TK_SEMI ){ sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse); pParse->zTail = &zSql[i]; } sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); } sqlite3ParserFree(pEngine, free); if( sqlite3_malloc_failed ){ pParse->rc = SQLITE_NOMEM; } if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ sqlite3SetString(&pParse->zErrMsg, sqlite3ErrStr(pParse->rc), (char*)0); } if( pParse->zErrMsg ){ if( pzErrMsg && *pzErrMsg==0 ){ *pzErrMsg = pParse->zErrMsg; }else{ sqliteFree(pParse->zErrMsg); } pParse->zErrMsg = 0; if( !nErr ) nErr++; } if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ sqlite3VdbeDelete(pParse->pVdbe); pParse->pVdbe = 0; } sqlite3DeleteTable(pParse->db, pParse->pNewTable); sqlite3DeleteTrigger(pParse->pNewTrigger); sqliteFree(pParse->apVarExpr); if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){ pParse->rc = SQLITE_ERROR; } return nErr; } /* ** Token types used by the sqlite3_complete() routine. See the header ** comments on that procedure for additional information. */ #define tkSEMI 0 #define tkWS 1 #define tkOTHER 2 #define tkEXPLAIN 3 #define tkCREATE 4 #define tkTEMP 5 #define tkTRIGGER 6 #define tkEND 7 /* ** Return TRUE if the given SQL string ends in a semicolon. ** ** Special handling is require for CREATE TRIGGER statements. ** Whenever the CREATE TRIGGER keywords are seen, the statement ** must end with ";END;". ** ** This implementation uses a state machine with 7 states: ** ** (0) START At the beginning or end of an SQL statement. This routine ** returns 1 if it ends in the START state and 0 if it ends ** in any other state. ** ** (1) NORMAL We are in the middle of statement which ends with a single ** semicolon. ** ** (2) EXPLAIN The keyword EXPLAIN has been seen at the beginning of ** a statement. ** ** (3) CREATE The keyword CREATE has been seen at the beginning of a ** statement, possibly preceeded by EXPLAIN and/or followed by ** TEMP or TEMPORARY ** ** (4) TRIGGER We are in the middle of a trigger definition that must be ** ended by a semicolon, the keyword END, and another semicolon. ** ** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at ** the end of a trigger definition. ** ** (6) END We've seen the ";END" of the ";END;" that occurs at the end ** of a trigger difinition. ** ** Transitions between states above are determined by tokens extracted ** from the input. The following tokens are significant: ** ** (0) tkSEMI A semicolon. ** (1) tkWS Whitespace ** (2) tkOTHER Any other SQL token. ** (3) tkEXPLAIN The "explain" keyword. ** (4) tkCREATE The "create" keyword. ** (5) tkTEMP The "temp" or "temporary" keyword. ** (6) tkTRIGGER The "trigger" keyword. ** (7) tkEND The "end" keyword. ** ** Whitespace never causes a state transition and is always ignored. ** ** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed ** to recognize the end of a trigger can be omitted. All we have to do ** is look for a semicolon that is not part of an string or comment. */ int sqlite3_complete(const char *zSql){ u8 state = 0; /* Current state, using numbers defined in header comment */ u8 token; /* Value of the next token */ #ifndef SQLITE_OMIT_TRIGGER /* A complex statement machine used to detect the end of a CREATE TRIGGER ** statement. This is the normal case. */ static const u8 trans[7][8] = { /* Token: */ /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ /* 0 START: */ { 0, 0, 1, 2, 3, 1, 1, 1, }, /* 1 NORMAL: */ { 0, 1, 1, 1, 1, 1, 1, 1, }, /* 2 EXPLAIN: */ { 0, 2, 1, 1, 3, 1, 1, 1, }, /* 3 CREATE: */ { 0, 3, 1, 1, 1, 3, 4, 1, }, /* 4 TRIGGER: */ { 5, 4, 4, 4, 4, 4, 4, 4, }, /* 5 SEMI: */ { 5, 5, 4, 4, 4, 4, 4, 6, }, /* 6 END: */ { 0, 6, 4, 4, 4, 4, 4, 4, }, }; #else /* If triggers are not suppored by this compile then the statement machine ** used to detect the end of a statement is much simplier */ static const u8 trans[2][3] = { /* Token: */ /* State: ** SEMI WS OTHER */ /* 0 START: */ { 0, 0, 1, }, /* 1 NORMAL: */ { 0, 1, 1, }, }; #endif /* SQLITE_OMIT_TRIGGER */ while( *zSql ){ switch( *zSql ){ case ';': { /* A semicolon */ token = tkSEMI; break; } case ' ': case '\r': case '\t': case '\n': case '\f': { /* White space is ignored */ token = tkWS; break; } case '/': { /* C-style comments */ if( zSql[1]!='*' ){ token = tkOTHER; break; } zSql += 2; while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; } if( zSql[0]==0 ) return 0; zSql++; token = tkWS; break; } case '-': { /* SQL-style comments from "--" to end of line */ if( zSql[1]!='-' ){ token = tkOTHER; break; } while( *zSql && *zSql!='\n' ){ zSql++; } if( *zSql==0 ) return state==0; token = tkWS; break; } case '[': { /* Microsoft-style identifiers in [...] */ zSql++; while( *zSql && *zSql!=']' ){ zSql++; } if( *zSql==0 ) return 0; token = tkOTHER; break; } case '"': /* single- and double-quoted strings */ case '\'': { int c = *zSql; zSql++; while( *zSql && *zSql!=c ){ zSql++; } if( *zSql==0 ) return 0; token = tkOTHER; break; } default: { int c; if( IdChar((u8)*zSql) ){ /* Keywords and unquoted identifiers */ int nId; for(nId=1; IdChar(zSql[nId]); nId++){} #ifdef SQLITE_OMIT_TRIGGER token = tkOTHER; #else switch( *zSql ){ case 'c': case 'C': { if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){ token = tkCREATE; }else{ token = tkOTHER; } break; } case 't': case 'T': { if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){ token = tkTRIGGER; }else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){ token = tkTEMP; }else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){ token = tkTEMP; }else{ token = tkOTHER; } break; } case 'e': case 'E': { if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){ token = tkEND; }else #ifndef SQLITE_OMIT_EXPLAIN if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){ token = tkEXPLAIN; }else #endif { token = tkOTHER; } break; } default: { token = tkOTHER; break; } } #endif /* SQLITE_OMIT_TRIGGER */ zSql += nId-1; }else{ /* Operators and special symbols */ token = tkOTHER; } break; } } state = trans[state][token]; zSql++; } return state==0; } #ifndef SQLITE_OMIT_UTF16 /* ** This routine is the same as the sqlite3_complete() routine described ** above, except that the parameter is required to be UTF-16 encoded, not ** UTF-8. */ int sqlite3_complete16(const void *zSql){ sqlite3_value *pVal; char const *zSql8; int rc = 0; pVal = sqlite3ValueNew(); sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8); if( zSql8 ){ rc = sqlite3_complete(zSql8); } sqlite3ValueFree(pVal); return rc; } #endif /* SQLITE_OMIT_UTF16 */ |
Changes to SQLite.Interop/src/trigger.c.
︙ | ︙ | |||
47 48 49 50 51 52 53 | int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ IdList *pColumns, /* column list if this is an UPDATE OF trigger */ SrcList *pTableName,/* The name of the table/view the trigger applies to */ int foreach, /* One of TK_ROW or TK_STATEMENT */ Expr *pWhen, /* WHEN clause */ int isTemp /* True if the TEMPORARY keyword is present */ ){ | | < | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ IdList *pColumns, /* column list if this is an UPDATE OF trigger */ SrcList *pTableName,/* The name of the table/view the trigger applies to */ int foreach, /* One of TK_ROW or TK_STATEMENT */ Expr *pWhen, /* WHEN clause */ int isTemp /* True if the TEMPORARY keyword is present */ ){ Trigger *pTrigger; Table *pTab; char *zName = 0; /* Name of the trigger */ sqlite3 *db = pParse->db; int iDb; /* The database to store the trigger in */ Token *pName; /* The unqualified db name */ DbFixer sFix; if( isTemp ){ /* If TEMP was specified, then the trigger name may not be qualified. */ if( pName2 && pName2->n>0 ){ sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name"); goto trigger_cleanup; } |
︙ | ︙ | |||
77 78 79 80 81 82 83 | } /* If the trigger name was unqualified, and the table is a temp table, ** then set iDb to 1 to create the trigger in the temporary database. ** If sqlite3SrcListLookup() returns 0, indicating the table does not ** exist, the error is caught by the block below. */ | < | < | | | | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | } /* If the trigger name was unqualified, and the table is a temp table, ** then set iDb to 1 to create the trigger in the temporary database. ** If sqlite3SrcListLookup() returns 0, indicating the table does not ** exist, the error is caught by the block below. */ if( !pTableName || sqlite3_malloc_failed ) goto trigger_cleanup; pTab = sqlite3SrcListLookup(pParse, pTableName); if( pName2->n==0 && pTab && pTab->iDb==1 ){ iDb = 1; } /* Ensure the table name matches database name and that the table exists */ if( sqlite3_malloc_failed ) goto trigger_cleanup; assert( pTableName->nSrc==1 ); if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) && sqlite3FixSrcList(&sFix, pTableName) ){ goto trigger_cleanup; } pTab = sqlite3SrcListLookup(pParse, pTableName); if( !pTab ){ /* The table does not exist. */ goto trigger_cleanup; } /* Check that the trigger name is not reserved and that no trigger of the ** specified name exists */ zName = sqlite3NameFromToken(pName); if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto trigger_cleanup; } if( sqlite3HashFind(&(db->aDb[iDb].trigHash), zName,pName->n+1) ){ sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); goto trigger_cleanup; } /* Do not create a trigger on a system table */ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); |
︙ | ︙ | |||
129 130 131 132 133 134 135 | goto trigger_cleanup; } if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" " trigger on table: %S", pTableName, 0); goto trigger_cleanup; } | < | | | > | | < < < < < < > < < | | | | | | | | | < < | < < < < < | | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | goto trigger_cleanup; } if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" " trigger on table: %S", pTableName, 0); goto trigger_cleanup; } #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_CREATE_TRIGGER; const char *zDb = db->aDb[pTab->iDb].zName; const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; if( pTab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ goto trigger_cleanup; } if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(pTab->iDb),0,zDb)){ goto trigger_cleanup; } } #endif /* INSTEAD OF triggers can only appear on views and BEFORE triggers ** cannot appear on views. So we might as well translate every ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code ** elsewhere. */ if (tr_tm == TK_INSTEAD){ tr_tm = TK_BEFORE; } /* Build the Trigger object */ pTrigger = (Trigger*)sqliteMalloc(sizeof(Trigger)); if( pTrigger==0 ) goto trigger_cleanup; pTrigger->name = zName; zName = 0; pTrigger->table = sqliteStrDup(pTableName->a[0].zName); if( sqlite3_malloc_failed ) goto trigger_cleanup; pTrigger->iDb = iDb; pTrigger->iTabDb = pTab->iDb; pTrigger->op = op; pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; pTrigger->pWhen = sqlite3ExprDup(pWhen); pTrigger->pColumns = sqlite3IdListDup(pColumns); pTrigger->foreach = foreach; sqlite3TokenCopy(&pTrigger->nameToken,pName); assert( pParse->pNewTrigger==0 ); pParse->pNewTrigger = pTrigger; trigger_cleanup: sqliteFree(zName); sqlite3SrcListDelete(pTableName); sqlite3IdListDelete(pColumns); sqlite3ExprDelete(pWhen); } /* ** This routine is called after all of the trigger actions have been parsed ** in order to complete the process of building the trigger. */ void sqlite3FinishTrigger( Parse *pParse, /* Parser context */ TriggerStep *pStepList, /* The triggered program */ Token *pAll /* Token that describes the complete CREATE TRIGGER */ ){ Trigger *pTrig = 0; /* The trigger whose construction is finishing up */ sqlite3 *db = pParse->db; /* The database */ DbFixer sFix; if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup; pTrig = pParse->pNewTrigger; pParse->pNewTrigger = 0; pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } if( sqlite3FixInit(&sFix, pParse, pTrig->iDb, "trigger", &pTrig->nameToken) && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ goto triggerfinish_cleanup; } /* if we are not initializing, and this trigger is not on a TEMP table, ** build the sqlite_master entry */ if( !db->init.busy ){ static const VdbeOpList insertTrig[] = { { OP_NewRecno, 0, 0, 0 }, { OP_String8, 0, 0, "trigger" }, { OP_String8, 0, 0, 0 }, /* 2: trigger name */ { OP_String8, 0, 0, 0 }, /* 3: table name */ { OP_Integer, 0, 0, 0 }, { OP_String8, 0, 0, "CREATE TRIGGER "}, { OP_String8, 0, 0, 0 }, /* 6: SQL */ { OP_Concat, 0, 0, 0 }, { OP_MakeRecord, 5, 0, "tttit" }, { OP_PutIntKey, 0, 0, 0 }, }; int addr; Vdbe *v; /* Make an entry in the sqlite_master table */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; sqlite3BeginWriteOperation(pParse, 0, pTrig->iDb); sqlite3OpenMasterTable(v, pTrig->iDb); addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig); sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0); sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0); sqlite3VdbeChangeP3(v, addr+6, pAll->z, pAll->n); sqlite3ChangeCookie(db, v, pTrig->iDb); sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeOp3(v, OP_ParseSchema, pTrig->iDb, 0, sqlite3MPrintf("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC); } if( db->init.busy ){ Table *pTab; sqlite3HashInsert(&db->aDb[pTrig->iDb].trigHash, pTrig->name, strlen(pTrig->name)+1, pTrig); pTab = sqlite3LocateTable(pParse,pTrig->table,db->aDb[pTrig->iTabDb].zName); assert( pTab!=0 ); pTrig->pNext = pTab->pTrigger; pTab->pTrigger = pTrig; pTrig = 0; } triggerfinish_cleanup: |
︙ | ︙ | |||
282 283 284 285 286 287 288 | ** string is ephemeral - it will go away as soon as the sqlite3_exec() ** call that started the parser exits. This routine makes a persistent ** copy of all the Expr.token.z strings so that the TriggerStep structure ** will be valid even after the sqlite3_exec() call returns. */ static void sqlitePersistTriggerStep(TriggerStep *p){ if( p->target.z ){ | | | 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | ** string is ephemeral - it will go away as soon as the sqlite3_exec() ** call that started the parser exits. This routine makes a persistent ** copy of all the Expr.token.z strings so that the TriggerStep structure ** will be valid even after the sqlite3_exec() call returns. */ static void sqlitePersistTriggerStep(TriggerStep *p){ if( p->target.z ){ p->target.z = sqliteStrNDup(p->target.z, p->target.n); p->target.dyn = 1; } if( p->pSelect ){ Select *pNew = sqlite3SelectDup(p->pSelect); sqlite3SelectDelete(p->pSelect); p->pSelect = pNew; } |
︙ | ︙ | |||
316 317 318 319 320 321 322 | ** a trigger step. Return a pointer to a TriggerStep structure. ** ** The parser calls this routine when it finds a SELECT statement in ** body of a TRIGGER. */ TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){ TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); | | < < < | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | ** a trigger step. Return a pointer to a TriggerStep structure. ** ** The parser calls this routine when it finds a SELECT statement in ** body of a TRIGGER. */ TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){ TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); if( pTriggerStep==0 ) return 0; pTriggerStep->op = TK_SELECT; pTriggerStep->pSelect = pSelect; pTriggerStep->orconf = OE_Default; sqlitePersistTriggerStep(pTriggerStep); return pTriggerStep; |
︙ | ︙ | |||
344 345 346 347 348 349 350 351 352 353 354 | Token *pTableName, /* Name of the table into which we insert */ IdList *pColumn, /* List of columns in pTableName to insert into */ ExprList *pEList, /* The VALUE clause: a list of values to be inserted */ Select *pSelect, /* A SELECT statement that supplies values */ int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ ){ TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); assert(pEList == 0 || pSelect == 0); assert(pEList != 0 || pSelect != 0); | > < | | | | | | | < < < < < | 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | Token *pTableName, /* Name of the table into which we insert */ IdList *pColumn, /* List of columns in pTableName to insert into */ ExprList *pEList, /* The VALUE clause: a list of values to be inserted */ Select *pSelect, /* A SELECT statement that supplies values */ int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ ){ TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); if( pTriggerStep==0 ) return 0; assert(pEList == 0 || pSelect == 0); assert(pEList != 0 || pSelect != 0); pTriggerStep->op = TK_INSERT; pTriggerStep->pSelect = pSelect; pTriggerStep->target = *pTableName; pTriggerStep->pIdList = pColumn; pTriggerStep->pExprList = pEList; pTriggerStep->orconf = orconf; sqlitePersistTriggerStep(pTriggerStep); return pTriggerStep; } /* ** Construct a trigger step that implements an UPDATE statement and return ** a pointer to that trigger step. The parser calls this routine when it |
︙ | ︙ | |||
437 438 439 440 441 442 443 | Trigger *pTrigger = 0; int i; const char *zDb; const char *zName; int nName; sqlite3 *db = pParse->db; | | | | | < | | | 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | Trigger *pTrigger = 0; int i; const char *zDb; const char *zName; int nName; sqlite3 *db = pParse->db; if( sqlite3_malloc_failed ) goto drop_trigger_cleanup; if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto drop_trigger_cleanup; } assert( pName->nSrc==1 ); zDb = pName->a[0].zDatabase; zName = pName->a[0].zName; nName = strlen(zName); for(i=0; i<db->nDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; pTrigger = sqlite3HashFind(&(db->aDb[j].trigHash), zName, nName+1); if( pTrigger ) break; } if( !pTrigger ){ sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); goto drop_trigger_cleanup; } sqlite3DropTriggerPtr(pParse, pTrigger, 0); drop_trigger_cleanup: sqlite3SrcListDelete(pName); } /* ** Return a pointer to the Table structure for the table that a trigger ** is set on. */ static Table *tableOfTrigger(sqlite3 *db, Trigger *pTrigger){ return sqlite3FindTable(db,pTrigger->table,db->aDb[pTrigger->iTabDb].zName); } /* ** Drop a trigger given a pointer to that trigger. If nested is false, ** then also generate code to remove the trigger from the SQLITE_MASTER ** table. */ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){ Table *pTable; Vdbe *v; sqlite3 *db = pParse->db; int iDb; iDb = pTrigger->iDb; assert( iDb>=0 && iDb<db->nDb ); pTable = tableOfTrigger(db, pTrigger); assert(pTable); assert( pTable->iDb==iDb || iDb==1 ); #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_TRIGGER; const char *zDb = db->aDb[iDb].zName; const char *zTab = SCHEMA_TABLE(iDb); if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) || |
︙ | ︙ | |||
518 519 520 521 522 523 524 | { OP_Column, 0, 0, 0}, { OP_Ne, 0, ADDR(8), 0}, { OP_Delete, 0, 0, 0}, { OP_Next, 0, ADDR(1), 0}, /* 8 */ }; sqlite3BeginWriteOperation(pParse, 0, iDb); | | | | 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 | { OP_Column, 0, 0, 0}, { OP_Ne, 0, ADDR(8), 0}, { OP_Delete, 0, 0, 0}, { OP_Next, 0, ADDR(1), 0}, /* 8 */ }; sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3OpenMasterTable(v, iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0); sqlite3ChangeCookie(db, v, iDb); sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeOp3(v, OP_DropTrigger, iDb, 0, pTrigger->name, 0); } } /* ** Remove a trigger from the hash tables of the sqlite* pointer. */ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ Trigger *pTrigger; int nName = strlen(zName); pTrigger = sqlite3HashInsert(&(db->aDb[iDb].trigHash), zName, nName+1, 0); if( pTrigger ){ Table *pTable = tableOfTrigger(db, pTrigger); assert( pTable!=0 ); if( pTable->pTrigger == pTrigger ){ pTable->pTrigger = pTrigger->pNext; }else{ Trigger *cc = pTable->pTrigger; |
︙ | ︙ | |||
625 626 627 628 629 630 631 | Parse *pParse, /* The parsing context */ TriggerStep *pStep /* The trigger containing the target token */ ){ Token sDb; /* Dummy database name token */ int iDb; /* Index of the database to use */ SrcList *pSrc; /* SrcList to be returned */ | | | | | 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 | Parse *pParse, /* The parsing context */ TriggerStep *pStep /* The trigger containing the target token */ ){ Token sDb; /* Dummy database name token */ int iDb; /* Index of the database to use */ SrcList *pSrc; /* SrcList to be returned */ iDb = pStep->pTrig->iDb; if( iDb==0 || iDb>=2 ){ assert( iDb<pParse->db->nDb ); sDb.z = pParse->db->aDb[iDb].zName; sDb.n = strlen(sDb.z); pSrc = sqlite3SrcListAppend(0, &sDb, &pStep->target); } else { pSrc = sqlite3SrcListAppend(0, &pStep->target, 0); } return pSrc; } |
︙ | ︙ | |||
738 739 740 741 742 743 744 | int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ Table *pTab, /* The table to code triggers from */ int newIdx, /* The indice of the "new" row to access */ int oldIdx, /* The indice of the "old" row to access */ int orconf, /* ON CONFLICT policy */ int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ ){ | | > | > | < | | < < < < | | | > > > > > | | | | > | 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 | int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ Table *pTab, /* The table to code triggers from */ int newIdx, /* The indice of the "new" row to access */ int oldIdx, /* The indice of the "old" row to access */ int orconf, /* ON CONFLICT policy */ int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ ){ Trigger *pTrigger; TriggerStack *pStack; TriggerStack trigStackEntry; assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE); assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER ); assert(newIdx != -1 || oldIdx != -1); pTrigger = pTab->pTrigger; while( pTrigger ){ int fire_this = 0; /* determine whether we should code this trigger */ if( pTrigger->op == op && pTrigger->tr_tm == tr_tm ){ fire_this = 1; for(pStack=pParse->trigStack; pStack; pStack=pStack->pNext){ if( pStack->pTrigger==pTrigger ){ fire_this = 0; } } if( op == TK_UPDATE && pTrigger->pColumns && !checkColumnOverLap(pTrigger->pColumns, pChanges) ){ fire_this = 0; } } if( fire_this ){ int endTrigger; Expr * whenExpr; AuthContext sContext; NameContext sNC; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; /* Push an entry on to the trigger stack */ trigStackEntry.pTrigger = pTrigger; trigStackEntry.newIdx = newIdx; trigStackEntry.oldIdx = oldIdx; trigStackEntry.pTab = pTab; trigStackEntry.pNext = pParse->trigStack; trigStackEntry.ignoreJump = ignoreJump; pParse->trigStack = &trigStackEntry; sqlite3AuthContextPush(pParse, &sContext, pTrigger->name); /* code the WHEN clause */ endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe); whenExpr = sqlite3ExprDup(pTrigger->pWhen); if( sqlite3ExprResolveNames(&sNC, whenExpr) ){ pParse->trigStack = trigStackEntry.pNext; sqlite3ExprDelete(whenExpr); return 1; } sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1); sqlite3ExprDelete(whenExpr); codeTriggerProgram(pParse, pTrigger->step_list, orconf); /* Pop the entry off the trigger stack */ pParse->trigStack = trigStackEntry.pNext; sqlite3AuthContextPop(&sContext); sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger); } pTrigger = pTrigger->pNext; } return 0; } #endif /* !defined(SQLITE_OMIT_TRIGGER) */ |
Changes to SQLite.Interop/src/update.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** ** $Id: update.c,v 1.1 2005/03/01 16:04:37 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Process an UPDATE statement. ** ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; ** \_______/ \________/ \______/ \________________/ * onError pTabList pChanges pWhere */ |
︙ | ︙ | |||
80 81 82 83 84 85 86 | int iCur; /* VDBE Cursor number of pTab */ sqlite3 *db; /* The database structure */ Index **apIdx = 0; /* An array of indices that need updating too */ char *aIdxUsed = 0; /* aIdxUsed[i]==1 if the i-th index is used */ int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the ** an expression for the i-th column of the table. ** aXRef[i]==-1 if the i-th column is not changed. */ | | | < < | < < | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | int iCur; /* VDBE Cursor number of pTab */ sqlite3 *db; /* The database structure */ Index **apIdx = 0; /* An array of indices that need updating too */ char *aIdxUsed = 0; /* aIdxUsed[i]==1 if the i-th index is used */ int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the ** an expression for the i-th column of the table. ** aXRef[i]==-1 if the i-th column is not changed. */ int chngRecno; /* True if the record number is being changed */ Expr *pRecnoExpr = 0; /* Expression defining the new record number */ int openAll = 0; /* True if all indices need to be opened */ AuthContext sContext; /* The authorization context */ NameContext sNC; /* The name-context to resolve expressions in */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* Trying to update a view */ int triggers_exist = 0; /* True if any row triggers exist */ #endif int newIdx = -1; /* index of trigger "new" temp table */ int oldIdx = -1; /* index of trigger "old" temp table */ sContext.pParse = 0; if( pParse->nErr || sqlite3_malloc_failed ) goto update_cleanup; db = pParse->db; assert( pTabList->nSrc==1 ); /* Locate the table which we want to update. */ pTab = sqlite3SrcListLookup(pParse, pTabList); if( pTab==0 ) goto update_cleanup; /* Figure out if we have any triggers and if the table being ** updated is a view */ #ifndef SQLITE_OMIT_TRIGGER triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges); isView = pTab->pSelect!=0; |
︙ | ︙ | |||
164 165 166 167 168 169 170 | /* Resolve the column names in all the expressions of the ** of the UPDATE statement. Also find the column index ** for each column to be updated in the pChanges array. For each ** column to be updated, make sure we have authorization to change ** that column. */ | | | | | | | | | > | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | /* Resolve the column names in all the expressions of the ** of the UPDATE statement. Also find the column index ** for each column to be updated in the pChanges array. For each ** column to be updated, make sure we have authorization to change ** that column. */ chngRecno = 0; for(i=0; i<pChanges->nExpr; i++){ if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){ goto update_cleanup; } for(j=0; j<pTab->nCol; j++){ if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){ if( j==pTab->iPKey ){ chngRecno = 1; pRecnoExpr = pChanges->a[i].pExpr; } aXRef[j] = i; break; } } if( j>=pTab->nCol ){ if( sqlite3IsRowid(pChanges->a[i].zName) ){ chngRecno = 1; pRecnoExpr = pChanges->a[i].pExpr; }else{ sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName); goto update_cleanup; } } #ifndef SQLITE_OMIT_AUTHORIZATION { int rc; rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, pTab->aCol[j].zName, db->aDb[pTab->iDb].zName); if( rc==SQLITE_DENY ){ goto update_cleanup; }else if( rc==SQLITE_IGNORE ){ aXRef[j] = -1; } } #endif } /* Allocate memory for the array apIdx[] and fill it with pointers to every ** index that needs to be updated. Indices only need updating if their ** key includes one of the columns named in pChanges or if the record ** number of the original table entry is changing. */ for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){ if( chngRecno ){ i = 0; }else { for(i=0; i<pIdx->nColumn; i++){ if( aXRef[pIdx->aiColumn[i]]>=0 ) break; } } if( i<pIdx->nColumn ) nIdx++; } if( nIdxTotal>0 ){ apIdx = sqliteMallocRaw( sizeof(Index*) * nIdx + nIdxTotal ); if( apIdx==0 ) goto update_cleanup; aIdxUsed = (char*)&apIdx[nIdx]; } for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ if( chngRecno ){ i = 0; }else{ for(i=0; i<pIdx->nColumn; i++){ if( aXRef[pIdx->aiColumn[i]]>=0 ) break; } } if( i<pIdx->nColumn ){ if( sqlite3CheckIndexCollSeq(pParse, pIdx) ) goto update_cleanup; apIdx[nIdx++] = pIdx; aIdxUsed[j] = 1; }else{ aIdxUsed[j] = 0; } } |
︙ | ︙ | |||
256 257 258 259 260 261 262 | } /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto update_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); | | | | | | | | | 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | } /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto update_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, 1, pTab->iDb); /* If we are trying to update a view, construct that view into ** a temporary table. */ if( isView ){ Select *pView; pView = sqlite3SelectDup(pTab->pSelect); sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0); sqlite3SelectDelete(pView); } /* Begin the database scan */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0); if( pWInfo==0 ) goto update_cleanup; /* Remember the index of every item to be updated. */ sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0); /* End the database scan loop. */ sqlite3WhereEnd(pWInfo); /* Initialize the count of updated rows */ |
︙ | ︙ | |||
298 299 300 301 302 303 304 | sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol); sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol); /* The top of the update loop for when there are triggers. */ | > | < < | | | | | > > | | | | | | | < | > | > < | | > | | | | < | | | | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 | sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol); sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol); /* The top of the update loop for when there are triggers. */ sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0); addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); /* Open a cursor and make it point to the record that is ** being updated. */ sqlite3VdbeAddOp(v, OP_Dup, 0, 0); if( !isView ){ sqlite3OpenTableForReading(v, iCur, pTab); } sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); /* Generate the OLD table */ sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); sqlite3VdbeAddOp(v, OP_RowData, iCur, 0); sqlite3VdbeAddOp(v, OP_PutIntKey, oldIdx, 0); /* Generate the NEW table */ if( chngRecno ){ sqlite3ExprCodeAndCache(pParse, pRecnoExpr); }else{ sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); } for(i=0; i<pTab->nCol; i++){ if( i==pTab->iPKey ){ sqlite3VdbeAddOp(v, OP_String8, 0, 0); continue; } j = aXRef[i]; if( j<0 ){ sqlite3VdbeAddOp(v, OP_Column, iCur, i); }else{ sqlite3ExprCodeAndCache(pParse, pChanges->a[j].pExpr); } } sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); if( !isView ){ sqlite3TableAffinityStr(v, pTab); } if( pParse->nErr ) goto update_cleanup; sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0); if( !isView ){ sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } /* Fire the BEFORE and INSTEAD OF triggers */ if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab, newIdx, oldIdx, onError, addr) ){ goto update_cleanup; } } if( !isView ){ /* ** Open every index that needs updating. Note that if any ** index could potentially invoke a REPLACE conflict resolution ** action, then we need to open all indices because we might need ** to be deleting some records. */ sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, iCur, pTab->tnum); sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol); if( onError==OE_Replace ){ openAll = 1; }else{ openAll = 0; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( pIdx->onError==OE_Replace ){ openAll = 1; break; } } } for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aIdxUsed[i] ){ sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); sqlite3VdbeOp3(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, (char*)&pIdx->keyInfo, P3_KEYINFO); assert( pParse->nTab>iCur+i+1 ); } } /* Loop over every record that needs updating. We have to load ** the old data for each record to be updated because some columns ** might not change and we will need to copy the old value. ** Also, the old data is needed to delete the old index entires. ** So make the cursor point at the old record. */ if( !triggers_exist ){ sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0); addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); } sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr); /* If the record number will change, push the record number as it ** will be after the update. (The old record number is currently ** on top of the stack.) */ if( chngRecno ){ sqlite3ExprCode(pParse, pRecnoExpr); sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); } /* Compute new data for this record. */ for(i=0; i<pTab->nCol; i++){ if( i==pTab->iPKey ){ sqlite3VdbeAddOp(v, OP_String8, 0, 0); continue; } j = aXRef[i]; if( j<0 ){ sqlite3VdbeAddOp(v, OP_Column, iCur, i); }else{ sqlite3ExprCode(pParse, pChanges->a[j].pExpr); } } /* Do constraint checks */ sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, onError, addr); /* Delete the old indices for the current record. */ sqlite3GenerateRowIndexDelete(db, v, pTab, iCur, aIdxUsed); /* If changing the record number, delete the old record. */ if( chngRecno ){ sqlite3VdbeAddOp(v, OP_Delete, iCur, 0); } /* Create the new index entries and the new record. */ sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, -1); } /* Increment the row counter */ if( db->flags & SQLITE_CountRows && !pParse->trigStack){ sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); } |
︙ | ︙ | |||
467 468 469 470 471 472 473 | } } /* Repeat the above with the next record to be updated, until ** all record selected by the WHERE clause have been updated. */ sqlite3VdbeAddOp(v, OP_Goto, 0, addr); | > | | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | } } /* Repeat the above with the next record to be updated, until ** all record selected by the WHERE clause have been updated. */ sqlite3VdbeAddOp(v, OP_Goto, 0, addr); sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v)); sqlite3VdbeAddOp(v, OP_ListReset, 0, 0); /* Close all tables if there were no FOR EACH ROW triggers */ if( !triggers_exist ){ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aIdxUsed[i] ){ sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0); } |
︙ | ︙ |
Changes to SQLite.Interop/src/utf.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used to translate between UTF-8, ** UTF-16, UTF-16BE, and UTF-16LE. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used to translate between UTF-8, ** UTF-16, UTF-16BE, and UTF-16LE. ** ** $Id: utf.c,v 1.1 2005/03/01 16:04:37 rmsimpson Exp $ ** ** Notes on UTF-8: ** ** Byte-0 Byte-1 Byte-2 Byte-3 Value ** 0xxxxxxx 00000000 00000000 0xxxxxxx ** 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx ** 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx |
︙ | ︙ | |||
268 269 270 271 272 273 274 | u8 temp; int rc; rc = sqlite3VdbeMemMakeWriteable(pMem); if( rc!=SQLITE_OK ){ assert( rc==SQLITE_NOMEM ); return SQLITE_NOMEM; } | | | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | u8 temp; int rc; rc = sqlite3VdbeMemMakeWriteable(pMem); if( rc!=SQLITE_OK ){ assert( rc==SQLITE_NOMEM ); return SQLITE_NOMEM; } zIn = pMem->z; zTerm = &zIn[pMem->n]; while( zIn<zTerm ){ temp = *zIn; *zIn = *(zIn+1); zIn++; *zIn++ = temp; } |
︙ | ︙ | |||
304 305 306 307 308 309 310 | /* Set zIn to point at the start of the input buffer and zTerm to point 1 ** byte past the end. ** ** Variable zOut is set to point at the output buffer. This may be space ** obtained from malloc(), or Mem.zShort, if it large enough and not in ** use, or the zShort array on the stack (see above). */ | | | 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | /* Set zIn to point at the start of the input buffer and zTerm to point 1 ** byte past the end. ** ** Variable zOut is set to point at the output buffer. This may be space ** obtained from malloc(), or Mem.zShort, if it large enough and not in ** use, or the zShort array on the stack (see above). */ zIn = pMem->z; zTerm = &zIn[pMem->n]; if( len>NBFS ){ zOut = sqliteMallocRaw(len); if( !zOut ) return SQLITE_NOMEM; }else{ zOut = zShort; } |
︙ | ︙ | |||
356 357 358 359 360 361 362 | assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); sqlite3VdbeMemRelease(pMem); pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short); pMem->enc = desiredEnc; if( zOut==zShort ){ memcpy(pMem->zShort, zOut, len); | | | | 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); sqlite3VdbeMemRelease(pMem); pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short); pMem->enc = desiredEnc; if( zOut==zShort ){ memcpy(pMem->zShort, zOut, len); zOut = pMem->zShort; pMem->flags |= (MEM_Term|MEM_Short); }else{ pMem->flags |= (MEM_Term|MEM_Dyn); } pMem->z = zOut; translate_out: #if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) { char zBuf[100]; sqlite3VdbeMemPrettyPrint(pMem, zBuf, 100); fprintf(stderr, "OUTPUT: %s\n", zBuf); |
︙ | ︙ | |||
446 447 448 449 450 451 452 | SKIP_UTF8(z); r++; } return r; } #ifndef SQLITE_OMIT_UTF16 | < < < < < < < < < < < < < < < < < | 446 447 448 449 450 451 452 453 454 455 456 457 458 459 | SKIP_UTF8(z); r++; } return r; } #ifndef SQLITE_OMIT_UTF16 /* ** pZ is a UTF-16 encoded unicode string. If nChar is less than zero, ** return the number of bytes up to (but not including), the first pair ** of consecutive 0x00 bytes in pZ. If nChar is not less than zero, ** then return the number of bytes in the first nChar unicode characters ** in pZ (or up until the first pair of 0x00 bytes, whichever comes first). */ |
︙ | ︙ |
Changes to SQLite.Interop/src/util.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < | < | < | < | < | < < | | < < < < < > > | < < < < < < < < | < < < < < < < < < < | < < < < < < < < < < < < < | < < < < < < < < < < | < < < < < < < | < < < < < < < < < < < | | < < < | < < < < < < < < < < < < < < < < | | < < < < < < | > > < < > > > < | | < < < | > > > > > > > > < < < < < < < | < < < < < < < < < < | < < < < < | < < < < | | > > | | | < < < < < < < | < | | < | < | | < > | | | < < | > | < < < | | < < < | < < | < < < | < < < < < < < < < | < < < < < < | | < | < < > | < < | > | > | < | > > > > | | < < < < < < < < < < < < < < | < > > > | > > | | | | | | | | | < | < < < < < < < | > | < > | < < | > > > > > | | < < < < < < < > | < > < < < < < < < < < < < | > > | < < | < < < | | < < | | < | < < | < < < | < < > > | | > | < < < < | > | | | | | | | > | | < | < < < < < | < < < < < < > | | | | < > | < | | > > | < < < | < < < < < < < < < < < < | < < > < < | < | < | < < | < < < < > | > > > > > > > | < < > < < < > > | < | < < | | < < < < < | > | < < < < < | | | | > > > < | | | < < < < | < < | | > | | > | | < | < < < | < < < < < < | < < < < < < < < < < | < < < < < < < < < < < | < < < < < < < < < < < < < | < < < < < < < < | | < < | | | | | | > > | | < | | | | < < < < < < < < < < < < < < | < < | < < < < | | > | | | > | | > > > > > | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.1 2005/03/01 16:04:37 rmsimpson Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> #if SQLITE_MEMDEBUG>2 && defined(__GLIBC__) #include <execinfo.h> void print_stack_trace(){ void *bt[30]; int i; int n = backtrace(bt, 30); fprintf(stderr, "STACK: "); for(i=0; i<n;i++){ fprintf(stderr, "%p ", bt[i]); } fprintf(stderr, "\n"); } #else #define print_stack_trace() #endif /* ** If malloc() ever fails, this global variable gets set to 1. ** This causes the library to abort and never again function. */ int sqlite3_malloc_failed = 0; /* ** If SQLITE_MEMDEBUG is defined, then use versions of malloc() and ** free() that track memory usage and check for buffer overruns. */ #ifdef SQLITE_MEMDEBUG /* ** For keeping track of the number of mallocs and frees. This ** is used to check for memory leaks. The iMallocFail and iMallocReset ** values are used to simulate malloc() failures during testing in ** order to verify that the library correctly handles an out-of-memory ** condition. */ int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */ int sqlite3_nFree; /* Number of sqliteFree() calls */ int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */ int sqlite3_iMallocReset = -1; /* When iMallocFail reaches 0, set to this */ #if SQLITE_MEMDEBUG>1 static int memcnt = 0; #endif /* ** Number of 32-bit guard words */ #define N_GUARD 1 /* ** Allocate new memory and set it to zero. Return NULL if ** no memory is available. */ void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){ void *p; int *pi; int i, k; if( sqlite3_iMallocFail>=0 ){ sqlite3_iMallocFail--; if( sqlite3_iMallocFail==0 ){ sqlite3_malloc_failed++; #if SQLITE_MEMDEBUG>1 fprintf(stderr,"**** failed to allocate %d bytes at %s:%d\n", n, zFile,line); #endif sqlite3_iMallocFail = sqlite3_iMallocReset; return 0; } } if( n==0 ) return 0; k = (n+sizeof(int)-1)/sizeof(int); pi = malloc( (N_GUARD*2+1+k)*sizeof(int)); if( pi==0 ){ if( n>0 ) sqlite3_malloc_failed++; return 0; } sqlite3_nMalloc++; for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122; pi[N_GUARD] = n; for(i=0; i<N_GUARD; i++) pi[k+1+N_GUARD+i] = 0xdead3344; p = &pi[N_GUARD+1]; memset(p, bZero==0, n); #if SQLITE_MEMDEBUG>1 print_stack_trace(); fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n", ++memcnt, n, (int)p, zFile,line); #endif return p; } /* ** Check to see if the given pointer was obtained from sqliteMalloc() ** and is able to hold at least N bytes. Raise an exception if this ** is not the case. ** ** This routine is used for testing purposes only. */ void sqlite3CheckMemory(void *p, int N){ int *pi = p; int n, i, k; pi -= N_GUARD+1; for(i=0; i<N_GUARD; i++){ assert( pi[i]==0xdead1122 ); } n = pi[N_GUARD]; assert( N>=0 && N<n ); k = (n+sizeof(int)-1)/sizeof(int); for(i=0; i<N_GUARD; i++){ assert( pi[k+N_GUARD+1+i]==0xdead3344 ); } } /* ** Free memory previously obtained from sqliteMalloc() */ void sqlite3Free_(void *p, char *zFile, int line){ if( p ){ int *pi, i, k, n; pi = p; pi -= N_GUARD+1; sqlite3_nFree++; for(i=0; i<N_GUARD; i++){ if( pi[i]!=0xdead1122 ){ fprintf(stderr,"Low-end memory corruption at 0x%x\n", (int)p); return; } } n = pi[N_GUARD]; k = (n+sizeof(int)-1)/sizeof(int); for(i=0; i<N_GUARD; i++){ if( pi[k+N_GUARD+1+i]!=0xdead3344 ){ fprintf(stderr,"High-end memory corruption at 0x%x\n", (int)p); return; } } memset(pi, 0xff, (k+N_GUARD*2+1)*sizeof(int)); #if SQLITE_MEMDEBUG>1 fprintf(stderr,"%06d free %d bytes at 0x%x from %s:%d\n", ++memcnt, n, (int)p, zFile,line); #endif free(pi); } } /* ** Resize a prior allocation. If p==0, then this routine ** works just like sqliteMalloc(). If n==0, then this routine ** works just like sqliteFree(). */ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){ int *oldPi, *pi, i, k, oldN, oldK; void *p; if( oldP==0 ){ return sqlite3Malloc_(n,1,zFile,line); } if( n==0 ){ sqlite3Free_(oldP,zFile,line); return 0; } oldPi = oldP; oldPi -= N_GUARD+1; if( oldPi[0]!=0xdead1122 ){ fprintf(stderr,"Low-end memory corruption in realloc at 0x%x\n", (int)oldP); return 0; } oldN = oldPi[N_GUARD]; oldK = (oldN+sizeof(int)-1)/sizeof(int); for(i=0; i<N_GUARD; i++){ if( oldPi[oldK+N_GUARD+1+i]!=0xdead3344 ){ fprintf(stderr,"High-end memory corruption in realloc at 0x%x\n", (int)oldP); return 0; } } k = (n + sizeof(int) - 1)/sizeof(int); pi = malloc( (k+N_GUARD*2+1)*sizeof(int) ); if( pi==0 ){ if( n>0 ) sqlite3_malloc_failed++; return 0; } for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122; pi[N_GUARD] = n; for(i=0; i<N_GUARD; i++) pi[k+N_GUARD+1+i] = 0xdead3344; p = &pi[N_GUARD+1]; memcpy(p, oldP, n>oldN ? oldN : n); if( n>oldN ){ memset(&((char*)p)[oldN], 0x55, n-oldN); } memset(oldPi, 0xab, (oldK+N_GUARD+2)*sizeof(int)); free(oldPi); #if SQLITE_MEMDEBUG>1 print_stack_trace(); fprintf(stderr,"%06d realloc %d to %d bytes at 0x%x to 0x%x at %s:%d\n", ++memcnt, oldN, n, (int)oldP, (int)p, zFile, line); #endif return p; } /* ** Make a copy of a string in memory obtained from sqliteMalloc() */ char *sqlite3StrDup_(const char *z, char *zFile, int line){ char *zNew; if( z==0 ) return 0; zNew = sqlite3Malloc_(strlen(z)+1, 0, zFile, line); if( zNew ) strcpy(zNew, z); return zNew; } char *sqlite3StrNDup_(const char *z, int n, char *zFile, int line){ char *zNew; if( z==0 ) return 0; zNew = sqlite3Malloc_(n+1, 0, zFile, line); if( zNew ){ memcpy(zNew, z, n); zNew[n] = 0; } return zNew; } /* ** A version of sqliteFree that is always a function, not a macro. */ void sqlite3FreeX(void *p){ sqliteFree(p); } #endif /* SQLITE_MEMDEBUG */ /* ** The following versions of malloc() and free() are for use in a ** normal build. */ #if !defined(SQLITE_MEMDEBUG) /* ** Allocate new memory and set it to zero. Return NULL if ** no memory is available. See also sqliteMallocRaw(). */ void *sqlite3Malloc(int n){ void *p; if( (p = malloc(n))==0 ){ if( n>0 ) sqlite3_malloc_failed++; }else{ memset(p, 0, n); } return p; } /* ** Allocate new memory but do not set it to zero. Return NULL if ** no memory is available. See also sqliteMalloc(). */ void *sqlite3MallocRaw(int n){ void *p; if( (p = malloc(n))==0 ){ if( n>0 ) sqlite3_malloc_failed++; } return p; } /* ** Free memory previously obtained from sqliteMalloc() */ void sqlite3FreeX(void *p){ if( p ){ free(p); } } /* ** Resize a prior allocation. If p==0, then this routine ** works just like sqliteMalloc(). If n==0, then this routine ** works just like sqliteFree(). */ void *sqlite3Realloc(void *p, int n){ void *p2; if( p==0 ){ return sqliteMalloc(n); } if( n==0 ){ sqliteFree(p); return 0; } p2 = realloc(p, n); if( p2==0 ){ if( n>0 ) sqlite3_malloc_failed++; } return p2; } /* ** Make a copy of a string in memory obtained from sqliteMalloc() */ char *sqlite3StrDup(const char *z){ char *zNew; if( z==0 ) return 0; zNew = sqliteMallocRaw(strlen(z)+1); if( zNew ) strcpy(zNew, z); return zNew; } char *sqlite3StrNDup(const char *z, int n){ char *zNew; if( z==0 ) return 0; zNew = sqliteMallocRaw(n+1); if( zNew ){ memcpy(zNew, z, n); zNew[n] = 0; } return zNew; } #endif /* !defined(SQLITE_MEMDEBUG) */ /* ** Create a string from the 2nd and subsequent arguments (up to the ** first NULL argument), store the string in memory obtained from ** sqliteMalloc() and make the pointer indicated by the 1st argument ** point to that string. The 1st argument must either be NULL or ** point to memory obtained from sqliteMalloc(). */ void sqlite3SetString(char **pz, const char *zFirst, ...){ va_list ap; int nByte; const char *z; char *zResult; if( pz==0 ) return; nByte = strlen(zFirst) + 1; va_start(ap, zFirst); while( (z = va_arg(ap, const char*))!=0 ){ nByte += strlen(z); } va_end(ap); sqliteFree(*pz); *pz = zResult = sqliteMallocRaw( nByte ); if( zResult==0 ){ return; } strcpy(zResult, zFirst); zResult += strlen(zResult); va_start(ap, zFirst); while( (z = va_arg(ap, const char*))!=0 ){ strcpy(zResult, z); zResult += strlen(zResult); } va_end(ap); #ifdef SQLITE_DEBUG #if SQLITE_DEBUG>1 fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz); #endif #endif } /* ** Set the most recent error code and error string for the sqlite ** handle "db". The error code is set to "err_code". ** ** If it is not NULL, string zFormat specifies the format of the ** error string in the style of the printf functions: The following ** format characters are allowed: ** ** %s Insert a string ** %z A string that should be freed after use ** %d Insert an integer ** %T Insert a token ** %S Insert the first element of a SrcList ** ** zFormat and any string tokens that follow it are assumed to be ** encoded in UTF-8. ** ** To clear the most recent error for slqite handle "db", sqlite3Error ** should be called with err_code set to SQLITE_OK and zFormat set ** to NULL. */ void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ if( db && (db->pErr || (db->pErr = sqlite3ValueNew())) ){ db->errCode = err_code; if( zFormat ){ char *z; va_list ap; va_start(ap, zFormat); z = sqlite3VMPrintf(zFormat, ap); va_end(ap); |
︙ | ︙ | |||
771 772 773 774 775 776 777 | pParse->nErr++; sqliteFree(pParse->zErrMsg); va_start(ap, zFormat); pParse->zErrMsg = sqlite3VMPrintf(zFormat, ap); va_end(ap); } | < < < < < < < < < < | | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 | pParse->nErr++; sqliteFree(pParse->zErrMsg); va_start(ap, zFormat); pParse->zErrMsg = sqlite3VMPrintf(zFormat, ap); va_end(ap); } /* ** Convert an SQL-style quoted string into a normal string by removing ** the quote characters. The conversion is done in-place. If the ** input does not begin with a quote character, then this routine ** is a no-op. ** ** 2002-Feb-14: This routine is extended to remove MS-Access style ** brackets from around identifers. For example: "[a-b-c]" becomes ** "a-b-c". */ void sqlite3Dequote(char *z){ int quote; int i, j; if( z==0 ) return; quote = z[0]; switch( quote ){ case '\'': break; case '"': break; case '[': quote = ']'; break; default: return; } for(i=1, j=0; z[i]; i++){ if( z[i]==quote ){ if( z[i+1]==quote ){ z[j++] = quote; i++; |
︙ | ︙ | |||
904 905 906 907 908 909 910 | ** is not, the result is undefined. ** ** This routine is used instead of the library atof() function because ** the library atof() might want to use "," as the decimal point instead ** of "." depending on how locale is set. But that would cause problems ** for SQL. So this routine always uses "." regardless of locale. */ | | < < | 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 | ** is not, the result is undefined. ** ** This routine is used instead of the library atof() function because ** the library atof() might want to use "," as the decimal point instead ** of "." depending on how locale is set. But that would cause problems ** for SQL. So this routine always uses "." regardless of locale. */ double sqlite3AtoF(const char *z, const char **pzEnd){ int sign = 1; LONGDOUBLE_TYPE v1 = 0.0; if( *z=='-' ){ sign = -1; z++; }else if( *z=='+' ){ z++; } |
︙ | ︙ | |||
954 955 956 957 958 959 960 | while( eval>=1 ){ scale *= 1.0e+1; eval -= 1; } if( esign<0 ){ v1 /= scale; }else{ v1 *= scale; } } | > | < < < < | 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 | while( eval>=1 ){ scale *= 1.0e+1; eval -= 1; } if( esign<0 ){ v1 /= scale; }else{ v1 *= scale; } } if( pzEnd ) *pzEnd = z; return sign<0 ? -v1 : v1; } /* ** Return TRUE if zNum is a 64-bit signed integer and write ** the value of the integer into *pNum. If zNum is not an integer ** or is an integer that is too large to be expressed with 64 bits, ** then return false. If n>0 and the integer is string is not |
︙ | ︙ | |||
1064 1065 1066 1067 1068 1069 1070 | ** call to sqlite3_close(db) and db has been deallocated. And we do ** not want to write into deallocated memory. */ int sqlite3SafetyOn(sqlite3 *db){ if( db->magic==SQLITE_MAGIC_OPEN ){ db->magic = SQLITE_MAGIC_BUSY; return 0; | | | | 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 | ** call to sqlite3_close(db) and db has been deallocated. And we do ** not want to write into deallocated memory. */ int sqlite3SafetyOn(sqlite3 *db){ if( db->magic==SQLITE_MAGIC_OPEN ){ db->magic = SQLITE_MAGIC_BUSY; return 0; }else if( db->magic==SQLITE_MAGIC_BUSY || db->magic==SQLITE_MAGIC_ERROR ){ db->magic = SQLITE_MAGIC_ERROR; db->flags |= SQLITE_Interrupt; } return 1; } /* ** Change the magic from SQLITE_MAGIC_BUSY to SQLITE_MAGIC_OPEN. ** Return an error (non-zero) if the magic was not SQLITE_MAGIC_BUSY ** when this routine is called. */ int sqlite3SafetyOff(sqlite3 *db){ if( db->magic==SQLITE_MAGIC_BUSY ){ db->magic = SQLITE_MAGIC_OPEN; return 0; }else if( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ERROR ){ db->magic = SQLITE_MAGIC_ERROR; db->flags |= SQLITE_Interrupt; } return 1; } /* |
︙ | ︙ | |||
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 | ** Read a 32-bit variable-length integer from memory starting at p[0]. ** Return the number of bytes read. The value is stored in *v. */ int sqlite3GetVarint32(const unsigned char *p, u32 *v){ u32 x; int n; unsigned char c; if( ((signed char*)p)[0]>=0 ){ *v = p[0]; return 1; } x = p[0] & 0x7f; if( ((signed char*)p)[1]>=0 ){ *v = (x<<7) | p[1]; return 2; } x = (x<<7) | (p[1] & 0x7f); n = 2; do{ x = (x<<7) | ((c = p[n++])&0x7f); }while( (c & 0x80)!=0 && n<9 ); *v = x; return n; } | > > > > > > > > > > > > > | 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 | ** Read a 32-bit variable-length integer from memory starting at p[0]. ** Return the number of bytes read. The value is stored in *v. */ int sqlite3GetVarint32(const unsigned char *p, u32 *v){ u32 x; int n; unsigned char c; #if 0 if( ((c = p[0]) & 0x80)==0 ){ *v = c; return 1; } x = c & 0x7f; if( ((c = p[1]) & 0x80)==0 ){ *v = (x<<7) | c; return 2; } x = (x<<7) | (c & 0x7f); #else if( ((signed char*)p)[0]>=0 ){ *v = p[0]; return 1; } x = p[0] & 0x7f; if( ((signed char*)p)[1]>=0 ){ *v = (x<<7) | p[1]; return 2; } x = (x<<7) | (p[1] & 0x7f); #endif n = 2; do{ x = (x<<7) | ((c = p[n++])&0x7f); }while( (c & 0x80)!=0 && n<9 ); *v = x; return n; } |
︙ | ︙ | |||
1241 1242 1243 1244 1245 1246 1247 | do{ i++; v >>= 7; }while( v!=0 && i<9 ); return i; } | | | | 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 | do{ i++; v >>= 7; }while( v!=0 && i<9 ); return i; } #if (!defined(SQLITE_OMIT_BLOB_LITERAL) && !defined(SQLITE_HAS_CODEC)) \ || defined(SQLITE_TEST) /* ** Translate a single byte of Hex into an integer. */ static int hexToInt(int h){ if( h>='0' && h<='9' ){ return h - '0'; }else if( h>='a' && h<='f' ){ return h - 'a' + 10; }else{ assert( h>='A' && h<='F' ); return h - 'A' + 10; } } #endif /* (!SQLITE_OMIT_BLOB_LITERAL && !SQLITE_HAS_CODEC) || SQLITE_TEST */ #if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) /* ** Convert a BLOB literal of the form "x'hhhhhh'" into its binary ** value. Return a pointer to its binary value. Space to hold the ** binary value has been obtained from malloc and must be freed by ** the calling routine. |
︙ | ︙ | |||
1305 1306 1307 1308 1309 1310 1311 1312 | }else{ assert( sizeof(p)==sizeof(v2) ); v2 = (u32)v; p = *(void**)&v2; } return p; } #endif | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 962 963 964 965 966 967 968 969 | }else{ assert( sizeof(p)==sizeof(v2) ); v2 = (u32)v; p = *(void**)&v2; } return p; } #endif |
Changes to SQLite.Interop/src/vacuum.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** | | < | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** ************************************************************************* ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** ** $Id: vacuum.c,v 1.1 2005/03/01 16:04:37 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #ifndef SQLITE_OMIT_VACUUM /* ** Generate a random name of 20 character in length. */ static void randomName(unsigned char *zBuf){ |
︙ | ︙ | |||
55 56 57 58 59 60 61 | sqlite3_stmt *pStmt; int rc; rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; while( SQLITE_ROW==sqlite3_step(pStmt) ){ | | | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | sqlite3_stmt *pStmt; int rc; rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; while( SQLITE_ROW==sqlite3_step(pStmt) ){ rc = execSql(db, sqlite3_column_text(pStmt, 0)); if( rc!=SQLITE_OK ){ sqlite3_finalize(pStmt); return rc; } } return sqlite3_finalize(pStmt); |
︙ | ︙ | |||
97 98 99 100 101 102 103 | #ifndef SQLITE_OMIT_VACUUM const char *zFilename; /* full pathname of the database file */ int nFilename; /* number of characters in zFilename[] */ char *zTemp = 0; /* a temporary file in same directory as zFilename */ Btree *pMain; /* The database being vacuumed */ Btree *pTemp; char *zSql = 0; | < < < < < < | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | #ifndef SQLITE_OMIT_VACUUM const char *zFilename; /* full pathname of the database file */ int nFilename; /* number of characters in zFilename[] */ char *zTemp = 0; /* a temporary file in same directory as zFilename */ Btree *pMain; /* The database being vacuumed */ Btree *pTemp; char *zSql = 0; if( !db->autoCommit ){ sqlite3SetString(pzErrMsg, "cannot VACUUM from within a transaction", (char*)0); rc = SQLITE_ERROR; goto end_of_vacuum; } |
︙ | ︙ | |||
162 163 164 165 166 167 168 | rc = SQLITE_NOMEM; goto end_of_vacuum; } rc = execSql(db, zSql); sqliteFree(zSql); zSql = 0; if( rc!=SQLITE_OK ) goto end_of_vacuum; | < | < < < | | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | rc = SQLITE_NOMEM; goto end_of_vacuum; } rc = execSql(db, zSql); sqliteFree(zSql); zSql = 0; if( rc!=SQLITE_OK ) goto end_of_vacuum; assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 ); pTemp = db->aDb[db->nDb-1].pBt; sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), sqlite3BtreeGetReserve(pMain)); assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) ); execSql(db, "PRAGMA vacuum_db.synchronous=OFF"); #ifndef SQLITE_OMIT_AUTOVACUUM sqlite3BtreeSetAutoVacuum(pTemp, sqlite3BtreeGetAutoVacuum(pMain)); #endif /* Begin a transaction */ rc = execSql(db, "BEGIN;"); if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Query the schema of the main database. Create a mirror schema ** in the temporary database. */ rc = execExecSql(db, "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14,100000000) " |
︙ | ︙ | |||
249 250 251 252 253 254 255 | ** transaction open on the vacuum database, but not on the main database. ** Open a btree level transaction on the main database. This allows a ** call to sqlite3BtreeCopyFile(). The main database btree level ** transaction is then committed, so the SQL level never knows it was ** opened for writing. This way, the SQL transaction used to create the ** temporary database never needs to be committed. */ | | | | > < < < < < < < < < < < < < < < < < < < | < > | > | | < | 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | ** transaction open on the vacuum database, but not on the main database. ** Open a btree level transaction on the main database. This allows a ** call to sqlite3BtreeCopyFile(). The main database btree level ** transaction is then committed, so the SQL level never knows it was ** opened for writing. This way, the SQL transaction used to create the ** temporary database never needs to be committed. */ if( sqlite3BtreeIsInTrans(pTemp) ){ u32 meta; int i; /* This array determines which meta meta values are preserved in the ** vacuum. Even entries are the meta value number and odd entries ** are an increment to apply to the meta value after the vacuum. ** The increment is used to increase the schema cookie so that other ** connections to the same database will know to reread the schema. */ static const unsigned char aCopy[] = { 1, 1, /* Add one to the old schema cookie */ 3, 0, /* Preserve the default page cache size */ 5, 0, /* Preserve the default text encoding */ 6, 0, /* Preserve the user version */ }; assert( 0==sqlite3BtreeIsInTrans(pMain) ); rc = sqlite3BtreeBeginTrans(pMain, 1); if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Copy Btree meta values */ for(i=0; i<sizeof(aCopy)/sizeof(aCopy[0]); i+=2){ rc = sqlite3BtreeGetMeta(pMain, aCopy[i], &meta); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]); } rc = sqlite3BtreeCopyFile(pMain, pTemp); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = sqlite3BtreeCommit(pMain); } end_of_vacuum: /* Currently there is an SQL level transaction open on the vacuum ** database. No locks are held on any other files (since the main file ** was committed at the btree level). So it safe to end the transaction ** by manually setting the autoCommit flag to true and detaching the ** vacuum database. The vacuum_db journal file is deleted when the pager ** is closed by the DETACH. */ db->autoCommit = 1; if( rc==SQLITE_OK ){ rc = execSql(db, "DETACH vacuum_db;"); }else{ execSql(db, "DETACH vacuum_db;"); } if( zTemp ){ sqlite3OsDelete(zTemp); sqliteFree(zTemp); } if( zSql ) sqliteFree( zSql ); sqlite3ResetInternalSchema(db, 0); #endif return rc; } |
Changes to SQLite.Interop/src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.1 2005/03/01 16:04:38 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
97 98 99 100 101 102 103 | ** from sqliteMalloc(). This is different from Stringify() above in that ** Stringify() will use the NBFS bytes of static string space if the string ** will fit but this routine always mallocs for space. ** Return non-zero if we run out of memory. */ #define Dynamicify(P,enc) sqlite3VdbeMemDynamicify(P) | < < < < < < < < < < < < < < < < > > > > > > > > > > > > > > > > > | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | ** from sqliteMalloc(). This is different from Stringify() above in that ** Stringify() will use the NBFS bytes of static string space if the string ** will fit but this routine always mallocs for space. ** Return non-zero if we run out of memory. */ #define Dynamicify(P,enc) sqlite3VdbeMemDynamicify(P) /* ** An ephemeral string value (signified by the MEM_Ephem flag) contains ** a pointer to a dynamically allocated string where some other entity ** is responsible for deallocating that string. Because the stack entry ** does not control the string, it might be deleted without the stack ** entry knowing it. ** ** This routine converts an ephemeral string into a dynamically allocated ** string that the stack entry itself controls. In other words, it ** converts an MEM_Ephem string into an MEM_Dyn string. */ #define Deephemeralize(P) \ if( ((P)->flags&MEM_Ephem)!=0 \ && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} /* ** Convert the given stack entity into a integer if it isn't one ** already. ** ** Any prior string or real representation is invalidated. ** NULLs are converted into 0. */ #define Integerify(P) sqlite3VdbeMemIntegerify(P) /* ** Convert P so that it has type MEM_Real. ** ** Any prior string or integer representation is invalidated. ** NULLs are converted into 0.0. */ #define Realify(P) sqlite3VdbeMemRealify(P) /* ** Argument pMem points at a memory cell that will be passed to a ** user-defined function or returned to the user as the result of a query. ** The second argument, 'db_enc' is the text encoding used by the vdbe for ** stack variables. This routine sets the pMem->enc and pMem->type ** variables used by the sqlite3_value_*() routines. */ |
︙ | ︙ | |||
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | } else if( flags & MEM_Str ){ pMem->type = SQLITE_TEXT; }else{ pMem->type = SQLITE_BLOB; } } /* ** Pop the stack N times. */ static void popStack(Mem **ppTos, int N){ Mem *pTos = *ppTos; while( N>0 ){ N--; Release(pTos); pTos--; } *ppTos = pTos; } /* ** Allocate cursor number iCur. Return a pointer to it. Return NULL ** if we run out of memory. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < < > | | | | < < < < < < | < < < | > > | < < < | < < | | < < | > | > > > | > > | | | | < < < < < < | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | } else if( flags & MEM_Str ){ pMem->type = SQLITE_TEXT; }else{ pMem->type = SQLITE_BLOB; } } /* ** Insert a new aggregate element and make it the element that ** has focus. ** ** Return 0 on success and 1 if memory is exhausted. */ static int AggInsert(Agg *p, char *zKey, int nKey){ AggElem *pElem; int i; int rc; pElem = sqliteMalloc( sizeof(AggElem) + nKey + (p->nMem-1)*sizeof(pElem->aMem[0]) ); if( pElem==0 ) return SQLITE_NOMEM; pElem->zKey = (char*)&pElem->aMem[p->nMem]; memcpy(pElem->zKey, zKey, nKey); pElem->nKey = nKey; if( p->pCsr ){ rc = sqlite3BtreeInsert(p->pCsr, zKey, nKey, &pElem, sizeof(AggElem*)); if( rc!=SQLITE_OK ){ sqliteFree(pElem); return rc; } } for(i=0; i<p->nMem; i++){ pElem->aMem[i].flags = MEM_Null; } p->pCurrent = pElem; return 0; } /* ** Pop the stack N times. */ static void popStack(Mem **ppTos, int N){ Mem *pTos = *ppTos; while( N>0 ){ N--; Release(pTos); pTos--; } *ppTos = pTos; } /* ** The parameters are pointers to the head of two sorted lists ** of Sorter structures. Merge these two lists together and return ** a single sorted list. This routine forms the core of the merge-sort ** algorithm. ** ** In the case of a tie, left sorts in front of right. */ static Sorter *Merge(Sorter *pLeft, Sorter *pRight, KeyInfo *pKeyInfo){ Sorter sHead; Sorter *pTail; pTail = &sHead; pTail->pNext = 0; while( pLeft && pRight ){ int c = sqlite3VdbeRecordCompare(pKeyInfo, pLeft->nKey, pLeft->zKey, pRight->nKey, pRight->zKey); if( c<=0 ){ pTail->pNext = pLeft; pLeft = pLeft->pNext; }else{ pTail->pNext = pRight; pRight = pRight->pNext; } pTail = pTail->pNext; } if( pLeft ){ pTail->pNext = pLeft; }else if( pRight ){ pTail->pNext = pRight; } return sHead.pNext; } /* ** Allocate cursor number iCur. Return a pointer to it. Return NULL ** if we run out of memory. */ static Cursor *allocateCursor(Vdbe *p, int iCur){ Cursor *pCx; assert( iCur<p->nCursor ); if( p->apCsr[iCur] ){ sqlite3VdbeFreeCursor(p->apCsr[iCur]); } p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) ); return pCx; } /* ** Apply any conversion required by the supplied column affinity to ** memory cell pRec. affinity may be one of: ** ** SQLITE_AFF_NUMERIC ** SQLITE_AFF_TEXT ** SQLITE_AFF_NONE ** SQLITE_AFF_INTEGER ** */ static void applyAffinity(Mem *pRec, char affinity, u8 enc){ if( affinity==SQLITE_AFF_NONE ){ /* do nothing */ }else if( affinity==SQLITE_AFF_TEXT ){ /* Only attempt the conversion to TEXT if there is an integer or real ** representation (blob and NULL do not get converted) but no string ** representation. */ if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){ sqlite3VdbeMemStringify(pRec, enc); } pRec->flags &= ~(MEM_Real|MEM_Int); }else{ if( 0==(pRec->flags&(MEM_Real|MEM_Int)) ){ /* pRec does not have a valid integer or real representation. ** Attempt a conversion if pRec has a string representation and ** it looks like a number. */ int realnum; sqlite3VdbeMemNulTerminate(pRec); if( pRec->flags&MEM_Str && sqlite3IsNumber(pRec->z, &realnum, enc) ){ if( realnum ){ Realify(pRec); }else{ Integerify(pRec); } } } if( affinity==SQLITE_AFF_INTEGER ){ /* For INTEGER affinity, try to convert a real value to an int */ if( (pRec->flags&MEM_Real) && !(pRec->flags&MEM_Int) ){ pRec->i = pRec->r; if( ((double)pRec->i)==pRec->r ){ pRec->flags |= MEM_Int; } } } } } #ifdef SQLITE_DEBUG /* ** Write a nice string representation of the contents of cell pMem ** into buffer zBuf, length nBuf. */ |
︙ | ︙ | |||
391 392 393 394 395 396 397 | int sqlite3VdbeExec( Vdbe *p /* The VDBE */ ){ int pc; /* The program counter */ Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ | < > < < < < < < < < < < < > > < < | 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 | int sqlite3VdbeExec( Vdbe *p /* The VDBE */ ){ int pc; /* The program counter */ Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ Mem *pTos; /* Top entry in the operand stack */ char zBuf[100]; /* Space to sprintf() an integer */ #ifdef VDBE_PROFILE unsigned long long start; /* CPU clock count at start of opcode */ int origPc; /* Program counter at start of opcode */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int nProgressOps = 0; /* Opcodes executed since progress callback. */ #endif if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE; assert( db->magic==SQLITE_MAGIC_BUSY ); assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); p->rc = SQLITE_OK; assert( p->explain==0 ); pTos = p->pTos; if( sqlite3_malloc_failed ) goto no_mem; if( p->popStack ){ popStack(&pTos, p->popStack); p->popStack = 0; } p->resOnStack = 0; CHECK_FOR_INTERRUPT; for(pc=p->pc; rc==SQLITE_OK; pc++){ assert( pc>=0 && pc<p->nOp ); assert( pTos<=&p->aStack[pc] ); #ifdef VDBE_PROFILE origPc = pc; start = hwtime(); #endif pOp = &p->aOp[pc]; /* Only allow tracing if SQLITE_DEBUG is defined. |
︙ | ︙ | |||
481 482 483 484 485 486 487 | } nProgressOps = 0; } nProgressOps++; } #endif | < < < < < < < < < < < < < < < < < < < < < < | | | | | < < | < | | > > > > > > | | < | < < < < < < < < < | | | | | | > | | | | < < | | < | > | > | | | > > | > | < | | < < > | < | | > | < > < | 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 | } nProgressOps = 0; } nProgressOps++; } #endif switch( pOp->opcode ){ /***************************************************************************** ** What follows is a massive switch statement where each case implements a ** separate instruction in the virtual machine. If we follow the usual ** indentation conventions, each case should be indented by 6 spaces. But ** that is a lot of wasted space on the left margin. So the code within ** the switch statement will break with convention and be flush-left. Another ** big comment (similar to this one) will mark the point in the code where ** we transition back to normal indentation. ** ** The formatting of each case is important. The makefile for SQLite ** generates two C files "opcodes.h" and "opcodes.c" by scanning this ** file looking for lines that begin with "case OP_". The opcodes.h files ** will be filled with #defines that give unique integer values to each ** opcode and the opcodes.c file is filled with an array of strings where ** each string is the symbolic name for the corresponding opcode. If the ** case statement is followed by a comment of the form "/# same as ... #/" ** that comment is used to determine the particular value of the opcode. ** ** Documentation about VDBE opcodes is generated by scanning this file ** for lines of that contain "Opcode:". That line and all subsequent ** comment lines are used in the generation of the opcode.html documentation ** file. ** ** SUMMARY: ** ** Formatting is important to scripts that scan this file. ** Do not deviate from the formatting style currently in use. ** *****************************************************************************/ /* Opcode: Goto * P2 * ** ** An unconditional jump to address P2. ** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. */ case OP_Goto: { CHECK_FOR_INTERRUPT; pc = pOp->p2 - 1; break; } /* Opcode: Gosub * P2 * ** ** Push the current address plus 1 onto the return address stack ** and then jump to address P2. ** ** The return address stack is of limited depth. If too many ** OP_Gosub operations occur without intervening OP_Returns, then ** the return address stack will fill up and processing will abort ** with a fatal error. */ case OP_Gosub: { assert( p->returnDepth<sizeof(p->returnStack)/sizeof(p->returnStack[0]) ); p->returnStack[p->returnDepth++] = pc+1; pc = pOp->p2 - 1; break; } /* Opcode: Return * * * ** ** Jump immediately to the next instruction after the last unreturned ** OP_Gosub. If an OP_Return has occurred for all OP_Gosubs, then ** processing aborts with a fatal error. */ case OP_Return: { assert( p->returnDepth>0 ); p->returnDepth--; pc = p->returnStack[p->returnDepth] - 1; break; } /* Opcode: Halt P1 P2 * ** ** Exit immediately. All open cursors, Lists, Sorts, etc are closed ** automatically. ** ** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(), ** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0). ** For errors, it can be some other value. If P1!=0 then P2 will determine ** whether or not to rollback the current transaction. Do not rollback ** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort, ** then back out all changes that have occurred during this execution of the ** VDBE, but do not rollback the transaction. ** ** There is an implied "Halt 0 0 0" instruction inserted at the very end of ** every program. So a jump past the last instruction of the program ** is the same as executing Halt. */ case OP_Halt: { p->pTos = pTos; p->rc = pOp->p1; p->pc = pc; p->errorAction = pOp->p2; if( pOp->p3 ){ sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK ); if( rc==SQLITE_BUSY ){ p->rc = SQLITE_BUSY; return SQLITE_BUSY; } return p->rc ? SQLITE_ERROR : SQLITE_DONE; } /* Opcode: Integer P1 * P3 ** ** The integer value P1 is pushed onto the stack. If P3 is not zero ** then it is assumed to be a string representation of the same integer. ** If P1 is zero and P3 is not zero, then the value is derived from P3. ** ** If the value cannot be represented as a 32-bits then its value ** will be in P3. */ case OP_Integer: { pTos++; if( pOp->p3==0 ){ pTos->flags = MEM_Int; pTos->i = pOp->p1; }else{ pTos->flags = MEM_Str|MEM_Static|MEM_Term; pTos->z = pOp->p3; pTos->n = strlen(pTos->z); pTos->enc = SQLITE_UTF8; pTos->i = sqlite3VdbeIntValue(pTos); pTos->flags |= MEM_Int; } break; } /* Opcode: Real * * P3 ** ** The string value P3 is converted to a real and pushed on to the stack. */ case OP_Real: { /* same as TK_FLOAT */ pTos++; pTos->flags = MEM_Str|MEM_Static|MEM_Term; pTos->z = pOp->p3; pTos->n = strlen(pTos->z); pTos->enc = SQLITE_UTF8; pTos->r = sqlite3VdbeRealValue(pTos); pTos->flags |= MEM_Real; sqlite3VdbeChangeEncoding(pTos, db->enc); break; } /* Opcode: String8 * * P3 ** ** P3 points to a nul terminated UTF-8 string. This opcode is transformed ** into an OP_String before it is executed for the first time. */ case OP_String8: { /* same as TK_STRING */ #ifndef SQLITE_OMIT_UTF16 pOp->opcode = OP_String; if( db->enc!=SQLITE_UTF8 && pOp->p3 ){ pTos++; sqlite3VdbeMemSetStr(pTos, pOp->p3, -1, SQLITE_UTF8, SQLITE_STATIC); if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pTos, db->enc) ) goto no_mem; if( SQLITE_OK!=sqlite3VdbeMemDynamicify(pTos) ) goto no_mem; pTos->flags &= ~(MEM_Dyn); pTos->flags |= MEM_Static; if( pOp->p3type==P3_DYNAMIC ){ sqliteFree(pOp->p3); } pOp->p3type = P3_DYNAMIC; pOp->p3 = pTos->z; break; } #endif /* Otherwise fall through to the next case, OP_String */ } /* Opcode: String * * P3 ** ** The string value P3 is pushed onto the stack. If P3==0 then a ** NULL is pushed onto the stack. P3 is assumed to be a nul terminated ** string encoded with the database native encoding. */ case OP_String: { pTos++; if( pOp->p3 ){ pTos->flags = MEM_Str|MEM_Static|MEM_Term; pTos->z = pOp->p3; #ifndef SQLITE_OMIT_UTF16 if( db->enc==SQLITE_UTF8 ){ pTos->n = strlen(pTos->z); }else{ pTos->n = sqlite3utf16ByteLen(pTos->z, -1); } #else assert( db->enc==SQLITE_UTF8 ); pTos->n = strlen(pTos->z); #endif pTos->enc = db->enc; }else{ pTos->flags = MEM_Null; } break; } #ifndef SQLITE_OMIT_BLOB_LITERAL /* Opcode: HexBlob * * P3 ** ** P3 is an UTF-8 SQL hex encoding of a blob. The blob is pushed onto the ** vdbe stack. ** |
︙ | ︙ | |||
784 785 786 787 788 789 790 | break; } /* Opcode: Pop P1 * * ** ** P1 elements are popped off of the top of stack and discarded. */ | | | 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 | break; } /* Opcode: Pop P1 * * ** ** P1 elements are popped off of the top of stack and discarded. */ case OP_Pop: { assert( pOp->p1>=0 ); popStack(&pTos, pOp->p1); assert( pTos>=&p->aStack[-1] ); break; } /* Opcode: Dup P1 P2 * |
︙ | ︙ | |||
827 828 829 830 831 832 833 | ** the stack and pushed back on top of the stack. The ** top of the stack is element 0, so "Pull 0 0 0" is ** a no-op. "Pull 1 0 0" swaps the top two elements of ** the stack. ** ** See also the Dup instruction. */ | | | 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 | ** the stack and pushed back on top of the stack. The ** top of the stack is element 0, so "Pull 0 0 0" is ** a no-op. "Pull 1 0 0" swaps the top two elements of ** the stack. ** ** See also the Dup instruction. */ case OP_Pull: { Mem *pFrom = &pTos[-pOp->p1]; int i; Mem ts; ts = *pFrom; Deephemeralize(pTos); for(i=0; i<pOp->p1; i++, pFrom++){ |
︙ | ︙ | |||
859 860 861 862 863 864 865 | /* Opcode: Push P1 * * ** ** Overwrite the value of the P1-th element down on the ** stack (P1==0 is the top of the stack) with the value ** of the top of the stack. Then pop the top of the stack. */ | | | < < < | < | | | < < < < < < < < < < < | < < | < < < < < | | < < < < | 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | /* Opcode: Push P1 * * ** ** Overwrite the value of the P1-th element down on the ** stack (P1==0 is the top of the stack) with the value ** of the top of the stack. Then pop the top of the stack. */ case OP_Push: { Mem *pTo = &pTos[-pOp->p1]; assert( pTo>=p->aStack ); sqlite3VdbeMemMove(pTo, pTos); pTos--; break; } /* Opcode: Callback P1 * * ** ** Pop P1 values off the stack and form them into an array. Then ** invoke the callback function using the newly formed array as the ** 3rd parameter. */ case OP_Callback: { int i; assert( p->nResColumn==pOp->p1 ); for(i=0; i<pOp->p1; i++){ Mem *pVal = &pTos[0-i]; sqlite3VdbeMemNulTerminate(pVal); storeTypeInfo(pVal, db->enc); } p->resOnStack = 1; p->nCallback++; p->popStack = pOp->p1; p->pc = pc + 1; p->pTos = pTos; return SQLITE_ROW; } /* Opcode: Concat P1 P2 * ** ** Look at the first P1+2 elements of the stack. Append them all ** together with the lowest element first. The original P1+2 elements |
︙ | ︙ | |||
945 946 947 948 949 950 951 | nByte = 0; for(i=0; i<nField; i++, pTerm++){ assert( pOp->p2==0 || (pTerm->flags&MEM_Str) ); if( pTerm->flags&MEM_Null ){ nByte = -1; break; } | | | 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 | nByte = 0; for(i=0; i<nField; i++, pTerm++){ assert( pOp->p2==0 || (pTerm->flags&MEM_Str) ); if( pTerm->flags&MEM_Null ){ nByte = -1; break; } Stringify(pTerm, db->enc); nByte += pTerm->n; } if( nByte<0 ){ /* If nByte is less than zero, then there is a NULL value on the stack. ** In this case just pop the values off the stack (if required) and ** push on a NULL. |
︙ | ︙ | |||
969 970 971 972 973 974 975 | */ zNew = sqliteMallocRaw( nByte+2 ); if( zNew==0 ) goto no_mem; j = 0; pTerm = &pTos[1-nField]; for(i=j=0; i<nField; i++, pTerm++){ int n = pTerm->n; | | | | 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 | */ zNew = sqliteMallocRaw( nByte+2 ); if( zNew==0 ) goto no_mem; j = 0; pTerm = &pTos[1-nField]; for(i=j=0; i<nField; i++, pTerm++){ int n = pTerm->n; assert( pTerm->flags & MEM_Str ); memcpy(&zNew[j], pTerm->z, n); j += n; } zNew[j] = 0; zNew[j+1] = 0; assert( j==nByte ); if( pOp->p2==0 ){ popStack(&pTos, nField); } pTos++; pTos->n = j; pTos->flags = MEM_Str|MEM_Dyn|MEM_Term; pTos->xDel = 0; pTos->enc = db->enc; pTos->z = zNew; } break; } /* Opcode: Add * * * ** |
︙ | ︙ | |||
1036 1037 1038 1039 1040 1041 1042 | ** first (what was on top of the stack) from the second (the ** next on stack) ** and push the remainder after division onto the stack. If either element ** is a string then it is converted to a double using the atof() ** function before the division. Division by zero returns NULL. ** If either operand is NULL, the result is NULL. */ | | | | | | < | < | 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 | ** first (what was on top of the stack) from the second (the ** next on stack) ** and push the remainder after division onto the stack. If either element ** is a string then it is converted to a double using the atof() ** function before the division. Division by zero returns NULL. ** If either operand is NULL, the result is NULL. */ case OP_Add: /* same as TK_PLUS */ case OP_Subtract: /* same as TK_MINUS */ case OP_Multiply: /* same as TK_STAR */ case OP_Divide: /* same as TK_SLASH */ case OP_Remainder: { /* same as TK_REM */ Mem *pNos = &pTos[-1]; assert( pNos>=p->aStack ); if( ((pTos->flags | pNos->flags) & MEM_Null)!=0 ){ Release(pTos); pTos--; Release(pTos); pTos->flags = MEM_Null; }else if( (pTos->flags & pNos->flags & MEM_Int)==MEM_Int ){ i64 a, b; a = pTos->i; |
︙ | ︙ | |||
1100 1101 1102 1103 1104 1105 1106 | } } Release(pTos); pTos--; Release(pTos); pTos->r = b; pTos->flags = MEM_Real; | < < < | 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 | } } Release(pTos); pTos--; Release(pTos); pTos->r = b; pTos->flags = MEM_Real; } break; divide_by_zero: Release(pTos); pTos--; Release(pTos); |
︙ | ︙ | |||
1125 1126 1127 1128 1129 1130 1131 | ** be returned. This is used by the built-in min(), max() and nullif() ** functions. ** ** The interface used by the implementation of the aforementioned functions ** to retrieve the collation sequence set by this opcode is not available ** publicly, only to user functions defined in func.c. */ | | | | | | | > | | 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 | ** be returned. This is used by the built-in min(), max() and nullif() ** functions. ** ** The interface used by the implementation of the aforementioned functions ** to retrieve the collation sequence set by this opcode is not available ** publicly, only to user functions defined in func.c. */ case OP_CollSeq: { assert( pOp->p3type==P3_COLLSEQ ); break; } /* Opcode: Function P1 P2 P3 ** ** Invoke a user function (P3 is a pointer to a Function structure that ** defines the function) with P1 arguments taken from the stack. Pop all ** arguments from the stack and push back the result. ** ** P2 is a 32-bit bitmask indicating whether or not each argument to the ** function was determined to be constant at compile time. If the first ** argument was constant then bit 0 of P2 is set. This is used to determine ** whether meta data associated with a user function argument using the ** sqlite3_set_auxdata() API may be safely retained until the next ** invocation of this opcode. ** ** See also: AggFunc */ case OP_Function: { int i; Mem *pArg; sqlite3_context ctx; sqlite3_value **apVal; int n = pOp->p1; n = pOp->p1; apVal = p->apArg; assert( apVal || n==0 ); pArg = &pTos[1-n]; for(i=0; i<n; i++, pArg++){ apVal[i] = pArg; storeTypeInfo(pArg, db->enc); } assert( pOp->p3type==P3_FUNCDEF || pOp->p3type==P3_VDBEFUNC ); if( pOp->p3type==P3_FUNCDEF ){ ctx.pFunc = (FuncDef*)pOp->p3; ctx.pVdbeFunc = 0; }else{ |
︙ | ︙ | |||
1183 1184 1185 1186 1187 1188 1189 | assert( pOp[-1].p3type==P3_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); ctx.pColl = (CollSeq *)pOp[-1].p3; } if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; (*ctx.pFunc->xFunc)(&ctx, n, apVal); if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; | | | | | | 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 | assert( pOp[-1].p3type==P3_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); ctx.pColl = (CollSeq *)pOp[-1].p3; } if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; (*ctx.pFunc->xFunc)(&ctx, n, apVal); if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; if( sqlite3_malloc_failed ) goto no_mem; popStack(&pTos, n); /* If any auxilary data functions have been called by this user function, ** immediately call the destructor for any non-static values. */ if( ctx.pVdbeFunc ){ sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p2); pOp->p3 = (char *)ctx.pVdbeFunc; pOp->p3type = P3_VDBEFUNC; } /* Copy the result of the function to the top of the stack */ sqlite3VdbeChangeEncoding(&ctx.s, db->enc); pTos++; pTos->flags = 0; sqlite3VdbeMemMove(pTos, &ctx.s); /* If the function returned an error, throw an exception */ if( ctx.isError ){ if( !(pTos->flags&MEM_Str) ){ sqlite3SetString(&p->zErrMsg, "user function error", (char*)0); }else{ sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pTos), (char*)0); sqlite3VdbeChangeEncoding(pTos, db->enc); } rc = SQLITE_ERROR; } break; } /* Opcode: BitAnd * * * |
︙ | ︙ | |||
1242 1243 1244 1245 1246 1247 1248 | /* Opcode: ShiftRight * * * ** ** Pop the top two elements from the stack. Convert both elements ** to integers. Push back onto the stack the second element shifted ** right by N bits where N is the top element on the stack. ** If either operand is NULL, the result is NULL. */ | | | | | | | 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 | /* Opcode: ShiftRight * * * ** ** Pop the top two elements from the stack. Convert both elements ** to integers. Push back onto the stack the second element shifted ** right by N bits where N is the top element on the stack. ** If either operand is NULL, the result is NULL. */ case OP_BitAnd: /* same as TK_BITAND */ case OP_BitOr: /* same as TK_BITOR */ case OP_ShiftLeft: /* same as TK_LSHIFT */ case OP_ShiftRight: { /* same as TK_RSHIFT */ Mem *pNos = &pTos[-1]; int a, b; assert( pNos>=p->aStack ); if( (pTos->flags | pNos->flags) & MEM_Null ){ popStack(&pTos, 2); pTos++; pTos->flags = MEM_Null; break; |
︙ | ︙ | |||
1280 1281 1282 1283 1284 1285 1286 | /* Opcode: AddImm P1 * * ** ** Add the value P1 to whatever is on top of the stack. The result ** is always an integer. ** ** To force the top of the stack to be an integer, just add 0. */ | | | | | | < | | 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 | /* Opcode: AddImm P1 * * ** ** Add the value P1 to whatever is on top of the stack. The result ** is always an integer. ** ** To force the top of the stack to be an integer, just add 0. */ case OP_AddImm: { assert( pTos>=p->aStack ); Integerify(pTos); pTos->i += pOp->p1; break; } /* Opcode: ForceInt P1 P2 * ** ** Convert the top of the stack into an integer. If the current top of ** the stack is not numeric (meaning that is is a NULL or a string that ** does not look like an integer or floating point number) then pop the ** stack and jump to P2. If the top of the stack is numeric then ** convert it into the least integer that is greater than or equal to its ** current value if P1==0, or to the least integer that is strictly ** greater than its current value if P1==1. */ case OP_ForceInt: { int v; assert( pTos>=p->aStack ); applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc); if( (pTos->flags & (MEM_Int|MEM_Real))==0 ){ Release(pTos); pTos--; pc = pOp->p2 - 1; break; } if( pTos->flags & MEM_Int ){ v = pTos->i + (pOp->p1!=0); }else{ Realify(pTos); v = (int)pTos->r; if( pTos->r>(double)v ) v++; if( pOp->p1 && pTos->r==(double)v ) v++; } Release(pTos); pTos->i = v; pTos->flags = MEM_Int; |
︙ | ︙ | |||
1333 1334 1335 1336 1337 1338 1339 | ** with out data loss, then jump immediately to P2, or if P2==0 ** raise an SQLITE_MISMATCH exception. ** ** If the top of the stack is not an integer and P2 is not zero and ** P1 is 1, then the stack is popped. In all other cases, the depth ** of the stack is unchanged. */ | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < | < < < < | | < | | 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 | ** with out data loss, then jump immediately to P2, or if P2==0 ** raise an SQLITE_MISMATCH exception. ** ** If the top of the stack is not an integer and P2 is not zero and ** P1 is 1, then the stack is popped. In all other cases, the depth ** of the stack is unchanged. */ case OP_MustBeInt: { assert( pTos>=p->aStack ); applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc); if( (pTos->flags & MEM_Int)==0 ){ if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; goto abort_due_to_error; }else{ if( pOp->p1 ) popStack(&pTos, 1); pc = pOp->p2 - 1; } }else{ Release(pTos); pTos->flags = MEM_Int; } break; } /* Opcode: Eq P1 P2 P3 ** ** Pop the top two elements from the stack. If they are equal, then ** jump to instruction P2. Otherwise, continue to the next instruction. ** ** The least significant byte of P1 may be either 0x00 or 0x01. If either ** operand is NULL (and thus if the result is unknown) then take the jump ** only if the least significant byte of P1 is 0x01. ** ** The second least significant byte of P1 must be an affinity character - ** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values ** according to the affinity before the comparison is made. If the byte is ** 0x00, then numeric affinity is used. ** ** Once any conversions have taken place, and neither value is NULL, ** the values are compared. If both values are blobs, or both are text, ** then memcmp() is used to determine the results of the comparison. If ** both values are numeric, then a numeric comparison is used. If the |
︙ | ︙ | |||
1530 1531 1532 1533 1534 1535 1536 | */ /* Opcode: Ge P1 P2 P3 ** ** This works just like the Eq opcode except that the jump is taken if ** the 2nd element down on the stack is greater than or equal to the ** top of the stack. See the Eq opcode for additional information. */ | | | | | | | < < < < < < < < < < < < < < < < < < < | | < | < | | | | | | | < | | | | 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 | */ /* Opcode: Ge P1 P2 P3 ** ** This works just like the Eq opcode except that the jump is taken if ** the 2nd element down on the stack is greater than or equal to the ** top of the stack. See the Eq opcode for additional information. */ case OP_Eq: /* same as TK_EQ */ case OP_Ne: /* same as TK_NE */ case OP_Lt: /* same as TK_LT */ case OP_Le: /* same as TK_LE */ case OP_Gt: /* same as TK_GT */ case OP_Ge: { /* same as TK_GE */ Mem *pNos; int flags; int res; char affinity; pNos = &pTos[-1]; flags = pTos->flags|pNos->flags; /* If either value is a NULL P2 is not zero, take the jump if the least ** significant byte of P1 is true. If P2 is zero, then push a NULL onto ** the stack. */ if( flags&MEM_Null ){ popStack(&pTos, 2); if( pOp->p2 ){ if( (pOp->p1&0xFF) ) pc = pOp->p2-1; }else{ pTos++; pTos->flags = MEM_Null; } break; } affinity = (pOp->p1>>8)&0xFF; if( affinity ){ applyAffinity(pNos, affinity, db->enc); applyAffinity(pTos, affinity, db->enc); } assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 ); res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3); switch( pOp->opcode ){ case OP_Eq: res = res==0; break; case OP_Ne: res = res!=0; break; |
︙ | ︙ | |||
1623 1624 1625 1626 1627 1628 1629 | */ /* Opcode: Or * * * ** ** Pop two values off the stack. Take the logical OR of the ** two values and push the resulting boolean value back onto the ** stack. */ | | | | | | 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 | */ /* Opcode: Or * * * ** ** Pop two values off the stack. Take the logical OR of the ** two values and push the resulting boolean value back onto the ** stack. */ case OP_And: /* same as TK_AND */ case OP_Or: { /* same as TK_OR */ Mem *pNos = &pTos[-1]; int v1, v2; /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */ assert( pNos>=p->aStack ); if( pTos->flags & MEM_Null ){ v1 = 2; }else{ Integerify(pTos); v1 = pTos->i==0; } if( pNos->flags & MEM_Null ){ v2 = 2; }else{ Integerify(pNos); v2 = pNos->i==0; } if( pOp->opcode==OP_And ){ static const unsigned char and_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; v1 = and_logic[v1*3+v2]; }else{ static const unsigned char or_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; |
︙ | ︙ | |||
1671 1672 1673 1674 1675 1676 1677 | */ /* Opcode: AbsValue * * * ** ** Treat the top of the stack as a numeric quantity. Replace it ** with its absolute value. If the top of the stack is NULL ** its value is unchanged. */ | | < | > > > | | | | | < < < < < < < | | 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 | */ /* Opcode: AbsValue * * * ** ** Treat the top of the stack as a numeric quantity. Replace it ** with its absolute value. If the top of the stack is NULL ** its value is unchanged. */ case OP_Negative: /* same as TK_UMINUS */ case OP_AbsValue: { assert( pTos>=p->aStack ); if( pTos->flags & MEM_Real ){ Release(pTos); if( pOp->opcode==OP_Negative || pTos->r<0.0 ){ pTos->r = -pTos->r; } pTos->flags = MEM_Real; }else if( pTos->flags & MEM_Int ){ Release(pTos); if( pOp->opcode==OP_Negative || pTos->i<0 ){ pTos->i = -pTos->i; } pTos->flags = MEM_Int; }else if( pTos->flags & MEM_Null ){ /* Do nothing */ }else{ Realify(pTos); if( pOp->opcode==OP_Negative || pTos->r<0.0 ){ pTos->r = -pTos->r; } pTos->flags = MEM_Real; } break; } /* Opcode: Not * * * ** ** Interpret the top of the stack as a boolean value. Replace it ** with its complement. If the top of the stack is NULL its value ** is unchanged. */ case OP_Not: { /* same as TK_NOT */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ Integerify(pTos); assert( (pTos->flags & MEM_Dyn)==0 ); pTos->i = !pTos->i; pTos->flags = MEM_Int; break; } /* Opcode: BitNot * * * ** ** Interpret the top of the stack as an value. Replace it ** with its ones-complement. If the top of the stack is NULL its ** value is unchanged. */ case OP_BitNot: { /* same as TK_BITNOT */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ Integerify(pTos); assert( (pTos->flags & MEM_Dyn)==0 ); pTos->i = ~pTos->i; pTos->flags = MEM_Int; break; } /* Opcode: Noop * * * ** ** Do nothing. This instruction is often useful as a jump ** destination. */ case OP_Noop: { break; } /* Opcode: If P1 P2 * ** ** Pop a single boolean from the stack. If the boolean popped is ** true, then jump to p2. Otherwise continue to the next instruction. |
︙ | ︙ | |||
1764 1765 1766 1767 1768 1769 1770 | ** false, then jump to p2. Otherwise continue to the next instruction. ** An integer is false if zero and true otherwise. A string is ** false if it has zero length and true otherwise. ** ** If the value popped of the stack is NULL, then take the jump if P1 ** is true and fall through if P1 is false. */ | | | < < < < | | 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 | ** false, then jump to p2. Otherwise continue to the next instruction. ** An integer is false if zero and true otherwise. A string is ** false if it has zero length and true otherwise. ** ** If the value popped of the stack is NULL, then take the jump if P1 ** is true and fall through if P1 is false. */ case OP_If: case OP_IfNot: { int c; assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ){ c = pOp->p1; }else{ c = sqlite3VdbeIntValue(pTos); if( pOp->opcode==OP_IfNot ) c = !c; } Release(pTos); pTos--; if( c ) pc = pOp->p2-1; break; } /* Opcode: IsNull P1 P2 * ** ** If any of the top abs(P1) values on the stack are NULL, then jump ** to P2. Pop the stack P1 times if P1>0. If P1<0 leave the stack ** unchanged. */ case OP_IsNull: { /* same as TK_ISNULL */ int i, cnt; Mem *pTerm; cnt = pOp->p1; if( cnt<0 ) cnt = -cnt; pTerm = &pTos[1-cnt]; assert( pTerm>=p->aStack ); for(i=0; i<cnt; i++, pTerm++){ |
︙ | ︙ | |||
1813 1814 1815 1816 1817 1818 1819 | /* Opcode: NotNull P1 P2 * ** ** Jump to P2 if the top P1 values on the stack are all not NULL. Pop the ** stack if P1 times if P1 is greater than zero. If P1 is less than ** zero then leave the stack unchanged. */ | | | > > > > | < < < < < < < > > > | 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 | /* Opcode: NotNull P1 P2 * ** ** Jump to P2 if the top P1 values on the stack are all not NULL. Pop the ** stack if P1 times if P1 is greater than zero. If P1 is less than ** zero then leave the stack unchanged. */ case OP_NotNull: { /* same as TK_NOTNULL */ int i, cnt; cnt = pOp->p1; if( cnt<0 ) cnt = -cnt; assert( &pTos[1-cnt] >= p->aStack ); for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){} if( i>=cnt ) pc = pOp->p2-1; if( pOp->p1>0 ) popStack(&pTos, cnt); break; } /* Opcode: SetNumColumns P1 P2 * ** ** Before the OP_Column opcode can be executed on a cursor, this ** opcode must be called to set the number of fields in the table. ** ** This opcode sets the number of columns for cursor P1 to P2. ** ** If OP_KeyAsData is to be applied to cursor P1, it must be executed ** before this op-code. */ case OP_SetNumColumns: { Cursor *pC; assert( (pOp->p1)<p->nCursor ); assert( p->apCsr[pOp->p1]!=0 ); pC = p->apCsr[pOp->p1]; pC->nField = pOp->p2; if( (!pC->keyAsData && pC->zeroData) || (pC->keyAsData && pC->intKey) ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } break; } /* Opcode: Column P1 P2 * ** ** Interpret the data that cursor P1 points to as a structure built using ** the MakeRecord instruction. (See the MakeRecord opcode for additional ** information about the format of the data.) Push onto the stack the value ** of the P2-th column contained in the data. If there are less that (P2+1) ** values in the record, push a NULL onto the stack. ** ** If the KeyAsData opcode has previously executed on this cursor, then the ** field might be extracted from the key rather than the data. ** ** If P1 is negative, then the record is stored on the stack rather than in ** a table. For P1==-1, the top of the stack is used. For P1==-2, the ** next on the stack is used. And so forth. The value pushed is always ** just a pointer into the record which is stored further down on the ** stack. The column value is not copied. The number of columns in the ** record is stored on the stack just above the record itself. */ case OP_Column: { u32 payloadSize; /* Number of bytes in the record */ int p1 = pOp->p1; /* P1 value of the opcode */ int p2 = pOp->p2; /* column number to retrieve */ Cursor *pC = 0; /* The VDBE cursor */ char *zRec; /* Pointer to complete record-data */ BtCursor *pCrsr; /* The BTree cursor */ u32 *aType; /* aType[i] holds the numeric type of the i-th column */ u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ u32 nField; /* number of fields in the record */ u32 szHdr; /* Number of bytes in the record header */ int len; /* The length of the serialized data for the column */ int offset = 0; /* Offset into the data */ int idx; /* Index into the header */ int i; /* Loop counter */ char *zData; /* Part of the record being decoded */ Mem sMem; /* For storing the record being decoded */ sMem.flags = 0; assert( p1<p->nCursor ); pTos++; |
︙ | ︙ | |||
1924 1925 1926 1927 1928 1929 1930 | /* The record is stored in a B-Tree */ rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; zRec = 0; pCrsr = pC->pCursor; if( pC->nullRow ){ payloadSize = 0; | | | | | | | < < < | | | < > | | | < < < | > > > | | | > > > > | | | | | | | > | | | < < | < | | | | | | < | | | < < < | < | 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 | /* The record is stored in a B-Tree */ rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; zRec = 0; pCrsr = pC->pCursor; if( pC->nullRow ){ payloadSize = 0; }else if( pC->cacheValid ){ payloadSize = pC->payloadSize; zRec = pC->aRow; }else if( pC->keyAsData ){ i64 payloadSize64; sqlite3BtreeKeySize(pCrsr, &payloadSize64); payloadSize = payloadSize64; }else{ sqlite3BtreeDataSize(pCrsr, &payloadSize); } nField = pC->nField; #ifndef SQLITE_OMIT_TRIGGER }else if( pC->pseudoTable ){ /* The record is the sole entry of a pseudo-table */ payloadSize = pC->nData; zRec = pC->pData; pC->cacheValid = 0; assert( payloadSize==0 || zRec!=0 ); nField = pC->nField; pCrsr = 0; #endif }else{ zRec = 0; payloadSize = 0; pCrsr = 0; nField = 0; } /* If payloadSize is 0, then just push a NULL onto the stack. */ if( payloadSize==0 ){ pTos->flags = MEM_Null; break; } assert( p2<nField ); /* Read and parse the table header. Store the results of the parse ** into the record header cache fields of the cursor. */ if( pC && pC->cacheValid ){ aType = pC->aType; aOffset = pC->aOffset; }else{ int avail; /* Number of bytes of available data */ if( pC && pC->aType ){ aType = pC->aType; }else{ aType = sqliteMallocRaw( 2*nField*sizeof(aType) ); } aOffset = &aType[nField]; if( aType==0 ){ goto no_mem; } /* Figure out how many bytes are in the header */ if( zRec ){ zData = zRec; }else{ if( pC->keyAsData ){ zData = (char*)sqlite3BtreeKeyFetch(pCrsr, &avail); }else{ zData = (char*)sqlite3BtreeDataFetch(pCrsr, &avail); } /* If KeyFetch()/DataFetch() managed to get the entire payload, ** save the payload in the pC->aRow cache. That will save us from ** having to make additional calls to fetch the content portion of ** the record. */ if( avail>=payloadSize ){ zRec = pC->aRow = zData; }else{ pC->aRow = 0; } } idx = sqlite3GetVarint32(zData, &szHdr); /* The KeyFetch() or DataFetch() above are fast and will get the entire ** record header in most cases. But they will fail to get the complete ** record header if the record header does not fit on a single page ** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to ** acquire the complete header text. */ if( !zRec && avail<szHdr ){ rc = sqlite3VdbeMemFromBtree(pCrsr, 0, szHdr, pC->keyAsData, &sMem); if( rc!=SQLITE_OK ){ goto op_column_out; } zData = sMem.z; } /* Scan the header and use it to fill in the aType[] and aOffset[] ** arrays. aType[i] will contain the type integer for the i-th ** column and aOffset[i] will contain the offset from the beginning ** of the record to the start of the data for the i-th column */ offset = szHdr; assert( offset>0 ); i = 0; while( idx<szHdr && i<nField && offset<=payloadSize ){ aOffset[i] = offset; idx += sqlite3GetVarint32(&zData[idx], &aType[i]); offset += sqlite3VdbeSerialTypeLen(aType[i]); i++; } Release(&sMem); sMem.flags = MEM_Null; /* If i is less that nField, then there are less fields in this ** record than SetNumColumns indicated there are columns in the ** table. Set the offset for any extra columns not present in ** the record to 0. This tells code below to push a NULL onto the ** stack instead of deserializing a value from the record. */ while( i<nField ){ aOffset[i++] = 0; } /* The header should end at the start of data and the data should ** end at last byte of the record. If this is not the case then ** we are dealing with a malformed record. */ if( idx!=szHdr || offset!=payloadSize ){ rc = SQLITE_CORRUPT; goto op_column_out; } /* Remember all aType and aColumn information if we have a cursor ** to remember it in. */ if( pC ){ pC->payloadSize = payloadSize; pC->aType = aType; pC->aOffset = aOffset; pC->cacheValid = 1; } } /* Get the column information. If aOffset[p2] is non-zero, then ** deserialize the value from the record. If aOffset[p2] is zero, ** then there are not enough fields in the record to satisfy the ** request. The value is NULL in this case. */ if( aOffset[p2] ){ assert( rc==SQLITE_OK ); if( zRec ){ zData = &zRec[aOffset[p2]]; }else{ len = sqlite3VdbeSerialTypeLen(aType[p2]); rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len,pC->keyAsData,&sMem); if( rc!=SQLITE_OK ){ goto op_column_out; } zData = sMem.z; } sqlite3VdbeSerialGet(zData, aType[p2], pTos); pTos->enc = db->enc; }else{ pTos->flags = MEM_Null; } /* If we dynamically allocated space to hold the data (in the ** sqlite3VdbeMemFromBtree() call above) then transfer control of that ** dynamically allocated space over to the pTos structure rather. ** This prevents a memory copy. */ |
︙ | ︙ | |||
2129 2130 2131 2132 2133 2134 2135 | ** sqlite3VdbeRecordCompare function will correctly compare two encoded ** records. Refer to source code comments for the details of the record ** format. ** ** The original stack entries are popped from the stack if P1>0 but ** remain on the stack if P1<0. ** | > > > | | | | > > | > < < < < < < < < < < | 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 | ** sqlite3VdbeRecordCompare function will correctly compare two encoded ** records. Refer to source code comments for the details of the record ** format. ** ** The original stack entries are popped from the stack if P1>0 but ** remain on the stack if P1<0. ** ** The P2 argument is divided into two 16-bit words before it is processed. ** If the hi-word is non-zero, then an extra integer is read from the stack ** and appended to the record as a varint. If the low-word of P2 is not ** zero and one or more of the entries are NULL, then jump to the value of ** the low-word of P2. This feature can be used to skip a uniqueness test ** on indices. ** ** P3 may be a string that is P1 characters long. The nth character of the ** string indicates the column affinity that should be used for the nth ** field of the index key (i.e. the first character of P3 corresponds to the ** lowest element on the stack). ** ** The mapping from character to affinity is as follows: ** 'n' = NUMERIC. ** 'i' = INTEGER. ** 't' = TEXT. ** 'o' = NONE. ** ** If P3 is NULL then all index fields have the affinity NONE. */ case OP_MakeRecord: { /* Assuming the record contains N fields, the record format looks ** like this: ** ** ------------------------------------------------------------------------ ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | ** ------------------------------------------------------------------------ |
︙ | ︙ | |||
2176 2177 2178 2179 2180 2181 2182 | unsigned char *zNewRecord; unsigned char *zCsr; Mem *pRec; Mem *pRowid = 0; int nData = 0; /* Number of bytes of data space */ int nHdr = 0; /* Number of bytes of header space */ int nByte = 0; /* Space required for this record */ | < < | | < | | | | | < < < | | | | | | < | | | | | < < < | | | | | | < | | 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 | unsigned char *zNewRecord; unsigned char *zCsr; Mem *pRec; Mem *pRowid = 0; int nData = 0; /* Number of bytes of data space */ int nHdr = 0; /* Number of bytes of header space */ int nByte = 0; /* Space required for this record */ u32 serial_type; /* Type field */ int containsNull = 0; /* True if any of the data fields are NULL */ char zTemp[NBFS]; /* Space to hold small records */ Mem *pData0; int leaveOnStack; /* If true, leave the entries on the stack */ int nField; /* Number of fields in the record */ int jumpIfNull; /* Jump here if non-zero and any entries are NULL. */ int addRowid; /* True to append a rowid column at the end */ char *zAffinity; /* The affinity string for the record */ leaveOnStack = ((pOp->p1<0)?1:0); nField = pOp->p1 * (leaveOnStack?-1:1); jumpIfNull = (pOp->p2 & 0x00FFFFFF); addRowid = ((pOp->p2>>24) & 0x0000FFFF)?1:0; zAffinity = pOp->p3; pData0 = &pTos[1-nField]; assert( pData0>=p->aStack ); containsNull = 0; /* Loop through the elements that will make up the record to figure ** out how much space is required for the new record. */ for(pRec=pData0; pRec<=pTos; pRec++){ if( zAffinity ){ applyAffinity(pRec, zAffinity[pRec-pData0], db->enc); } if( pRec->flags&MEM_Null ){ containsNull = 1; } serial_type = sqlite3VdbeSerialType(pRec); nData += sqlite3VdbeSerialTypeLen(serial_type); nHdr += sqlite3VarintLen(serial_type); } /* If we have to append a varint rowid to this record, set 'rowid' ** to the value of the rowid and increase nByte by the amount of space ** required to store it and the 0x00 seperator byte. */ if( addRowid ){ pRowid = &pTos[0-nField]; assert( pRowid>=p->aStack ); Integerify(pRowid); serial_type = sqlite3VdbeSerialType(pRowid); nData += sqlite3VdbeSerialTypeLen(serial_type); nHdr += sqlite3VarintLen(serial_type); } /* Add the initial header varint and total the size */ nHdr += sqlite3VarintLen(nHdr); nByte = nHdr+nData; /* Allocate space for the new record. */ if( nByte>sizeof(zTemp) ){ zNewRecord = sqliteMallocRaw(nByte); if( !zNewRecord ){ goto no_mem; } }else{ zNewRecord = zTemp; } /* Write the record */ zCsr = zNewRecord; zCsr += sqlite3PutVarint(zCsr, nHdr); for(pRec=pData0; pRec<=pTos; pRec++){ serial_type = sqlite3VdbeSerialType(pRec); zCsr += sqlite3PutVarint(zCsr, serial_type); /* serial type */ } if( addRowid ){ zCsr += sqlite3PutVarint(zCsr, sqlite3VdbeSerialType(pRowid)); } for(pRec=pData0; pRec<=pTos; pRec++){ zCsr += sqlite3VdbeSerialPut(zCsr, pRec); /* serial data */ } if( addRowid ){ zCsr += sqlite3VdbeSerialPut(zCsr, pRowid); } assert( zCsr==(zNewRecord+nByte) ); /* Pop entries off the stack if required. Push the new record on. */ if( !leaveOnStack ){ popStack(&pTos, nField+addRowid); } pTos++; pTos->n = nByte; if( nByte<=sizeof(zTemp) ){ assert( zNewRecord==(unsigned char *)zTemp ); pTos->z = pTos->zShort; memcpy(pTos->zShort, zTemp, nByte); pTos->flags = MEM_Blob | MEM_Short; }else{ assert( zNewRecord!=(unsigned char *)zTemp ); pTos->z = zNewRecord; pTos->flags = MEM_Blob | MEM_Dyn; pTos->xDel = 0; } /* If a NULL was encountered and jumpIfNull is non-zero, take the jump. */ if( jumpIfNull && containsNull ){ pc = jumpIfNull - 1; } break; } /* Opcode: Statement P1 * * ** ** Begin an individual statement transaction which is part of a larger ** BEGIN..COMMIT transaction. This is needed so that the statement ** can be rolled back after an error without having to roll back the ** entire transaction. The statement transaction will automatically ** commit when the VDBE halts. ** ** The statement is begun on the database file with index P1. The main ** database file has an index of 0 and the file used for temporary tables ** has an index of 1. */ case OP_Statement: { int i = pOp->p1; Btree *pBt; if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt) && !(db->autoCommit) ){ assert( sqlite3BtreeIsInTrans(pBt) ); if( !sqlite3BtreeIsInStmt(pBt) ){ rc = sqlite3BtreeBeginStmt(pBt); } } break; } /* Opcode: AutoCommit P1 P2 * ** ** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll ** back any currently active btree transactions. If there are any active ** VMs (apart from this one), then the COMMIT or ROLLBACK statement fails. ** ** This instruction causes the VM to halt. */ case OP_AutoCommit: { u8 i = pOp->p1; u8 rollback = pOp->p2; assert( i==1 || i==0 ); assert( i==1 || rollback==0 ); assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */ if( db->activeVdbeCnt>1 && i && !db->autoCommit ){ /* If this instruction implements a COMMIT or ROLLBACK, other VMs are ** still running, and a transaction is active, return an error indicating ** that the other VMs must complete first. */ sqlite3SetString(&p->zErrMsg, "cannot ", rollback?"rollback":"commit", " transaction - SQL statements in progress", 0); rc = SQLITE_ERROR; }else if( i!=db->autoCommit ){ db->autoCommit = i; if( pOp->p2 ){ assert( i==1 ); sqlite3RollbackAll(db); }else if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ p->pTos = pTos; p->pc = pc; db->autoCommit = 1-i; p->rc = SQLITE_BUSY; return SQLITE_BUSY; } return SQLITE_DONE; }else{ sqlite3SetString(&p->zErrMsg, (!i)?"cannot start a transaction within a transaction":( (rollback)?"cannot rollback - no transaction is active": "cannot commit - no transaction is active"), 0); rc = SQLITE_ERROR; } break; } /* Opcode: Transaction P1 P2 * |
︙ | ︙ | |||
2386 2387 2388 2389 2390 2391 2392 | ** underway. Starting a write transaction also creates a rollback journal. A ** write transaction must be started before any changes can be made to the ** database. If P2 is 2 or greater then an EXCLUSIVE lock is also obtained ** on the file. ** ** If P2 is zero, then a read-lock is obtained on the database file. */ | | < | 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 | ** underway. Starting a write transaction also creates a rollback journal. A ** write transaction must be started before any changes can be made to the ** database. If P2 is 2 or greater then an EXCLUSIVE lock is also obtained ** on the file. ** ** If P2 is zero, then a read-lock is obtained on the database file. */ case OP_Transaction: { int i = pOp->p1; Btree *pBt; assert( i>=0 && i<db->nDb ); pBt = db->aDb[i].pBt; if( pBt ){ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); if( rc==SQLITE_BUSY ){ p->pc = pc; p->rc = SQLITE_BUSY; p->pTos = pTos; return SQLITE_BUSY; } if( rc!=SQLITE_OK && rc!=SQLITE_READONLY /* && rc!=SQLITE_BUSY */ ){ goto abort_due_to_error; } } break; |
︙ | ︙ | |||
2450 2451 2452 2453 2454 2455 2456 | ** P2==0 is the schema version. P2==1 is the database format. ** P2==2 is the recommended pager cache size, and so forth. P1==0 is ** the main database file and P1==1 is the database file used to store ** temporary tables. ** ** A transaction must be started before executing this opcode. */ | | | | < < < | 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 | ** P2==0 is the schema version. P2==1 is the database format. ** P2==2 is the recommended pager cache size, and so forth. P1==0 is ** the main database file and P1==1 is the database file used to store ** temporary tables. ** ** A transaction must be started before executing this opcode. */ case OP_SetCookie: { Db *pDb; assert( pOp->p2<SQLITE_N_BTREE_META ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); assert( pTos>=p->aStack ); Integerify(pTos); /* See note about index shifting on OP_ReadCookie */ rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pTos->i); if( pOp->p2==0 ){ /* When the schema cookie changes, record the new cookie internally */ pDb->schema_cookie = pTos->i; db->flags |= SQLITE_InternChanges; } assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; break; } /* Opcode: VerifyCookie P1 P2 * |
︙ | ︙ | |||
2489 2490 2491 2492 2493 2494 2495 | ** This operation is used to detect when that the cookie has changed ** and that the current process needs to reread the schema. ** ** Either a transaction needs to have been started or an OP_Open needs ** to be executed (to establish a read lock) before this opcode is ** invoked. */ | | | 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 | ** This operation is used to detect when that the cookie has changed ** and that the current process needs to reread the schema. ** ** Either a transaction needs to have been started or an OP_Open needs ** to be executed (to establish a read lock) before this opcode is ** invoked. */ case OP_VerifyCookie: { int iMeta; Btree *pBt; assert( pOp->p1>=0 && pOp->p1<db->nDb ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&iMeta); }else{ |
︙ | ︙ | |||
2549 2550 2551 2552 2553 2554 2555 | ** ** This instruction works just like OpenRead except that it opens the cursor ** in read/write mode. For a given table, there can be one or more read-only ** cursors or a single read/write cursor but not both. ** ** See also OpenRead. */ | | | < | | < | < < < < < < < | | > > > | > | < | > | < < < < < < < < < < < < | | < < < < < < < < < < < | | | | | < > > > > > > > | | | 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 | ** ** This instruction works just like OpenRead except that it opens the cursor ** in read/write mode. For a given table, there can be one or more read-only ** cursors or a single read/write cursor but not both. ** ** See also OpenRead. */ case OP_OpenRead: case OP_OpenWrite: { int i = pOp->p1; int p2 = pOp->p2; int wrFlag; Btree *pX; int iDb; Cursor *pCur; assert( pTos>=p->aStack ); Integerify(pTos); iDb = pTos->i; assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; assert( iDb>=0 && iDb<db->nDb ); pX = db->aDb[iDb].pBt; assert( pX!=0 ); wrFlag = pOp->opcode==OP_OpenWrite; if( p2<=0 ){ assert( pTos>=p->aStack ); Integerify(pTos); p2 = pTos->i; assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; if( p2<2 ){ sqlite3SetString(&p->zErrMsg, "root page number less than 2", (char*)0); rc = SQLITE_INTERNAL; break; } } assert( i>=0 ); pCur = allocateCursor(p, i); if( pCur==0 ) goto no_mem; pCur->nullRow = 1; if( pX==0 ) break; /* We always provide a key comparison function. If the table being ** opened is of type INTKEY, the comparision function will be ignored. */ rc = sqlite3BtreeCursor(pX, p2, wrFlag, sqlite3VdbeRecordCompare, pOp->p3, &pCur->pCursor); pCur->pKeyInfo = (KeyInfo*)pOp->p3; if( pCur->pKeyInfo ){ pCur->pIncrKey = &pCur->pKeyInfo->incrKey; pCur->pKeyInfo->enc = p->db->enc; }else{ pCur->pIncrKey = &pCur->bogusIncrKey; } switch( rc ){ case SQLITE_BUSY: { p->pc = pc; p->rc = SQLITE_BUSY; p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */ return SQLITE_BUSY; } case SQLITE_OK: { int flags = sqlite3BtreeFlags(pCur->pCursor); pCur->intKey = (flags & BTREE_INTKEY)!=0; pCur->zeroData = (flags & BTREE_ZERODATA)!=0; break; } case SQLITE_EMPTY: { rc = SQLITE_OK; break; } default: { goto abort_due_to_error; } } break; } /* Opcode: OpenTemp P1 * P3 ** ** Open a new cursor to a transient table. ** The transient cursor is always opened read/write even if ** the main database is read-only. The transient table is deleted ** automatically when the cursor is closed. ** ** The cursor points to a BTree table if P3==0 and to a BTree index ** if P3 is not 0. If P3 is not NULL, it points to a KeyInfo structure ** that defines the format of keys in the index. ** ** This opcode is used for tables that exist for the duration of a single ** SQL statement only. Tables created using CREATE TEMPORARY TABLE ** are opened using OP_OpenRead or OP_OpenWrite. "Temporary" in the ** context of this opcode means for the duration of a single SQL statement ** whereas "Temporary" in the context of CREATE TABLE means for the duration ** of the connection to the database. Same word; different meanings. */ case OP_OpenTemp: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); pCx = allocateCursor(p, i); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; rc = sqlite3BtreeFactory(db, 0, 1, TEMP_PAGES, &pCx->pBt); if( rc==SQLITE_OK ){ rc = sqlite3BtreeBeginTrans(pCx->pBt, 1); } if( rc==SQLITE_OK ){ |
︙ | ︙ | |||
2686 2687 2688 2689 2690 2691 2692 | assert( pOp->p3type==P3_KEYINFO ); rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA); if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, sqlite3VdbeRecordCompare, pOp->p3, &pCx->pCursor); pCx->pKeyInfo = (KeyInfo*)pOp->p3; | | < | < < | | < < | | 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 | assert( pOp->p3type==P3_KEYINFO ); rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA); if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, sqlite3VdbeRecordCompare, pOp->p3, &pCx->pCursor); pCx->pKeyInfo = (KeyInfo*)pOp->p3; pCx->pKeyInfo->enc = p->db->enc; pCx->pIncrKey = &pCx->pKeyInfo->incrKey; } }else{ rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, 0, &pCx->pCursor); pCx->intKey = 1; pCx->pIncrKey = &pCx->bogusIncrKey; } } break; } #ifndef SQLITE_OMIT_TRIGGER /* Opcode: OpenPseudo P1 * * ** ** Open a new cursor that points to a fake table that contains a single ** row of data. Any attempt to write a second row of data causes the ** first row to be deleted. All data is deleted when the cursor is ** closed. ** ** A pseudo-table created by this opcode is useful for holding the ** NEW or OLD tables in a trigger. */ case OP_OpenPseudo: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); pCx = allocateCursor(p, i); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->pseudoTable = 1; pCx->pIncrKey = &pCx->bogusIncrKey; break; } #endif /* Opcode: Close P1 * * ** ** Close a cursor previously opened as P1. If P1 is not ** currently open, this instruction is a no-op. */ case OP_Close: { int i = pOp->p1; if( i>=0 && i<p->nCursor ){ sqlite3VdbeFreeCursor(p->apCsr[i]); p->apCsr[i] = 0; } break; } |
︙ | ︙ | |||
2781 2782 2783 2784 2785 2786 2787 | ** cursor P1 so that it points to the largest entry that is less than ** or equal to the key that was popped from the stack. ** If there are no records less than or eqal to the key and P2 is not zero, ** then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt */ | | | | | | | | | < | | | | | | 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 | ** cursor P1 so that it points to the largest entry that is less than ** or equal to the key that was popped from the stack. ** If there are no records less than or eqal to the key and P2 is not zero, ** then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt */ case OP_MoveLt: case OP_MoveLe: case OP_MoveGe: case OP_MoveGt: { int i = pOp->p1; Cursor *pC; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; assert( pC!=0 ); if( pC->pCursor!=0 ){ int res, oc; oc = pOp->opcode; pC->nullRow = 0; *pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe; if( pC->intKey ){ i64 iKey; Integerify(pTos); iKey = intToKey(pTos->i); if( pOp->p2==0 && pOp->opcode==OP_MoveGe ){ pC->movetoTarget = iKey; pC->deferredMoveto = 1; assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; break; } rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pC->lastRecno = pTos->i; pC->recnoIsValid = res==0; }else{ Stringify(pTos, db->enc); rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pC->recnoIsValid = 0; } pC->deferredMoveto = 0; pC->cacheValid = 0; *pC->pIncrKey = 0; sqlite3_search_count++; if( oc==OP_MoveGe || oc==OP_MoveGt ){ if( res<0 ){ rc = sqlite3BtreeNext(pC->pCursor, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; pC->recnoIsValid = 0; }else{ res = 0; } }else{ assert( oc==OP_MoveLt || oc==OP_MoveLe ); if( res>=0 ){ rc = sqlite3BtreePrevious(pC->pCursor, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; pC->recnoIsValid = 0; }else{ /* res might be negative because the table is empty. Check to ** see if this is the case. */ res = sqlite3BtreeEof(pC->pCursor); } } |
︙ | ︙ | |||
2863 2864 2865 2866 2867 2868 2869 | Release(pTos); pTos--; break; } /* Opcode: Distinct P1 P2 * ** | | < < | < | | | < < < < < | | | | < < < < < < < | | | | | | | | | | | | | | | | | | | | 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 | Release(pTos); pTos--; break; } /* Opcode: Distinct P1 P2 * ** ** Use the top of the stack as a string key. If a record with that key does ** not exist in the table of cursor P1, then jump to P2. If the record ** does already exist, then fall thru. The cursor is left pointing ** at the record if it exists. The key is not popped from the stack. ** ** This operation is similar to NotFound except that this operation ** does not pop the key from the stack. ** ** See also: Found, NotFound, MoveTo, IsUnique, NotExists */ /* Opcode: Found P1 P2 * ** ** Use the top of the stack as a string key. If a record with that key ** does exist in table of P1, then jump to P2. If the record ** does not exist, then fall thru. The cursor is left pointing ** to the record if it exists. The key is popped from the stack. ** ** See also: Distinct, NotFound, MoveTo, IsUnique, NotExists */ /* Opcode: NotFound P1 P2 * ** ** Use the top of the stack as a string key. If a record with that key ** does not exist in table of P1, then jump to P2. If the record ** does exist, then fall thru. The cursor is left pointing to the ** record if it exists. The key is popped from the stack. ** ** The difference between this operation and Distinct is that ** Distinct does not pop the key from the stack. ** ** See also: Distinct, Found, MoveTo, NotExists, IsUnique */ case OP_Distinct: case OP_NotFound: case OP_Found: { int i = pOp->p1; int alreadyExists = 0; Cursor *pC; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); if( (pC = p->apCsr[i])->pCursor!=0 ){ int res, rx; assert( pC->intKey==0 ); Stringify(pTos, db->enc); rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); alreadyExists = rx==SQLITE_OK && res==0; pC->deferredMoveto = 0; pC->cacheValid = 0; } if( pOp->opcode==OP_Found ){ if( alreadyExists ) pc = pOp->p2 - 1; }else{ if( !alreadyExists ) pc = pOp->p2 - 1; } if( pOp->opcode!=OP_Distinct ){ Release(pTos); pTos--; } break; } /* Opcode: IsUnique P1 P2 * ** ** The top of the stack is an integer record number. Call this ** record number R. The next on the stack is an index key created ** using MakeIdxKey. Call it K. This instruction pops R from the ** stack but it leaves K unchanged. ** ** P1 is an index. So it has no data and its key consists of a ** record generated by OP_MakeIdxKey. This key contains one or more ** fields followed by a ROWID field. ** ** This instruction asks if there is an entry in P1 where the ** fields matches K but the rowid is different from R. ** If there is no such entry, then there is an immediate ** jump to P2. If any entry does exist where the index string ** matches K but the record number is not R, then the record ** number for that entry is pushed onto the stack and control ** falls through to the next instruction. ** ** See also: Distinct, NotFound, NotExists, Found */ case OP_IsUnique: { int i = pOp->p1; Mem *pNos = &pTos[-1]; Cursor *pCx; BtCursor *pCrsr; i64 R; /* Pop the value R off the top of the stack */ assert( pNos>=p->aStack ); Integerify(pTos); R = pTos->i; assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; assert( i>=0 && i<=p->nCursor ); pCx = p->apCsr[i]; assert( pCx!=0 ); pCrsr = pCx->pCursor; if( pCrsr!=0 ){ int res, rc; i64 v; /* The record number on the P1 entry that matches K */ char *zKey; /* The value of K */ int nKey; /* Number of bytes in K */ int len; /* Number of bytes in K without the rowid at the end */ int szRowid; /* Size of the rowid column at the end of zKey */ /* Make sure K is a string and make zKey point to K */ Stringify(pNos, db->enc); zKey = pNos->z; nKey = pNos->n; szRowid = sqlite3VdbeIdxRowidLen(nKey, zKey); len = nKey-szRowid; /* Search for an entry in P1 where all but the last four bytes match K. ** If there is no such entry, jump immediately to P2. */ assert( pCx->deferredMoveto==0 ); pCx->cacheValid = 0; rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; if( res<0 ){ rc = sqlite3BtreeNext(pCrsr, &res); if( res ){ pc = pOp->p2 - 1; break; } } rc = sqlite3VdbeIdxKeyCompare(pCx, len, zKey, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; if( res>0 ){ pc = pOp->p2 - 1; break; } /* At this point, pCrsr is pointing to an entry in P1 where all but |
︙ | ︙ | |||
3049 3050 3051 3052 3053 3054 3055 | ** ** Use the top of the stack as a integer key. If a record with that key ** does not exist in table of P1, then jump to P2. If the record ** does exist, then fall thru. The cursor is left pointing to the ** record if it exists. The integer key is popped from the stack. ** ** The difference between this operation and NotFound is that this | | < | | | | | | | < < < < < < < < < < < < < < < < < < | | | | 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 | ** ** Use the top of the stack as a integer key. If a record with that key ** does not exist in table of P1, then jump to P2. If the record ** does exist, then fall thru. The cursor is left pointing to the ** record if it exists. The integer key is popped from the stack. ** ** The difference between this operation and NotFound is that this ** operation assumes the key is an integer and NotFound assumes it ** is a string. ** ** See also: Distinct, Found, MoveTo, NotFound, IsUnique */ case OP_NotExists: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int res; u64 iKey; assert( pTos->flags & MEM_Int ); assert( p->apCsr[i]->intKey ); iKey = intToKey(pTos->i); rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res); pC->lastRecno = pTos->i; pC->recnoIsValid = res==0; pC->nullRow = 0; pC->cacheValid = 0; if( res!=0 ){ pc = pOp->p2 - 1; pC->recnoIsValid = 0; } } Release(pTos); pTos--; break; } /* Opcode: NewRecno P1 P2 * ** ** Get a new integer record number used as the key to a table. ** The record number is not previously used as a key in the database ** table that cursor P1 points to. The new record number is pushed ** onto the stack. ** ** If P2>0 then P2 is a memory cell that holds the largest previously ** generated record number. No new record numbers are allowed to be less ** than this value. When this value reaches its maximum, a SQLITE_FULL ** error is generated. The P2 memory cell is updated with the generated ** record number. This P2 mechanism is used to help implement the ** AUTOINCREMENT feature. */ case OP_NewRecno: { int i = pOp->p1; i64 v = 0; Cursor *pC; assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); if( (pC = p->apCsr[i])->pCursor==0 ){ /* The zero initialization above is all that is needed */ |
︙ | ︙ | |||
3160 3161 3162 3163 3164 3165 3166 | ** to double the speed of the COPY operation. */ int res, rx=SQLITE_OK, cnt; i64 x; cnt = 0; if( (sqlite3BtreeFlags(pC->pCursor)&(BTREE_INTKEY|BTREE_ZERODATA)) != BTREE_INTKEY ){ | | | < < < | | 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 | ** to double the speed of the COPY operation. */ int res, rx=SQLITE_OK, cnt; i64 x; cnt = 0; if( (sqlite3BtreeFlags(pC->pCursor)&(BTREE_INTKEY|BTREE_ZERODATA)) != BTREE_INTKEY ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_INTKEY)!=0 ); assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_ZERODATA)==0 ); #ifdef SQLITE_32BIT_ROWID # define MAX_ROWID 0x7fffffff #else /* Some compilers complain about constants of the form 0x7fffffffffffffff. ** Others complain about 0x7ffffffffffffffffLL. The following macro seems ** to provide the constant while making all compilers happy. */ # define MAX_ROWID ( (((u64)0x7fffffff)<<32) | (u64)0xffffffff ) #endif if( !pC->useRandomRowid ){ if( pC->nextRowidValid ){ v = pC->nextRowid; }else{ rx = sqlite3BtreeLast(pC->pCursor, &res); if( res ){ v = 1; }else{ sqlite3BtreeKeySize(pC->pCursor, &v); v = keyToInt(v); if( v==MAX_ROWID ){ pC->useRandomRowid = 1; }else{ v++; } } } #ifndef SQLITE_OMIT_AUTOINCREMENT if( pOp->p2 ){ Mem *pMem; assert( pOp->p2>0 && pOp->p2<p->nMem ); /* P2 is a valid memory cell */ pMem = &p->aMem[pOp->p2]; Integerify(pMem); assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P2) holds an integer */ if( pMem->i==MAX_ROWID || pC->useRandomRowid ){ rc = SQLITE_FULL; goto abort_due_to_error; } if( v<pMem->i+1 ){ v = pMem->i + 1; |
︙ | ︙ | |||
3246 3247 3248 3249 3250 3251 3252 | }while( cnt<1000 && rx==SQLITE_OK && res==0 ); db->priorNewRowid = v; if( rx==SQLITE_OK && res==0 ){ rc = SQLITE_FULL; goto abort_due_to_error; } } | | | | > > > > > > | | > | > > > | | > > > > | | > > > > > | > > > > > > | > | | | | > > > > > > | | | | < < < < < < < < < < < | | < < < < < < < < < < < < < < < < < < | < < < < < < < < | > > > > > > > > > > > > > > > > > | 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 | }while( cnt<1000 && rx==SQLITE_OK && res==0 ); db->priorNewRowid = v; if( rx==SQLITE_OK && res==0 ){ rc = SQLITE_FULL; goto abort_due_to_error; } } pC->recnoIsValid = 0; pC->deferredMoveto = 0; pC->cacheValid = 0; } pTos++; pTos->i = v; pTos->flags = MEM_Int; break; } /* Opcode: PutIntKey P1 P2 * ** ** Write an entry into the table of cursor P1. A new entry is ** created if it doesn't already exist or the data for an existing ** entry is overwritten. The data is the value on the top of the ** stack. The key is the next value down on the stack. The key must ** be an integer. The stack is popped twice by this instruction. ** ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is ** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P2 is set, ** then rowid is stored for subsequent return by the ** sqlite3_last_insert_rowid() function (otherwise it's unmodified). */ /* Opcode: PutStrKey P1 * * ** ** Write an entry into the table of cursor P1. A new entry is ** created if it doesn't already exist or the data for an existing ** entry is overwritten. The data is the value on the top of the ** stack. The key is the next value down on the stack. The key must ** be a string. The stack is popped twice by this instruction. ** ** P1 may not be a pseudo-table opened using the OpenPseudo opcode. */ case OP_PutIntKey: case OP_PutStrKey: { Mem *pNos = &pTos[-1]; int i = pOp->p1; Cursor *pC; assert( pNos>=p->aStack ); assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); if( ((pC = p->apCsr[i])->pCursor!=0 || pC->pseudoTable) ){ char *zKey; i64 nKey; i64 iKey; if( pOp->opcode==OP_PutStrKey ){ Stringify(pNos, db->enc); nKey = pNos->n; zKey = pNos->z; }else{ assert( pNos->flags & MEM_Int ); /* If the table is an INTKEY table, set nKey to the value of ** the integer key, and zKey to NULL. Otherwise, set nKey to ** sizeof(i64) and point zKey at iKey. iKey contains the integer ** key in the on-disk byte order. */ iKey = intToKey(pNos->i); if( pC->intKey ){ nKey = intToKey(pNos->i); zKey = 0; }else{ nKey = sizeof(i64); zKey = (char*)&iKey; } if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i; if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){ pC->nextRowidValid = 0; } } if( pTos->flags & MEM_Null ){ pTos->z = 0; pTos->n = 0; }else{ assert( pTos->flags & (MEM_Blob|MEM_Str) ); } #ifndef SQLITE_OMIT_TRIGGER if( pC->pseudoTable ){ /* PutStrKey does not work for pseudo-tables. ** The following assert makes sure we are not trying to use ** PutStrKey on a pseudo-table */ assert( pOp->opcode==OP_PutIntKey ); sqliteFree(pC->pData); pC->iKey = iKey; pC->nData = pTos->n; if( pTos->flags & MEM_Dyn ){ pC->pData = pTos->z; pTos->flags = MEM_Null; }else{ pC->pData = sqliteMallocRaw( pC->nData+2 ); if( !pC->pData ) goto no_mem; memcpy(pC->pData, pTos->z, pC->nData); pC->pData[pC->nData] = 0; pC->pData[pC->nData+1] = 0; } pC->nullRow = 0; }else{ #endif rc = sqlite3BtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n); #ifndef SQLITE_OMIT_TRIGGER } #endif pC->recnoIsValid = 0; pC->deferredMoveto = 0; pC->cacheValid = 0; } popStack(&pTos, 2); break; } /* Opcode: Delete P1 P2 * ** ** Delete the record at which the P1 cursor is currently pointing. ** ** The cursor will be left pointing at either the next or the previous ** record in the table. If it is left pointing at the next record, then ** the next Next instruction will be a no-op. Hence it is OK to delete ** a record from within an Next loop. ** ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is ** incremented (otherwise not). ** ** If P1 is a pseudo-table, then this instruction is a no-op. */ case OP_Delete: { int i = pOp->p1; Cursor *pC; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; assert( pC!=0 ); if( pC->pCursor!=0 ){ rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; rc = sqlite3BtreeDelete(pC->pCursor); pC->nextRowidValid = 0; pC->cacheValid = 0; } if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; break; } /* Opcode: ResetCount P1 * * ** ** This opcode resets the VMs internal change counter to 0. If P1 is true, ** then the value of the change counter is copied to the database handle ** change counter (returned by subsequent calls to sqlite3_changes()) ** before it is reset. This is used by trigger programs. */ case OP_ResetCount: { if( pOp->p1 ){ sqlite3VdbeSetChanges(db, p->nChange); } p->nChange = 0; break; } /* Opcode: KeyAsData P1 P2 * ** ** Turn the key-as-data mode for cursor P1 either on (if P2==1) or ** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls ** data off of the key rather than the data. This is used for ** processing compound selects. */ case OP_KeyAsData: { int i = pOp->p1; Cursor *pC; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; assert( pC!=0 ); pC->keyAsData = pOp->p2; break; } /* Opcode: RowData P1 * * ** ** Push onto the stack the complete row data for cursor P1. ** There is no interpretation of the data. It is just copied ** onto the stack exactly as it is found in the database file. ** |
︙ | ︙ | |||
3435 3436 3437 3438 3439 3440 3441 | */ case OP_RowKey: case OP_RowData: { int i = pOp->p1; Cursor *pC; u32 n; | < < < | | | < | | | > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | < < < < < < < < < < < < < < < < < < | | | | 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 | */ case OP_RowKey: case OP_RowData: { int i = pOp->p1; Cursor *pC; u32 n; pTos++; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; assert( pC!=0 ); if( pC->nullRow ){ pTos->flags = MEM_Null; }else if( pC->pCursor!=0 ){ BtCursor *pCrsr = pC->pCursor; rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; if( pC->nullRow ){ pTos->flags = MEM_Null; break; }else if( pC->keyAsData || pOp->opcode==OP_RowKey ){ i64 n64; assert( !pC->intKey ); sqlite3BtreeKeySize(pCrsr, &n64); n = n64; }else{ sqlite3BtreeDataSize(pCrsr, &n); } pTos->n = n; if( n<=NBFS ){ pTos->flags = MEM_Blob | MEM_Short; pTos->z = pTos->zShort; }else{ char *z = sqliteMallocRaw( n ); if( z==0 ) goto no_mem; pTos->flags = MEM_Blob | MEM_Dyn; pTos->xDel = 0; pTos->z = z; } if( pC->keyAsData || pOp->opcode==OP_RowKey ){ sqlite3BtreeKey(pCrsr, 0, n, pTos->z); }else{ sqlite3BtreeData(pCrsr, 0, n, pTos->z); } #ifndef SQLITE_OMIT_TRIGGER }else if( pC->pseudoTable ){ pTos->n = pC->nData; pTos->z = pC->pData; pTos->flags = MEM_Blob|MEM_Ephem; #endif }else{ pTos->flags = MEM_Null; } break; } /* Opcode: Recno P1 * * ** ** Push onto the stack an integer which is the first 4 bytes of the ** the key to the current entry in a sequential scan of the database ** file P1. The sequential scan should have been started using the ** Next opcode. */ case OP_Recno: { int i = pOp->p1; Cursor *pC; i64 v; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; assert( pC!=0 ); rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; pTos++; if( pC->recnoIsValid ){ v = pC->lastRecno; }else if( pC->pseudoTable ){ v = keyToInt(pC->iKey); }else if( pC->nullRow || pC->pCursor==0 ){ pTos->flags = MEM_Null; break; }else{ assert( pC->pCursor!=0 ); sqlite3BtreeKeySize(pC->pCursor, &v); v = keyToInt(v); } pTos->i = v; pTos->flags = MEM_Int; break; } #ifndef SQLITE_OMIT_COMPOUND_SELECT /* Opcode: FullKey P1 * * ** ** Extract the complete key from the record that cursor P1 is currently ** pointing to and push the key onto the stack as a string. ** ** Compare this opcode to Recno. The Recno opcode extracts the first ** 4 bytes of the key and pushes those bytes onto the stack as an ** integer. This instruction pushes the entire key as a string. ** ** This opcode may not be used on a pseudo-table. */ case OP_FullKey: { int i = pOp->p1; BtCursor *pCrsr; Cursor *pC; assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); assert( p->apCsr[i]->keyAsData ); assert( !p->apCsr[i]->pseudoTable ); pTos++; pTos->flags = MEM_Null; if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ i64 amt; char *z; rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; assert( pC->intKey==0 ); sqlite3BtreeKeySize(pCrsr, &amt); if( amt<=0 ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } if( amt>NBFS ){ z = sqliteMallocRaw( amt ); if( z==0 ) goto no_mem; pTos->flags = MEM_Blob | MEM_Dyn; pTos->xDel = 0; }else{ z = pTos->zShort; pTos->flags = MEM_Blob | MEM_Short; } sqlite3BtreeKey(pCrsr, 0, amt, z); pTos->z = z; pTos->n = amt; } break; } #endif /* Opcode: NullRow P1 * * ** ** Move the cursor P1 to a null row. Any OP_Column operations ** that occur while the cursor is on the null row will always push ** a NULL onto the stack. */ case OP_NullRow: { int i = pOp->p1; Cursor *pC; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; assert( pC!=0 ); pC->nullRow = 1; pC->recnoIsValid = 0; break; } /* Opcode: Last P1 P2 * ** ** The next use of the Recno or Column or Next instruction for P1 ** will refer to the last entry in the database table or index. ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. */ case OP_Last: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; assert( pC!=0 ); if( (pCrsr = pC->pCursor)!=0 ){ int res; rc = sqlite3BtreeLast(pCrsr, &res); pC->nullRow = res; pC->deferredMoveto = 0; pC->cacheValid = 0; if( res && pOp->p2>0 ){ pc = pOp->p2 - 1; } }else{ pC->nullRow = 0; } break; } /* Opcode: Rewind P1 P2 * ** ** The next use of the Recno or Column or Next instruction for P1 ** will refer to the first entry in the database table or index. ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. */ case OP_Rewind: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; int res; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; assert( pC!=0 ); if( (pCrsr = pC->pCursor)!=0 ){ rc = sqlite3BtreeFirst(pCrsr, &res); pC->atFirst = res==0; pC->deferredMoveto = 0; pC->cacheValid = 0; }else{ res = 1; } pC->nullRow = res; if( res && pOp->p2>0 ){ pc = pOp->p2 - 1; } |
︙ | ︙ | |||
3636 3637 3638 3639 3640 3641 3642 | /* Opcode: Prev P1 P2 * ** ** Back up cursor P1 so that it points to the previous key/data pair in its ** table or index. If there is no previous key/value pairs then fall through ** to the following instruction. But if the cursor backup was successful, ** jump immediately to P2. */ | | | | | | | | | | | > > | < > > > > > > > > > > > > > > > > > > > > > > > > > > | | | < | | | | | | | | | | 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 | /* Opcode: Prev P1 P2 * ** ** Back up cursor P1 so that it points to the previous key/data pair in its ** table or index. If there is no previous key/value pairs then fall through ** to the following instruction. But if the cursor backup was successful, ** jump immediately to P2. */ case OP_Prev: case OP_Next: { Cursor *pC; BtCursor *pCrsr; CHECK_FOR_INTERRUPT; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); if( (pCrsr = pC->pCursor)!=0 ){ int res; if( pC->nullRow ){ res = 1; }else{ assert( pC->deferredMoveto==0 ); rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) : sqlite3BtreePrevious(pCrsr, &res); pC->nullRow = res; pC->cacheValid = 0; } if( res==0 ){ pc = pOp->p2 - 1; sqlite3_search_count++; } }else{ pC->nullRow = 1; } pC->recnoIsValid = 0; break; } /* Opcode: IdxPut P1 P2 P3 ** ** The top of the stack holds a SQL index key made using the ** MakeIdxKey instruction. This opcode writes that key into the ** index P1. Data for the entry is nil. ** ** If P2==1, then the key must be unique. If the key is not unique, ** the program aborts with a SQLITE_CONSTRAINT error and the database ** is rolled back. If P3 is not null, then it becomes part of the ** error message returned with the SQLITE_CONSTRAINT. */ case OP_IdxPut: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); assert( pTos->flags & MEM_Blob ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int nKey = pTos->n; const char *zKey = pTos->z; if( pOp->p2 ){ int res; int len; /* 'len' is the length of the key minus the rowid at the end */ len = nKey - sqlite3VdbeIdxRowidLen(nKey, zKey); rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; while( res!=0 && !sqlite3BtreeEof(pCrsr) ){ int c; if( sqlite3VdbeIdxKeyCompare(pC, len, zKey, &c)==SQLITE_OK && c==0 ){ rc = SQLITE_CONSTRAINT; if( pOp->p3 && pOp->p3[0] ){ sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0); } goto abort_due_to_error; } if( res<0 ){ sqlite3BtreeNext(pCrsr, &res); res = +1; }else{ break; } } } assert( pC->intKey==0 ); rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0); assert( pC->deferredMoveto==0 ); pC->cacheValid = 0; } Release(pTos); pTos--; break; } /* Opcode: IdxDelete P1 * * ** ** The top of the stack is an index key built using the MakeIdxKey opcode. ** This opcode removes that entry from the index. */ case OP_IdxDelete: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( pTos->flags & MEM_Blob ); assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int rx, res; rx = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res); if( rx==SQLITE_OK && res==0 ){ rc = sqlite3BtreeDelete(pCrsr); } assert( pC->deferredMoveto==0 ); pC->cacheValid = 0; } Release(pTos); pTos--; break; } /* Opcode: IdxRecno P1 * * ** ** Push onto the stack an integer which is the varint located at the ** end of the index key pointed to by cursor P1. This integer should be ** the record number of the table entry to which this index entry points. ** ** See also: Recno, MakeIdxKey. */ case OP_IdxRecno: { int i = pOp->p1; BtCursor *pCrsr; Cursor *pC; assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); pTos++; pTos->flags = MEM_Null; if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ i64 rowid; assert( pC->deferredMoveto==0 ); assert( pC->intKey==0 ); if( pC->nullRow ){ pTos->flags = MEM_Null; }else{ rc = sqlite3VdbeIdxRowid(pCrsr, &rowid); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } |
︙ | ︙ | |||
3806 3807 3808 3809 3810 3811 3812 | ** In either case, the stack is popped once. ** ** If P3 is the "+" string (or any other non-NULL string) then the ** index taken from the top of the stack is temporarily increased by ** an epsilon prior to the comparison. This makes the opcode work ** like IdxLE. */ | | | | > | | | | 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 | ** In either case, the stack is popped once. ** ** If P3 is the "+" string (or any other non-NULL string) then the ** index taken from the top of the stack is temporarily increased by ** an epsilon prior to the comparison. This makes the opcode work ** like IdxLE. */ case OP_IdxLT: case OP_IdxGT: case OP_IdxGE: { int i= pOp->p1; BtCursor *pCrsr; Cursor *pC; assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); assert( pTos>=p->aStack ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int res, rc; assert( pTos->flags & MEM_Blob ); /* Created using OP_Make*Key */ Stringify(pTos, db->enc); assert( pC->deferredMoveto==0 ); *pC->pIncrKey = pOp->p3!=0; assert( pOp->p3==0 || pOp->opcode!=OP_IdxGT ); rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, pTos->z, &res); *pC->pIncrKey = 0; if( rc!=SQLITE_OK ){ break; } if( pOp->opcode==OP_IdxLT ){ res = -res; }else if( pOp->opcode==OP_IdxGE ){ |
︙ | ︙ | |||
3845 3846 3847 3848 3849 3850 3851 | pTos--; break; } /* Opcode: IdxIsNull P1 P2 * ** ** The top of the stack contains an index entry such as might be generated | | | | | | 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 | pTos--; break; } /* Opcode: IdxIsNull P1 P2 * ** ** The top of the stack contains an index entry such as might be generated ** by the MakeIdxKey opcode. This routine looks at the first P1 fields of ** that key. If any of the first P1 fields are NULL, then a jump is made ** to address P2. Otherwise we fall straight through. ** ** The index entry is always popped from the stack. */ case OP_IdxIsNull: { int i = pOp->p1; int k, n; const char *z; u32 serial_type; assert( pTos>=p->aStack ); assert( pTos->flags & MEM_Blob ); z = pTos->z; n = pTos->n; k = sqlite3GetVarint32(z, &serial_type); for(; k<n && i>0; i--){ k += sqlite3GetVarint32(&z[k], &serial_type); if( serial_type==0 ){ /* Serial type 0 is a NULL */ pc = pOp->p2-1; break; } } Release(pTos); pTos--; |
︙ | ︙ | |||
3925 3926 3927 3928 3929 3930 3931 | ** ** The table being clear is in the main database file if P2==0. If ** P2==1 then the table to be clear is in the auxiliary database file ** that is used to store tables create using CREATE TEMPORARY TABLE. ** ** See also: Destroy */ | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 | ** ** The table being clear is in the main database file if P2==0. If ** P2==1 then the table to be clear is in the auxiliary database file ** that is used to store tables create using CREATE TEMPORARY TABLE. ** ** See also: Destroy */ case OP_Clear: { rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1); break; } /* Opcode: CreateTable P1 * * ** ** Allocate a new table in the main database file if P2==0 or in the |
︙ | ︙ | |||
4018 4019 4020 4021 4022 4023 4024 | ** ** Read and parse all entries from the SQLITE_MASTER table of database P1 ** that match the WHERE clause P3. ** ** This opcode invokes the parser to create a new virtual machine, ** then runs the new virtual machine. It is thus a reentrant opcode. */ | | | < < < < < < < < | < < < < < < < < < < < < | | | | 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 | ** ** Read and parse all entries from the SQLITE_MASTER table of database P1 ** that match the WHERE clause P3. ** ** This opcode invokes the parser to create a new virtual machine, ** then runs the new virtual machine. It is thus a reentrant opcode. */ case OP_ParseSchema: { char *zSql; int iDb = pOp->p1; const char *zMaster; InitData initData; assert( iDb>=0 && iDb<db->nDb ); if( !DbHasProperty(db, iDb, DB_SchemaLoaded) ) break; zMaster = iDb==1 ? TEMP_MASTER_NAME : MASTER_NAME; initData.db = db; initData.pzErrMsg = &p->zErrMsg; zSql = sqlite3MPrintf( "SELECT name, rootpage, sql, %d FROM '%q'.%s WHERE %s", pOp->p1, db->aDb[iDb].zName, zMaster, pOp->p3); if( zSql==0 ) goto no_mem; sqlite3SafetyOff(db); assert( db->init.busy==0 ); db->init.busy = 1; rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); db->init.busy = 0; sqlite3SafetyOn(db); sqliteFree(zSql); break; } /* Opcode: DropTable P1 * P3 ** ** Remove the internal (in-memory) data structures that describe ** the table named P3 in database P1. This is called after a table ** is dropped in order to keep the internal representation of the ** schema consistent with what is on disk. */ case OP_DropTable: { sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p3); break; } /* Opcode: DropIndex P1 * P3 ** ** Remove the internal (in-memory) data structures that describe ** the index named P3 in database P1. This is called after an index ** is dropped in order to keep the internal representation of the ** schema consistent with what is on disk. */ case OP_DropIndex: { sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p3); break; } /* Opcode: DropTrigger P1 * P3 ** ** Remove the internal (in-memory) data structures that describe ** the trigger named P3 in database P1. This is called after a trigger ** is dropped in order to keep the internal representation of the ** schema consistent with what is on disk. */ case OP_DropTrigger: { sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3); break; } #ifndef SQLITE_OMIT_INTEGRITY_CHECK /* Opcode: IntegrityCk * P2 * |
︙ | ︙ | |||
4148 4149 4150 4151 4152 4153 4154 | }else{ pTos->z = z; pTos->n = strlen(z); pTos->flags = MEM_Str | MEM_Dyn | MEM_Term; pTos->xDel = 0; } pTos->enc = SQLITE_UTF8; | | | | | > > > > > > > > > > > | | | > > > > > > > > > > > > > > > > > > > > | | | < > < | > | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 | }else{ pTos->z = z; pTos->n = strlen(z); pTos->flags = MEM_Str | MEM_Dyn | MEM_Term; pTos->xDel = 0; } pTos->enc = SQLITE_UTF8; sqlite3VdbeChangeEncoding(pTos, db->enc); sqliteFree(aRoot); break; } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* Opcode: ListWrite * * * ** ** Write the integer on the top of the stack ** into the temporary storage list. */ case OP_ListWrite: { Keylist *pKeylist; assert( pTos>=p->aStack ); pKeylist = p->pList; if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){ pKeylist = sqliteMallocRaw( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) ); if( pKeylist==0 ) goto no_mem; pKeylist->nKey = 1000; pKeylist->nRead = 0; pKeylist->nUsed = 0; pKeylist->pNext = p->pList; p->pList = pKeylist; } Integerify(pTos); pKeylist->aKey[pKeylist->nUsed++] = pTos->i; assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; break; } /* Opcode: ListRewind * * * ** ** Rewind the temporary buffer back to the beginning. */ case OP_ListRewind: { /* What this opcode codes, really, is reverse the order of the ** linked list of Keylist structures so that they are read out ** in the same order that they were read in. */ Keylist *pRev, *pTop; pRev = 0; while( p->pList ){ pTop = p->pList; p->pList = pTop->pNext; pTop->pNext = pRev; pRev = pTop; } p->pList = pRev; break; } /* Opcode: ListRead * P2 * ** ** Attempt to read an integer from the temporary storage buffer ** and push it onto the stack. If the storage buffer is empty, ** push nothing but instead jump to P2. */ case OP_ListRead: { Keylist *pKeylist; CHECK_FOR_INTERRUPT; pKeylist = p->pList; if( pKeylist!=0 ){ assert( pKeylist->nRead>=0 ); assert( pKeylist->nRead<pKeylist->nUsed ); assert( pKeylist->nRead<pKeylist->nKey ); pTos++; pTos->i = pKeylist->aKey[pKeylist->nRead++]; pTos->flags = MEM_Int; if( pKeylist->nRead>=pKeylist->nUsed ){ p->pList = pKeylist->pNext; sqliteFree(pKeylist); } }else{ pc = pOp->p2 - 1; } break; } /* Opcode: ListReset * * * ** ** Reset the temporary storage buffer so that it holds nothing. */ case OP_ListReset: { if( p->pList ){ sqlite3VdbeKeylistFree(p->pList); p->pList = 0; } break; } #ifndef SQLITE_OMIT_SUBQUERY /* Opcode: AggContextPush * * * ** ** Save the state of the current aggregator. It is restored an ** AggContextPop opcode. ** */ case OP_AggContextPush: { p->pAgg++; assert( p->pAgg<&p->apAgg[p->nAgg] ); break; } /* Opcode: AggContextPop * * * ** ** Restore the aggregator to the state it was in when AggContextPush ** was last called. Any data in the current aggregator is deleted. */ case OP_AggContextPop: { p->pAgg--; assert( p->pAgg>=p->apAgg ); break; } #endif #ifndef SQLITE_OMIT_TRIGGER /* Opcode: ContextPush * * * ** ** Save the current Vdbe context such that it can be restored by a ContextPop ** opcode. The context stores the last insert row id, the last statement change ** count, and the current statement change count. */ case OP_ContextPush: { int i = p->contextStackTop++; Context *pContext; assert( i>=0 ); /* FIX ME: This should be allocated as part of the vdbe at compile-time */ if( i>=p->contextStackDepth ){ p->contextStackDepth = i+1; p->contextStack = sqliteRealloc(p->contextStack, sizeof(Context)*(i+1)); if( p->contextStack==0 ) goto no_mem; } pContext = &p->contextStack[i]; pContext->lastRowid = db->lastRowid; pContext->nChange = p->nChange; pContext->pList = p->pList; p->pList = 0; break; } /* Opcode: ContextPop * * * ** ** Restore the Vdbe context to the state it was in when contextPush was last ** executed. The context stores the last insert row id, the last statement ** change count, and the current statement change count. */ case OP_ContextPop: { Context *pContext = &p->contextStack[--p->contextStackTop]; assert( p->contextStackTop>=0 ); db->lastRowid = pContext->lastRowid; p->nChange = pContext->nChange; sqlite3VdbeKeylistFree(p->pList); p->pList = pContext->pList; break; } #endif /* #ifndef SQLITE_OMIT_TRIGGER */ /* Opcode: SortPut * * * ** ** The TOS is the key and the NOS is the data. Pop both from the stack ** and put them on the sorter. The key and data should have been ** made using the MakeRecord opcode. */ case OP_SortPut: { Mem *pNos = &pTos[-1]; Sorter *pSorter; assert( pNos>=p->aStack ); if( Dynamicify(pTos, db->enc) ) goto no_mem; pSorter = sqliteMallocRaw( sizeof(Sorter) ); if( pSorter==0 ) goto no_mem; pSorter->pNext = p->pSort; p->pSort = pSorter; assert( pTos->flags & MEM_Dyn ); pSorter->nKey = pTos->n; pSorter->zKey = pTos->z; pSorter->data.flags = MEM_Null; rc = sqlite3VdbeMemMove(&pSorter->data, pNos); pTos -= 2; break; } /* Opcode: Sort * * P3 ** ** Sort all elements on the sorter. The algorithm is a ** mergesort. The P3 argument is a pointer to a KeyInfo structure ** that describes the keys to be sorted. */ case OP_Sort: { int i; KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3; Sorter *pElem; Sorter *apSorter[NSORT]; sqlite3_sort_count++; pKeyInfo->enc = p->db->enc; for(i=0; i<NSORT; i++){ apSorter[i] = 0; } while( p->pSort ){ pElem = p->pSort; p->pSort = pElem->pNext; pElem->pNext = 0; for(i=0; i<NSORT-1; i++){ if( apSorter[i]==0 ){ apSorter[i] = pElem; break; }else{ pElem = Merge(apSorter[i], pElem, pKeyInfo); apSorter[i] = 0; } } if( i>=NSORT-1 ){ apSorter[NSORT-1] = Merge(apSorter[NSORT-1],pElem, pKeyInfo); } } pElem = 0; for(i=0; i<NSORT; i++){ pElem = Merge(apSorter[i], pElem, pKeyInfo); } p->pSort = pElem; break; } /* Opcode: SortNext * P2 * ** ** Push the data for the topmost element in the sorter onto the ** stack, then remove the element from the sorter. If the sorter ** is empty, push nothing on the stack and instead jump immediately ** to instruction P2. */ case OP_SortNext: { Sorter *pSorter = p->pSort; CHECK_FOR_INTERRUPT; if( pSorter!=0 ){ p->pSort = pSorter->pNext; pTos++; pTos->flags = MEM_Null; rc = sqlite3VdbeMemMove(pTos, &pSorter->data); sqliteFree(pSorter->zKey); sqliteFree(pSorter); }else{ pc = pOp->p2 - 1; } break; } /* Opcode: SortReset * * * ** ** Remove any elements that remain on the sorter. */ case OP_SortReset: { sqlite3VdbeSorterReset(p); break; } /* Opcode: MemStore P1 P2 * ** ** Write the top of the stack into memory location P1. ** P1 should be a small integer since space is allocated ** for all memory locations between 0 and P1 inclusive. ** ** After the data is stored in the memory location, the ** stack is popped once if P2 is 1. If P2 is zero, then ** the original data remains on the stack. */ case OP_MemStore: { assert( pTos>=p->aStack ); assert( pOp->p1>=0 && pOp->p1<p->nMem ); rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], pTos); pTos--; /* If P2 is 0 then fall thru to the next opcode, OP_MemLoad, that will ** restore the top of the stack to its original value. |
︙ | ︙ | |||
4279 4280 4281 4282 4283 4284 4285 | ** ** Set the value of memory cell P1 to the maximum of its current value ** and the value on the top of the stack. The stack is unchanged. ** ** This instruction throws an error if the memory cell is not initially ** an integer. */ | | | | | > > | | | | | > > > | < < | | | | > > > | < > | | < < < < < | < < < | < < < < < < < < | < | < | < > | < > > | | < < < < < | < | | < < < < < < | < < | < < | | | | | | < > > > | | > | > > | > > | > | | > > | | > | | > > < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < > > > > > | > > > > > > > > > > | > > > > > > > > > > > | | | | | > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < > > > < < < | | > > > | 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 | ** ** Set the value of memory cell P1 to the maximum of its current value ** and the value on the top of the stack. The stack is unchanged. ** ** This instruction throws an error if the memory cell is not initially ** an integer. */ case OP_MemMax: { int i = pOp->p1; Mem *pMem; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nMem ); pMem = &p->aMem[i]; Integerify(pMem); Integerify(pTos); if( pMem->i<pTos->i){ pMem->i = pTos->i; } break; } #endif /* SQLITE_OMIT_AUTOINCREMENT */ /* Opcode: MemIncr P1 P2 * ** ** Increment the integer valued memory cell P1 by 1. If P2 is not zero ** and the result after the increment is exactly 1, then jump ** to P2. ** ** This instruction throws an error if the memory cell is not initially ** an integer. */ case OP_MemIncr: { int i = pOp->p1; Mem *pMem; assert( i>=0 && i<p->nMem ); pMem = &p->aMem[i]; assert( pMem->flags==MEM_Int ); pMem->i++; if( pOp->p2>0 && pMem->i==1 ){ pc = pOp->p2 - 1; } break; } /* Opcode: IfMemPos P1 P2 * ** ** If the value of memory cell P1 is 1 or greater, jump to P2. This ** opcode assumes that memory cell P1 holds an integer value. */ case OP_IfMemPos: { int i = pOp->p1; Mem *pMem; assert( i>=0 && i<p->nMem ); pMem = &p->aMem[i]; assert( pMem->flags==MEM_Int ); if( pMem->i>0 ){ pc = pOp->p2 - 1; } break; } /* Opcode: AggReset P1 P2 P3 ** ** Reset the current aggregator context so that it no longer contains any ** data. Future aggregator elements will contain P2 values each and be sorted ** using the KeyInfo structure pointed to by P3. ** ** If P1 is non-zero, then only a single aggregator row is available (i.e. ** there is no GROUP BY expression). In this case it is illegal to invoke ** OP_AggFocus. */ case OP_AggReset: { assert( !pOp->p3 || pOp->p3type==P3_KEYINFO ); if( pOp->p1 ){ rc = sqlite3VdbeAggReset(0, p->pAgg, (KeyInfo *)pOp->p3); p->pAgg->nMem = pOp->p2; /* Agg.nMem is used by AggInsert() */ rc = AggInsert(p->pAgg, 0, 0); }else{ rc = sqlite3VdbeAggReset(db, p->pAgg, (KeyInfo *)pOp->p3); p->pAgg->nMem = pOp->p2; } if( rc!=SQLITE_OK ){ goto abort_due_to_error; } p->pAgg->apFunc = sqliteMalloc( p->pAgg->nMem*sizeof(p->pAgg->apFunc[0]) ); if( p->pAgg->apFunc==0 ) goto no_mem; break; } /* Opcode: AggInit * P2 P3 ** ** Initialize the function parameters for an aggregate function. ** The aggregate will operate out of aggregate column P2. ** P3 is a pointer to the FuncDef structure for the function. */ case OP_AggInit: { int i = pOp->p2; assert( i>=0 && i<p->pAgg->nMem ); p->pAgg->apFunc[i] = (FuncDef*)pOp->p3; break; } /* Opcode: AggFunc * P2 P3 ** ** Execute the step function for an aggregate. The ** function has P2 arguments. P3 is a pointer to the FuncDef ** structure that specifies the function. ** ** The top of the stack must be an integer which is the index of ** the aggregate column that corresponds to this aggregate function. ** Ideally, this index would be another parameter, but there are ** no free parameters left. The integer is popped from the stack. */ case OP_AggFunc: { int n = pOp->p2; int i; Mem *pMem, *pRec; sqlite3_context ctx; sqlite3_value **apVal; assert( n>=0 ); assert( pTos->flags==MEM_Int ); pRec = &pTos[-n]; assert( pRec>=p->aStack ); apVal = p->apArg; assert( apVal || n==0 ); for(i=0; i<n; i++, pRec++){ apVal[i] = pRec; storeTypeInfo(pRec, db->enc); } i = pTos->i; assert( i>=0 && i<p->pAgg->nMem ); ctx.pFunc = (FuncDef*)pOp->p3; pMem = &p->pAgg->pCurrent->aMem[i]; ctx.s.z = pMem->zShort; /* Space used for small aggregate contexts */ ctx.pAgg = pMem->z; ctx.cnt = ++pMem->i; ctx.isError = 0; ctx.pColl = 0; if( ctx.pFunc->needCollSeq ){ assert( pOp>p->aOp ); assert( pOp[-1].p3type==P3_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); ctx.pColl = (CollSeq *)pOp[-1].p3; } (ctx.pFunc->xStep)(&ctx, n, apVal); pMem->z = ctx.pAgg; pMem->flags = MEM_AggCtx; popStack(&pTos, n+1); if( ctx.isError ){ rc = SQLITE_ERROR; } break; } /* Opcode: AggFocus * P2 * ** ** Pop the top of the stack and use that as an aggregator key. If ** an aggregator with that same key already exists, then make the ** aggregator the current aggregator and jump to P2. If no aggregator ** with the given key exists, create one and make it current but ** do not jump. ** ** The order of aggregator opcodes is important. The order is: ** AggReset AggFocus AggNext. In other words, you must execute ** AggReset first, then zero or more AggFocus operations, then ** zero or more AggNext operations. You must not execute an AggFocus ** in between an AggNext and an AggReset. */ case OP_AggFocus: { char *zKey; int nKey; int res; assert( pTos>=p->aStack ); Stringify(pTos, db->enc); zKey = pTos->z; nKey = pTos->n; assert( p->pAgg->pBtree ); assert( p->pAgg->pCsr ); rc = sqlite3BtreeMoveto(p->pAgg->pCsr, zKey, nKey, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } if( res==0 ){ rc = sqlite3BtreeData(p->pAgg->pCsr, 0, sizeof(AggElem*), (char *)&p->pAgg->pCurrent); pc = pOp->p2 - 1; }else{ rc = AggInsert(p->pAgg, zKey, nKey); } if( rc!=SQLITE_OK ){ goto abort_due_to_error; } Release(pTos); pTos--; break; } /* Opcode: AggSet * P2 * ** ** Move the top of the stack into the P2-th field of the current ** aggregate. String values are duplicated into new memory. */ case OP_AggSet: { AggElem *pFocus; int i = pOp->p2; pFocus = p->pAgg->pCurrent; assert( pTos>=p->aStack ); if( pFocus==0 ) goto no_mem; assert( i>=0 && i<p->pAgg->nMem ); rc = sqlite3VdbeMemMove(&pFocus->aMem[i], pTos); pTos--; break; } /* Opcode: AggGet P1 P2 * ** ** Push a new entry onto the stack which is a copy of the P2-th field ** of the current aggregate. Strings are not duplicated so ** string values will be ephemeral. ** ** If P1 is zero, then the value is pulled out of the current aggregate ** in the current aggregate context. If P1 is greater than zero, then ** the value is taken from the P1th outer aggregate context. (i.e. if ** P1==1 then read from the aggregate context that will be restored ** by the next OP_AggContextPop opcode). */ case OP_AggGet: { AggElem *pFocus; int i = pOp->p2; Agg *pAgg = &p->pAgg[-pOp->p1]; assert( pAgg>=p->apAgg ); pFocus = pAgg->pCurrent; if( pFocus==0 ){ int res; if( sqlite3_malloc_failed ) goto no_mem; rc = sqlite3BtreeFirst(pAgg->pCsr, &res); if( rc!=SQLITE_OK ){ return rc; } if( res!=0 ){ rc = AggInsert(pAgg, "", 1); pFocus = pAgg->pCurrent; }else{ rc = sqlite3BtreeData(pAgg->pCsr, 0, 4, (char *)&pFocus); } } assert( i>=0 && i<pAgg->nMem ); pTos++; sqlite3VdbeMemShallowCopy(pTos, &pFocus->aMem[i], MEM_Ephem); if( pTos->flags&MEM_Str ){ sqlite3VdbeChangeEncoding(pTos, db->enc); } break; } /* Opcode: AggNext * P2 * ** ** Make the next aggregate value the current aggregate. The prior ** aggregate is deleted. If all aggregate values have been consumed, ** jump to P2. ** ** The order of aggregator opcodes is important. The order is: ** AggReset AggFocus AggNext. In other words, you must execute ** AggReset first, then zero or more AggFocus operations, then ** zero or more AggNext operations. You must not execute an AggFocus ** in between an AggNext and an AggReset. */ case OP_AggNext: { int res; assert( rc==SQLITE_OK ); CHECK_FOR_INTERRUPT; if( p->pAgg->searching==0 ){ p->pAgg->searching = 1; if( p->pAgg->pCsr ){ rc = sqlite3BtreeFirst(p->pAgg->pCsr, &res); }else{ res = 0; } }else{ if( p->pAgg->pCsr ){ rc = sqlite3BtreeNext(p->pAgg->pCsr, &res); }else{ res = 1; } } if( rc!=SQLITE_OK ) goto abort_due_to_error; if( res!=0 ){ pc = pOp->p2 - 1; }else{ int i; sqlite3_context ctx; Mem *aMem; if( p->pAgg->pCsr ){ rc = sqlite3BtreeData(p->pAgg->pCsr, 0, sizeof(AggElem*), (char *)&p->pAgg->pCurrent); if( rc!=SQLITE_OK ) goto abort_due_to_error; } aMem = p->pAgg->pCurrent->aMem; for(i=0; i<p->pAgg->nMem; i++){ FuncDef *pFunc = p->pAgg->apFunc[i]; Mem *pMem = &aMem[i]; if( pFunc==0 || pFunc->xFinalize==0 ) continue; ctx.s.flags = MEM_Null; ctx.s.z = pMem->zShort; ctx.pAgg = (void*)pMem->z; ctx.cnt = pMem->i; ctx.pFunc = pFunc; pFunc->xFinalize(&ctx); pMem->z = ctx.pAgg; if( pMem->z && pMem->z!=pMem->zShort ){ sqliteFree( pMem->z ); } *pMem = ctx.s; if( pMem->flags & MEM_Short ){ pMem->z = pMem->zShort; } } } break; } /* Opcode: Vacuum * * * ** ** Vacuum the entire database. This opcode will cause other virtual ** machines to be created and run. It may not be called from within ** a transaction. */ case OP_Vacuum: { if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; rc = sqlite3RunVacuum(&p->zErrMsg, db); if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; break; } /* Opcode: Expire P1 * * ** ** Cause precompiled statements to become expired. An expired statement ** fails with an error code of SQLITE_SCHEMA if it is ever executed ** (via sqlite3_step()). ** ** If P1 is 0, then all SQL statements become expired. If P1 is non-zero, ** then only the currently executing statement is affected. */ case OP_Expire: { if( !pOp->p1 ){ sqlite3ExpirePreparedStatements(db); }else{ p->expired = 1; } break; } /* An other opcode is illegal... */ default: { sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",pOp->opcode); sqlite3SetString(&p->zErrMsg, "unknown opcode ", zBuf, (char*)0); rc = SQLITE_INTERNAL; break; } /***************************************************************************** ** The cases of the switch statement above this line should all be indented ** by 6 spaces. But the left-most 6 spaces have been removed to improve the ** readability. From this point on down, the normal indentation rules are ** restored. *****************************************************************************/ } #ifdef VDBE_PROFILE { long long elapse = hwtime() - start; pOp->cycles += elapse; pOp->cnt++; #if 0 fprintf(stdout, "%10lld ", elapse); sqlite3VdbePrintOp(stdout, origPc, &p->aOp[origPc]); #endif } #endif /* The following code adds nothing to the actual functionality ** of the program. It is only here for testing and debugging. ** On the other hand, it does burn CPU cycles every time through ** the evaluator loop. So we can leave it out when NDEBUG is defined. */ #ifndef NDEBUG /* Sanity checking on the top element of the stack */ if( pTos>=p->aStack ){ sqlite3VdbeMemSanity(pTos, db->enc); } if( pc<-1 || pc>=p->nOp ){ sqlite3SetString(&p->zErrMsg, "jump destination out of range", (char*)0); rc = SQLITE_INTERNAL; } #ifdef SQLITE_DEBUG /* Code for tracing the vdbe stack. */ if( p->trace && pTos>=p->aStack ){ int i; fprintf(p->trace, "Stack:"); for(i=0; i>-5 && &pTos[i]>=p->aStack; i--){ if( pTos[i].flags & MEM_Null ){ |
︙ | ︙ | |||
4611 4612 4613 4614 4615 4616 4617 | p->rc = rc; rc = SQLITE_ERROR; }else{ rc = SQLITE_DONE; } sqlite3VdbeHalt(p); p->pTos = pTos; | < | 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 | p->rc = rc; rc = SQLITE_ERROR; }else{ rc = SQLITE_DONE; } sqlite3VdbeHalt(p); p->pTos = pTos; return rc; /* Jump to here if a malloc() fails. It's hard to get a malloc() ** to fail on a modern VM computer, so this code is untested. */ no_mem: sqlite3SetString(&p->zErrMsg, "out of memory", (char*)0); |
︙ | ︙ | |||
4633 4634 4635 4636 4637 4638 4639 | /* Fall thru into abort_due_to_error */ /* Jump to here for any other kind of fatal error. The "rc" variable ** should hold the error number. */ abort_due_to_error: if( p->zErrMsg==0 ){ | | | 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 | /* Fall thru into abort_due_to_error */ /* Jump to here for any other kind of fatal error. The "rc" variable ** should hold the error number. */ abort_due_to_error: if( p->zErrMsg==0 ){ if( sqlite3_malloc_failed ) rc = SQLITE_NOMEM; sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0); } goto vdbe_halt; /* Jump to here if the sqlite3_interrupt() API sets the interrupt ** flag. */ |
︙ | ︙ |
Changes to SQLite.Interop/src/vdbe.h.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** ** $Id: vdbe.h,v 1.1 2005/03/01 16:04:38 rmsimpson Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
34 35 36 37 38 39 40 | ** as an instance of the following structure: */ struct VdbeOp { u8 opcode; /* What operation to perform */ int p1; /* First operand */ int p2; /* Second parameter (often the jump destination) */ char *p3; /* Third parameter */ | | | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | ** as an instance of the following structure: */ struct VdbeOp { u8 opcode; /* What operation to perform */ int p1; /* First operand */ int p2; /* Second parameter (often the jump destination) */ char *p3; /* Third parameter */ int p3type; /* P3_STATIC, P3_DYNAMIC or P3_POINTER */ #ifdef VDBE_PROFILE int cnt; /* Number of times this instruction was executed */ long long cycles; /* Total time spend executing this instruction */ #endif }; typedef struct VdbeOp VdbeOp; |
︙ | ︙ | |||
60 61 62 63 64 65 66 67 68 69 70 | /* ** Allowed values of VdbeOp.p3type */ #define P3_NOTUSED 0 /* The P3 parameter is not used */ #define P3_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ #define P3_STATIC (-2) /* Pointer to a static string */ #define P3_COLLSEQ (-4) /* P3 is a pointer to a CollSeq structure */ #define P3_FUNCDEF (-5) /* P3 is a pointer to a FuncDef structure */ #define P3_KEYINFO (-6) /* P3 is a pointer to a KeyInfo structure */ #define P3_VDBEFUNC (-7) /* P3 is a pointer to a VdbeFunc structure */ | > < | | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | /* ** Allowed values of VdbeOp.p3type */ #define P3_NOTUSED 0 /* The P3 parameter is not used */ #define P3_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ #define P3_STATIC (-2) /* Pointer to a static string */ #define P3_POINTER (-3) /* P3 is a pointer to some structure or object */ #define P3_COLLSEQ (-4) /* P3 is a pointer to a CollSeq structure */ #define P3_FUNCDEF (-5) /* P3 is a pointer to a FuncDef structure */ #define P3_KEYINFO (-6) /* P3 is a pointer to a KeyInfo structure */ #define P3_VDBEFUNC (-7) /* P3 is a pointer to a VdbeFunc structure */ /* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure ** is made. That copy is freed when the Vdbe is finalized. But if the ** argument is P3_KEYINFO_HANDOFF, the passed in pointer is used. It still ** gets freed when the Vdbe is finalized so it still should be obtained ** from a single sqliteMalloc(). But no copy is made and the calling ** function should *not* try to free the KeyInfo. */ #define P3_KEYINFO_HANDOFF (-7) /* ** The following macro converts a relative address in the p2 field ** of a VdbeOp structure into a negative number so that ** sqlite3VdbeAddOpList() knows that the address is relative. Calling ** the macro again restores the address. */ |
︙ | ︙ | |||
100 101 102 103 104 105 106 | Vdbe *sqlite3VdbeCreate(sqlite3*); void sqlite3VdbeCreateCallback(Vdbe*, int*); int sqlite3VdbeAddOp(Vdbe*,int,int,int); int sqlite3VdbeOp3(Vdbe*,int,int,int,const char *zP3,int); int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); | < > > | < | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | Vdbe *sqlite3VdbeCreate(sqlite3*); void sqlite3VdbeCreateCallback(Vdbe*, int*); int sqlite3VdbeAddOp(Vdbe*,int,int,int); int sqlite3VdbeOp3(Vdbe*,int,int,int,const char *zP3,int); int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); void sqlite3VdbeDequoteP3(Vdbe*, int addr); int sqlite3VdbeFindOp(Vdbe*, int, int, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeDelete(Vdbe*); void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int); int sqlite3VdbeFinalize(Vdbe*); void sqlite3VdbeResolveLabel(Vdbe*, int); int sqlite3VdbeCurrentAddr(Vdbe*); void sqlite3VdbeTrace(Vdbe*,FILE*); int sqlite3VdbeReset(Vdbe*); int sqliteVdbeSetVariables(Vdbe*,int,const char**); void sqlite3VdbeSetNumCols(Vdbe*,int); int sqlite3VdbeSetColName(Vdbe*, int, const char *, int); void sqlite3VdbeCountChanges(Vdbe*); #ifndef NDEBUG void sqlite3VdbeComment(Vdbe*, const char*, ...); # define VdbeComment(X) sqlite3VdbeComment X #else # define VdbeComment(X) #endif #endif |
Changes to SQLite.Interop/src/vdbeInt.h.
︙ | ︙ | |||
56 57 58 59 60 61 62 | ** If the Cursor.isTriggerRow flag is set it means that this cursor is ** really a single row that represents the NEW or OLD pseudo-table of ** a row trigger. The data for the row is stored in Cursor.pData and ** the rowid is in Cursor.iKey. */ struct Cursor { BtCursor *pCursor; /* The cursor structure of the backend */ | < | | > | | < | | < | < < < < < | < < > > > > > > > > > > > > > > > > > > > | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | ** If the Cursor.isTriggerRow flag is set it means that this cursor is ** really a single row that represents the NEW or OLD pseudo-table of ** a row trigger. The data for the row is stored in Cursor.pData and ** the rowid is in Cursor.iKey. */ struct Cursor { BtCursor *pCursor; /* The cursor structure of the backend */ i64 lastRecno; /* Last recno from a Next or NextIdx operation */ i64 nextRowid; /* Next rowid returned by OP_NewRowid */ Bool zeroed; /* True if zeroed out and ready for reuse */ Bool recnoIsValid; /* True if lastRecno is valid */ Bool keyAsData; /* The OP_Column command works on key instead of data */ Bool atFirst; /* True if pointing to first entry */ Bool useRandomRowid; /* Generate new record numbers semi-randomly */ Bool nullRow; /* True if pointing to a row with no data */ Bool nextRowidValid; /* True if the nextRowid field is valid */ Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */ Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ Bool intKey; /* True if the table requires integer keys */ Bool zeroData; /* True if table contains keys only - no data */ u8 bogusIncrKey; /* Something for pIncrKey to point to if pKeyInfo==0 */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ Btree *pBt; /* Separate file holding temporary table */ int nData; /* Number of bytes in pData */ char *pData; /* Data for a NEW or OLD pseudo-table */ i64 iKey; /* Key for the NEW or OLD pseudo-table row */ u8 *pIncrKey; /* Pointer to pKeyInfo->incrKey */ KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ int nField; /* Number of fields in the header */ /* Cached information about the header for the data record that the ** cursor is currently pointing to. Only valid if cacheValid is true. ** zRow might point to (ephemeral) data for the current row, or it might ** be NULL. */ Bool cacheValid; /* True if the cache is valid */ int payloadSize; /* Total number of bytes in the record */ u32 *aType; /* Type values for all entries in the record */ u32 *aOffset; /* Cached offsets to the start of each columns data */ u8 *aRow; /* Data for the current row, if all on one page */ }; typedef struct Cursor Cursor; /* ** Number of bytes of string storage space available to each stack ** layer without having to malloc. NBFS is short for Number of Bytes ** For Strings. */ #define NBFS 32 /* ** Internally, the vdbe manipulates nearly all SQL values as Mem ** structures. Each Mem struct may cache multiple representations (string, ** integer etc.) of the same value. A value (and therefore Mem structure) ** has the following properties: ** ** Each value has a manifest type. The manifest type of the value stored ** in a Mem struct is returned by the MemType(Mem*) macro. The type is ** one of SQLITE_NULL, SQLITE_INTEGER, SQLITE_REAL, SQLITE_TEXT or ** SQLITE_BLOB. */ struct Mem { i64 i; /* Integer value */ int n; /* Number of characters in string value, including '\0' */ u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ u8 type; /* One of MEM_Null, MEM_Str, etc. */ u8 enc; /* TEXT_Utf8, TEXT_Utf16le, or TEXT_Utf16be */ double r; /* Real value */ char *z; /* String or BLOB value */ void (*xDel)(void *); /* If not null, call this function to delete Mem.z */ char zShort[NBFS]; /* Space for short strings */ }; typedef struct Mem Mem; /* ** A sorter builds a list of elements to be sorted. Each element of ** the list is an instance of the following structure. */ typedef struct Sorter Sorter; struct Sorter { int nKey; /* Number of bytes in the key */ char *zKey; /* The key by which we will sort */ Mem data; Sorter *pNext; /* Next in the list */ }; /* ** Number of buckets used for merge-sort. */ #define NSORT 30 /* One or more of the following flags are set to indicate the validOK ** representations of the value stored in the Mem struct. ** ** If the MEM_Null flag is set, then the value is an SQL NULL value. ** No other flags may be set in this case. ** ** If the MEM_Str flag is set then Mem.z points at a string representation. |
︙ | ︙ | |||
160 161 162 163 164 165 166 | ** string is \000 or \u0000 terminated */ #define MEM_Term 0x0020 /* String rep is nul terminated */ #define MEM_Dyn 0x0040 /* Need to call sqliteFree() on Mem.z */ #define MEM_Static 0x0080 /* Mem.z points to a static string */ #define MEM_Ephem 0x0100 /* Mem.z points to an ephemeral string */ #define MEM_Short 0x0200 /* Mem.z points to Mem.zShort */ | > > > > > | | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | ** string is \000 or \u0000 terminated */ #define MEM_Term 0x0020 /* String rep is nul terminated */ #define MEM_Dyn 0x0040 /* Need to call sqliteFree() on Mem.z */ #define MEM_Static 0x0080 /* Mem.z points to a static string */ #define MEM_Ephem 0x0100 /* Mem.z points to an ephemeral string */ #define MEM_Short 0x0200 /* Mem.z points to Mem.zShort */ /* The following MEM_ value appears only in AggElem.aMem.s.flag fields. ** It indicates that the corresponding AggElem.aMem.z points to a ** aggregate function context that needs to be finalized. */ #define MEM_AggCtx 0x0400 /* Mem.z points to an agg function context */ /* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains ** additional information about auxiliary information bound to arguments ** of the function. This is used to implement the sqlite3_get_auxdata() ** and sqlite3_set_auxdata() APIs. The "auxdata" is some auxiliary data ** that can be associated with a constant argument to a function. This |
︙ | ︙ | |||
192 193 194 195 196 197 198 | ** implement the SQL functions. ** ** There is a typedef for this structure in sqlite.h. So all routines, ** even the public interface to SQLite, can use a pointer to this structure. ** But this file is the only place where the internal details of this ** structure are known. ** | | | | | | > | > > > > > > > > > > > > > > > > > > > > > > > > | | > | | | | | | | < < < < < < < < < < < < < | | | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | ** implement the SQL functions. ** ** There is a typedef for this structure in sqlite.h. So all routines, ** even the public interface to SQLite, can use a pointer to this structure. ** But this file is the only place where the internal details of this ** structure are known. ** ** This structure is defined inside of vdbe.c because it uses substructures ** (Mem) which are only defined there. */ struct sqlite3_context { FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */ VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */ Mem s; /* The return value is stored here */ void *pAgg; /* Aggregate context */ u8 isError; /* Set to true for an error */ int cnt; /* Number of times that the step function has been called */ CollSeq *pColl; }; /* ** An Agg structure describes an Aggregator. Each Agg consists of ** zero or more Aggregator elements (AggElem). Each AggElem contains ** a key and one or more values. The values are used in processing ** aggregate functions in a SELECT. The key is used to implement ** the GROUP BY clause of a select. */ typedef struct Agg Agg; typedef struct AggElem AggElem; struct Agg { int nMem; /* Number of values stored in each AggElem */ AggElem *pCurrent; /* The AggElem currently in focus */ FuncDef **apFunc; /* Information about aggregate functions */ Btree *pBtree; /* The tmp. btree used to group elements, if required. */ BtCursor *pCsr; /* Read/write cursor to the table in pBtree */ int nTab; /* Root page of the table in pBtree */ u8 searching; /* True between the first AggNext and AggReset */ }; struct AggElem { char *zKey; /* The key to this AggElem */ int nKey; /* Number of bytes in the key, including '\0' at end */ Mem aMem[1]; /* The values for this AggElem */ }; /* ** A Set structure is used for quick testing to see if a value ** is part of a small set. Sets are used to implement code like ** this: ** x.y IN ('hi','hoo','hum') */ typedef struct Set Set; struct Set { Hash hash; /* A set is just a hash table */ HashElem *prev; /* Previously accessed hash elemen */ }; /* ** A Keylist is a bunch of keys into a table. The keylist can ** grow without bound. The keylist stores the ROWIDs of database ** records that need to be deleted or updated. */ typedef struct Keylist Keylist; struct Keylist { int nKey; /* Number of slots in aKey[] */ int nUsed; /* Next unwritten slot in aKey[] */ int nRead; /* Next unread slot in aKey[] */ Keylist *pNext; /* Next block of keys */ i64 aKey[1]; /* One or more keys. Extra space allocated as needed */ }; /* ** A Context stores the last insert rowid, the last statement change count, ** and the current statement change count (i.e. changes since last statement). ** The current keylist is also stored in the context. ** Elements of Context structure type make up the ContextStack, which is ** updated by the ContextPush and ContextPop opcodes (used by triggers). ** The context is pushed before executing a trigger a popped when the ** trigger finishes. */ typedef struct Context Context; struct Context { int lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ int nChange; /* Statement changes (Vdbe.nChanges) */ Keylist *pList; /* Records that will participate in a DELETE or UPDATE */ }; /* ** An instance of the virtual machine. This structure contains the complete ** state of the virtual machine. ** ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_compile() |
︙ | ︙ | |||
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | int *aLabel; /* Space to hold the labels */ Mem *aStack; /* The operand stack, except string values */ Mem *pTos; /* Top entry in the operand stack */ Mem **apArg; /* Arguments to currently executing user function */ Mem *aColName; /* Column names to return */ int nCursor; /* Number of slots in apCsr[] */ Cursor **apCsr; /* One element of this array for each open cursor */ int nVar; /* Number of entries in aVar[] */ Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ int okVar; /* True if azVar[] has been initialized */ int magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ int nCallback; /* Number of callbacks invoked so far */ | > > > > < | < < > > > | | | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 | int *aLabel; /* Space to hold the labels */ Mem *aStack; /* The operand stack, except string values */ Mem *pTos; /* Top entry in the operand stack */ Mem **apArg; /* Arguments to currently executing user function */ Mem *aColName; /* Column names to return */ int nCursor; /* Number of slots in apCsr[] */ Cursor **apCsr; /* One element of this array for each open cursor */ Sorter *pSort; /* A linked list of objects to be sorted */ int nVar; /* Number of entries in aVar[] */ Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ int okVar; /* True if azVar[] has been initialized */ int magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ int nAgg; /* Number of elements in apAgg */ Agg *apAgg; /* Array of aggregate contexts */ Agg *pAgg; /* Current aggregate context */ int nCallback; /* Number of callbacks invoked so far */ Keylist *pList; /* A list of ROWIDs */ int contextStackTop; /* Index of top element in the context stack */ int contextStackDepth; /* The size of the "context" stack */ Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/ int pc; /* The program counter */ int rc; /* Value to return */ unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */ int errorAction; /* Recovery action to do in case of an error */ int inTempTrans; /* True if temp database is transactioned */ int returnStack[100]; /* Return address stack for OP_Gosub & OP_Return */ int returnDepth; /* Next unused element in returnStack[] */ int nResColumn; /* Number of columns in one row of the result set */ char **azResColumn; /* Values for one row of result */ int popStack; /* Pop the stack this much on entry to VdbeExec() */ char *zErrMsg; /* Error message written here */ u8 resOnStack; /* True if there are result values on the stack */ u8 explain; /* True if EXPLAIN present on SQL command */ u8 changeCntOn; /* True to update the change-counter */ u8 aborted; /* True if ROLLBACK in another VM causes an abort */ u8 expired; /* True if the VM needs to be recompiled */ int nChange; /* Number of db changes made since last reset */ }; /* ** The following are allowed values for Vdbe.magic */ #define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ #define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ #define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */ #define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ /* ** Function prototypes */ void sqlite3VdbeFreeCursor(Cursor*); void sqlite3VdbeSorterReset(Vdbe*); int sqlite3VdbeAggReset(sqlite3*, Agg *, KeyInfo *); void sqlite3VdbeKeylistFree(Keylist*); void sqliteVdbePopStack(Vdbe*,int); int sqlite3VdbeCursorMoveto(Cursor*); #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) void sqlite3VdbePrintOp(FILE*, int, Op*); #endif #ifdef SQLITE_DEBUG void sqlite3VdbePrintSql(Vdbe*); #endif int sqlite3VdbeSerialTypeLen(u32); u32 sqlite3VdbeSerialType(Mem*); int sqlite3VdbeSerialPut(unsigned char*, Mem*); int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); void sqlite3VdbeDeleteAuxData(VdbeFunc*, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*); int sqlite3VdbeIdxRowid(BtCursor *, i64 *); int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); |
︙ | ︙ | |||
365 366 367 368 369 370 371 | void sqlite3VdbeMemSetNull(Mem*); int sqlite3VdbeMemMakeWriteable(Mem*); int sqlite3VdbeMemDynamicify(Mem*); int sqlite3VdbeMemStringify(Mem*, int); i64 sqlite3VdbeIntValue(Mem*); int sqlite3VdbeMemIntegerify(Mem*); double sqlite3VdbeRealValue(Mem*); | < < < < < < < < | 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 | void sqlite3VdbeMemSetNull(Mem*); int sqlite3VdbeMemMakeWriteable(Mem*); int sqlite3VdbeMemDynamicify(Mem*); int sqlite3VdbeMemStringify(Mem*, int); i64 sqlite3VdbeIntValue(Mem*); int sqlite3VdbeMemIntegerify(Mem*); double sqlite3VdbeRealValue(Mem*); int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*); void sqlite3VdbeMemRelease(Mem *p); #ifndef NDEBUG void sqlite3VdbeMemSanity(Mem*, u8); #endif int sqlite3VdbeMemTranslate(Mem*, u8); void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf); int sqlite3VdbeMemHandleBom(Mem *pMem); |
Changes to SQLite.Interop/src/vdbeapi.c.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** ** This file contains code use to implement APIs that are part of the ** VDBE. */ #include "sqliteInt.h" #include "vdbeInt.h" | < > > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | ************************************************************************* ** ** This file contains code use to implement APIs that are part of the ** VDBE. */ #include "sqliteInt.h" #include "vdbeInt.h" /* ** Return TRUE (non-zero) of the statement supplied as an argument needs ** to be recompiled. A statement needs to be recompiled whenever the ** execution environment changes in a way that would alter the program ** that sqlite3_prepare() generates. For example, if new functions or ** collating sequences are registered or if an authorizer function is ** added or changed. ** ***** EXPERIMENTAL ****** */ int sqlite3_expired(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; return p==0 || p->expired; } /**************************** sqlite3_value_ ******************************* |
︙ | ︙ | |||
54 55 56 57 58 59 60 | int sqlite3_value_int(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal); } sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal); } const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ | | | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | int sqlite3_value_int(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal); } sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal); } const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ return (const char *)sqlite3ValueText(pVal, SQLITE_UTF8); } #ifndef SQLITE_OMIT_UTF16 const void *sqlite3_value_text16(sqlite3_value* pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); } const void *sqlite3_value_text16be(sqlite3_value *pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16BE); |
︙ | ︙ | |||
81 82 83 84 85 86 87 | */ void sqlite3_result_blob( sqlite3_context *pCtx, const void *z, int n, void (*xDel)(void *) ){ | | | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | */ void sqlite3_result_blob( sqlite3_context *pCtx, const void *z, int n, void (*xDel)(void *) ){ assert( n>0 ); sqlite3VdbeMemSetStr(&pCtx->s, z, n, 0, xDel); } void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ sqlite3VdbeMemSetDouble(&pCtx->s, rVal); } void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ pCtx->isError = 1; |
︙ | ︙ | |||
152 153 154 155 156 157 158 | ** statement is completely executed or an error occurs. */ int sqlite3_step(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; sqlite3 *db; int rc; | < < < < | < < < < < < | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | ** statement is completely executed or an error occurs. */ int sqlite3_step(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; sqlite3 *db; int rc; if( p==0 || p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_MISUSE; } if( p->aborted ){ return SQLITE_ABORT; } if( p->pc<=0 && p->expired ){ if( p->rc==SQLITE_OK ){ p->rc = SQLITE_SCHEMA; } return SQLITE_ERROR; } db = p->db; if( sqlite3SafetyOn(db) ){ p->rc = SQLITE_MISUSE; return SQLITE_MISUSE; } if( p->pc<0 ){ /* Invoke the trace callback if there is one */ if( (db = p->db)->xTrace && !db->init.busy ){ assert( p->nOp>0 ); assert( p->aOp[p->nOp-1].opcode==OP_Noop ); assert( p->aOp[p->nOp-1].p3!=0 ); assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC ); sqlite3SafetyOff(db); db->xTrace(db->pTraceArg, p->aOp[p->nOp-1].p3); if( sqlite3SafetyOn(db) ){ p->rc = SQLITE_MISUSE; return SQLITE_MISUSE; } } /* Print a copy of SQL as it is executed if the SQL_TRACE pragma is turned ** on in debugging mode. */ #ifdef SQLITE_DEBUG if( (db->flags & SQLITE_SqlTrace)!=0 ){ sqlite3DebugPrintf("SQL-trace: %s\n", p->aOp[p->nOp-1].p3); |
︙ | ︙ | |||
220 221 222 223 224 225 226 | rc = sqlite3VdbeExec(p); } if( sqlite3SafetyOff(db) ){ rc = SQLITE_MISUSE; } | < < < < < < < < < < < < < < < < < | < > > > > < < | < < < < < < | | | | | | | < | | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | rc = sqlite3VdbeExec(p); } if( sqlite3SafetyOff(db) ){ rc = SQLITE_MISUSE; } sqlite3Error(p->db, rc, p->zErrMsg); return rc; } /* ** Extract the user data from a sqlite3_context structure and return a ** pointer to it. */ void *sqlite3_user_data(sqlite3_context *p){ assert( p && p->pFunc ); return p->pFunc->pUserData; } /* ** Allocate or return the aggregate context for a user function. A new ** context is allocated on the first call. Subsequent calls return the ** same context that was returned on prior calls. ** ** This routine is defined here in vdbe.c because it depends on knowing ** the internals of the sqlite3_context structure which is only defined in ** this source file. */ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ assert( p && p->pFunc && p->pFunc->xStep ); if( p->pAgg==0 ){ if( nByte<=NBFS ){ p->pAgg = (void*)p->s.z; memset(p->pAgg, 0, nByte); }else{ p->pAgg = sqliteMalloc( nByte ); } } return p->pAgg; } /* ** Return the auxilary data pointer, if any, for the iArg'th argument to ** the user-function defined by pCtx. */ void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ |
︙ | ︙ | |||
308 309 310 311 312 313 314 | struct AuxData *pAuxData; VdbeFunc *pVdbeFunc; if( iArg<0 ) return; pVdbeFunc = pCtx->pVdbeFunc; if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){ int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg; | | < | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | struct AuxData *pAuxData; VdbeFunc *pVdbeFunc; if( iArg<0 ) return; pVdbeFunc = pCtx->pVdbeFunc; if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){ int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg; pCtx->pVdbeFunc = pVdbeFunc = sqliteRealloc(pVdbeFunc, nMalloc); if( !pVdbeFunc ) return; memset(&pVdbeFunc->apAux[pVdbeFunc->nAux], 0, sizeof(struct AuxData)*(iArg+1-pVdbeFunc->nAux)); pVdbeFunc->nAux = iArg+1; pVdbeFunc->pFunc = pCtx->pFunc; } pAuxData = &pVdbeFunc->apAux[iArg]; |
︙ | ︙ | |||
335 336 337 338 339 340 341 | ** ** This routine is defined here in vdbe.c because it depends on knowing ** the internals of the sqlite3_context structure which is only defined in ** this source file. */ int sqlite3_aggregate_count(sqlite3_context *p){ assert( p && p->pFunc && p->pFunc->xStep ); | | | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | ** ** This routine is defined here in vdbe.c because it depends on knowing ** the internals of the sqlite3_context structure which is only defined in ** this source file. */ int sqlite3_aggregate_count(sqlite3_context *p){ assert( p && p->pFunc && p->pFunc->xStep ); return p->cnt; } /* ** Return the number of columns in the result set for the statement pStmt. */ int sqlite3_column_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; |
︙ | ︙ | |||
375 376 377 378 379 380 381 | if( nullMem.flags==0 ){ nullMem.flags = MEM_Null; } sqlite3Error(pVm->db, SQLITE_RANGE, 0); return &nullMem; } return &pVm->pTos[(1-vals)+i]; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < | < < | < < | < < | < < | < < | < < < < < < < | < < < | | < < < < < < < < < < | > > | | < < < < < | < < < < < | < < < | < < < < < < < < < < < < < < < < | < < > < < < < | | < | | < < < < < | | < < < < | | 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 | if( nullMem.flags==0 ){ nullMem.flags = MEM_Null; } sqlite3Error(pVm->db, SQLITE_RANGE, 0); return &nullMem; } return &pVm->pTos[(1-vals)+i]; } /**************************** sqlite3_column_ ******************************* ** The following routines are used to access elements of the current row ** in the result set. */ const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ return sqlite3_value_blob( columnMem(pStmt,i) ); } int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ return sqlite3_value_bytes( columnMem(pStmt,i) ); } int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ return sqlite3_value_bytes16( columnMem(pStmt,i) ); } double sqlite3_column_double(sqlite3_stmt *pStmt, int i){ return sqlite3_value_double( columnMem(pStmt,i) ); } int sqlite3_column_int(sqlite3_stmt *pStmt, int i){ return sqlite3_value_int( columnMem(pStmt,i) ); } sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ return sqlite3_value_int64( columnMem(pStmt,i) ); } const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){ return sqlite3_value_text( columnMem(pStmt,i) ); } #ifndef SQLITE_OMIT_UTF16 const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ return sqlite3_value_text16( columnMem(pStmt,i) ); } #endif /* SQLITE_OMIT_UTF16 */ int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ return sqlite3_value_type( columnMem(pStmt,i) ); } /* ** Convert the N-th element of pStmt->pColName[] into a string using ** xFunc() then return that string. If N is out of range, return 0. ** If useType is 1, then use the second set of N elements (the datatype ** names) instead of the first set. */ static const void *columnName( sqlite3_stmt *pStmt, int N, const void *(*xFunc)(Mem*), int useType ){ Vdbe *p = (Vdbe *)pStmt; int n = sqlite3_column_count(pStmt); if( p==0 || N>=n || N<0 ){ return 0; } if( useType ){ N += n; } return xFunc(&p->aColName[N]); } /* ** Return the name of the Nth column of the result set returned by SQL ** statement pStmt. */ const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 0); } /* ** Return the column declaration type (if applicable) of the 'i'th column ** of the result set of SQL statement pStmt, encoded as UTF-8. */ const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 1); } #ifndef SQLITE_OMIT_UTF16 /* ** Return the name of the 'i'th column of the result set of SQL statement ** pStmt, encoded as UTF-16. */ const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 0); } /* ** Return the column declaration type (if applicable) of the 'i'th column ** of the result set of SQL statement pStmt, encoded as UTF-16. */ const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 1); } #endif /* SQLITE_OMIT_UTF16 */ /******************************* sqlite3_bind_ *************************** ** ** Routines used to attach values to wildcards in a compiled SQL statement. */ /* ** Unbind the value bound to variable i in virtual machine p. This is the ** the same as binding a NULL value to the column. If the "i" parameter is ** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK. ** ** The error code stored in database p->db is overwritten with the return ** value in any case. */ static int vdbeUnbind(Vdbe *p, int i){ Mem *pVar; if( p==0 || p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ sqlite3Error(p->db, SQLITE_MISUSE, 0); return SQLITE_MISUSE; } if( i<1 || i>p->nVar ){ sqlite3Error(p->db, SQLITE_RANGE, 0); return SQLITE_RANGE; } i--; |
︙ | ︙ | |||
631 632 633 634 635 636 637 | } pVar = &p->aVar[i-1]; rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); if( rc ){ return rc; } if( rc==SQLITE_OK && encoding!=0 ){ | | | 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 | } pVar = &p->aVar[i-1]; rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); if( rc ){ return rc; } if( rc==SQLITE_OK && encoding!=0 ){ rc = sqlite3VdbeChangeEncoding(pVar, p->db->enc); } return rc; } /* ** Bind a blob value to an SQL statement variable. |
︙ | ︙ | |||
759 760 761 762 763 764 765 | if( z && strcmp(z,zName)==0 ){ return i+1; } } } return 0; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 618 619 620 621 622 623 624 | if( z && strcmp(z,zName)==0 ){ return i+1; } } } return 0; } |
Changes to SQLite.Interop/src/vdbeaux.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | /* ** When debugging the code generator in a symbolic debugger, one can ** set the sqlite3_vdbe_addop_trace to 1 and all opcodes will be printed ** as they are added to the instruction stream. */ | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | /* ** When debugging the code generator in a symbolic debugger, one can ** set the sqlite3_vdbe_addop_trace to 1 and all opcodes will be printed ** as they are added to the instruction stream. */ #ifndef NDEBUG int sqlite3_vdbe_addop_trace = 0; #endif /* ** Create a new virtual database engine. */ |
︙ | ︙ | |||
53 54 55 56 57 58 59 | */ void sqlite3VdbeTrace(Vdbe *p, FILE *trace){ p->trace = trace; } /* ** Resize the Vdbe.aOp array so that it contains at least N | < < < | < < < < | | | | < | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | */ void sqlite3VdbeTrace(Vdbe *p, FILE *trace){ p->trace = trace; } /* ** Resize the Vdbe.aOp array so that it contains at least N ** elements. */ static void resizeOpArray(Vdbe *p, int N){ if( p->nOpAlloc<N ){ int oldSize = p->nOpAlloc; p->nOpAlloc = N+100; p->aOp = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op)); if( p->aOp ){ memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op)); } } } /* ** Add a new instruction to the list of instructions current in the ** VDBE. Return the address of the new instruction. |
︙ | ︙ | |||
98 99 100 101 102 103 104 | int i; VdbeOp *pOp; i = p->nOp; p->nOp++; assert( p->magic==VDBE_MAGIC_INIT ); resizeOpArray(p, i+1); | | < | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | int i; VdbeOp *pOp; i = p->nOp; p->nOp++; assert( p->magic==VDBE_MAGIC_INIT ); resizeOpArray(p, i+1); if( p->aOp==0 ){ return 0; } pOp = &p->aOp[i]; pOp->opcode = op; pOp->p1 = p1; pOp->p2 = p2; pOp->p3 = 0; pOp->p3type = P3_NOTUSED; #ifdef SQLITE_DEBUG if( sqlite3_vdbe_addop_trace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]); #endif return i; } /* |
︙ | ︙ | |||
143 144 145 146 147 148 149 | */ int sqlite3VdbeMakeLabel(Vdbe *p){ int i; i = p->nLabel++; assert( p->magic==VDBE_MAGIC_INIT ); if( i>=p->nLabelAlloc ){ p->nLabelAlloc = p->nLabelAlloc*2 + 10; | < | | 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | */ int sqlite3VdbeMakeLabel(Vdbe *p){ int i; i = p->nLabel++; assert( p->magic==VDBE_MAGIC_INIT ); if( i>=p->nLabelAlloc ){ p->nLabelAlloc = p->nLabelAlloc*2 + 10; p->aLabel = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0])); } if( p->aLabel ){ p->aLabel[i] = -1; } return -1-i; } |
︙ | ︙ | |||
166 167 168 169 170 171 172 173 | assert( p->magic==VDBE_MAGIC_INIT ); assert( j>=0 && j<p->nLabel ); if( p->aLabel ){ p->aLabel[j] = p->nOp; } } /* | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | assert( p->magic==VDBE_MAGIC_INIT ); assert( j>=0 && j<p->nLabel ); if( p->aLabel ){ p->aLabel[j] = p->nOp; } } /* ** Loop through the program looking for P2 values that are negative. ** Each such value is a label. Resolve the label by setting the P2 ** value to its correct non-zero value. ** ** This routine is called once after all opcodes have been inserted. */ static void resolveP2Values(Vdbe *p){ int i; Op *pOp; int *aLabel = p->aLabel; if( aLabel==0 ) return; for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ if( pOp->p2>=0 ) continue; assert( -1-pOp->p2<p->nLabel ); pOp->p2 = aLabel[-1-pOp->p2]; } sqliteFree(p->aLabel); p->aLabel = 0; } /* ** Return the address of the next instruction to be inserted. */ int sqlite3VdbeCurrentAddr(Vdbe *p){ assert( p->magic==VDBE_MAGIC_INIT ); return p->nOp; } /* ** Add a whole list of operations to the operation stack. Return the ** address of the first operation added. */ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){ int addr; assert( p->magic==VDBE_MAGIC_INIT ); resizeOpArray(p, p->nOp + nOp); if( p->aOp==0 ){ return 0; } addr = p->nOp; if( nOp>0 ){ int i; VdbeOpList const *pIn = aOp; for(i=0; i<nOp; i++, pIn++){ |
︙ | ︙ | |||
347 348 349 350 351 352 353 | void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){ assert( val>=0 ); assert( p->magic==VDBE_MAGIC_INIT ); if( p && addr>=0 && p->nOp>addr && p->aOp ){ p->aOp[addr].p2 = val; } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | > | | < < < < < < | < < < < < > | | > < | < < < < < < | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){ assert( val>=0 ); assert( p->magic==VDBE_MAGIC_INIT ); if( p && addr>=0 && p->nOp>addr && p->aOp ){ p->aOp[addr].p2 = val; } } /* ** Change the value of the P3 operand for a specific instruction. ** This routine is useful when a large program is loaded from a ** static array using sqlite3VdbeAddOpList but we want to make a ** few minor changes to the program. ** ** If n>=0 then the P3 operand is dynamic, meaning that a copy of ** the string is made into memory obtained from sqliteMalloc(). ** A value of n==0 means copy bytes of zP3 up to and including the ** first null byte. If n>0 then copy n+1 bytes of zP3. ** ** If n==P3_STATIC it means that zP3 is a pointer to a constant static ** string and we can just copy the pointer. n==P3_POINTER means zP3 is ** a pointer to some object other than a string. n==P3_COLLSEQ and ** n==P3_KEYINFO mean that zP3 is a pointer to a CollSeq or KeyInfo ** structure. A copy is made of KeyInfo structures into memory obtained ** from sqliteMalloc. ** ** If addr<0 then change P3 on the most recently inserted instruction. */ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){ Op *pOp; assert( p->magic==VDBE_MAGIC_INIT ); if( p==0 || p->aOp==0 ) return; if( addr<0 || addr>=p->nOp ){ addr = p->nOp - 1; if( addr<0 ) return; } pOp = &p->aOp[addr]; if( pOp->p3 && pOp->p3type==P3_DYNAMIC ){ sqliteFree(pOp->p3); pOp->p3 = 0; } if( zP3==0 ){ pOp->p3 = 0; pOp->p3type = P3_NOTUSED; }else if( n==P3_KEYINFO ){ KeyInfo *pKeyInfo; int nField, nByte; nField = ((KeyInfo*)zP3)->nField; nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]); pKeyInfo = sqliteMallocRaw( nByte ); pOp->p3 = (char*)pKeyInfo; if( pKeyInfo ){ memcpy(pKeyInfo, zP3, nByte); pOp->p3type = P3_KEYINFO; }else{ pOp->p3type = P3_NOTUSED; } }else if( n==P3_KEYINFO_HANDOFF ){ pOp->p3 = (char*)zP3; pOp->p3type = P3_KEYINFO; |
︙ | ︙ | |||
468 469 470 471 472 473 474 | /* ** Replace the P3 field of the most recently coded instruction with ** comment text. */ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ va_list ap; assert( p->nOp>0 ); | | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 | /* ** Replace the P3 field of the most recently coded instruction with ** comment text. */ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ va_list ap; assert( p->nOp>0 ); assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0 ); va_start(ap, zFormat); sqlite3VdbeChangeP3(p, -1, sqlite3VMPrintf(zFormat, ap), P3_DYNAMIC); va_end(ap); } #endif /* ** If the P3 operand to the specified instruction appears ** to be a quoted string token, then this procedure removes ** the quotes. ** ** The quoting operator can be either a grave ascent (ASCII 0x27) ** or a double quote character (ASCII 0x22). Two quotes in a row ** resolve to be a single actual quote character within the string. */ void sqlite3VdbeDequoteP3(Vdbe *p, int addr){ Op *pOp; assert( p->magic==VDBE_MAGIC_INIT ); if( p->aOp==0 ) return; if( addr<0 || addr>=p->nOp ){ addr = p->nOp - 1; if( addr<0 ) return; } pOp = &p->aOp[addr]; if( pOp->p3==0 || pOp->p3[0]==0 ) return; if( pOp->p3type==P3_STATIC ){ pOp->p3 = sqliteStrDup(pOp->p3); pOp->p3type = P3_DYNAMIC; } assert( pOp->p3type==P3_DYNAMIC ); sqlite3Dequote(pOp->p3); } /* ** Search the current program starting at instruction addr for the given ** opcode and P2 value. Return the address plus 1 if found and 0 if not ** found. */ int sqlite3VdbeFindOp(Vdbe *p, int addr, int op, int p2){ int i; assert( p->magic==VDBE_MAGIC_INIT ); for(i=addr; i<p->nOp; i++){ if( p->aOp[i].opcode==op && p->aOp[i].p2==p2 ) return i+1; } return 0; } /* ** Return the opcode for a given address. */ VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ assert( p->magic==VDBE_MAGIC_INIT ); assert( addr>=0 && addr<p->nOp ); return &p->aOp[addr]; } #if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \ || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) /* ** Compute a string that describes the P3 parameter for an opcode. ** Use zTemp for any required temporary buffer space. */ static char *displayP3(Op *pOp, char *zTemp, int nTemp){ char *zP3; assert( nTemp>=20 ); switch( pOp->p3type ){ case P3_POINTER: { sprintf(zTemp, "ptr(%#x)", (int)pOp->p3); zP3 = zTemp; break; } case P3_KEYINFO: { int i, j; KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3; sprintf(zTemp, "keyinfo(%d", pKeyInfo->nField); i = strlen(zTemp); for(j=0; j<pKeyInfo->nField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; |
︙ | ︙ | |||
610 611 612 613 614 615 616 | ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. */ if( p->pTos==&p->aStack[4] ){ releaseMemArray(p->aStack, 5); } p->resOnStack = 0; | | | < | 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 | ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. */ if( p->pTos==&p->aStack[4] ){ releaseMemArray(p->aStack, 5); } p->resOnStack = 0; i = p->pc++; if( i>=p->nOp ){ p->rc = SQLITE_OK; rc = SQLITE_DONE; }else if( db->flags & SQLITE_Interrupt ){ db->flags &= ~SQLITE_Interrupt; p->rc = SQLITE_INTERRUPT; rc = SQLITE_ERROR; |
︙ | ︙ | |||
651 652 653 654 655 656 657 | pMem++; pMem->flags = MEM_Short|MEM_Str|MEM_Term; /* P3 */ pMem->z = displayP3(pOp, pMem->zShort, sizeof(pMem->zShort)); pMem->type = SQLITE_TEXT; pMem->enc = SQLITE_UTF8; | | | 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 | pMem++; pMem->flags = MEM_Short|MEM_Str|MEM_Term; /* P3 */ pMem->z = displayP3(pOp, pMem->zShort, sizeof(pMem->zShort)); pMem->type = SQLITE_TEXT; pMem->enc = SQLITE_UTF8; p->nResColumn = 5; p->pTos = pMem; p->rc = SQLITE_OK; p->resOnStack = 1; rc = SQLITE_ROW; } return rc; } |
︙ | ︙ | |||
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 | ** VDBE_MAGIC_RUN. */ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ int nMem, /* Number of memory cells to allocate */ int nCursor, /* Number of cursors to allocate */ int isExplain /* True if the EXPLAIN keywords is present */ ){ int n; assert( p!=0 ); assert( p->magic==VDBE_MAGIC_INIT ); /* There should be at least one opcode. */ assert( p->nOp>0 ); | > < < < < < < < | < < < < | < < | | | > | | | > > > > > | 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 | ** VDBE_MAGIC_RUN. */ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ int nMem, /* Number of memory cells to allocate */ int nCursor, /* Number of cursors to allocate */ int nAgg, /* Number of aggregate contexts required */ int isExplain /* True if the EXPLAIN keywords is present */ ){ int n; assert( p!=0 ); assert( p->magic==VDBE_MAGIC_INIT ); /* There should be at least one opcode. */ assert( p->nOp>0 ); /* No instruction ever pushes more than a single element onto the ** stack. And the stack never grows on successive executions of the ** same loop. So the total number of instructions is an upper bound ** on the maximum stack depth required. ** ** Allocation all the stack space we will ever need. */ if( p->aStack==0 ){ resolveP2Values(p); assert( nVar>=0 ); n = isExplain ? 10 : p->nOp; p->aStack = sqliteMalloc( n*sizeof(p->aStack[0]) /* aStack */ + n*sizeof(Mem*) /* apArg */ + nVar*sizeof(Mem) /* aVar */ + nVar*sizeof(char*) /* azVar */ + nMem*sizeof(Mem) /* aMem */ + nCursor*sizeof(Cursor*) /* apCsr */ + nAgg*sizeof(Agg) /* Aggregate contexts */ ); if( !sqlite3_malloc_failed ){ p->aMem = &p->aStack[n]; p->nMem = nMem; p->aVar = &p->aMem[nMem]; p->nVar = nVar; p->okVar = 0; p->apArg = (Mem**)&p->aVar[nVar]; p->azVar = (char**)&p->apArg[n]; p->apCsr = (Cursor**)&p->azVar[nVar]; if( nAgg>0 ){ p->nAgg = nAgg; p->apAgg = (Agg*)&p->apCsr[nCursor]; } p->nCursor = nCursor; for(n=0; n<nVar; n++){ p->aVar[n].flags = MEM_Null; } } } p->pAgg = p->apAgg; for(n=0; n<p->nMem; n++){ p->aMem[n].flags = MEM_Null; } #ifdef SQLITE_DEBUG if( (p->db->flags & SQLITE_VdbeListing)!=0 || sqlite3OsFileExists("vdbe_explain") |
︙ | ︙ | |||
779 780 781 782 783 784 785 | p->uniqueCnt = 0; p->returnDepth = 0; p->errorAction = OE_Abort; p->popStack = 0; p->explain |= isExplain; p->magic = VDBE_MAGIC_RUN; p->nChange = 0; | < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 | p->uniqueCnt = 0; p->returnDepth = 0; p->errorAction = OE_Abort; p->popStack = 0; p->explain |= isExplain; p->magic = VDBE_MAGIC_RUN; p->nChange = 0; #ifdef VDBE_PROFILE { int i; for(i=0; i<p->nOp; i++){ p->aOp[i].cnt = 0; p->aOp[i].cycles = 0; } } #endif } /* ** Remove any elements that remain on the sorter for the VDBE given. */ void sqlite3VdbeSorterReset(Vdbe *p){ while( p->pSort ){ Sorter *pSorter = p->pSort; p->pSort = pSorter->pNext; sqliteFree(pSorter->zKey); sqlite3VdbeMemRelease(&pSorter->data); sqliteFree(pSorter); } } /* ** Free all resources allociated with AggElem pElem, an element of ** aggregate pAgg. */ static void freeAggElem(AggElem *pElem, Agg *pAgg){ int i; for(i=0; i<pAgg->nMem; i++){ Mem *pMem = &pElem->aMem[i]; if( pAgg->apFunc && pAgg->apFunc[i] && (pMem->flags & MEM_AggCtx)!=0 ){ sqlite3_context ctx; ctx.pFunc = pAgg->apFunc[i]; ctx.s.flags = MEM_Null; ctx.pAgg = pMem->z; ctx.cnt = pMem->i; ctx.isError = 0; (*ctx.pFunc->xFinalize)(&ctx); pMem->z = ctx.pAgg; if( pMem->z!=0 && pMem->z!=pMem->zShort ){ sqliteFree(pMem->z); } sqlite3VdbeMemRelease(&ctx.s); }else{ sqlite3VdbeMemRelease(pMem); } } sqliteFree(pElem); } /* ** Reset an Agg structure. Delete all its contents. ** ** For installable aggregate functions, if the step function has been ** called, make sure the finalizer function has also been called. The ** finalizer might need to free memory that was allocated as part of its ** private context. If the finalizer has not been called yet, call it ** now. ** ** If db is NULL, then this is being called from sqliteVdbeReset(). In ** this case clean up all references to the temp-table used for ** aggregates (if it was ever opened). ** ** If db is not NULL, then this is being called from with an OP_AggReset ** opcode. Open the temp-table, if it has not already been opened and ** delete the contents of the table used for aggregate information, ready ** for the next round of aggregate processing. */ int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){ int rc = 0; BtCursor *pCsr; if( !pAgg ) return SQLITE_OK; pCsr = pAgg->pCsr; assert( (pCsr && pAgg->nTab>0) || (!pCsr && pAgg->nTab==0) || sqlite3_malloc_failed ); /* If pCsr is not NULL, then the table used for aggregate information ** is open. Loop through it and free the AggElem* structure pointed at ** by each entry. If the finalizer has not been called for an AggElem, ** do that too. Finally, clear the btree table itself. */ if( pCsr ){ int res; assert( pAgg->pBtree ); assert( pAgg->nTab>0 ); rc=sqlite3BtreeFirst(pCsr, &res); while( res==0 && rc==SQLITE_OK ){ AggElem *pElem; rc = sqlite3BtreeData(pCsr, 0, sizeof(AggElem*), (char *)&pElem); if( rc!=SQLITE_OK ){ return rc; } assert( pAgg->apFunc!=0 ); freeAggElem(pElem, pAgg); rc=sqlite3BtreeNext(pCsr, &res); } if( rc!=SQLITE_OK ){ return rc; } sqlite3BtreeCloseCursor(pCsr); sqlite3BtreeClearTable(pAgg->pBtree, pAgg->nTab); }else{ /* The cursor may not be open because the aggregator was never used, ** or it could be that it was used but there was no GROUP BY clause. */ if( pAgg->pCurrent ){ freeAggElem(pAgg->pCurrent, pAgg); } } /* If db is not NULL and we have not yet and we have not yet opened ** the temporary btree then do so and create the table to store aggregate ** information. ** ** If db is NULL, then close the temporary btree if it is open. */ if( db ){ if( !pAgg->pBtree ){ assert( pAgg->nTab==0 ); #ifndef SQLITE_OMIT_MEMORYDB rc = sqlite3BtreeFactory(db, ":memory:", 0, TEMP_PAGES, &pAgg->pBtree); #else rc = sqlite3BtreeFactory(db, 0, 0, TEMP_PAGES, &pAgg->pBtree); #endif if( rc!=SQLITE_OK ) return rc; sqlite3BtreeBeginTrans(pAgg->pBtree, 1); rc = sqlite3BtreeCreateTable(pAgg->pBtree, &pAgg->nTab, 0); if( rc!=SQLITE_OK ) return rc; } assert( pAgg->nTab!=0 ); rc = sqlite3BtreeCursor(pAgg->pBtree, pAgg->nTab, 1, sqlite3VdbeRecordCompare, pKeyInfo, &pAgg->pCsr); if( rc!=SQLITE_OK ) return rc; }else{ if( pAgg->pBtree ){ sqlite3BtreeClose(pAgg->pBtree); pAgg->pBtree = 0; pAgg->nTab = 0; } pAgg->pCsr = 0; } if( pAgg->apFunc ){ sqliteFree(pAgg->apFunc); pAgg->apFunc = 0; } pAgg->pCurrent = 0; pAgg->nMem = 0; pAgg->searching = 0; return SQLITE_OK; } /* ** Delete a keylist */ void sqlite3VdbeKeylistFree(Keylist *p){ while( p ){ Keylist *pNext = p->pNext; sqliteFree(p); p = pNext; } } /* ** Close a cursor and release all the resources that cursor happens ** to hold. */ void sqlite3VdbeFreeCursor(Cursor *pCx){ if( pCx==0 ){ return; |
︙ | ︙ | |||
838 839 840 841 842 843 844 | int i; if( p->aStack ){ releaseMemArray(p->aStack, 1 + (p->pTos - p->aStack)); p->pTos = &p->aStack[-1]; } closeAllCursors(p); releaseMemArray(p->aMem, p->nMem); | > | > > | > > > > | < | | | 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 | int i; if( p->aStack ){ releaseMemArray(p->aStack, 1 + (p->pTos - p->aStack)); p->pTos = &p->aStack[-1]; } closeAllCursors(p); releaseMemArray(p->aMem, p->nMem); if( p->pList ){ sqlite3VdbeKeylistFree(p->pList); p->pList = 0; } if( p->contextStack ){ for(i=0; i<p->contextStackTop; i++){ sqlite3VdbeKeylistFree(p->contextStack[i].pList); } sqliteFree(p->contextStack); } sqlite3VdbeSorterReset(p); for(i=0; i<p->nAgg; i++){ sqlite3VdbeAggReset(0, &p->apAgg[i], 0); } p->contextStack = 0; p->contextStackDepth = 0; p->contextStackTop = 0; sqliteFree(p->zErrMsg); p->zErrMsg = 0; } /* ** Set the number of result columns that will be returned by this SQL ** statement. This is now set at compile time, rather than during ** execution of the vdbe program so that sqlite3_column_count() can ** be called on an SQL statement before sqlite3_step(). */ void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ Mem *pColName; int n; assert( 0==p->nResColumn ); p->nResColumn = nResColumn; n = nResColumn*2; p->aColName = pColName = (Mem*)sqliteMalloc( sizeof(Mem)*n ); if( p->aColName==0 ) return; while( n-- > 0 ){ (pColName++)->flags = MEM_Null; } } |
︙ | ︙ | |||
887 888 889 890 891 892 893 | ** the string is freed using sqliteFree() when the vdbe is finished with ** it. Otherwise, N bytes of zName are copied. */ int sqlite3VdbeSetColName(Vdbe *p, int idx, const char *zName, int N){ int rc; Mem *pColName; assert( idx<(2*p->nResColumn) ); | | | 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 | ** the string is freed using sqliteFree() when the vdbe is finished with ** it. Otherwise, N bytes of zName are copied. */ int sqlite3VdbeSetColName(Vdbe *p, int idx, const char *zName, int N){ int rc; Mem *pColName; assert( idx<(2*p->nResColumn) ); if( sqlite3_malloc_failed ) return SQLITE_NOMEM; assert( p->aColName!=0 ); pColName = &(p->aColName[idx]); if( N==P3_DYNAMIC || N==P3_STATIC ){ rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, SQLITE_STATIC); }else{ rc = sqlite3VdbeMemSetStr(pColName, zName, N, SQLITE_UTF8,SQLITE_TRANSIENT); } |
︙ | ︙ | |||
924 925 926 927 928 929 930 931 932 933 934 935 936 937 | needXcommit = 1; if( i!=1 ) nTrans++; } } /* If there are any write-transactions at all, invoke the commit hook */ if( needXcommit && db->xCommitCallback ){ sqlite3SafetyOff(db); rc = db->xCommitCallback(db->pCommitArg); sqlite3SafetyOn(db); if( rc ){ return SQLITE_CONSTRAINT; } } | > | 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 | needXcommit = 1; if( i!=1 ) nTrans++; } } /* If there are any write-transactions at all, invoke the commit hook */ if( needXcommit && db->xCommitCallback ){ int rc; sqlite3SafetyOff(db); rc = db->xCommitCallback(db->pCommitArg); sqlite3SafetyOn(db); if( rc ){ return SQLITE_CONSTRAINT; } } |
︙ | ︙ | |||
964 965 966 967 968 969 970 | } } /* The complex case - There is a multi-file write-transaction active. ** This requires a master journal file to ensure the transaction is ** committed atomicly. */ | < < | > < < < | | | < | 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 | } } /* The complex case - There is a multi-file write-transaction active. ** This requires a master journal file to ensure the transaction is ** committed atomicly. */ else{ char *zMaster = 0; /* File-name for the master journal */ char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt); OsFile master; /* Select a master journal file name */ do { u32 random; sqliteFree(zMaster); sqlite3Randomness(sizeof(random), &random); zMaster = sqlite3MPrintf("%s-mj%08X", zMainFile, random&0x7fffffff); if( !zMaster ){ return SQLITE_NOMEM; } }while( sqlite3OsFileExists(zMaster) ); /* Open the master journal. */ memset(&master, 0, sizeof(master)); rc = sqlite3OsOpenExclusive(zMaster, &master, 0); if( rc!=SQLITE_OK ){ sqliteFree(zMaster); return rc; } /* Write the name of each database file in the transaction into the new ** master journal file. If an error occurs at this point close ** and delete the master journal file. All the individual journal files ** still have 'null' as the master journal pointer, so they will roll ** back independently if a failure occurs. */ for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( i==1 ) continue; /* Ignore the TEMP database */ if( pBt && sqlite3BtreeIsInTrans(pBt) ){ char const *zFile = sqlite3BtreeGetJournalname(pBt); if( zFile[0]==0 ) continue; /* Ignore :memory: databases */ rc = sqlite3OsWrite(&master, zFile, strlen(zFile)+1); if( rc!=SQLITE_OK ){ sqlite3OsClose(&master); sqlite3OsDelete(zMaster); sqliteFree(zMaster); return rc; } } } /* Sync the master journal file. Before doing this, open the directory ** the master journal file is store in so that it gets synced too. */ zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt); rc = sqlite3OsOpenDirectory(zMainFile, &master); if( rc!=SQLITE_OK || (rc = sqlite3OsSync(&master))!=SQLITE_OK ){ sqlite3OsClose(&master); sqlite3OsDelete(zMaster); sqliteFree(zMaster); return rc; } /* Sync all the db files involved in the transaction. The same call |
︙ | ︙ | |||
1085 1086 1087 1088 1089 1090 1091 | for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ sqlite3BtreeCommit(pBt); } } } | < | 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 | for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ sqlite3BtreeCommit(pBt); } } } return rc; } /* ** Find every active VM other than pVdbe and change its status to ** aborted. This happens when one VM causes a rollback due to an |
︙ | ︙ | |||
1150 1151 1152 1153 1154 1155 1156 | ** means the close did not happen and needs to be repeated. */ int sqlite3VdbeHalt(Vdbe *p){ sqlite3 *db = p->db; int i; int (*xFunc)(Btree *pBt) = 0; /* Function to call on each btree backend */ | < < < < < | | < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < | < < < < < | > | < < < < | | | > | 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 | ** means the close did not happen and needs to be repeated. */ int sqlite3VdbeHalt(Vdbe *p){ sqlite3 *db = p->db; int i; int (*xFunc)(Btree *pBt) = 0; /* Function to call on each btree backend */ if( p->magic!=VDBE_MAGIC_RUN ){ /* Already halted. Nothing to do. */ assert( p->magic==VDBE_MAGIC_HALT ); return SQLITE_OK; } closeAllCursors(p); checkActiveVdbeCnt(db); if( p->pc<0 ){ /* No commit or rollback needed if the program never started */ }else if( db->autoCommit && db->activeVdbeCnt==1 ){ if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ /* The auto-commit flag is true, there are no other active queries ** using this handle and the vdbe program was successful or hit an ** 'OR FAIL' constraint. This means a commit is required. */ int rc = vdbeCommit(db); if( rc==SQLITE_BUSY ){ return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ p->rc = rc; xFunc = sqlite3BtreeRollback; } }else{ xFunc = sqlite3BtreeRollback; } }else{ if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ xFunc = sqlite3BtreeCommitStmt; }else if( p->errorAction==OE_Abort ){ xFunc = sqlite3BtreeRollbackStmt; }else{ xFunc = sqlite3BtreeRollback; db->autoCommit = 1; abortOtherActiveVdbes(p); } } /* If xFunc is not NULL, then it is one of sqlite3BtreeRollback, ** sqlite3BtreeRollbackStmt or sqlite3BtreeCommitStmt. Call it once on ** each backend. If an error occurs and the return code is still ** SQLITE_OK, set the return code to the new error value. */ for(i=0; xFunc && i<db->nDb; i++){ int rc; Btree *pBt = db->aDb[i].pBt; if( pBt ){ rc = xFunc(pBt); if( p->rc==SQLITE_OK ) p->rc = rc; } } /* If this was an INSERT, UPDATE or DELETE, set the change counter. */ if( p->changeCntOn && p->pc>=0 ){ if( !xFunc || xFunc==sqlite3BtreeCommitStmt ){ sqlite3VdbeSetChanges(db, p->nChange); }else{ sqlite3VdbeSetChanges(db, 0); } p->nChange = 0; } /* Rollback or commit any schema changes that occurred. */ if( p->rc!=SQLITE_OK ){ sqlite3RollbackInternalChanges(db); }else if( db->flags & SQLITE_InternChanges ){ sqlite3CommitInternalChanges(db); } /* We have successfully halted and closed the VM. Record this fact. */ if( p->pc>=0 ){ db->activeVdbeCnt--; } p->magic = VDBE_MAGIC_HALT; |
︙ | ︙ | |||
1327 1328 1329 1330 1331 1332 1333 | /* Reclaim all memory used by the VDBE */ Cleanup(p); /* Save profiling information from this VDBE run. */ | | | 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 | /* Reclaim all memory used by the VDBE */ Cleanup(p); /* Save profiling information from this VDBE run. */ assert( p->pTos<&p->aStack[p->pc<0?0:p->pc] || sqlite3_malloc_failed==1 ); #ifdef VDBE_PROFILE { FILE *out = fopen("vdbe_profile.out", "a"); if( out ){ int i; fprintf(out, "---- "); for(i=0; i<p->nOp; i++){ |
︙ | ︙ | |||
1412 1413 1414 1415 1416 1417 1418 | } if( p->pNext ){ p->pNext->pPrev = p->pPrev; } if( p->aOp ){ for(i=0; i<p->nOp; i++){ Op *pOp = &p->aOp[i]; | > > > | > > > > | 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 | } if( p->pNext ){ p->pNext->pPrev = p->pPrev; } if( p->aOp ){ for(i=0; i<p->nOp; i++){ Op *pOp = &p->aOp[i]; if( pOp->p3type==P3_DYNAMIC || pOp->p3type==P3_KEYINFO ){ sqliteFree(pOp->p3); } if( pOp->p3type==P3_VDBEFUNC ){ VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3; sqlite3VdbeDeleteAuxData(pVdbeFunc, 0); sqliteFree(pVdbeFunc); } } sqliteFree(p->aOp); } releaseMemArray(p->aVar, p->nVar); sqliteFree(p->aLabel); sqliteFree(p->aStack); releaseMemArray(p->aColName, p->nResColumn*2); |
︙ | ︙ | |||
1434 1435 1436 1437 1438 1439 1440 | ** MoveTo now. Return an error code. If no MoveTo is pending, this ** routine does nothing and returns SQLITE_OK. */ int sqlite3VdbeCursorMoveto(Cursor *p){ if( p->deferredMoveto ){ int res, rc; extern int sqlite3_search_count; | | | | | | | 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 | ** MoveTo now. Return an error code. If no MoveTo is pending, this ** routine does nothing and returns SQLITE_OK. */ int sqlite3VdbeCursorMoveto(Cursor *p){ if( p->deferredMoveto ){ int res, rc; extern int sqlite3_search_count; assert( p->intKey ); if( p->intKey ){ rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, &res); }else{ rc = sqlite3BtreeMoveto(p->pCursor,(char*)&p->movetoTarget, sizeof(i64),&res); } if( rc ) return rc; *p->pIncrKey = 0; p->lastRecno = keyToInt(p->movetoTarget); p->recnoIsValid = res==0; if( res<0 ){ rc = sqlite3BtreeNext(p->pCursor, &res); if( rc ) return rc; } sqlite3_search_count++; p->deferredMoveto = 0; p->cacheValid = 0; } return SQLITE_OK; } /* ** The following functions: ** |
︙ | ︙ | |||
1488 1489 1490 1491 1492 1493 1494 | ** 1 1 signed integer ** 2 2 signed integer ** 3 3 signed integer ** 4 4 signed integer ** 5 6 signed integer ** 6 8 signed integer ** 7 8 IEEE float | < < | < < | | < < < < | | 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 | ** 1 1 signed integer ** 2 2 signed integer ** 3 3 signed integer ** 4 4 signed integer ** 5 6 signed integer ** 6 8 signed integer ** 7 8 IEEE float ** 8-11 reserved for expansion ** N>=12 and even (N-12)/2 BLOB ** N>=13 and odd (N-13)/2 text ** */ /* ** Return the serial-type for the value stored in pMem. */ u32 sqlite3VdbeSerialType(Mem *pMem){ int flags = pMem->flags; if( flags&MEM_Null ){ return 0; } if( flags&MEM_Int ){ /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ # define MAX_6BYTE ((((i64)0x00010000)<<32)-1) i64 i = pMem->i; u64 u = i<0 ? -i : i; if( u<=127 ) return 1; if( u<=32767 ) return 2; if( u<=8388607 ) return 3; if( u<=2147483647 ) return 4; if( u<=MAX_6BYTE ) return 5; return 6; } |
︙ | ︙ | |||
1554 1555 1556 1557 1558 1559 1560 | } /* ** Write the serialized data blob for the value stored in pMem into ** buf. It is assumed that the caller has allocated sufficient space. ** Return the number of bytes written. */ | | | > > > > > | | | | | | < < < < > > | < < | | < < < < < | | > > | > > > | | > | | < > | < < | < < < < < < < < | < | | < < | | | < < < < < | > | > | < < > | < | > < | > < | | | < < < < < | | | | | | | | < | < | < < < < < < < < < < < < < < < < < | 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 | } /* ** Write the serialized data blob for the value stored in pMem into ** buf. It is assumed that the caller has allocated sufficient space. ** Return the number of bytes written. */ int sqlite3VdbeSerialPut(unsigned char *buf, Mem *pMem){ u32 serial_type = sqlite3VdbeSerialType(pMem); int len; /* NULL */ if( serial_type==0 ){ return 0; } /* Integer and Real */ if( serial_type<=7 ){ u64 v; int i; if( serial_type==7 ){ v = *(u64*)&pMem->r; }else{ v = *(u64*)&pMem->i; } len = i = sqlite3VdbeSerialTypeLen(serial_type); while( i-- ){ buf[i] = (v&0xFF); v >>= 8; } return len; } /* String or blob */ assert( serial_type>=12 ); len = sqlite3VdbeSerialTypeLen(serial_type); memcpy(buf, pMem->z, len); return len; } /* ** Deserialize the data blob pointed to by buf as serial type serial_type ** and store the result in pMem. Return the number of bytes read. */ int sqlite3VdbeSerialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ ){ int len; if( serial_type==0 ){ /* NULL */ pMem->flags = MEM_Null; return 0; } len = sqlite3VdbeSerialTypeLen(serial_type); if( serial_type<=7 ){ /* Integer and Real */ if( serial_type<=4 ){ /* 32-bit integer type. This is handled by a special case for ** performance reasons. */ int v = buf[0]; int n; if( v&0x80 ){ v |= -256; } for(n=1; n<len; n++){ v = (v<<8) | buf[n]; } pMem->flags = MEM_Int; pMem->i = v; return n; }else{ u64 v = 0; int n; if( buf[0]&0x80 ){ v = -1; } for(n=0; n<len; n++){ v = (v<<8) | buf[n]; } if( serial_type==7 ){ pMem->flags = MEM_Real; pMem->r = *(double*)&v; }else{ pMem->flags = MEM_Int; pMem->i = *(i64*)&v; } } }else{ /* String or blob */ assert( serial_type>=12 ); pMem->z = (char *)buf; pMem->n = len; pMem->xDel = 0; if( serial_type&0x01 ){ pMem->flags = MEM_Str | MEM_Ephem; }else{ pMem->flags = MEM_Blob | MEM_Ephem; } } return len; } /* ** This function compares the two table rows or index records specified by ** {nKey1, pKey1} and {nKey2, pKey2}, returning a negative, zero ** or positive integer if {nKey1, pKey1} is less than, equal to or ** greater than {nKey2, pKey2}. Both Key1 and Key2 must be byte strings ** composed by the OP_MakeRecord opcode of the VDBE. |
︙ | ︙ | |||
1720 1721 1722 1723 1724 1725 1726 | const unsigned char *aKey2 = (const unsigned char *)pKey2; Mem mem1; Mem mem2; mem1.enc = pKeyInfo->enc; mem2.enc = pKeyInfo->enc; | | | | | | | > | | | 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 | const unsigned char *aKey2 = (const unsigned char *)pKey2; Mem mem1; Mem mem2; mem1.enc = pKeyInfo->enc; mem2.enc = pKeyInfo->enc; idx1 = sqlite3GetVarint32(pKey1, &szHdr1); d1 = szHdr1; idx2 = sqlite3GetVarint32(pKey2, &szHdr2); d2 = szHdr2; nField = pKeyInfo->nField; while( idx1<szHdr1 && idx2<szHdr2 ){ u32 serial_type1; u32 serial_type2; /* Read the serial types for the next element in each key. */ idx1 += sqlite3GetVarint32(&aKey1[idx1], &serial_type1); if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break; idx2 += sqlite3GetVarint32(&aKey2[idx2], &serial_type2); if( d2>=nKey2 && sqlite3VdbeSerialTypeLen(serial_type2)>0 ) break; /* Assert that there is enough space left in each key for the blob of ** data to go with the serial type just read. This assert may fail if ** the file is corrupted. Then read the value from each key into mem1 ** and mem2 respectively. */ d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); d2 += sqlite3VdbeSerialGet(&aKey2[d2], serial_type2, &mem2); rc = sqlite3MemCompare(&mem1, &mem2, i<nField ? pKeyInfo->aColl[i] : 0); sqlite3VdbeMemRelease(&mem1); sqlite3VdbeMemRelease(&mem2); if( rc!=0 ){ break; } i++; } /* One of the keys ran out of fields, but all the fields up to that point ** were equal. If the incrKey flag is true, then the second key is ** treated as larger. */ if( rc==0 ){ if( pKeyInfo->incrKey ){ rc = -1; }else if( d1<nKey1 ){ rc = 1; }else if( d2<nKey2 ){ rc = -1; } } if( pKeyInfo->aSortOrder && i<pKeyInfo->nField && pKeyInfo->aSortOrder[i] ){ rc = -rc; } return rc; } /* |
︙ | ︙ | |||
1803 1804 1805 1806 1807 1808 1809 | u32 szHdr; /* Size of the header */ u32 typeRowid; /* Serial type of the rowid */ u32 lenRowid; /* Size of the rowid */ Mem m, v; sqlite3BtreeKeySize(pCur, &nCellKey); if( nCellKey<=0 ){ | | | | | | 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 | u32 szHdr; /* Size of the header */ u32 typeRowid; /* Serial type of the rowid */ u32 lenRowid; /* Size of the rowid */ Mem m, v; sqlite3BtreeKeySize(pCur, &nCellKey); if( nCellKey<=0 ){ return SQLITE_CORRUPT; } rc = sqlite3VdbeMemFromBtree(pCur, 0, nCellKey, 1, &m); if( rc ){ return rc; } sqlite3GetVarint32(m.z, &szHdr); sqlite3GetVarint32(&m.z[szHdr-1], &typeRowid); lenRowid = sqlite3VdbeSerialTypeLen(typeRowid); sqlite3VdbeSerialGet(&m.z[m.n-lenRowid], typeRowid, &v); *rowid = v.i; sqlite3VdbeMemRelease(&m); return SQLITE_OK; } /* ** Compare the key of the index entry that cursor pC is point to against |
︙ | ︙ | |||
1848 1849 1850 1851 1852 1853 1854 | *res = 0; return SQLITE_OK; } rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m); if( rc ){ return rc; } | | | 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 | *res = 0; return SQLITE_OK; } rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m); if( rc ){ return rc; } lenRowid = sqlite3VdbeIdxRowidLen(m.n, m.z); *res = sqlite3VdbeRecordCompare(pC->pKeyInfo, m.n-lenRowid, m.z, nKey, pKey); sqlite3VdbeMemRelease(&m); return SQLITE_OK; } /* ** This routine sets the value to be returned by subsequent calls to |
︙ | ︙ | |||
1887 1888 1889 1890 1891 1892 1893 | */ void sqlite3ExpirePreparedStatements(sqlite3 *db){ Vdbe *p; for(p = db->pVdbe; p; p=p->pNext){ p->expired = 1; } } | < < < < < < < | 1843 1844 1845 1846 1847 1848 1849 | */ void sqlite3ExpirePreparedStatements(sqlite3 *db){ Vdbe *p; for(p = db->pVdbe; p; p=p->pNext){ p->expired = 1; } } |
Deleted SQLite.Interop/src/vdbefifo.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to SQLite.Interop/src/vdbemem.c.
︙ | ︙ | |||
37 38 39 40 41 42 43 | int rc; if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){ return SQLITE_OK; } #ifdef SQLITE_OMIT_UTF16 return SQLITE_ERROR; #else | < < < < < < < < < < | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | int rc; if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){ return SQLITE_OK; } #ifdef SQLITE_OMIT_UTF16 return SQLITE_ERROR; #else rc = sqlite3VdbeMemTranslate(pMem, desiredEnc); if( rc==SQLITE_NOMEM ){ sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Null; pMem->z = 0; } return rc; #endif } /* ** Make the given Mem object MEM_Dyn. |
︙ | ︙ | |||
79 80 81 82 83 84 85 | return SQLITE_NOMEM; } pMem->flags |= MEM_Dyn|MEM_Term; pMem->xDel = 0; memcpy(z, pMem->z, n ); z[n] = 0; z[n+1] = 0; | | | | | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | return SQLITE_NOMEM; } pMem->flags |= MEM_Dyn|MEM_Term; pMem->xDel = 0; memcpy(z, pMem->z, n ); z[n] = 0; z[n+1] = 0; pMem->z = z; pMem->flags &= ~(MEM_Ephem|MEM_Static|MEM_Short); return SQLITE_OK; } /* ** Make the given Mem object either MEM_Short or MEM_Dyn so that bytes ** of the Mem.z[] array can be modified. ** ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. */ int sqlite3VdbeMemMakeWriteable(Mem *pMem){ int n; u8 *z; if( (pMem->flags & (MEM_Ephem|MEM_Static))==0 ){ return SQLITE_OK; } assert( (pMem->flags & MEM_Dyn)==0 ); assert( pMem->flags & (MEM_Str|MEM_Blob) ); if( (n = pMem->n)+2<sizeof(pMem->zShort) ){ z = pMem->zShort; pMem->flags |= MEM_Short|MEM_Term; }else{ z = sqliteMallocRaw( n+2 ); if( z==0 ){ return SQLITE_NOMEM; } pMem->flags |= MEM_Dyn|MEM_Term; pMem->xDel = 0; } memcpy(z, pMem->z, n ); z[n] = 0; z[n+1] = 0; pMem->z = z; pMem->flags &= ~(MEM_Ephem|MEM_Static); return SQLITE_OK; } /* ** Make sure the given Mem is \u0000 terminated. */ |
︙ | ︙ | |||
168 169 170 171 172 173 174 | ** sqlite3_value_text()), or for ensuring that values to be used as btree ** keys are strings. In the former case a NULL pointer is returned the ** user and the later is an internal programming error. */ int sqlite3VdbeMemStringify(Mem *pMem, int enc){ int rc = SQLITE_OK; int fg = pMem->flags; | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < | < | 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | ** sqlite3_value_text()), or for ensuring that values to be used as btree ** keys are strings. In the former case a NULL pointer is returned the ** user and the later is an internal programming error. */ int sqlite3VdbeMemStringify(Mem *pMem, int enc){ int rc = SQLITE_OK; int fg = pMem->flags; u8 *z = pMem->zShort; assert( !(fg&(MEM_Str|MEM_Blob)) ); assert( fg&(MEM_Int|MEM_Real) ); /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8 ** string representation of the value. Then, if the required encoding ** is UTF-16le or UTF-16be do a translation. ** ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16. */ if( fg & MEM_Real ){ sqlite3_snprintf(NBFS, z, "%.15g", pMem->r); }else{ assert( fg & MEM_Int ); sqlite3_snprintf(NBFS, z, "%lld", pMem->i); } pMem->n = strlen(z); pMem->z = z; pMem->enc = SQLITE_UTF8; pMem->flags |= MEM_Str | MEM_Short | MEM_Term; sqlite3VdbeChangeEncoding(pMem, enc); return rc; } /* ** Release any memory held by the Mem. This may leave the Mem in an ** inconsistent state, for example with (Mem.z==0) and ** (Mem.type==SQLITE_TEXT). */ void sqlite3VdbeMemRelease(Mem *p){ if( p->flags & MEM_Dyn ){ if( p->xDel ){ p->xDel((void *)p->z); }else{ sqliteFree(p->z); } p->z = 0; p->xDel = 0; } } |
︙ | ︙ | |||
260 261 262 263 264 265 266 | return pMem->i; }else if( flags & MEM_Real ){ return (i64)pMem->r; }else if( flags & (MEM_Str|MEM_Blob) ){ i64 value; if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) || sqlite3VdbeMemNulTerminate(pMem) ){ | | > > > > > > > > > > < | | < < < < < < < < < < < < < < < < < < < < < < < | | < < < < < < < < < < < | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | return pMem->i; }else if( flags & MEM_Real ){ return (i64)pMem->r; }else if( flags & (MEM_Str|MEM_Blob) ){ i64 value; if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) || sqlite3VdbeMemNulTerminate(pMem) ){ return SQLITE_NOMEM; } assert( pMem->z ); sqlite3atoi64(pMem->z, &value); return value; }else{ return 0; } } /* ** Convert pMem to type integer. Invalidate any prior representations. */ int sqlite3VdbeMemIntegerify(Mem *pMem){ pMem->i = sqlite3VdbeIntValue(pMem); sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Int; return SQLITE_OK; } /* ** Return the best representation of pMem that we can get into a ** double. If pMem is already a double or an integer, return its ** value. If it is a string or blob, try to convert it to a double. ** If it is a NULL, return 0.0. */ double sqlite3VdbeRealValue(Mem *pMem){ if( pMem->flags & MEM_Real ){ return pMem->r; }else if( pMem->flags & MEM_Int ){ return (double)pMem->i; }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) || sqlite3VdbeMemNulTerminate(pMem) ){ return SQLITE_NOMEM; } assert( pMem->z ); return sqlite3AtoF(pMem->z, 0); }else{ return 0.0; } } /* ** Convert pMem so that it is of type MEM_Real. Invalidate any ** prior representations. */ int sqlite3VdbeMemRealify(Mem *pMem){ pMem->r = sqlite3VdbeRealValue(pMem); sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Real; return SQLITE_OK; } /* ** Delete any previous value and set the value stored in *pMem to NULL. */ void sqlite3VdbeMemSetNull(Mem *pMem){ sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Null; pMem->type = SQLITE_NULL; } /* ** Delete any previous value and set the value stored in *pMem to val, ** manifest type INTEGER. */ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ |
︙ | ︙ | |||
467 468 469 470 471 472 473 | pMem->n = n; assert( enc==0 || enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); switch( enc ){ case 0: pMem->flags |= MEM_Blob; | < | 402 403 404 405 406 407 408 409 410 411 412 413 414 415 | pMem->n = n; assert( enc==0 || enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); switch( enc ){ case 0: pMem->flags |= MEM_Blob; break; case SQLITE_UTF8: pMem->flags |= MEM_Str; if( n<0 ){ pMem->n = strlen(z); pMem->flags |= MEM_Term; |
︙ | ︙ | |||
575 576 577 578 579 580 581 | return -1; } assert( pMem1->enc==pMem2->enc ); assert( pMem1->enc==SQLITE_UTF8 || pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); | | | | | 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 | return -1; } assert( pMem1->enc==pMem2->enc ); assert( pMem1->enc==SQLITE_UTF8 || pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); /* This assert may fail if the collation sequence is deleted after this ** vdbe program is compiled. The documentation defines this as an ** undefined condition. A crash is usual result. */ assert( !pColl || pColl->xCmp ); if( pColl ){ if( pMem1->enc==pColl->enc ){ return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); }else{ |
︙ | ︙ | |||
670 671 672 673 674 675 676 | rc = sqlite3BtreeKey(pCur, offset, amt, zData); }else{ rc = sqlite3BtreeData(pCur, offset, amt, zData); } zData[amt] = 0; zData[amt+1] = 0; if( rc!=SQLITE_OK ){ | | < < < < < | 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 | rc = sqlite3BtreeKey(pCur, offset, amt, zData); }else{ rc = sqlite3BtreeData(pCur, offset, amt, zData); } zData[amt] = 0; zData[amt+1] = 0; if( rc!=SQLITE_OK ){ if( amt>NBFS ){ sqliteFree(zData); } return rc; } } return SQLITE_OK; } |
︙ | ︙ | |||
728 729 730 731 732 733 734 | /* Cannot define a string subtype for non-string objects */ assert( (pMem->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short))==0 ); assert( pMem->xDel==0 ); } /* MEM_Null excludes all other types */ assert( (pMem->flags&(MEM_Str|MEM_Int|MEM_Real|MEM_Blob))==0 || (pMem->flags&MEM_Null)==0 ); | < | | > < < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 | /* Cannot define a string subtype for non-string objects */ assert( (pMem->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short))==0 ); assert( pMem->xDel==0 ); } /* MEM_Null excludes all other types */ assert( (pMem->flags&(MEM_Str|MEM_Int|MEM_Real|MEM_Blob))==0 || (pMem->flags&MEM_Null)==0 ); if( (pMem->flags & (MEM_Int|MEM_Real))==(MEM_Int|MEM_Real) ){ assert( pMem->r==pMem->i ); } } #endif /* This function is only available internally, it is not part of the ** external API. It works in a similar way to sqlite3_value_text(), ** except the data returned is in the encoding specified by the second ** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or ** SQLITE_UTF8. */ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ if( !pVal ) return 0; assert( enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE || enc==SQLITE_UTF8); if( pVal->flags&MEM_Null ){ return 0; } if( pVal->flags&MEM_Str ){ sqlite3VdbeChangeEncoding(pVal, enc); }else if( !(pVal->flags&MEM_Blob) ){ sqlite3VdbeMemStringify(pVal, enc); } return (const void *)(pVal->z); } /* ** Create a new sqlite3_value object. */ sqlite3_value* sqlite3ValueNew(){ Mem *p = sqliteMalloc(sizeof(*p)); if( p ){ p->flags = MEM_Null; p->type = SQLITE_NULL; } return p; } /* ** Change the string value of an sqlite3_value object */ void sqlite3ValueSetStr( sqlite3_value *v, int n, const void *z, |
︙ | ︙ |
Changes to SQLite.Interop/src/where.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | > > > | < < < < < < < | < < < > | | | | | | | < < < < < < < < | | > > | | < < < < < | | < < > > > | | | | > > > > > | < | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** ** $Id: where.c,v 1.1 2005/03/01 16:04:39 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** The query generator uses an array of instances of this structure to ** help it analyze the subexpressions of the WHERE clause. Each WHERE ** clause subexpression is separated from the others by an AND operator. ** ** The idxLeft and idxRight fields are the VDBE cursor numbers for the ** table that contains the column that appears on the left-hand and ** right-hand side of ExprInfo.p. If either side of ExprInfo.p is ** something other than a simple column reference, then idxLeft or ** idxRight are -1. ** ** It is the VDBE cursor number is the value stored in Expr.iTable ** when Expr.op==TK_COLUMN and the value stored in SrcList.a[].iCursor. ** ** prereqLeft, prereqRight, and prereqAll record sets of cursor numbers, ** but they do so indirectly. A single ExprMaskSet structure translates ** cursor number into bits and the translated bit is stored in the prereq ** fields. The translation is used in order to maximize the number of ** bits that will fit in a Bitmask. The VDBE cursor numbers might be ** spread out over the non-negative integers. For example, the cursor ** numbers might be 3, 8, 9, 10, 20, 23, 41, and 45. The ExprMaskSet ** translates these sparse cursor numbers into consecutive integers ** beginning with 0 in order to make the best possible use of the available ** bits in the Bitmask. So, in the example above, the cursor numbers ** would be mapped into integers 0 through 7. ** ** prereqLeft tells us every VDBE cursor that is referenced on the ** left-hand side of ExprInfo.p. prereqRight does the same for the ** right-hand side of the expression. The following identity always ** holds: ** ** prereqAll = prereqLeft | prereqRight ** ** The ExprInfo.indexable field is true if the ExprInfo.p expression ** is of a form that might control an index. Indexable expressions ** look like this: ** ** <column> <op> <expr> ** ** Where <column> is a simple column name and <op> is on of the operators ** that allowedOp() recognizes. */ typedef struct ExprInfo ExprInfo; struct ExprInfo { Expr *p; /* Pointer to the subexpression */ u8 indexable; /* True if this subexprssion is usable by an index */ short int idxLeft; /* p->pLeft is a column in this table number. -1 if ** p->pLeft is not the column of any table */ short int idxRight; /* p->pRight is a column in this table number. -1 if ** p->pRight is not the column of any table */ Bitmask prereqLeft; /* Bitmask of tables referenced by p->pLeft */ Bitmask prereqRight; /* Bitmask of tables referenced by p->pRight */ Bitmask prereqAll; /* Bitmask of tables referenced by p */ }; /* ** An instance of the following structure keeps track of a mapping ** between VDBE cursor numbers and bits of the bitmasks in ExprInfo. ** ** The VDBE cursor numbers are small integers contained in ** SrcList_item.iCursor and Expr.iTable fields. For any given WHERE ** clause, the cursor numbers might not begin with 0 and they might ** contain gaps in the numbering sequence. But we want to make maximum ** use of the bits in our bitmasks. This structure provides a mapping ** from the sparse cursor numbers into consecutive integers beginning |
︙ | ︙ | |||
150 151 152 153 154 155 156 | */ typedef struct ExprMaskSet ExprMaskSet; struct ExprMaskSet { int n; /* Number of assigned cursor values */ int ix[sizeof(Bitmask)*8]; /* Cursor assigned to each bit */ }; | < < < < < < < < < < < | < < < < < < < < < < < < < | < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | | | | | > | > | > > > > | | > | | > | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | */ typedef struct ExprMaskSet ExprMaskSet; struct ExprMaskSet { int n; /* Number of assigned cursor values */ int ix[sizeof(Bitmask)*8]; /* Cursor assigned to each bit */ }; /* ** Determine the number of elements in an array. */ #define ARRAYSIZE(X) (sizeof(X)/sizeof(X[0])) /* ** This routine identifies subexpressions in the WHERE clause where ** each subexpression is separate by the AND operator. aSlot is ** filled with pointers to the subexpressions. For example: ** ** WHERE a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22) ** \________/ \_______________/ \________________/ ** slot[0] slot[1] slot[2] ** ** The original WHERE clause in pExpr is unaltered. All this routine ** does is make aSlot[] entries point to substructure within pExpr. ** ** aSlot[] is an array of subexpressions structures. There are nSlot ** spaces left in this array. This routine finds as many AND-separated ** subexpressions as it can and puts pointers to those subexpressions ** into aSlot[] entries. The return value is the number of slots filled. */ static int exprSplit(int nSlot, ExprInfo *aSlot, Expr *pExpr){ int cnt = 0; if( pExpr==0 || nSlot<1 ) return 0; if( nSlot==1 || pExpr->op!=TK_AND ){ aSlot[0].p = pExpr; return 1; } if( pExpr->pLeft->op!=TK_AND ){ aSlot[0].p = pExpr->pLeft; cnt = 1 + exprSplit(nSlot-1, &aSlot[1], pExpr->pRight); }else{ cnt = exprSplit(nSlot, aSlot, pExpr->pLeft); cnt += exprSplit(nSlot-cnt, &aSlot[cnt], pExpr->pRight); } return cnt; } /* ** Initialize an expression mask set */ #define initMaskSet(P) memset(P, 0, sizeof(*P)) |
︙ | ︙ | |||
284 285 286 287 288 289 290 | } } return 0; } /* ** Create a new mask for cursor iCursor. | < < < < < | | | | > > > > > > | < < | < > > | > > > > > < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < | < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < | < < | < < < < < | < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < | < | < < < | | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | < < < < < < | < < < < < < | < < < < < < | < < < < < | < | < < < | | | < | | | > > | | | < < < < > | | < < < < < < < < < < < | < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < > | | | | > | < | | | < | | < | < | < < < < < < | < < < < < < < < < | | < < < < < < < > | < | < < < < | < < < < < < < < < < < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > > > | | | | < | < < < < < | | > | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | | | | | < < > | < < < | < < < < | < | < < < | < < < < < < | < | | < < < < < < < | | < > < < < < < < < < | | | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < | < < | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 | } } return 0; } /* ** Create a new mask for cursor iCursor. */ static void createMask(ExprMaskSet *pMaskSet, int iCursor){ if( pMaskSet->n<ARRAYSIZE(pMaskSet->ix) ){ pMaskSet->ix[pMaskSet->n++] = iCursor; } } /* ** Destroy an expression mask set */ #define freeMaskSet(P) /* NO-OP */ /* ** This routine walks (recursively) an expression tree and generates ** a bitmask indicating which tables are used in that expression ** tree. ** ** In order for this routine to work, the calling function must have ** previously invoked sqlite3ExprResolveNames() on the expression. See ** the header comment on that routine for additional information. ** The sqlite3ExprResolveNames() routines looks for column names and ** sets their opcodes to TK_COLUMN and their Expr.iTable fields to ** the VDBE cursor number of the table. */ static Bitmask exprListTableUsage(ExprMaskSet *, ExprList *); static Bitmask exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){ Bitmask mask = 0; if( p==0 ) return 0; if( p->op==TK_COLUMN ){ mask = getMask(pMaskSet, p->iTable); return mask; } mask = exprTableUsage(pMaskSet, p->pRight); mask |= exprTableUsage(pMaskSet, p->pLeft); mask |= exprListTableUsage(pMaskSet, p->pList); if( p->pSelect ){ Select *pS = p->pSelect; mask |= exprListTableUsage(pMaskSet, pS->pEList); mask |= exprListTableUsage(pMaskSet, pS->pGroupBy); mask |= exprListTableUsage(pMaskSet, pS->pOrderBy); mask |= exprTableUsage(pMaskSet, pS->pWhere); mask |= exprTableUsage(pMaskSet, pS->pHaving); } return mask; } static Bitmask exprListTableUsage(ExprMaskSet *pMaskSet, ExprList *pList){ int i; Bitmask mask = 0; if( pList ){ for(i=0; i<pList->nExpr; i++){ mask |= exprTableUsage(pMaskSet, pList->a[i].pExpr); } } return mask; } /* ** Return TRUE if the given operator is one of the operators that is ** allowed for an indexable WHERE clause term. The allowed operators are ** "=", "<", ">", "<=", ">=", and "IN". */ static int allowedOp(int op){ assert( TK_GT==TK_LE-1 && TK_LE==TK_LT-1 && TK_LT==TK_GE-1 && TK_EQ==TK_GT-1); return op==TK_IN || (op>=TK_EQ && op<=TK_GE); } /* ** Swap two objects of type T. */ #define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} /* ** Return the index in the SrcList that uses cursor iCur. If iCur is ** used by the first entry in SrcList return 0. If iCur is used by ** the second entry return 1. And so forth. ** ** SrcList is the set of tables in the FROM clause in the order that ** they will be processed. The value returned here gives us an index ** of which tables will be processed first. */ static int tableOrder(SrcList *pList, int iCur){ int i; struct SrcList_item *pItem; for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ if( pItem->iCursor==iCur ) return i; } return -1; } /* ** The input to this routine is an ExprInfo structure with only the ** "p" field filled in. The job of this routine is to analyze the ** subexpression and populate all the other fields of the ExprInfo ** structure. */ static void exprAnalyze(SrcList *pSrc, ExprMaskSet *pMaskSet, ExprInfo *pInfo){ Expr *pExpr = pInfo->p; pInfo->prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); pInfo->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight); pInfo->prereqAll = exprTableUsage(pMaskSet, pExpr); pInfo->indexable = 0; pInfo->idxLeft = -1; pInfo->idxRight = -1; if( allowedOp(pExpr->op) && (pInfo->prereqRight & pInfo->prereqLeft)==0 ){ if( pExpr->pRight && pExpr->pRight->op==TK_COLUMN ){ pInfo->idxRight = pExpr->pRight->iTable; pInfo->indexable = 1; } if( pExpr->pLeft->op==TK_COLUMN ){ pInfo->idxLeft = pExpr->pLeft->iTable; pInfo->indexable = 1; } } if( pInfo->indexable ){ assert( pInfo->idxLeft!=pInfo->idxRight ); /* We want the expression to be of the form "X = expr", not "expr = X". ** So flip it over if necessary. If the expression is "X = Y", then ** we want Y to come from an earlier table than X. ** ** The collating sequence rule is to always choose the left expression. ** So if we do a flip, we also have to move the collating sequence. */ if( tableOrder(pSrc,pInfo->idxLeft)<tableOrder(pSrc,pInfo->idxRight) ){ assert( pExpr->op!=TK_IN ); SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl); SWAP(Expr*,pExpr->pRight,pExpr->pLeft); if( pExpr->op>=TK_GT ){ assert( TK_LT==TK_GT+2 ); assert( TK_GE==TK_LE+2 ); assert( TK_GT>TK_EQ ); assert( TK_GT<TK_LE ); assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE ); pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT; } SWAP(unsigned, pInfo->prereqLeft, pInfo->prereqRight); SWAP(short int, pInfo->idxLeft, pInfo->idxRight); } } } /* ** This routine decides if pIdx can be used to satisfy the ORDER BY ** clause. If it can, it returns 1. If pIdx cannot satisfy the ** ORDER BY clause, this routine returns 0. ** ** pOrderBy is an ORDER BY clause from a SELECT statement. pTab is the ** left-most table in the FROM clause of that same SELECT statement and ** the table has a cursor number of "base". pIdx is an index on pTab. ** ** nEqCol is the number of columns of pIdx that are used as equality ** constraints. Any of these columns may be missing from the ORDER BY ** clause and the match can still be a success. ** ** If the index is UNIQUE, then the ORDER BY clause is allowed to have ** additional terms past the end of the index and the match will still ** be a success. ** ** All terms of the ORDER BY that match against the index must be either ** ASC or DESC. (Terms of the ORDER BY clause past the end of a UNIQUE ** index do not need to satisfy this constraint.) The *pbRev value is ** set to 1 if the ORDER BY clause is all DESC and it is set to 0 if ** the ORDER BY clause is all ASC. */ static int isSortingIndex( Parse *pParse, /* Parsing context */ Index *pIdx, /* The index we are testing */ Table *pTab, /* The table to be sorted */ int base, /* Cursor number for pTab */ ExprList *pOrderBy, /* The ORDER BY clause */ int nEqCol, /* Number of index columns with == constraints */ int *pbRev /* Set to 1 if ORDER BY is DESC */ ){ int i, j; /* Loop counters */ int sortOrder; /* Which direction we are sorting */ int nTerm; /* Number of ORDER BY terms */ struct ExprList_item *pTerm; /* A term of the ORDER BY clause */ sqlite3 *db = pParse->db; assert( pOrderBy!=0 ); nTerm = pOrderBy->nExpr; assert( nTerm>0 ); /* Match terms of the ORDER BY clause against columns of ** the index. */ for(i=j=0, pTerm=pOrderBy->a; j<nTerm && i<pIdx->nColumn; i++){ Expr *pExpr; /* The expression of the ORDER BY pTerm */ CollSeq *pColl; /* The collating sequence of pExpr */ pExpr = pTerm->pExpr; if( pExpr->op!=TK_COLUMN || pExpr->iTable!=base ){ /* Can not use an index sort on anything that is not a column in the ** left-most table of the FROM clause */ return 0; } pColl = sqlite3ExprCollSeq(pParse, pExpr); if( !pColl ) pColl = db->pDfltColl; if( pExpr->iColumn!=pIdx->aiColumn[i] || pColl!=pIdx->keyInfo.aColl[i] ){ /* Term j of the ORDER BY clause does not match column i of the index */ if( i<nEqCol ){ /* If an index column that is constrained by == fails to match an ** ORDER BY term, that is OK. Just ignore that column of the index */ continue; }else{ /* If an index column fails to match and is not constrained by == ** then the index cannot satisfy the ORDER BY constraint. */ return 0; } } if( i>nEqCol ){ if( pTerm->sortOrder!=sortOrder ){ /* Indices can only be used if all ORDER BY terms past the ** equality constraints are all either DESC or ASC. */ return 0; } }else{ sortOrder = pTerm->sortOrder; } j++; pTerm++; } /* The index can be used for sorting if all terms of the ORDER BY clause ** or covered or if we ran out of index columns and the it is a UNIQUE ** index. */ if( j>=nTerm || (i>=pIdx->nColumn && pIdx->onError!=OE_None) ){ *pbRev = sortOrder==SQLITE_SO_DESC; return 1; } return 0; } /* ** Check table to see if the ORDER BY clause in pOrderBy can be satisfied ** by sorting in order of ROWID. Return true if so and set *pbRev to be ** true for reverse ROWID and false for forward ROWID order. */ static int sortableByRowid( int base, /* Cursor number for table to be sorted */ ExprList *pOrderBy, /* The ORDER BY clause */ int *pbRev /* Set to 1 if ORDER BY is DESC */ ){ Expr *p; assert( pOrderBy!=0 ); assert( pOrderBy->nExpr>0 ); p = pOrderBy->a[0].pExpr; if( p->op==TK_COLUMN && p->iTable==base && p->iColumn==-1 ){ *pbRev = pOrderBy->a[0].sortOrder; return 1; } return 0; } /* ** Disable a term in the WHERE clause. Except, do not disable the term ** if it controls a LEFT OUTER JOIN and it did not originate in the ON ** or USING clause of that join. ** ** Consider the term t2.z='ok' in the following queries: ** ** (1) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok' ** (2) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok' ** (3) SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok' ** ** The t2.z='ok' is disabled in the in (2) because it originates ** in the ON clause. The term is disabled in (3) because it is not part ** of a LEFT OUTER JOIN. In (1), the term is not disabled. ** ** Disabling a term causes that term to not be tested in the inner loop ** of the join. Disabling is an optimization. We would get the correct ** results if nothing were ever disabled, but joins might run a little ** slower. The trick is to disable as much as we can without disabling ** too much. If we disabled in (1), we'd get the wrong answer. ** See ticket #813. */ static void disableTerm(WhereLevel *pLevel, Expr **ppExpr){ Expr *pExpr = *ppExpr; if( pLevel->iLeftJoin==0 || ExprHasProperty(pExpr, EP_FromJoin) ){ *ppExpr = 0; } } /* ** Generate code that builds a probe for an index. Details: ** ** * Check the top nColumn entries on the stack. If any ** of those entries are NULL, jump immediately to brk, ** which is the loop exit, since no index entry will match ** if any part of the key is NULL. ** ** * Construct a probe entry from the top nColumn entries in ** the stack with affinities appropriate for index pIdx. */ static void buildIndexProbe(Vdbe *v, int nColumn, int brk, Index *pIdx){ sqlite3VdbeAddOp(v, OP_NotNull, -nColumn, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, brk); sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqlite3IndexAffinityStr(v, pIdx); } /* ** Generate code for an equality term of the WHERE clause. An equality ** term can be either X=expr or X IN (...). pTerm is the X. */ static void codeEqualityTerm( Parse *pParse, /* The parsing context */ ExprInfo *pTerm, /* The term of the WHERE clause to be coded */ int brk, /* Jump here to abandon the loop */ WhereLevel *pLevel /* When level of the FROM clause we are working on */ ){ Expr *pX = pTerm->p; if( pX->op!=TK_IN ){ assert( pX->op==TK_EQ ); sqlite3ExprCode(pParse, pX->pRight); #ifndef SQLITE_OMIT_SUBQUERY }else{ int iTab; Vdbe *v = pParse->pVdbe; sqlite3CodeSubselect(pParse, pX); iTab = pX->iTable; sqlite3VdbeAddOp(v, OP_Rewind, iTab, brk); sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1); VdbeComment((v, "# %.*s", pX->span.n, pX->span.z)); pLevel->inP2 = sqlite3VdbeAddOp(v, OP_Column, iTab, 0); pLevel->inOp = OP_Next; pLevel->inP1 = iTab; #endif } disableTerm(pLevel, &pTerm->p); } /* ** The number of bits in a Bitmask */ #define BMS (sizeof(Bitmask)*8-1) /* ** Generate the beginning of the loop used for WHERE clause processing. ** The return value is a pointer to an opaque structure that contains ** information needed to terminate the loop. Later, the calling routine ** should invoke sqlite3WhereEnd() with the return value of this function |
︙ | ︙ | |||
1347 1348 1349 1350 1351 1352 1353 | ** foreach row2 in t2 do |-- by sqlite3WhereBegin() ** foreach row3 in t3 do / ** ... ** end \ Code generated ** end |-- by sqlite3WhereEnd() ** end / ** | < < < < < < | | 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 | ** foreach row2 in t2 do |-- by sqlite3WhereBegin() ** foreach row3 in t3 do / ** ... ** end \ Code generated ** end |-- by sqlite3WhereEnd() ** end / ** ** There are Btree cursors associated with each table. t1 uses cursor ** number pTabList->a[0].iCursor. t2 uses the cursor pTabList->a[1].iCursor. ** And so forth. This routine generates code to open those VDBE cursors ** and sqlite3WhereEnd() generates the code to close them. ** ** The code that sqlite3WhereBegin() generates leaves the cursors named ** in pTabList pointing at their appropriate entries. The [...] code ** can use OP_Column and OP_Recno opcodes on these cursors to extract ** data from the various tables of the loop. ** ** If the WHERE clause is empty, the foreach loops must each scan their ** entire tables. Thus a three-way join is an O(N^3) operation. But if ** the tables have indices and there are terms in the WHERE clause that ** refer to those indices, a complete table scan can be avoided and the ** code will run much faster. Most of the work of this routine is checking |
︙ | ︙ | |||
1413 1414 1415 1416 1417 1418 1419 | ** If the where clause loops cannot be arranged to provide the correct ** output order, then the *ppOrderBy is unchanged. */ WhereInfo *sqlite3WhereBegin( Parse *pParse, /* The parser context */ SrcList *pTabList, /* A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ | | > | > | | > > > | < < | | | > | > > > > > | > | > | > | | < < < > | < < | > > | < > > | > | < < | < | > | | < < | > > > > | < < < < | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < | < | > > | | < > > | > > > > > | | > > | > > > > > | > > > > | | | < > > > > > > > > > > > | | | | > > > > > | > > > > > > > | > > > > > > > | > > | > > > > > > > > > > > > > > > | > > > > > | > > > > > > | > > | | | | | < < < < | > > > > > > > > > > > > > | | | | > > > > > > > > > > > > > > > | > | | | < < < < < < < < < < < < < < < < < < < | | < < < < < < < < < < < | < | | > | | < < | > > | | < < < | < < < < > | | < | | > | > | | | < > > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | > | > | | < > > > > > > > > > > > | > | < > > > | < > | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < | | | | | < | | < < | | | > | > | | | < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < | > | < < < | < < | > < | | | > | | | | | 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 | ** If the where clause loops cannot be arranged to provide the correct ** output order, then the *ppOrderBy is unchanged. */ WhereInfo *sqlite3WhereBegin( Parse *pParse, /* The parser context */ SrcList *pTabList, /* A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */ Fetch *pFetch /* Initial location of cursors. NULL otherwise */ ){ int i; /* Loop counter */ WhereInfo *pWInfo; /* Will become the return value of this function */ Vdbe *v = pParse->pVdbe; /* The virtual database engine */ int brk, cont = 0; /* Addresses used during code generation */ int nExpr; /* Number of subexpressions in the WHERE clause */ Bitmask loopMask; /* One bit set for each outer loop */ ExprInfo *pTerm; /* A single term in the WHERE clause; ptr to aExpr[] */ ExprMaskSet maskSet; /* The expression mask set */ int iDirectEq[BMS]; /* Term of the form ROWID==X for the N-th table */ int iDirectLt[BMS]; /* Term of the form ROWID<X or ROWID<=X */ int iDirectGt[BMS]; /* Term of the form ROWID>X or ROWID>=X */ ExprInfo aExpr[101]; /* The WHERE clause is divided into these terms */ struct SrcList_item *pTabItem; /* A single entry from pTabList */ WhereLevel *pLevel; /* A single level in the pWInfo list */ /* The number of terms in the FROM clause is limited by the number of ** bits in a Bitmask */ if( pTabList->nSrc>sizeof(Bitmask)*8 ){ sqlite3ErrorMsg(pParse, "at most %d tables in a join", sizeof(Bitmask)*8); return 0; } /* Split the WHERE clause into separate subexpressions where each ** subexpression is separated by an AND operator. If the aExpr[] ** array fills up, the last entry might point to an expression which ** contains additional unfactored AND operators. */ initMaskSet(&maskSet); memset(aExpr, 0, sizeof(aExpr)); nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere); if( nExpr==ARRAYSIZE(aExpr) ){ sqlite3ErrorMsg(pParse, "WHERE clause too complex - no more " "than %d terms allowed", (int)ARRAYSIZE(aExpr)-1); return 0; } /* Allocate and initialize the WhereInfo structure that will become the ** return value. */ pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel)); if( sqlite3_malloc_failed ){ /* sqliteFree(pWInfo); // Leak memory when malloc fails */ return 0; } pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; pWInfo->iBreak = sqlite3VdbeMakeLabel(v); /* Special case: a WHERE clause that is constant. Evaluate the ** expression and either jump over all of the code or fall thru. */ if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstant(pWhere)) ){ sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1); pWhere = 0; } /* Analyze all of the subexpressions. */ for(i=0; i<pTabList->nSrc; i++){ createMask(&maskSet, pTabList->a[i].iCursor); } for(pTerm=aExpr, i=0; i<nExpr; i++, pTerm++){ exprAnalyze(pTabList, &maskSet, pTerm); } /* Figure out what index to use (if any) for each nested loop. ** Make pWInfo->a[i].pIdx point to the index to use for the i-th nested ** loop where i==0 is the outer loop and i==pTabList->nSrc-1 is the inner ** loop. ** ** If terms exist that use the ROWID of any table, then set the ** iDirectEq[], iDirectLt[], or iDirectGt[] elements for that table ** to the index of the term containing the ROWID. We always prefer ** to use a ROWID which can directly access a table rather than an ** index which requires reading an index first to get the rowid then ** doing a second read of the actual database table. ** ** Actually, if there are more than 32 tables in the join, only the ** first 32 tables are candidates for indices. This is (again) due ** to the limit of 32 bits in an integer bitmask. */ loopMask = 0; pTabItem = pTabList->a; pLevel = pWInfo->a; for(i=0; i<pTabList->nSrc && i<ARRAYSIZE(iDirectEq); i++,pTabItem++,pLevel++){ int j; int iCur = pTabItem->iCursor; /* The cursor for this table */ Bitmask mask = getMask(&maskSet, iCur); /* Cursor mask for this table */ Table *pTab = pTabItem->pTab; Index *pIdx; Index *pBestIdx = 0; int bestScore = 0; int bestRev = 0; /* Check to see if there is an expression that uses only the ** ROWID field of this table. For terms of the form ROWID==expr ** set iDirectEq[i] to the index of the term. For terms of the ** form ROWID<expr or ROWID<=expr set iDirectLt[i] to the term index. ** For terms like ROWID>expr or ROWID>=expr set iDirectGt[i]. ** ** (Added:) Treat ROWID IN expr like ROWID=expr. */ pLevel->iIdxCur = -1; iDirectEq[i] = -1; iDirectLt[i] = -1; iDirectGt[i] = -1; for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){ Expr *pX = pTerm->p; if( pTerm->idxLeft==iCur && pX->pLeft->iColumn<0 && (pTerm->prereqRight & loopMask)==pTerm->prereqRight ){ switch( pX->op ){ case TK_IN: case TK_EQ: iDirectEq[i] = j; break; case TK_LE: case TK_LT: iDirectLt[i] = j; break; case TK_GE: case TK_GT: iDirectGt[i] = j; break; } } } /* If we found a term that tests ROWID with == or IN, that term ** will be used to locate the rows in the database table. There ** is not need to continue into the code below that looks for ** an index. We will always use the ROWID over an index. */ if( iDirectEq[i]>=0 ){ loopMask |= mask; pLevel->pIdx = 0; continue; } /* Do a search for usable indices. Leave pBestIdx pointing to ** the "best" index. pBestIdx is left set to NULL if no indices ** are usable. ** ** The best index is the one with the highest score. The score ** for the index is determined as follows. For each of the ** left-most terms that is fixed by an equality operator, add ** 32 to the score. The right-most term of the index may be ** constrained by an inequality. Add 4 if for an "x<..." constraint ** and add 8 for an "x>..." constraint. If both constraints ** are present, add 12. ** ** If the left-most term of the index uses an IN operator ** (ex: "x IN (...)") then add 16 to the score. ** ** If an index can be used for sorting, add 2 to the score. ** If an index contains all the terms of a table that are ever ** used by any expression in the SQL statement, then add 1 to ** the score. ** ** This scoring system is designed so that the score can later be ** used to determine how the index is used. If the score&0x1c is 0 ** then all constraints are equalities. If score&0x4 is not 0 then ** there is an inequality used as a termination key. (ex: "x<...") ** If score&0x8 is not 0 then there is an inequality used as the ** start key. (ex: "x>..."). A score or 0x10 is the special case ** of an IN operator constraint. (ex: "x IN ..."). ** ** The IN operator (as in "<expr> IN (...)") is treated the same as ** an equality comparison except that it can only be used on the ** left-most column of an index and other terms of the WHERE clause ** cannot be used in conjunction with the IN operator to help satisfy ** other columns of the index. */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ Bitmask eqMask = 0; /* Index columns covered by an x=... term */ Bitmask ltMask = 0; /* Index columns covered by an x<... term */ Bitmask gtMask = 0; /* Index columns covered by an x>... term */ Bitmask inMask = 0; /* Index columns covered by an x IN .. term */ Bitmask m; int nEq, score, bRev = 0; if( pIdx->nColumn>sizeof(eqMask)*8 ){ continue; /* Ignore indices with too many columns to analyze */ } for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){ Expr *pX = pTerm->p; CollSeq *pColl = sqlite3ExprCollSeq(pParse, pX->pLeft); if( !pColl && pX->pRight ){ pColl = sqlite3ExprCollSeq(pParse, pX->pRight); } if( !pColl ){ pColl = pParse->db->pDfltColl; } if( pTerm->idxLeft==iCur && (pTerm->prereqRight & loopMask)==pTerm->prereqRight ){ int iColumn = pX->pLeft->iColumn; int k; char idxaff = pIdx->pTable->aCol[iColumn].affinity; for(k=0; k<pIdx->nColumn; k++){ /* If the collating sequences or affinities don't match, ** ignore this index. */ if( pColl!=pIdx->keyInfo.aColl[k] ) continue; if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue; if( pIdx->aiColumn[k]==iColumn ){ switch( pX->op ){ case TK_IN: { if( k==0 ) inMask |= 1; break; } case TK_EQ: { eqMask |= ((Bitmask)1)<<k; break; } case TK_LE: case TK_LT: { ltMask |= ((Bitmask)1)<<k; break; } case TK_GE: case TK_GT: { gtMask |= ((Bitmask)1)<<k; break; } default: { /* CANT_HAPPEN */ assert( 0 ); break; } } break; } } } } /* The following loop ends with nEq set to the number of columns ** on the left of the index with == constraints. */ for(nEq=0; nEq<pIdx->nColumn; nEq++){ m = (((Bitmask)1)<<(nEq+1))-1; if( (m & eqMask)!=m ) break; } /* Begin assemblying the score */ score = nEq*32; /* Base score is 32 times number of == constraints */ m = ((Bitmask)1)<<nEq; if( m & ltMask ) score+=4; /* Increase score for a < constraint */ if( m & gtMask ) score+=8; /* Increase score for a > constraint */ if( score==0 && inMask ) score = 16; /* Default score for IN constraint */ /* Give bonus points if this index can be used for sorting */ if( i==0 && score!=16 && ppOrderBy && *ppOrderBy ){ int base = pTabList->a[0].iCursor; if( isSortingIndex(pParse, pIdx, pTab, base, *ppOrderBy, nEq, &bRev) ){ score += 2; } } /* Check to see if we can get away with using just the index without ** ever reading the table. If that is the case, then add one bonus ** point to the score. */ if( score && pTabItem->colUsed < (((Bitmask)1)<<(BMS-1)) ){ for(m=0, j=0; j<pIdx->nColumn; j++){ int x = pIdx->aiColumn[j]; if( x<BMS-1 ){ m |= ((Bitmask)1)<<x; } } if( (pTabItem->colUsed & m)==pTabItem->colUsed ){ score++; } } /* If the score for this index is the best we have seen so far, then ** save it */ if( score>bestScore ){ pBestIdx = pIdx; bestScore = score; bestRev = bRev; } } pLevel->pIdx = pBestIdx; pLevel->score = bestScore; pLevel->bRev = bestRev; loopMask |= mask; if( pBestIdx ){ pLevel->iIdxCur = pParse->nTab++; } } /* Check to see if the ORDER BY clause is or can be satisfied by the ** use of an index on the first table. */ if( ppOrderBy && *ppOrderBy && pTabList->nSrc>0 ){ Index *pIdx; /* Index derived from the WHERE clause */ Table *pTab; /* Left-most table in the FROM clause */ int bRev = 0; /* True to reverse the output order */ int iCur; /* Btree-cursor that will be used by pTab */ WhereLevel *pLevel0 = &pWInfo->a[0]; pTab = pTabList->a[0].pTab; pIdx = pLevel0->pIdx; iCur = pTabList->a[0].iCursor; if( pIdx==0 && sortableByRowid(iCur, *ppOrderBy, &bRev) ){ /* The ORDER BY clause specifies ROWID order, which is what we ** were going to be doing anyway... */ *ppOrderBy = 0; pLevel0->bRev = bRev; }else if( pLevel0->score==16 ){ /* If there is already an IN index on the left-most table, ** it will not give the correct sort order. ** So, pretend that no suitable index is found. */ }else if( iDirectEq[0]>=0 || iDirectLt[0]>=0 || iDirectGt[0]>=0 ){ /* If the left-most column is accessed using its ROWID, then do ** not try to sort by index. But do delete the ORDER BY clause ** if it is redundant. */ }else if( (pLevel0->score&2)!=0 ){ /* The index that was selected for searching will cause rows to ** appear in sorted order. */ *ppOrderBy = 0; } } /* Open all tables in the pTabList and any indices selected for ** searching those tables. */ sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */ pLevel = pWInfo->a; for(i=0, pTabItem=pTabList->a; i<pTabList->nSrc; i++, pTabItem++, pLevel++){ Table *pTab; Index *pIx; int iIdxCur = pLevel->iIdxCur; pTab = pTabItem->pTab; if( pTab->isTransient || pTab->pSelect ) continue; if( (pLevel->score & 1)==0 ){ sqlite3OpenTableForReading(v, pTabItem->iCursor, pTab); } pLevel->iTabCur = pTabItem->iCursor; if( (pIx = pLevel->pIdx)!=0 ){ sqlite3VdbeAddOp(v, OP_Integer, pIx->iDb, 0); sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIx->tnum, (char*)&pIx->keyInfo, P3_KEYINFO); } if( (pLevel->score & 1)!=0 ){ sqlite3VdbeAddOp(v, OP_KeyAsData, iIdxCur, 1); sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1); } sqlite3CodeVerifySchema(pParse, pTab->iDb); } pWInfo->iTop = sqlite3VdbeCurrentAddr(v); /* Generate the code to do the search */ loopMask = 0; pLevel = pWInfo->a; pTabItem = pTabList->a; for(i=0; i<pTabList->nSrc; i++, pTabItem++, pLevel++){ int j, k; int iCur = pTabItem->iCursor; /* The VDBE cursor for the table */ Index *pIdx; /* The index we will be using */ int iIdxCur; /* The VDBE cursor for the index */ int omitTable; /* True if we use the index only */ pIdx = pLevel->pIdx; iIdxCur = pLevel->iIdxCur; pLevel->inOp = OP_Noop; /* Check to see if it is appropriate to omit the use of the table ** here and use its index instead. */ omitTable = (pLevel->score&1)!=0; /* If this is the right table of a LEFT OUTER JOIN, allocate and ** initialize a memory cell that records if this table matches any ** row of the left table of the join. */ if( i>0 && (pTabList->a[i-1].jointype & JT_LEFT)!=0 ){ if( !pParse->nMem ) pParse->nMem++; pLevel->iLeftJoin = pParse->nMem++; sqlite3VdbeAddOp(v, OP_String8, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1); VdbeComment((v, "# init LEFT JOIN no-match flag")); } if( i<ARRAYSIZE(iDirectEq) && (k = iDirectEq[i])>=0 ){ /* Case 1: We can directly reference a single row using an ** equality comparison against the ROWID field. Or ** we reference multiple rows using a "rowid IN (...)" ** construct. */ assert( k<nExpr ); pTerm = &aExpr[k]; assert( pTerm->p!=0 ); assert( pTerm->idxLeft==iCur ); assert( omitTable==0 ); brk = pLevel->brk = sqlite3VdbeMakeLabel(v); codeEqualityTerm(pParse, pTerm, brk, pLevel); cont = pLevel->cont = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk); sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk); VdbeComment((v, "pk")); pLevel->op = OP_Noop; }else if( pIdx!=0 && pLevel->score>3 && (pLevel->score&0x0c)==0 ){ /* Case 2: There is an index and all terms of the WHERE clause that ** refer to the index using the "==" or "IN" operators. */ int start; int nColumn = (pLevel->score+16)/32; brk = pLevel->brk = sqlite3VdbeMakeLabel(v); /* For each column of the index, find the term of the WHERE clause that ** constraints that column. If the WHERE clause term is X=expr, then ** evaluation expr and leave the result on the stack */ for(j=0; j<nColumn; j++){ for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){ Expr *pX = pTerm->p; if( pX==0 ) continue; if( pTerm->idxLeft==iCur && (pTerm->prereqRight & loopMask)==pTerm->prereqRight && pX->pLeft->iColumn==pIdx->aiColumn[j] && (pX->op==TK_EQ || pX->op==TK_IN) ){ char idxaff = pIdx->pTable->aCol[pX->pLeft->iColumn].affinity; if( sqlite3IndexAffinityOk(pX, idxaff) ){ codeEqualityTerm(pParse, pTerm, brk, pLevel); break; } } } } pLevel->iMem = pParse->nMem++; cont = pLevel->cont = sqlite3VdbeMakeLabel(v); buildIndexProbe(v, nColumn, brk, pIdx); sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0); /* Generate code (1) to move to the first matching element of the table. ** Then generate code (2) that jumps to "brk" after the cursor is past ** the last matching element of the table. The code (1) is executed ** once to initialize the search, the code (2) is executed before each ** iteration of the scan to see if the scan has finished. */ if( pLevel->bRev ){ /* Scan in reverse order */ sqlite3VdbeAddOp(v, OP_MoveLe, iIdxCur, brk); start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); sqlite3VdbeAddOp(v, OP_IdxLT, iIdxCur, brk); pLevel->op = OP_Prev; }else{ /* Scan in the forward order */ sqlite3VdbeAddOp(v, OP_MoveGe, iIdxCur, brk); start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); sqlite3VdbeOp3(v, OP_IdxGE, iIdxCur, brk, "+", P3_STATIC); pLevel->op = OP_Next; } sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0); sqlite3VdbeAddOp(v, OP_IdxIsNull, nColumn, cont); if( !omitTable ){ sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0); sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); } pLevel->p1 = iIdxCur; pLevel->p2 = start; }else if( i<ARRAYSIZE(iDirectLt) && (iDirectLt[i]>=0 || iDirectGt[i]>=0) ){ /* Case 3: We have an inequality comparison against the ROWID field. */ int testOp = OP_Noop; int start; int bRev = pLevel->bRev; assert( omitTable==0 ); brk = pLevel->brk = sqlite3VdbeMakeLabel(v); cont = pLevel->cont = sqlite3VdbeMakeLabel(v); if( bRev ){ int t = iDirectGt[i]; iDirectGt[i] = iDirectLt[i]; iDirectLt[i] = t; } if( iDirectGt[i]>=0 ){ Expr *pX; k = iDirectGt[i]; assert( k<nExpr ); pTerm = &aExpr[k]; pX = pTerm->p; assert( pX!=0 ); assert( pTerm->idxLeft==iCur ); sqlite3ExprCode(pParse, pX->pRight); sqlite3VdbeAddOp(v, OP_ForceInt, pX->op==TK_LE || pX->op==TK_GT, brk); sqlite3VdbeAddOp(v, bRev ? OP_MoveLt : OP_MoveGe, iCur, brk); VdbeComment((v, "pk")); disableTerm(pLevel, &pTerm->p); }else{ sqlite3VdbeAddOp(v, bRev ? OP_Last : OP_Rewind, iCur, brk); } if( iDirectLt[i]>=0 ){ Expr *pX; k = iDirectLt[i]; assert( k<nExpr ); pTerm = &aExpr[k]; pX = pTerm->p; assert( pX!=0 ); assert( pTerm->idxLeft==iCur ); sqlite3ExprCode(pParse, pX->pRight); pLevel->iMem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); if( pX->op==TK_LT || pX->op==TK_GT ){ testOp = bRev ? OP_Le : OP_Ge; }else{ testOp = bRev ? OP_Lt : OP_Gt; } disableTerm(pLevel, &pTerm->p); } start = sqlite3VdbeCurrentAddr(v); pLevel->op = bRev ? OP_Prev : OP_Next; pLevel->p1 = iCur; pLevel->p2 = start; if( testOp!=OP_Noop ){ sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); sqlite3VdbeAddOp(v, testOp, 0, brk); } }else if( pIdx==0 ){ /* Case 4: There is no usable index. We must do a complete ** scan of the entire database table. */ int start; int opRewind; assert( omitTable==0 ); brk = pLevel->brk = sqlite3VdbeMakeLabel(v); cont = pLevel->cont = sqlite3VdbeMakeLabel(v); if( pLevel->bRev ){ opRewind = OP_Last; pLevel->op = OP_Prev; }else{ opRewind = OP_Rewind; pLevel->op = OP_Next; } sqlite3VdbeAddOp(v, opRewind, iCur, brk); start = sqlite3VdbeCurrentAddr(v); pLevel->p1 = iCur; pLevel->p2 = start; }else{ /* Case 5: The WHERE clause term that refers to the right-most ** column of the index is an inequality. For example, if ** the index is on (x,y,z) and the WHERE clause is of the ** form "x=5 AND y<10" then this case is used. Only the ** right-most column can be an inequality - the rest must ** use the "==" operator. ** ** This case is also used when there are no WHERE clause ** constraints but an index is selected anyway, in order ** to force the output order to conform to an ORDER BY. */ int score = pLevel->score; int nEqColumn = score/32; int start; int leFlag=0, geFlag=0; int testOp; /* Evaluate the equality constraints */ for(j=0; j<nEqColumn; j++){ int iIdxCol = pIdx->aiColumn[j]; for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){ Expr *pX = pTerm->p; if( pX==0 ) continue; if( pTerm->idxLeft==iCur && pX->op==TK_EQ && (pTerm->prereqRight & loopMask)==pTerm->prereqRight && pX->pLeft->iColumn==iIdxCol ){ sqlite3ExprCode(pParse, pX->pRight); disableTerm(pLevel, &pTerm->p); break; } } } /* Duplicate the equality term values because they will all be ** used twice: once to make the termination key and once to make the ** start key. */ for(j=0; j<nEqColumn; j++){ sqlite3VdbeAddOp(v, OP_Dup, nEqColumn-1, 0); } /* Labels for the beginning and end of the loop */ cont = pLevel->cont = sqlite3VdbeMakeLabel(v); brk = pLevel->brk = sqlite3VdbeMakeLabel(v); /* Generate the termination key. This is the key value that ** will end the search. There is no termination key if there ** are no equality terms and no "X<..." term. ** ** 2002-Dec-04: On a reverse-order scan, the so-called "termination" ** key computed here really ends up being the start key. */ if( (score & 4)!=0 ){ for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){ Expr *pX = pTerm->p; if( pX==0 ) continue; if( pTerm->idxLeft==iCur && (pX->op==TK_LT || pX->op==TK_LE) && (pTerm->prereqRight & loopMask)==pTerm->prereqRight && pX->pLeft->iColumn==pIdx->aiColumn[j] ){ sqlite3ExprCode(pParse, pX->pRight); leFlag = pX->op==TK_LE; disableTerm(pLevel, &pTerm->p); break; } } testOp = OP_IdxGE; }else{ testOp = nEqColumn>0 ? OP_IdxGE : OP_Noop; leFlag = 1; } if( testOp!=OP_Noop ){ int nCol = nEqColumn + ((score & 4)!=0); pLevel->iMem = pParse->nMem++; buildIndexProbe(v, nCol, brk, pIdx); if( pLevel->bRev ){ int op = leFlag ? OP_MoveLe : OP_MoveLt; sqlite3VdbeAddOp(v, op, iIdxCur, brk); }else{ sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); } }else if( pLevel->bRev ){ sqlite3VdbeAddOp(v, OP_Last, iIdxCur, brk); } /* Generate the start key. This is the key that defines the lower ** bound on the search. There is no start key if there are no ** equality terms and if there is no "X>..." term. In ** that case, generate a "Rewind" instruction in place of the ** start key search. ** ** 2002-Dec-04: In the case of a reverse-order search, the so-called ** "start" key really ends up being used as the termination key. */ if( (score & 8)!=0 ){ for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){ Expr *pX = pTerm->p; if( pX==0 ) continue; if( pTerm->idxLeft==iCur && (pX->op==TK_GT || pX->op==TK_GE) && (pTerm->prereqRight & loopMask)==pTerm->prereqRight && pX->pLeft->iColumn==pIdx->aiColumn[j] ){ sqlite3ExprCode(pParse, pX->pRight); geFlag = pX->op==TK_GE; disableTerm(pLevel, &pTerm->p); break; } } }else{ geFlag = 1; } if( nEqColumn>0 || (score&8)!=0 ){ int nCol = nEqColumn + ((score&8)!=0); buildIndexProbe(v, nCol, brk, pIdx); if( pLevel->bRev ){ pLevel->iMem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); testOp = OP_IdxLT; }else{ int op = geFlag ? OP_MoveGe : OP_MoveGt; sqlite3VdbeAddOp(v, op, iIdxCur, brk); } }else if( pLevel->bRev ){ testOp = OP_Noop; }else{ sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, brk); } /* Generate the the top of the loop. If there is a termination ** key we have to test for that key and abort at the top of the ** loop. */ start = sqlite3VdbeCurrentAddr(v); if( testOp!=OP_Noop ){ sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); sqlite3VdbeAddOp(v, testOp, iIdxCur, brk); if( (leFlag && !pLevel->bRev) || (!geFlag && pLevel->bRev) ){ sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC); } } sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0); sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + ((score&4)!=0), cont); if( !omitTable ){ sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0); sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); } /* Record the instruction used to terminate the loop. */ pLevel->op = pLevel->bRev ? OP_Prev : OP_Next; pLevel->p1 = iIdxCur; pLevel->p2 = start; } loopMask |= getMask(&maskSet, iCur); /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. */ for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){ if( pTerm->p==0 ) continue; if( (pTerm->prereqAll & loopMask)!=pTerm->prereqAll ) continue; if( pLevel->iLeftJoin && !ExprHasProperty(pTerm->p,EP_FromJoin) ){ continue; } sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1); pTerm->p = 0; } brk = cont; /* For a LEFT OUTER JOIN, generate code that will record the fact that ** at least one row of the right table has matched the left table. */ if( pLevel->iLeftJoin ){ pLevel->top = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp(v, OP_Integer, 1, 0); sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1); VdbeComment((v, "# record LEFT JOIN hit")); for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){ if( pTerm->p==0 ) continue; if( (pTerm->prereqAll & loopMask)!=pTerm->prereqAll ) continue; sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1); pTerm->p = 0; } } } pWInfo->iContinue = cont; freeMaskSet(&maskSet); return pWInfo; } /* ** Generate the end of the WHERE loop. See comments on ** sqlite3WhereBegin() for additional information. */ void sqlite3WhereEnd(WhereInfo *pWInfo){ Vdbe *v = pWInfo->pParse->pVdbe; int i; WhereLevel *pLevel; SrcList *pTabList = pWInfo->pTabList; struct SrcList_item *pTabItem; /* Generate loop termination code. */ for(i=pTabList->nSrc-1; i>=0; i--){ pLevel = &pWInfo->a[i]; sqlite3VdbeResolveLabel(v, pLevel->cont); if( pLevel->op!=OP_Noop ){ sqlite3VdbeAddOp(v, pLevel->op, pLevel->p1, pLevel->p2); } sqlite3VdbeResolveLabel(v, pLevel->brk); if( pLevel->inOp!=OP_Noop ){ sqlite3VdbeAddOp(v, pLevel->inOp, pLevel->inP1, pLevel->inP2); } if( pLevel->iLeftJoin ){ int addr; addr = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iLeftJoin, 0); sqlite3VdbeAddOp(v, OP_NotNull, 1, addr+4 + (pLevel->iIdxCur>=0)); sqlite3VdbeAddOp(v, OP_NullRow, pTabList->a[i].iCursor, 0); if( pLevel->iIdxCur>=0 ){ sqlite3VdbeAddOp(v, OP_NullRow, pLevel->iIdxCur, 0); } sqlite3VdbeAddOp(v, OP_Goto, 0, pLevel->top); } } /* The "break" point is here, just past the end of the outer loop. ** Set it. */ sqlite3VdbeResolveLabel(v, pWInfo->iBreak); /* Close all of the cursors that were opend by sqlite3WhereBegin. */ pLevel = pWInfo->a; pTabItem = pTabList->a; for(i=0; i<pTabList->nSrc; i++, pTabItem++, pLevel++){ Table *pTab = pTabItem->pTab; assert( pTab!=0 ); if( pTab->isTransient || pTab->pSelect ) continue; if( (pLevel->score & 1)==0 ){ sqlite3VdbeAddOp(v, OP_Close, pTabItem->iCursor, 0); } if( pLevel->pIdx!=0 ){ sqlite3VdbeAddOp(v, OP_Close, pLevel->iIdxCur, 0); } /* Make cursor substitutions for cases where we want to use ** just the index and never reference the table. ** ** Calls to the code generator in between sqlite3WhereBegin and ** sqlite3WhereEnd will have created code that references the table ** directly. This loop scans all that code looking for opcodes ** that reference the table and converts them into opcodes that ** reference the index. */ if( pLevel->score & 1 ){ int i, j, last; VdbeOp *pOp; Index *pIdx = pLevel->pIdx; assert( pIdx!=0 ); pOp = sqlite3VdbeGetOp(v, pWInfo->iTop); last = sqlite3VdbeCurrentAddr(v); for(i=pWInfo->iTop; i<last; i++, pOp++){ if( pOp->p1!=pLevel->iTabCur ) continue; if( pOp->opcode==OP_Column ){ pOp->p1 = pLevel->iIdxCur; for(j=0; j<pIdx->nColumn; j++){ if( pOp->p2==pIdx->aiColumn[j] ){ pOp->p2 = j; break; } } }else if( pOp->opcode==OP_Recno ){ pOp->p1 = pLevel->iIdxCur; pOp->opcode = OP_IdxRecno; }else if( pOp->opcode==OP_NullRow ){ pOp->opcode = OP_Noop; } } } } /* Final cleanup */ sqliteFree(pWInfo); return; } |
Changes to SQLite.NET.sln.
1 2 3 | Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 | | < < < < < | < < < < < < < < < < < < < < < | < < | < < | < | < < < | | < < < | | < < < < | | < < < < < < < | < | | < < < < < < < < | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Data.SQLite", "System.Data.SQLite\System.Data.SQLite.csproj", "{AC139951-261A-4463-B6FA-AEBC25283A66}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "test\test.csproj", "{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = postProject readme.htm = readme.htm EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SQLite.Interop", "SQLite.Interop\SQLite.Interop.vcproj", "{10B51CE8-A838-44DE-BD82-B658F0296F80}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|Mixed Platforms = Debug|Mixed Platforms Debug|Win32 = Debug|Win32 Release|Any CPU = Release|Any CPU Release|Mixed Platforms = Release|Mixed Platforms Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Any CPU.Build.0 = Debug|Any CPU {AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Win32.ActiveCfg = Debug|Any CPU {AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Any CPU.ActiveCfg = Release|Any CPU {AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Any CPU.Build.0 = Release|Any CPU {AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Mixed Platforms.Build.0 = Release|Any CPU {AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Win32.ActiveCfg = Release|Any CPU {E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Any CPU.Build.0 = Debug|Any CPU {E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Win32.ActiveCfg = Debug|Any CPU {E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Release|Any CPU.ActiveCfg = Release|Any CPU {E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Release|Any CPU.Build.0 = Release|Any CPU {E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Release|Mixed Platforms.Build.0 = Release|Any CPU {E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Release|Win32.ActiveCfg = Release|Any CPU {10B51CE8-A838-44DE-BD82-B658F0296F80}.Debug|Any CPU.ActiveCfg = Debug|Win32 {10B51CE8-A838-44DE-BD82-B658F0296F80}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {10B51CE8-A838-44DE-BD82-B658F0296F80}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {10B51CE8-A838-44DE-BD82-B658F0296F80}.Debug|Win32.ActiveCfg = Debug|Win32 {10B51CE8-A838-44DE-BD82-B658F0296F80}.Debug|Win32.Build.0 = Debug|Win32 {10B51CE8-A838-44DE-BD82-B658F0296F80}.Release|Any CPU.ActiveCfg = Release|Win32 {10B51CE8-A838-44DE-BD82-B658F0296F80}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {10B51CE8-A838-44DE-BD82-B658F0296F80}.Release|Mixed Platforms.Build.0 = Release|Win32 {10B51CE8-A838-44DE-BD82-B658F0296F80}.Release|Win32.ActiveCfg = Release|Win32 {10B51CE8-A838-44DE-BD82-B658F0296F80}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal |
Deleted SQLite.NET.suo.
cannot compute difference between binary files
Changes to System.Data.SQLite/AssemblyInfo.cs.
|
| < < < < < | < < < < < < | < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("System.Data.SQLite")] [assembly: AssemblyDescription("ADO.NET 2.0 Data Provider for SQLite")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("System.Data.SQLite")] [assembly: AssemblyCopyright("Public Domain")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM componenets. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.6.*")] |
Deleted System.Data.SQLite/DataTypes.xml.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted System.Data.SQLite/MetaDataCollections.xml.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to System.Data.SQLite/SQLite3.cs.
1 2 3 4 5 6 7 8 9 10 11 12 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Runtime.InteropServices; using System.Collections.Generic; | < > | > > < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Runtime.InteropServices; using System.Collections.Generic; /// <summary> /// This class implements SQLiteBase completely, and is the guts of the code that interop's SQLite with .NET /// </summary> internal class SQLite3 : SQLiteBase { /// <summary> /// The opaque pointer returned to us by the sqlite provider /// </summary> protected int _sql; /// <summary> /// The user-defined functions registered on this connection /// </summary> protected SQLiteFunction[] _functionsArray; internal SQLite3(DateTimeFormat fmt) : base(fmt) { _sql = 0; _functionsArray = null; } protected override void Dispose(bool bDisposing) { Close(); } internal override void Close() { if (_sql != 0) { int n = UnsafeNativeMethods.sqlite3_close_interop(_sql); if (n > 0) throw new SQLiteException(n, SQLiteLastError()); SQLiteFunction.UnbindFunctions(this, _functionsArray); } _sql = 0; } internal override string Version { get { int len; return ToString(UnsafeNativeMethods.sqlite3_libversion_interop(out len), len); } |
︙ | ︙ | |||
98 99 100 101 102 103 104 | } if (n > 0) throw new SQLiteException(n, str); } internal override bool Step(SQLiteStatement stmt) { int n; | < < < < | < < < < | | < < < < < < < < < | < | | < < < < | | < < < < | | < < | > | | | < < | | < | | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | } if (n > 0) throw new SQLiteException(n, str); } internal override bool Step(SQLiteStatement stmt) { int n; while (true) { n = UnsafeNativeMethods.sqlite3_step_interop(stmt._sqlite_stmt); if (n == 100) return true; if (n == 101) return false; if (n > 0) { // An error occurred, attempt to reset the statement. If the reset worked because the // schema has changed, re-try the step again. Otherwise throw the original error. string str = SQLiteLastError(); if (Reset(stmt) == false) throw new SQLiteException(n, str); } } } internal override void Finalize(SQLiteStatement stmt) { if (stmt._sqlite_stmt > 0) { int n = UnsafeNativeMethods.sqlite3_finalize_interop(stmt._sqlite_stmt); if (n > 0) throw new SQLiteException(n, SQLiteLastError()); } stmt._sqlite_stmt = 0; } internal override bool Reset(SQLiteStatement stmt) { int n = UnsafeNativeMethods.sqlite3_reset_interop(stmt._sqlite_stmt); // If the schema changed, try and re-prepare it if (n == 17) // SQLITE_SCHEMA { // Recreate a dummy statement int nc = 0; string str; using (SQLiteStatement tmp = Prepare(stmt._sqlStatement, ref nc, out str)) { // Finalize the existing statement Finalize(stmt); // Reassign a new statement pointer to the old statement and clear the temporary one stmt._sqlite_stmt = tmp._sqlite_stmt; tmp._sqlite_stmt = 0; // Reapply parameters stmt.BindParameters(); } return true; // Reset was OK, with schema change } if (n > 0) throw new SQLiteException(n, SQLiteLastError()); return false; // We reset OK, no schema changes } internal override string SQLiteLastError() { int len; return ToString(UnsafeNativeMethods.sqlite3_errmsg_interop(_sql, out len), len); } internal override SQLiteStatement Prepare(string strSql, ref int nParamStart, out string strRemain) { int stmt; IntPtr ptr; int len; byte[] b = ToUTF8(strSql); int n = UnsafeNativeMethods.sqlite3_prepare_interop(_sql, b, b.Length - 1, out stmt, out ptr, out len); if (n > 0) throw new SQLiteException(n, SQLiteLastError()); strRemain = ToString(ptr, len); SQLiteStatement cmd = new SQLiteStatement(this, stmt, strSql.Substring(0, strSql.Length - strRemain.Length), ref nParamStart); return cmd; } internal override void Bind_Double(SQLiteStatement stmt, int index, double value) { int n = UnsafeNativeMethods.sqlite3_bind_double_interop(stmt._sqlite_stmt, index, ref value); |
︙ | ︙ | |||
286 287 288 289 290 291 292 293 294 | { int len; return ToString(UnsafeNativeMethods.sqlite3_column_name_interop(stmt._sqlite_stmt, index, out len), len); } internal override string ColumnType(SQLiteStatement stmt, int index, out TypeAffinity nAffinity) { int len; IntPtr p = UnsafeNativeMethods.sqlite3_column_decltype_interop(stmt._sqlite_stmt, index, out len); | > > < > < < | | < | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | { int len; return ToString(UnsafeNativeMethods.sqlite3_column_name_interop(stmt._sqlite_stmt, index, out len), len); } internal override string ColumnType(SQLiteStatement stmt, int index, out TypeAffinity nAffinity) { nAffinity = TypeAffinity.None; int len; IntPtr p = UnsafeNativeMethods.sqlite3_column_decltype_interop(stmt._sqlite_stmt, index, out len); if (p != IntPtr.Zero) return ToString(p, len); else { nAffinity = UnsafeNativeMethods.sqlite3_column_type_interop(stmt._sqlite_stmt, index); switch (nAffinity) { case TypeAffinity.Int64: return "BIGINT"; case TypeAffinity.Double: return "DOUBLE"; case TypeAffinity.Blob: return "BLOB"; default: return "TEXT"; } } } internal override int ColumnIndex(SQLiteStatement stmt, string columnName) { for (int n = 0; n < ColumnCount(stmt); n++) { if (String.Compare(columnName, ColumnName(stmt, n), true) == 0) return n; } return -1; } internal override double GetDouble(SQLiteStatement stmt, int index) { double value; |
︙ | ︙ | |||
520 521 522 523 524 525 526 | return UnsafeNativeMethods.sqlite3_aggregate_context_interop(context, 1); } internal override void SetRealColNames(bool bOn) { UnsafeNativeMethods.sqlite3_realcolnames(_sql, Convert.ToInt32(bOn)); } | | < < < < | < < < < < < < < | 486 487 488 489 490 491 492 493 494 | return UnsafeNativeMethods.sqlite3_aggregate_context_interop(context, 1); } internal override void SetRealColNames(bool bOn) { UnsafeNativeMethods.sqlite3_realcolnames(_sql, Convert.ToInt32(bOn)); } } } |
Changes to System.Data.SQLite/SQLite3_UTF16.cs.
︙ | ︙ | |||
11 12 13 14 15 16 17 | using System.Runtime.InteropServices; /// <summary> /// Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode) /// </summary> internal class SQLite3_UTF16 : SQLite3 { | | > > > > > | | < < | < < | | < | | | < < < < < < < | < | > | | < < | > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | using System.Runtime.InteropServices; /// <summary> /// Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode) /// </summary> internal class SQLite3_UTF16 : SQLite3 { internal SQLite3_UTF16(DateTimeFormat fmt) : base(fmt) { } /// <summary> /// Overrides SQLiteConvert.ToString() to marshal UTF-16 strings instead of UTF-8 /// </summary> /// <param name="b">A pointer to a UTF-16 string</param> /// <param name="nbytelen">The length (IN BYTES) of the string</param> /// <returns>A .NET string</returns> public override string ToString(IntPtr b, int nbytelen) { if (nbytelen == 0) return ""; return Marshal.PtrToStringUni(b, nbytelen / 2); } /// <summary> /// Another custom string marshaling function /// </summary> /// <param name="b">A pointer to a zero-terminated UTF-16 string</param> /// <returns>A .NET string</returns> internal string ToString(IntPtr b) { if (b == IntPtr.Zero) return ""; return Marshal.PtrToStringUni(b); } internal override void Open(string strFilename) { if (_sql != 0) return; int n = UnsafeNativeMethods.sqlite3_open16_interop(strFilename, out _sql); if (n > 0) throw new SQLiteException(n, SQLiteLastError()); _functionsArray = SQLiteFunction.BindFunctions(this); } internal override string SQLiteLastError() { return ToString(UnsafeNativeMethods.sqlite3_errmsg16_interop(_sql)); } internal override SQLiteStatement Prepare(string strSql, ref int nParamStart, out string strRemain) { int stmt; IntPtr ptr; int n = UnsafeNativeMethods.sqlite3_prepare16_interop(_sql, strSql, strSql.Length, out stmt, out ptr); if (n > 0) throw new SQLiteException(n, SQLiteLastError()); strRemain = ToString(ptr); SQLiteStatement cmd = new SQLiteStatement(this, stmt, strSql.Substring(0, strSql.Length - strRemain.Length), ref nParamStart); return cmd; } internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt) { Bind_Text(stmt, index, ToString(dt)); } internal override void Bind_Text(SQLiteStatement stmt, int index, string value) { int n = UnsafeNativeMethods.sqlite3_bind_text16_interop(stmt._sqlite_stmt, index, value, value.Length * 2, -1); if (n > 0) throw new SQLiteException(n, SQLiteLastError()); } internal override string ColumnName(SQLiteStatement stmt, int index) { return ToString(UnsafeNativeMethods.sqlite3_column_name16_interop(stmt._sqlite_stmt, index)); } internal override DateTime GetDateTime(SQLiteStatement stmt, int index) { return ToDateTime(GetText(stmt, index)); } internal override string GetText(SQLiteStatement stmt, int index) { return ToString(UnsafeNativeMethods.sqlite3_column_text16_interop(stmt._sqlite_stmt, index)); } internal override string ColumnType(SQLiteStatement stmt, int index, out TypeAffinity nAffinity) { nAffinity = TypeAffinity.None; IntPtr p = UnsafeNativeMethods.sqlite3_column_decltype16_interop(stmt._sqlite_stmt, index); if (p != IntPtr.Zero) return ToString(p); else { nAffinity = UnsafeNativeMethods.sqlite3_column_type_interop(stmt._sqlite_stmt, index); switch (nAffinity) { case TypeAffinity.Int64: return "BIGINT"; case TypeAffinity.Double: return "DOUBLE"; case TypeAffinity.Blob: |
︙ | ︙ | |||
146 147 148 149 150 151 152 | if (n > 0) throw new SQLiteException(n, SQLiteLastError()); return nCookie; } internal override string GetParamValueText(int ptr) { | < | | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | if (n > 0) throw new SQLiteException(n, SQLiteLastError()); return nCookie; } internal override string GetParamValueText(int ptr) { return ToString(UnsafeNativeMethods.sqlite3_value_text16_interop(ptr)); } internal override void ReturnError(int context, string value) { UnsafeNativeMethods.sqlite3_result_error16_interop(context, value, value.Length); } internal override void ReturnText(int context, string value) { UnsafeNativeMethods.sqlite3_result_text16_interop(context, value, value.Length, -1); } } } |
Changes to System.Data.SQLite/SQLiteBase.cs.
︙ | ︙ | |||
14 15 16 17 18 19 20 | /// <summary> /// This internal class provides the foundation of SQLite support. It defines all the abstract members needed to implement /// a SQLite data provider, and inherits from SQLiteConvert which allows for simple translations of string to and from SQLite. /// </summary> internal abstract class SQLiteBase : SQLiteConvert, IDisposable { | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | /// <summary> /// This internal class provides the foundation of SQLite support. It defines all the abstract members needed to implement /// a SQLite data provider, and inherits from SQLiteConvert which allows for simple translations of string to and from SQLite. /// </summary> internal abstract class SQLiteBase : SQLiteConvert, IDisposable { internal SQLiteBase(DateTimeFormat fmt) : base(fmt) {} /// <summary> /// Returns a string representing the active version of SQLite /// </summary> internal abstract string Version { get; } /// <summary> |
︙ | ︙ | |||
63 64 65 66 67 68 69 | /// <returns></returns> internal abstract string SQLiteLastError(); /// <summary> /// Prepares a SQL statement for execution. /// </summary> /// <param name="strSql">The SQL command text to prepare</param> | | > > > > | | < < | | | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | /// <returns></returns> internal abstract string SQLiteLastError(); /// <summary> /// Prepares a SQL statement for execution. /// </summary> /// <param name="strSql">The SQL command text to prepare</param> /// <param name="nParamStart">When preparing multiple statements that are tied together into a single command, /// this value should be initialized to 0 for the first statement prepared. On return from this function, the /// variable will automatically be incremented by 1 for each unnamed parameter that occurred in the statement. /// When implementing this function, one need only pass the nParamStart variable by reference to the SQLiteStatement() /// constructor. SQLiteStatement will take care of it.</param> /// <param name="strRemain">The remainder of the statement that was not processed. Each call to prepare parses the /// SQL up to to either the end of the text or to the first semi-colon delimiter. The remaining text is returned /// here for a subsequent call to Prepare() until all the text has been processed.</param> /// <returns>Returns an initialized SQLiteStatement.</returns> internal abstract SQLiteStatement Prepare(string strSql, ref int nParamStart, out string strRemain); /// <summary> /// Steps through a prepared statement. /// </summary> /// <param name="stmt">The SQLiteStatement to step through</param> /// <returns>True if a row was returned, False if not.</returns> internal abstract bool Step(SQLiteStatement stmt); /// <summary> /// Finalizes a prepared statement. /// </summary> /// <param name="stmt">The statement to finalize</param> internal abstract void Finalize(SQLiteStatement stmt); /// <summary> /// Resets a prepared statement so it can be executed again. If the error returned is SQLITE_SCHEMA, /// transparently attempt to rebuild the SQL statement and throw an error if that was not possible. /// </summary> /// <param name="stmt">The statement to reset</param> /// <returns>Returns true if the schema changed while resetting, or false otherwise.</returns> internal abstract bool Reset(SQLiteStatement stmt); /// <summary> /// An interop-specific function, this call sets an internal flag in the sqlite.interop.dll which causes all column names /// of subsequently-prepared statements to return in Database.Table.Column format, ignoring all aliases that may have been applied /// to tables or columns in a resultset. /// </summary> /// <remarks> |
︙ | ︙ | |||
126 127 128 129 130 131 132 | internal abstract Int32 GetInt32(SQLiteStatement stmt, int index); internal abstract Int64 GetInt64(SQLiteStatement stmt, int index); internal abstract string GetText(SQLiteStatement stmt, int index); internal abstract long GetBytes(SQLiteStatement stmt, int index, int nDataoffset, byte[] bDest, int nStart, int nLength); internal abstract long GetChars(SQLiteStatement stmt, int index, int nDataoffset, char[] bDest, int nStart, int nLength); internal abstract DateTime GetDateTime(SQLiteStatement stmt, int index); internal abstract bool IsNull(SQLiteStatement stmt, int index); | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | internal abstract Int32 GetInt32(SQLiteStatement stmt, int index); internal abstract Int64 GetInt64(SQLiteStatement stmt, int index); internal abstract string GetText(SQLiteStatement stmt, int index); internal abstract long GetBytes(SQLiteStatement stmt, int index, int nDataoffset, byte[] bDest, int nStart, int nLength); internal abstract long GetChars(SQLiteStatement stmt, int index, int nDataoffset, char[] bDest, int nStart, int nLength); internal abstract DateTime GetDateTime(SQLiteStatement stmt, int index); internal abstract bool IsNull(SQLiteStatement stmt, int index); internal abstract int CreateCollation(string strCollation, SQLiteCollation func); internal abstract int CreateFunction(string strFunction, int nArgs, SQLiteCallback func, SQLiteCallback funcstep, SQLiteCallback funcfinal); internal abstract void FreeFunction(int nCookie); internal abstract int AggregateCount(int context); internal abstract int AggregateContext(int context); |
︙ | ︙ | |||
181 182 183 184 185 186 187 | internal abstract void ReturnDouble(int context, double value); internal abstract void ReturnError(int context, string value); internal abstract void ReturnInt32(int context, Int32 value); internal abstract void ReturnInt64(int context, Int64 value); internal abstract void ReturnNull(int context); internal abstract void ReturnText(int context, string value); | < < < < | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | internal abstract void ReturnDouble(int context, double value); internal abstract void ReturnError(int context, string value); internal abstract void ReturnInt32(int context, Int32 value); internal abstract void ReturnInt64(int context, Int64 value); internal abstract void ReturnNull(int context); internal abstract void ReturnText(int context, string value); protected virtual void Dispose(bool bDisposing) { } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } } } |
Changes to System.Data.SQLite/SQLiteCommand.cs.
︙ | ︙ | |||
11 12 13 14 15 16 17 | using System.Data; using System.Data.Common; using System.Collections.Generic; /// <summary> /// SQLite implementation of DbCommand. /// </summary> | | < < < | < < < | < < < | < < < | < < < | < < < | < < < | < < | < < < < | | | | | | | < < < < < < < < < < < < < < < < < | | | | < < < < < | | > | | | | > | > > < < | < < < < < | | < < | < | | < | < < < < < < | < < < < < < < < < > | > > > > > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | using System.Data; using System.Data.Common; using System.Collections.Generic; /// <summary> /// SQLite implementation of DbCommand. /// </summary> public sealed class SQLiteCommand : DbCommand { private string _commandText; private SQLiteConnection _cnn; private SQLiteDataReader _dataReader; private int _commandTimeout; private bool _designTimeVisible; private UpdateRowSource _updateRowSource; private SQLiteParameterCollection _parameterCollection; internal SQLiteStatement[] _statementList; ///<overloads> /// Constructs a new SQLiteCommand /// </overloads> /// <summary> /// Default constructor /// </summary> public SQLiteCommand() { Initialize(null, null); } /// <summary> /// Initializes the command with the given command text /// </summary> /// <param name="strSql">The SQL command text</param> public SQLiteCommand(string strSql) { Initialize(strSql, null); } /// <summary> /// Initializes the command with the given SQL command text and attach the command to the specified /// connection. /// </summary> /// <param name="strSql">The SQL command text</param> /// <param name="cnn">The connection to associate with the command</param> public SQLiteCommand(string strSql, SQLiteConnection cnn) { Initialize(strSql, cnn); } /// <summary> /// Initializes the command and associates it with the specified connection. /// </summary> /// <param name="cnn"></param> public SQLiteCommand(SQLiteConnection cnn) { Initialize(null, cnn); } private void Initialize(string strSql, SQLiteConnection cnn) { _statementList = null; _dataReader = null; _commandTimeout = 30; _parameterCollection = new SQLiteParameterCollection(this); _designTimeVisible = true; _updateRowSource = UpdateRowSource.FirstReturnedRecord; if (strSql != null) CommandText = strSql; if (cnn != null) DbConnection = cnn; } /// <summary> /// /// </summary> /// <param name="disposing"></param> protected override void Dispose(bool disposing) { base.Dispose(disposing); ClearCommands(); _parameterCollection.Clear(); } internal void ClearCommands() { if (_statementList == null) return; for (int n = 0; n < _statementList.Length; n++) _statementList[n].Dispose(); _statementList = null; _parameterCollection.Unbind(); } internal void BuildCommands() { ClearCommands(); if (_cnn.State != ConnectionState.Open) return; string strRemain = _commandText; SQLiteStatement itm; int nStart = 0; List<SQLiteStatement> lst = new List<SQLiteStatement>(); try { while (strRemain.Length > 0) { itm = _cnn._sql.Prepare(strRemain, ref nStart, out strRemain); if (itm != null) lst.Add(itm); } } catch (Exception e) { ClearCommands(); throw (e); } _statementList = new SQLiteStatement[lst.Count]; lst.CopyTo(_statementList, 0); } /// <summary> /// Not implemented /// </summary> public override void Cancel() { throw new NotImplementedException(); } /// <summary> /// The SQL command text associated with the command /// </summary> public override string CommandText { get { return _commandText; } set { if (_commandText == value) return; if (_dataReader != null) { throw new InvalidOperationException("Cannot set CommandText while a DataReader is active"); } // if (value == null) // throw new ArgumentNullException(); ClearCommands(); _commandText = value; if (_cnn == null) return; BuildCommands(); } } /// <summary> /// The amount of time to wait for the connection to become available before erroring out /// </summary> public override int CommandTimeout |
︙ | ︙ | |||
261 262 263 264 265 266 267 | { return CommandType.Text; } set { if (value != CommandType.Text) { | | < < < < < < < < < | | > > | > | | < < | | < | | < < < < < < < < < < < < < < < < < < < | | > > | > | | | > | < < | < < < < < < < < < < < | | < < < < | | | < < | < < | | < < < < < < | < > | < < < < < < > > | < | < | | < | > < < < < | | | < < < | < | < < < | < < < < < | < | < | < | < | < | > > | > | > > < < < < < < < < < < < < < < < < < < < < < < < < < > > > > > | 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | { return CommandType.Text; } set { if (value != CommandType.Text) { throw new NotImplementedException(); } } } /// <summary> /// Create a new parameter /// </summary> /// <returns></returns> protected override DbParameter CreateDbParameter() { return new SQLiteParameter(); } /// <summary> /// The connection associated with this command /// </summary> protected override DbConnection DbConnection { get { return _cnn; } set { if (_dataReader != null) throw new InvalidOperationException("Cannot set Connection while a DataReader is active"); if (_cnn != null) { ClearCommands(); _cnn._commandList.Remove(this); } _cnn = (SQLiteConnection)value; _cnn._commandList.Add(this); if (_commandText != null) BuildCommands(); } } /// <summary> /// Returns the SQLiteParameterCollection for the given command /// </summary> protected override DbParameterCollection DbParameterCollection { get { return _parameterCollection; } } /// <summary> /// The transaction associated with this command. SQLite only supports one transaction per connection, so this property forwards to the /// command's underlying connection. /// </summary> protected override DbTransaction DbTransaction { get { return _cnn._activeTransaction; } set { if (_cnn == null) return; if (value != _cnn._activeTransaction && value != null) { throw new ArgumentOutOfRangeException(); } } } /// <summary> /// /// </summary> /// <param name="behavior"></param> /// <returns></returns> protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) { if (_dataReader != null) throw new InvalidOperationException("DataReader already active on this command"); if (_cnn == null) throw new InvalidOperationException("No connection associated with this Command"); if (_cnn.State != ConnectionState.Open) throw new InvalidOperationException("Database is not open"); int n; if (_statementList.Length == 0) { BuildCommands(); } // Make sure all parameters are mapped properly to associated statement(s) _parameterCollection.MapParameters(); // Bind all parameters to their statements for (n = 0; n < _statementList.Length; n++) _statementList[n].BindParameters(); _cnn._sql.SetTimeout(_commandTimeout * 1000); _dataReader = new SQLiteDataReader(this, behavior); return _dataReader; } internal void ClearDataReader() { _dataReader = null; } /// <summary> /// Execute the command and return the number of rows inserted/updated affected by it. /// </summary> /// <returns></returns> public override int ExecuteNonQuery() { using (DbDataReader rd = ExecuteDbDataReader(CommandBehavior.Default)) { rd.Close(); return rd.RecordsAffected; } } /// <summary> /// Execute the command and return the first column of the first row of the resultset (if present), or null if no resultset was returned. /// </summary> /// <returns></returns> public override object ExecuteScalar() { using (DbDataReader rd = ExecuteDbDataReader(CommandBehavior.Default)) { if (rd.Read()) return rd[0]; } return null; } /// <summary> /// Prepares the command for execution. /// </summary> public override void Prepare() { if (_statementList.Length == 0) { BuildCommands(); } } /// <summary> /// Sets the method the SQLiteCommandBuilder uses to determine how to update inserted or updated rows in a DataTable. /// </summary> public override UpdateRowSource UpdatedRowSource { |
︙ | ︙ | |||
537 538 539 540 541 542 543 | return _designTimeVisible; } set { _designTimeVisible = value; } } | | < < < < < < < < < < | < < < < | 379 380 381 382 383 384 385 386 387 | return _designTimeVisible; } set { _designTimeVisible = value; } } } } |
Added System.Data.SQLite/SQLiteCommandBase.cs.
> > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | using System; namespace System.Data.SQLite { internal sealed class SQLiteCommandBase : IDisposable { internal SQLiteBase _sqlbase; internal string _strCommand; internal int _sqlite_stmt; internal SQLiteCommandBase(SQLiteBase sqlbase, int stmt, string strCommand) { _sqlbase = sqlbase; _sqlite_stmt = stmt; _strCommand = strCommand; } #region IDisposable Members public void Dispose() { _sqlbase.Finalize(this); } #endregion } } |
Changes to System.Data.SQLite/SQLiteCommandBuilder.cs.
1 2 3 4 5 6 7 8 9 10 11 12 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data; using System.Data.Common; | < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data; using System.Data.Common; /// <summary> /// SQLite implementation of DbCommandBuilder. /// </summary> public sealed class SQLiteCommandBuilder : DbCommandBuilder { /// <summary> /// Default constructor /// </summary> public SQLiteCommandBuilder() { } |
︙ | ︙ | |||
41 42 43 44 45 46 47 | /// </summary> /// <param name="parameter">The parameter to use in applying custom behaviors to a row</param> /// <param name="row">The row to apply the parameter to</param> /// <param name="statementType">The type of statement</param> /// <param name="whereClause">Whether the application of the parameter is part of a WHERE clause</param> protected override void ApplyParameterInfo(DbParameter parameter, DataRow row, StatementType statementType, bool whereClause) { | < < | | | | | > > > > > > > > > > > > | > | < | < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | /// </summary> /// <param name="parameter">The parameter to use in applying custom behaviors to a row</param> /// <param name="row">The row to apply the parameter to</param> /// <param name="statementType">The type of statement</param> /// <param name="whereClause">Whether the application of the parameter is part of a WHERE clause</param> protected override void ApplyParameterInfo(DbParameter parameter, DataRow row, StatementType statementType, bool whereClause) { } /// <overloads> /// Not implemented. Throws a NotImplementedException() if called. /// </overloads> /// <summary> /// Not implemented. /// </summary> /// <param name="parameterName">The name of the parameter</param> /// <returns>Error</returns> protected override string GetParameterName(string parameterName) { throw new NotImplementedException(); } /// <summary> /// Not implemented. /// </summary> /// <param name="parameterOrdinal">The ordinal of the parameter</param> /// <returns>Error</returns> protected override string GetParameterName(int parameterOrdinal) { return null; } /// <summary> /// Returns a placeholder character for the specified parameter ordinal. /// </summary> /// <param name="parameterOrdinal">The index of the parameter to provide a placeholder for</param> /// <returns>Returns a "?" character, used for all placeholders.</returns> protected override string GetParameterPlaceholder(int parameterOrdinal) { return "?"; } #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// Obsolete /// </summary> [Obsolete] protected override DbProviderFactory ProviderFactory { get { return new SQLiteFactory(); } } #endif /// <summary> /// Not implemented. /// </summary> /// <param name="adapter">A data adapter to receive events on.</param> protected override void SetRowUpdatingHandler(DbDataAdapter adapter) { } } } |
Changes to System.Data.SQLite/SQLiteConnection.cs.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data; using System.Data.Common; using System.Collections.Generic; | < | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data; using System.Data.Common; using System.Collections.Generic; /// <summary> /// The I/O file cache flushing behavior for the connection /// </summary> public enum SyncMode { /// <summary> /// Normal file flushing at critical sections of the code /// </summary> Normal = 0, /// <summary> /// Full file flushing after every write operation |
︙ | ︙ | |||
82 83 84 85 86 87 88 | /// </item> /// <item> /// <description>Page Size</description> /// <description>{size in bytes}</description> /// <description>N</description> /// <description>1024</description> /// </item> | < < < < < < | < < < < > > | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | /// </item> /// <item> /// <description>Page Size</description> /// <description>{size in bytes}</description> /// <description>N</description> /// <description>1024</description> /// </item> /// </list> /// </remarks> public sealed class SQLiteConnection : DbConnection, ICloneable { /// <summary> /// State of the current connection /// </summary> private ConnectionState _connectionState; /// <summary> /// The connection string /// </summary> private string _connectionString; /// <summary> /// One transaction allowed per connection please! /// </summary> internal DbTransaction _activeTransaction; /// <summary> /// The base SQLite object to interop with /// </summary> internal SQLiteBase _sql; /// <summary> /// Commands associated with this connection /// </summary> internal List<SQLiteCommand> _commandList; #if !PLATFORM_COMPACTFRAMEWORK /// <event/> /// <summary> /// This event is raised whenever the database is opened or closed. /// </summary> public override event StateChangeEventHandler StateChange; #endif ///<overloads> /// Constructs a new SQLiteConnection object /// </overloads> /// <summary> /// Default constructor /// </summary> |
︙ | ︙ | |||
165 166 167 168 169 170 171 | // Reattach all attached databases from the existing connection using (DataTable tbl = cnn.GetSchema("Catalogs")) { foreach (DataRow row in tbl.Rows) { str = row[0].ToString(); | | < | < < < | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | // Reattach all attached databases from the existing connection using (DataTable tbl = cnn.GetSchema("Catalogs")) { foreach (DataRow row in tbl.Rows) { str = row[0].ToString(); if (String.Compare(str, "MAIN", true) != 0 && String.Compare(str, "TEMP", true) != 0) { _sql.Execute(String.Format("ATTACH DATABASE '{0}' AS [{1}]", row[1], row[0])); } } } } } #if PLATFORM_COMPACTFRAMEWORK public override int ConnectionTimeout { get { return 30; } } |
︙ | ︙ | |||
213 214 215 216 217 218 219 | if (connectionString != null) ConnectionString = connectionString; } /// <summary> /// Disposes of the SQLiteConnection, closing it if it is active. /// </summary> | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > < < < | < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | if (connectionString != null) ConnectionString = connectionString; } /// <summary> /// Disposes of the SQLiteConnection, closing it if it is active. /// </summary> /// <param name="bDisposing">True if the connection is being explicitly closed.</param> protected override void Dispose(bool bDisposing) { base.Dispose(bDisposing); Close(); } internal void OnStateChange(ConnectionState newState) { ConnectionState oldState = _connectionState; _connectionState = newState; #if !PLATFORM_COMPACTFRAMEWORK if (StateChange != null && oldState != newState) { StateChangeEventArgs e = new StateChangeEventArgs(oldState, newState); StateChange(this, e); } #endif } /// <summary> /// Creates a new SQLiteTransaction if one isn't already active on the connection. /// </summary> /// <param name="isolationLevel">SQLite doesn't support varying isolation levels, so this parameter is ignored.</param> /// <returns>Returns a SQLiteTransaction object.</returns> protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) { if (_connectionState != ConnectionState.Open) throw new InvalidOperationException(); if (_activeTransaction != null) throw new ArgumentException("Transaction already pending"); _activeTransaction = new SQLiteTransaction(this); return _activeTransaction; } /// <summary> /// Not implemented /// </summary> /// <param name="databaseName"></param> public override void ChangeDatabase(string databaseName) { throw new NotImplementedException(); } /// <summary> /// When the database connection is closed, all commands linked to this connection are automatically reset. /// </summary> public override void Close() { if (_sql != null) { for (int n = 0; n < _commandList.Count; n++) { _commandList[n].ClearCommands(); } _sql.Close(); } _sql = null; |
︙ | ︙ | |||
461 462 463 464 465 466 467 | /// <description>N</description> /// <description>Normal</description> /// </item> /// <item> /// <description>Page Size</description> /// <description>{size in bytes}</description> /// <description>N</description> | < < < < < | < | 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | /// <description>N</description> /// <description>Normal</description> /// </item> /// <item> /// <description>Page Size</description> /// <description>{size in bytes}</description> /// <description>N</description> /// <description>4096</description> /// </item> /// </list> /// </remarks> public override string ConnectionString { get { |
︙ | ︙ | |||
493 494 495 496 497 498 499 | } } /// <summary> /// Create a new SQLiteCommand and associate it with this connection. /// </summary> /// <returns>Returns an instantiated SQLiteCommand object already assigned to this connection.</returns> | | < < < < < < < | < < < < | < | < < | < > < | > > | < | < | | | | < < < < < > | < | | | | | | | < | < | | | | | | | 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 | } } /// <summary> /// Create a new SQLiteCommand and associate it with this connection. /// </summary> /// <returns>Returns an instantiated SQLiteCommand object already assigned to this connection.</returns> protected override DbCommand CreateDbCommand() { return new SQLiteCommand(this); } /// <summary> /// Not implemented. Returns null. /// </summary> public override string DataSource { get { return null; } } /// <summary> /// Not implemented. Returns null. /// </summary> public override string Database { get { return null; } } /// <summary> /// Parses the connection string into component parts /// </summary> /// <returns>An array of key-value pairs representing each parameter of the connection string</returns> internal KeyValuePair<string, string>[] ParseConnectionString() { string s = _connectionString; int n; KeyValuePair<string, string> kv; List<KeyValuePair<string, string>> ls = new List<KeyValuePair<string, string>>(); // First split into semi-colon delimited values. The Split() function of SQLiteBase accounts for and properly // skips semi-colons in quoted strings string[] arParts = SQLiteConvert.Split(s, ';'); string[] arPiece; // For each semi-colon piece, split into key and value pairs by the presence of the = sign for (n = 0; n < arParts.Length; n++) { arPiece = SQLiteConvert.Split(arParts[n], '='); if (arPiece.Length == 2) { kv.Key = arPiece[0]; kv.Value = arPiece[1]; ls.Add(kv); } } KeyValuePair<string, string>[] ar = new KeyValuePair<string, string>[ls.Count]; ls.CopyTo(ar, 0); // Return the array of key-value pairs return ar; } /// <summary> /// Looks for a key in the array of key/values of the parameter string. If not found, return the specified default value /// </summary> /// <param name="opts">The Key/Value pair array to look in</param> /// <param name="key">The key to find</param> /// <param name="defValue">The default value to return if the key is not found</param> /// <returns>The value corresponding to the specified key, or the default value if not found.</returns> internal string FindKey(KeyValuePair<string, string>[] opts, string key, string defValue) { for (int n = 0; n < opts.Length; n++) { if (String.Compare(opts[n].Key, key, true) == 0) { return opts[n].Value; } } return defValue; } /// <summary> /// Opens the connection using the parameters found in the <see cref="ConnectionString">ConnectionString</see> /// </summary> public override void Open() { if (_connectionState != ConnectionState.Closed) throw new InvalidOperationException(); Close(); KeyValuePair<string, string>[] opts = ParseConnectionString(); if (Convert.ToInt32(FindKey(opts, "Version", "3")) != 3) throw new NotImplementedException("Only SQLite Version 3 is supported at this time"); try { string strFile = FindKey(opts, "Data Source", ""); bool bUTF16 = (Convert.ToBoolean(FindKey(opts, "UseUTF16Encoding", "False")) == true); if (bUTF16) _sql = new SQLite3_UTF16(String.Compare(FindKey(opts, "DateTimeFormat", "ISO8601"), "TICKS") == 0 ? DateTimeFormat.Ticks : DateTimeFormat.ISO8601); else _sql = new SQLite3(String.Compare(FindKey(opts, "DateTimeFormat", "ISO8601"), "TICKS") == 0 ? DateTimeFormat.Ticks : DateTimeFormat.ISO8601); _sql.Open(strFile); if (bUTF16 == true) _sql.Execute("PRAGMA encoding = 'UTF-16'"); else _sql.Execute("PRAGMA encoding = 'UTF-8'"); _sql.Execute(String.Format("PRAGMA Synchronous={0}", FindKey(opts, "Synchronous", "Normal"))); _sql.Execute(String.Format("PRAGMA Cache_Size={0}", FindKey(opts, "Cache Size", "2000"))); if (String.Compare(strFile, ":MEMORY:", true) != 0) _sql.Execute(String.Format("PRAGMA Page_Size={0}", FindKey(opts, "Page Size", "1024"))); } catch (SQLiteException e) { OnStateChange(ConnectionState.Broken); throw (e); } OnStateChange(ConnectionState.Open); } /// <summary> /// Returns the version of the underlying SQLite database engine /// </summary> |
︙ | ︙ | |||
653 654 655 656 657 658 659 | } /// <summary> /// Returns the state of the connection. /// </summary> public override ConnectionState State { | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 | } /// <summary> /// Returns the state of the connection. /// </summary> public override ConnectionState State { get { return _connectionState; } } ///<overloads> /// The following commands are used to extract schema information out of the database. Valid schema types are: /// <list type="bullet"> /// <item> /// <description>MetaDataCollections</description> |
︙ | ︙ | |||
772 773 774 775 776 777 778 | throw new InvalidOperationException(); string[] parms = new string[5]; restrictionValues.CopyTo(parms, 0); if (restrictionValues == null) restrictionValues = new string[0]; | | < < < < < < < < < < | < < < < | > < > > > | > > > | > > > | > > > > > > > > > > > > > > > < < < < < | 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 | throw new InvalidOperationException(); string[] parms = new string[5]; restrictionValues.CopyTo(parms, 0); if (restrictionValues == null) restrictionValues = new string[0]; switch (collectionName.ToUpper()) { case "METADATACOLLECTIONS": return Schema_MetaDataCollections(); case "DATASOURCEINFORMATION": return Schema_DataSourceInformation(); case "COLUMNS": return Schema_Columns(parms[0], parms[2], parms[3]); case "INDEXES": return Schema_Indexes(parms[0], parms[2], parms[4]); case "TABLES": return Schema_Tables(parms[0], parms[2], parms[3]); case "VIEWS": return Schema_Views(parms[0], parms[2]); case "CATALOGS": return Schema_Catalogs(parms[0]); } return null; } private DataTable Schema_MetaDataCollections() { DataTable tbl = new DataTable("MetaDataCollections"); DataRow row; tbl.Columns.Add("CollectionName", typeof(string)); tbl.Columns.Add("NumberOfRestrictions", typeof(int)); tbl.Columns.Add("NumberOfIdentifierParts", typeof(int)); tbl.BeginLoadData(); row = tbl.NewRow(); row.ItemArray = new object[] { "MetaDataCollections", 0, 0 }; tbl.Rows.Add(row); row = tbl.NewRow(); row.ItemArray = new object[] { "DataSourceInformation", 0, 0 }; tbl.Rows.Add(row); row = tbl.NewRow(); row.ItemArray = new object[] { "Catalogs", 1, 1 }; tbl.Rows.Add(row); row = tbl.NewRow(); row.ItemArray = new object[] { "Columns", 4, 4 }; tbl.Rows.Add(row); row = tbl.NewRow(); row.ItemArray = new object[] { "Indexes", 5, 4 }; tbl.Rows.Add(row); row = tbl.NewRow(); row.ItemArray = new object[] { "Tables", 4, 3 }; tbl.Rows.Add(row); row = tbl.NewRow(); row.ItemArray = new object[] { "Views", 3, 3 }; tbl.Rows.Add(row); tbl.AcceptChanges(); tbl.EndLoadData(); return tbl; } private DataTable Schema_DataSourceInformation() { DataTable tbl = new DataTable("DataSourceInformation"); DataRow row; tbl.Columns.Add("CompositeIdentifierSeparatorPattern", typeof(string)); tbl.Columns.Add("DataSourceProductName", typeof(string)); tbl.Columns.Add("DataSourceProductVersion", typeof(string)); tbl.Columns.Add("DataSourceProductVersionNormalized", typeof(string)); tbl.Columns.Add("GroupByBehavior", typeof(int)); tbl.Columns.Add("IdentifierPattern", typeof(string)); tbl.Columns.Add("IdentifierCase", typeof(int)); |
︙ | ︙ | |||
861 862 863 864 865 866 867 | tbl.BeginLoadData(); // TODO: Fixup the regular expressions to support only the SQLite stuff, they were originally cloned // from JET's DataSourceInformation return result. row = tbl.NewRow(); row.ItemArray = new object[] { | | > > | < < | < > | | < < < > | > > < < < < < < < < | | | | | | < < < < < < < < | | | | | | | | | < | | | | | | | | | | | < | < < < < < < < < < < < | < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | > | | | < | | < | < | < < < < < < < < < < < > > > > > | | | | | < | | < < < < < < < < < | | | | < | | < | < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 | tbl.BeginLoadData(); // TODO: Fixup the regular expressions to support only the SQLite stuff, they were originally cloned // from JET's DataSourceInformation return result. row = tbl.NewRow(); row.ItemArray = new object[] { DBNull.Value, "SQLite", _sql.Version, _sql.Version, 3, @"[^ ][^\.!`\[\]]*", 1, DBNull.Value, "?", "?", 0, DBNull.Value, @"`(([^`]|``)*)`", 1, DBNull.Value, DBNull.Value, DBNull.Value }; tbl.Rows.Add(row); tbl.AcceptChanges(); tbl.EndLoadData(); return tbl; } private DataTable Schema_Columns(string strCatalog, string strTable, string strColumn) { DataTable tbl = new DataTable("Columns"); DataRow row; tbl.Columns.Add("TABLE_CATALOG", typeof(string)); tbl.Columns.Add("TABLE_SCHEMA", typeof(string)); tbl.Columns.Add("TABLE_NAME", typeof(string)); tbl.Columns.Add("COLUMN_NAME", typeof(string)); tbl.Columns.Add("COLUMN_GUID", typeof(Guid)); tbl.Columns.Add("COLUMN_PROPID", typeof(long)); tbl.Columns.Add("ORDINAL_POSITION", typeof(long)); tbl.Columns.Add("COLUMN_HASDEFAULT", typeof(bool)); tbl.Columns.Add("COLUMN_DEFAULT", typeof(string)); tbl.Columns.Add("COLUMN_FLAGS", typeof(long)); tbl.Columns.Add("IS_NULLABLE", typeof(bool)); tbl.Columns.Add("DATA_TYPE", typeof(int)); tbl.Columns.Add("TYPE_GUID", typeof(Guid)); tbl.Columns.Add("CHARACTER_MAXIMUM_LENGTH", typeof(long)); tbl.Columns.Add("CHARACTER_OCTET_LENGTH", typeof(long)); tbl.Columns.Add("NUMERIC_PRECISION", typeof(int)); tbl.Columns.Add("NUMERIC_SCALE", typeof(short)); tbl.Columns.Add("DATETIME_PRECISION", typeof(long)); tbl.Columns.Add("CHARACTER_SET_CATALOG", typeof(string)); tbl.Columns.Add("CHARACTER_SET_SCHEMA", typeof(string)); tbl.Columns.Add("CHARACTER_SET_NAME", typeof(string)); tbl.Columns.Add("COLLATION_CATALOG", typeof(string)); tbl.Columns.Add("COLLATION_SCHEMA", typeof(string)); tbl.Columns.Add("COLLATION_NAME", typeof(string)); tbl.Columns.Add("DOMAIN_CATALOG", typeof(string)); tbl.Columns.Add("DOMAIN_NAME", typeof(string)); tbl.Columns.Add("DESCRIPTION", typeof(string)); tbl.BeginLoadData(); if (strCatalog == null || strCatalog == "") strCatalog = "main"; using (SQLiteCommand cmd = new SQLiteCommand(String.Format("SELECT * FROM [{0}].[{1}]", strCatalog, strTable), this)) { using (SQLiteDataReader rd = (SQLiteDataReader)cmd.ExecuteReader()) { using (DataTable tblSchema = rd.GetSchemaTable()) { foreach (DataRow schemaRow in tblSchema.Rows) { if (String.Compare(schemaRow[SchemaTableColumn.ColumnName].ToString(), strColumn, true) == 0 || strColumn == null) { row = tbl.NewRow(); row["TABLE_NAME"] = strTable; row["COLUMN_NAME"] = schemaRow[SchemaTableColumn.ColumnName]; row["TABLE_CATALOG"] = schemaRow[SchemaTableOptionalColumn.BaseCatalogName]; row["ORDINAL_POSITION"] = schemaRow[SchemaTableColumn.ColumnOrdinal]; row["COLUMN_HASDEFAULT"] = (schemaRow[SchemaTableOptionalColumn.DefaultValue] != DBNull.Value); row["COLUMN_DEFAULT"] = schemaRow[SchemaTableOptionalColumn.DefaultValue]; row["IS_NULLABLE"] = schemaRow[SchemaTableColumn.AllowDBNull]; row["DATA_TYPE"] = schemaRow[SchemaTableColumn.ProviderType]; row["CHARACTER_MAXIMUM_LENGTH"] = schemaRow[SchemaTableColumn.ColumnSize]; tbl.Rows.Add(row); } } } } } tbl.AcceptChanges(); tbl.EndLoadData(); return tbl; } private DataTable Schema_Indexes(string strCatalog, string strIndex, string strTable) { DataTable tbl = new DataTable("Indexes"); DataRow row; tbl.Columns.Add("TABLE_CATALOG", typeof(string)); tbl.Columns.Add("TABLE_SCHEMA", typeof(string)); tbl.Columns.Add("TABLE_NAME", typeof(string)); tbl.Columns.Add("INDEX_CATALOG", typeof(string)); tbl.Columns.Add("INDEX_SCHEMA", typeof(string)); tbl.Columns.Add("INDEX_NAME", typeof(string)); tbl.Columns.Add("PRIMARY_KEY", typeof(bool)); tbl.Columns.Add("UNIQUE", typeof(bool)); tbl.Columns.Add("CLUSTERED", typeof(bool)); tbl.Columns.Add("TYPE", typeof(int)); tbl.Columns.Add("FILL_FACTOR", typeof(int)); tbl.Columns.Add("INITIAL_SIZE", typeof(int)); tbl.Columns.Add("NULLS", typeof(int)); tbl.Columns.Add("SORT_BOOKMARKS", typeof(bool)); tbl.Columns.Add("AUTO_UPDATE", typeof(bool)); tbl.Columns.Add("NULL_COLLATION", typeof(int)); tbl.Columns.Add("ORDINAL_POSITION", typeof(long)); tbl.Columns.Add("COLUMN_NAME", typeof(string)); tbl.Columns.Add("COLUMN_GUID", typeof(Guid)); tbl.Columns.Add("COLUMN_PROPID", typeof(long)); tbl.Columns.Add("COLLATION", typeof(short)); tbl.Columns.Add("CARDINALITY", typeof(Decimal)); tbl.Columns.Add("PAGES", typeof(int)); tbl.Columns.Add("FILTER_CONDITION", typeof(string)); tbl.Columns.Add("INTEGRATED", typeof(bool)); tbl.BeginLoadData(); if (strCatalog == null || strCatalog == "") strCatalog = "main"; using (SQLiteCommand cmd = new SQLiteCommand(String.Format("SELECT * FROM [{0}].[sqlite_master] WHERE [type] = 'index'", strCatalog), this)) { using (SQLiteDataReader rd = (SQLiteDataReader)cmd.ExecuteReader()) { while (rd.Read()) { if (String.Compare(rd.GetString(1), strIndex, true) == 0 || strIndex == null) { if (String.Compare(rd.GetString(2), strTable, true) == 0 || strTable == null) { row = tbl.NewRow(); row["TABLE_CATALOG"] = strCatalog; row["TABLE_NAME"] = rd.GetString(2); row["INDEX_NAME"] = rd.GetString(1); tbl.Rows.Add(row); } } } } } tbl.AcceptChanges(); tbl.EndLoadData(); return tbl; } private DataTable Schema_Tables(string strCatalog, string strTable, string strType) { DataTable tbl = new DataTable("Tables"); DataRow row; string strItem; tbl.Columns.Add("TABLE_CATALOG", typeof(string)); tbl.Columns.Add("TABLE_SCHEMA", typeof(string)); tbl.Columns.Add("TABLE_NAME", typeof(string)); tbl.Columns.Add("TABLE_TYPE", typeof(string)); tbl.Columns.Add("TABLE_GUID", typeof(Guid)); tbl.Columns.Add("DESCRIPTION", typeof(string)); tbl.Columns.Add("TABLE_PROPID", typeof(long)); tbl.Columns.Add("DATE_CREATED", typeof(DateTime)); tbl.Columns.Add("DATE_MODIFIED", typeof(DateTime)); tbl.BeginLoadData(); if (strCatalog == null || strCatalog == "") strCatalog = "main"; using (SQLiteCommand cmd = new SQLiteCommand(String.Format("SELECT * FROM [{0}].[sqlite_master] WHERE [type] NOT LIKE 'index'", strCatalog), this)) { using (SQLiteDataReader rd = (SQLiteDataReader)cmd.ExecuteReader()) { while (rd.Read()) { strItem = rd.GetString(0).ToUpper(); if (rd.GetString(2).ToUpper().IndexOf("SQLITE_") == 0) strItem = "SYSTEM TABLE"; if (String.Compare(strItem, strType, true) == 0 || strType == null) { if (String.Compare(rd.GetString(2), strTable, true) == 0 || strTable == null) { row = tbl.NewRow(); row["TABLE_CATALOG"] = strCatalog; row["TABLE_NAME"] = rd.GetString(2); row["TABLE_TYPE"] = strItem; tbl.Rows.Add(row); } } } } } tbl.AcceptChanges(); tbl.EndLoadData(); return tbl; } private DataTable Schema_Views(string strCatalog, string strView) { DataTable tbl = new DataTable("Views"); DataRow row; string strItem; int nPos; tbl.Columns.Add("TABLE_CATALOG", typeof(string)); tbl.Columns.Add("TABLE_SCHEMA", typeof(string)); tbl.Columns.Add("TABLE_NAME", typeof(string)); tbl.Columns.Add("VIEW_DEFINITION", typeof(string)); tbl.Columns.Add("CHECK_OPTION", typeof(bool)); tbl.Columns.Add("IS_UPDATEABLE", typeof(bool)); tbl.Columns.Add("DESCRIPTION", typeof(string)); tbl.Columns.Add("DATE_CREATED", typeof(DateTime)); tbl.Columns.Add("DATE_MODIFIED", typeof(DateTime)); tbl.BeginLoadData(); if (strCatalog == null || strCatalog == "") strCatalog = "main"; using (SQLiteCommand cmd = new SQLiteCommand(String.Format("SELECT * FROM [{0}].[sqlite_master] WHERE [type] LIKE 'view'", strCatalog), this)) { using (SQLiteDataReader rd = (SQLiteDataReader)cmd.ExecuteReader()) { while (rd.Read()) { if (String.Compare(rd.GetString(1), strView, true) == 0 || strView == null) { strItem = rd.GetString(4); nPos = Globalization.CultureInfo.InvariantCulture.CompareInfo.IndexOf(strItem, " AS "); if (nPos > -1) { strItem = strItem.Substring(nPos + 4); row = tbl.NewRow(); row["TABLE_CATALOG"] = strCatalog; row["TABLE_NAME"] = rd.GetString(2); row["IS_UPDATEABLE"] = false; row["VIEW_DEFINITION"] = strItem; tbl.Rows.Add(row); } } } } } tbl.AcceptChanges(); tbl.EndLoadData(); return tbl; } private DataTable Schema_Catalogs(string strCatalog) { DataTable tbl = new DataTable("Catalogs"); DataRow row; tbl.Columns.Add("CATALOG_NAME", typeof(string)); tbl.Columns.Add("DESCRIPTION", typeof(string)); tbl.BeginLoadData(); using (SQLiteCommand cmd = new SQLiteCommand("PRAGMA database_list", this)) { using (SQLiteDataReader rd = (SQLiteDataReader)cmd.ExecuteReader()) { while (rd.Read()) { if (strCatalog == null || String.Compare(rd.GetString(1), strCatalog, true) == 0) { row = tbl.NewRow(); row["CATALOG_NAME"] = rd.GetString(1); tbl.Rows.Add(row); } } } } tbl.AcceptChanges(); tbl.EndLoadData(); return tbl; } } } |
Changes to System.Data.SQLite/SQLiteConnectionStringBuilder.cs.
1 2 3 4 5 6 7 8 9 10 11 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data.Common; | < < < < < < < < < < < < < | | | < < < < > > > | > > > > | > > > > | > > | > > > > > < < < < | | < < < | | > > > > > > > > > > > > > | < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < | < < | | | > | < | < | | | | < < < < < < < | | | < | < | | | < < < < < < < < < | | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data.Common; #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// SQLite implementation of DbConnectionStringBuilder. /// </summary> public sealed class SQLiteConnectionStringBuilder : DbConnectionStringBuilder { /// <overloads> /// Constructs a new instance of the class /// </overloads> /// <summary> /// Default constructor /// </summary> public SQLiteConnectionStringBuilder() { Initialize(null); } /// <summary> /// Constructs a new instance of the class using the specified connection string. /// </summary> /// <param name="cnnString">The connection string to parse</param> public SQLiteConnectionStringBuilder(string cnnString) { Initialize(cnnString); } private void Initialize(string cnnString) { ConnectionString = cnnString; Reset(); } internal void Reset() { if (this.ContainsKey("Version") == false) Version = 3; if (ContainsKey("UseUTF16Encoding") == false) UseUTF16Encoding = false; if (ContainsKey("Cache Size") == false) CacheSize = 2000; if (ContainsKey("Synchronous") == false) SyncMode = SyncMode.Normal; if (ContainsKey("DateTimeFormat") == false) DateTimeFormat = DateTimeFormat.ISO8601; if (ContainsKey("Page Size") == false) PageSize = 4096; } /// <summary> /// Gets/Sets the default version of the SQLite engine to instantiate. Currently the only valid value is 3, indicating version 3 of the sqlite library. /// </summary> public int Version { get { return Convert.ToInt32(this["Version"]); } set { if (value != 3) throw new NotImplementedException(); this["Version"] = value; } } /// <summary> /// Gets/Sets the synchronous mode of the connection string. Default is "Normal". /// </summary> public SyncMode SyncMode { get { string s = this["Synchronous"].ToString().ToUpper(); switch (s) { case "FULL": return SyncMode.Full; case "OFF": return SyncMode.Off; default: return SyncMode.Normal; } } set { string s = "Normal"; if (value == SyncMode.Full) s = "Full"; else if (value == SyncMode.Off) s = "Off"; this["Synchronous"] = s; } } /// <summary> /// Gets/Sets the encoding for the connection string. The default is "False" which indicates UTF-8 encoding. /// </summary> public bool UseUTF16Encoding { get { return (this["UseUTF16Encoding"].ToString().ToUpper() == "TRUE"); } set { this["UseUTF16Encoding"] = ((value == true) ? "True" : "False"); } } /// <summary> /// Gets/Sets the filename to open on the connection string. /// </summary> public string DataSource { get { return this["Data Source"].ToString(); } set { this["Data Source"] = value; } } /// <summary> /// Gets/Sets the page size for the connection. /// </summary> public int PageSize { get { return Convert.ToInt32(this["Page Size"]); } set { this["Page Size"] = value; } } /// <summary> /// Gets/Sets the cache size for the connection. /// </summary> public int CacheSize { get { return Convert.ToInt32(this["Cache Size"]); } set { this["Cache Size"] = value; } } /// <summary> /// Gets/Sets the datetime format for the connection. /// </summary> public DateTimeFormat DateTimeFormat { get { switch(this["DateTimeFormat"].ToString().ToUpper()) { case "TICKS": return DateTimeFormat.Ticks; default: return DateTimeFormat.ISO8601; } } set { switch (value) { case DateTimeFormat.Ticks: this["DateTimeFormat"] = "Ticks"; break; case DateTimeFormat.ISO8601: this["DateTimeFormat"] = "ISO8601"; break; } } } } #endif } |
Changes to System.Data.SQLite/SQLiteConvert.cs.
1 2 3 4 5 6 7 8 9 10 11 12 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Runtime.InteropServices; using System.Collections.Generic; | < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Runtime.InteropServices; using System.Collections.Generic; /// <summary> /// SQLite has very limited types, and is inherently text-based. The first 5 types below represent the sum of all types SQLite /// understands. The DateTime extension to the spec is for internal use only. /// </summary> public enum TypeAffinity { /// <summary> /// All integers in SQLite default to Int64 /// </summary> Int64 = 1, /// <summary> /// All floating point numbers in SQLite default to double /// </summary> Double = 2, |
︙ | ︙ | |||
47 48 49 50 51 52 53 | /// <summary> /// Null types can be returned from functions /// </summary> Null = 5, /// <summary> /// Used internally by this provider /// </summary> | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < | | | > | > > > > > > > > > > > > | | > | | | | | | | | | | | | | | | | > | | | | | | > > > | > > > > > > > > > > > > > > > > > > > | > > > > > > | | | | | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | /// <summary> /// Null types can be returned from functions /// </summary> Null = 5, /// <summary> /// Used internally by this provider /// </summary> DateTime = 128, /// <summary> /// Used internally by this provider /// </summary> None=256, } /// <summary> /// This implementation of SQLite for ADO.NET can process date/time fields in databases in only one of two formats. Ticks and ISO8601. /// Ticks is inherently more accurate, but less compatible with 3rd party tools that query the database, and renders the DateTime field /// unreadable without post-processing. /// ISO8601 is more compatible, readable, fully-processable, but less accurate as it doesn't provide time down to fractions of a second. /// </summary> public enum DateTimeFormat { /// <summary> /// Using ticks is more accurate but less compatible with other viewers and utilities that access your database. /// </summary> Ticks = 0, /// <summary> /// The default format for this provider. More compatible with SQLite's intended usage of datetimes, but overall less accurate than Ticks as it doesn't /// natively support times down to fractions of a second. /// </summary> ISO8601 = 1, } /// <summary> /// This base class provides datatype conversion services for the SQLite provider. /// </summary> public abstract class SQLiteConvert { /// <summary> /// An array of ISO8601 datetime formats we support conversion from /// </summary> private static string[] _datetimeFormats; /// <summary> /// An UTF-8 Encoding instance, so we can convert strings to and from UTF8 /// </summary> private Text.UTF8Encoding _utf8; /// <summary> /// The default DateTime format for this instance /// </summary> private DateTimeFormat _datetimeFormat; /// <summary> /// Static constructor, initializes the supported ISO8601 date time formats /// </summary> static SQLiteConvert() { _datetimeFormats = new string[] {"yyyy-MM-dd HH:mm:ss", "yyyyMMddHHmmss", "yyyyMMddTHHmmssfffffff", "yyyy-MM-dd", "yy-MM-dd", "yyyyMMdd", "HH:mm:ss", "THHmmss" }; } internal SQLiteConvert(DateTimeFormat fmt) { _datetimeFormat = fmt; _utf8 = new System.Text.UTF8Encoding(); } #region UTF-8 Conversion Functions /// <summary> /// Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character. /// </summary> /// <param name="strSrc">The string to convert to UTF-8</param> /// <returns>A byte array containing the converted string plus an extra 0 terminating byte at the end of the array.</returns> public byte[] ToUTF8(string strSrc) { Byte[] b; int nlen = _utf8.GetByteCount(strSrc) + 1; b = new byte[nlen]; nlen = _utf8.GetBytes(strSrc, 0, strSrc.Length, b, 0); b[nlen] = 0; return b; } /// <summary> /// Convert a DateTime to a UTF-8 encoded, zero-terminated byte array. /// </summary> /// <remarks> /// This function is a convenience function, which first calls ToString() on the DateTime, and then calls ToUTF8() with the /// string result. /// </remarks> /// <param name="dtSrc">The DateTime to convert.</param> /// <returns>The UTF-8 encoded string, including a 0 terminating byte at the end of the array.</returns> public byte[] ToUTF8(DateTime dtSrc) { return ToUTF8(ToString(dtSrc)); } /// <summary> /// Converts a UTF-8 encoded IntPtr of the specified length into a .NET string /// </summary> /// <param name="b">The pointer to the memory where the UTF-8 string is encoded</param> /// <param name="nlen">The number of bytes to decode</param> /// <returns>A string containing the translated character(s)</returns> public virtual string ToString(IntPtr b, int nlen) { if (nlen == 0) return ""; byte[] byt; byt = new byte[nlen]; Marshal.Copy(b, byt, 0, nlen); return _utf8.GetString(byt, 0, nlen); } #endregion #region DateTime Conversion Functions /// <summary> /// Converts a string into a DateTime, using the current DateTimeFormat specified for the connection when it was opened. /// </summary> /// <remarks> /// Acceptable ISO8601 DateTime formats are: /// yyyy-MM-dd HH:mm:ss /// yyyyMMddHHmmss /// yyyyMMddTHHmmssfffffff /// yyyy-MM-dd /// yy-MM-dd /// yyyyMMdd /// HH:mm:ss /// THHmmss /// </remarks> /// <param name="strSrc">The string containing either a Tick value or an ISO8601-format string</param> /// <returns>A DateTime value</returns> public DateTime ToDateTime(string strSrc) { switch (_datetimeFormat) { case DateTimeFormat.Ticks: return new DateTime(Convert.ToInt64(strSrc)); default: return DateTime.ParseExact(strSrc, _datetimeFormats, System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None); } } /// <summary> /// Attempt to convert the specified string to a datetime value. /// </summary> /// <param name="strSrc">The string to parse into a datetime</param> /// <param name="result">If successful, a valid datetime structure</param> /// <returns>Returns true if the string was a valid ISO8601 datetime, false otherwise.</returns> public bool TryToDateTime(string strSrc, out DateTime result) { switch (_datetimeFormat) { case DateTimeFormat.ISO8601: return DateTime.TryParseExact(strSrc, _datetimeFormats, System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None, out result); case DateTimeFormat.Ticks: { long n; if (long.TryParse(strSrc, out n) == true) { result = new DateTime(n); return true; } } break; } result = DateTime.Now; return false; } /// <summary> /// Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened. /// </summary> /// <param name="dtSrc">The DateTime value to convert</param> /// <returns>Either a string consisting of the tick count for DateTimeFormat.Ticks, or a date/time in ISO8601 format.</returns> public string ToString(DateTime dtSrc) { switch (_datetimeFormat) { case DateTimeFormat.Ticks: return dtSrc.Ticks.ToString(); default: return dtSrc.ToString(_datetimeFormats[0]); } } /// <summary> /// Internal function to convert a UTF-8 encoded IntPtr of the specified length to a DateTime. /// </summary> /// <remarks> |
︙ | ︙ | |||
279 280 281 282 283 284 285 | /// [0] One<br/> /// [1] Two<br/> /// [2] Three, Four<br/> /// [3] Five<br/> /// <br/> /// Note that the leading and trailing spaces were removed from each item during the split. /// </remarks> | | | | | | | | | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | < | < < < | < < < < < | | | | | | | | | | | > > > | > > > > > > | > | > > > | > | > > | < | | | > | > | | > | | | | | > | > > | > > | | | | | | < | | | | > | < < < < > | < | | | < < < | < | | | | | | | | | | > | | | | | | | | > | < > | | < | > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 | /// [0] One<br/> /// [1] Two<br/> /// [2] Three, Four<br/> /// [3] Five<br/> /// <br/> /// Note that the leading and trailing spaces were removed from each item during the split. /// </remarks> /// <param name="src">Source string to split apart</param> /// <param name="sep">Separator character</param> /// <returns>A string array of the split up elements</returns> public static string[] Split(string src, char sep) { char[] toks = new char[2] { '\"', sep }; char[] quot = new char[1] { '\"' }; int n = 0; List<string> ls = new List<string>(); string s; while (src.Length > 0) { n = src.IndexOfAny(toks, n); if (n == -1) break; if (src[n] == toks[0]) { src = src.Remove(n, 1); n = src.IndexOfAny(quot, n); if (n == -1) { src = "\"" + src; break; } src = src.Remove(n, 1); } else { s = src.Substring(0, n).Trim(); src = src.Substring(n + 1).Trim(); if (s.Length > 0) ls.Add(s); n = 0; } } if (src.Length > 0) ls.Add(src); string[] ar = new string[ls.Count]; ls.CopyTo(ar, 0); return ar; } #region Type Conversions /// <summary> /// For a given intrinsic type, return a DbType /// </summary> /// <param name="typ">The native type to convert</param> /// <returns>The corresponding (closest match) DbType</returns> internal static DbType TypeToDbType(Type typ) { switch (Type.GetTypeCode(typ)) { case TypeCode.Int16: return DbType.Int16; case TypeCode.Int32: return DbType.Int32; case TypeCode.Int64: return DbType.Int64; case TypeCode.UInt16: return DbType.UInt16; case TypeCode.UInt32: return DbType.UInt32; case TypeCode.UInt64: return DbType.UInt64; case TypeCode.Double: return DbType.Double; case TypeCode.Single: return DbType.Single; case TypeCode.Decimal: return DbType.Decimal; case TypeCode.Boolean: return DbType.Boolean; case TypeCode.SByte: case TypeCode.Char: return DbType.SByte; case TypeCode.DateTime: return DbType.DateTime; case TypeCode.String: return DbType.String; case TypeCode.Object: if (typ == typeof(byte[])) return DbType.Binary; if (typ == typeof(Guid)) return DbType.Guid; return DbType.String; } return DbType.String; } /// <summary> /// Convert a DbType to a Type /// </summary> /// <param name="typ">The DbType to convert from</param> /// <returns>The closest-match .NET type</returns> internal static Type DbTypeToType(DbType typ) { switch (typ) { case DbType.Binary: return typeof(byte[]); case DbType.Boolean: return typeof(bool); case DbType.Byte: return typeof(byte); case DbType.Currency: case DbType.Decimal: return typeof(decimal); case DbType.DateTime: return typeof(DateTime); case DbType.Double: return typeof(double); case DbType.Guid: return typeof(Guid); case DbType.Int16: case DbType.UInt16: return typeof(Int16); case DbType.Int32: case DbType.UInt32: return typeof(Int32); case DbType.Int64: case DbType.UInt64: return typeof(Int64); case DbType.String: return typeof(string); case DbType.SByte: return typeof(char); case DbType.Single: return typeof(float); } return typeof(string); } /// <summary> /// For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types. /// </summary> /// <param name="typ">The type to evaluate</param> /// <returns>The SQLite type affinity for that type.</returns> internal static TypeAffinity TypeToAffinity(Type typ) { switch (Type.GetTypeCode(typ)) { case TypeCode.DBNull: return TypeAffinity.Null; case TypeCode.String: return TypeAffinity.Text; case TypeCode.DateTime: return TypeAffinity.DateTime; case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: case TypeCode.Char: case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Boolean: return TypeAffinity.Int64; case TypeCode.Double: case TypeCode.Single: case TypeCode.Decimal: return TypeAffinity.Double; case TypeCode.Object: if (typ == typeof(byte[])) return TypeAffinity.Blob; else return TypeAffinity.Text; } return TypeAffinity.Text; } /// <summary> /// For a given type name, return a closest-match .NET type /// </summary> /// <param name="Name">The name of the type to match</param> /// <returns>The .NET DBType the text evaluates to.</returns> internal static DbType TypeNameToDbType(string Name) { if (Name == null) return DbType.Object; Name = Name.ToUpper(); if (Name.IndexOf("LONGTEXT") > -1) return DbType.String; if (Name.IndexOf("LONGCHAR") > -1) return DbType.String; if (Name.IndexOf("SMALLINT") > -1) return DbType.Int16; if (Name.IndexOf("BIGINT") > -1) return DbType.Int64; if (Name.IndexOf("COUNTER") > -1) return DbType.Int64; if (Name.IndexOf("AUTOINCREMENT") > -1) return DbType.Int64; if (Name.IndexOf("IDENTITY") > -1) return DbType.Int64; if (Name.IndexOf("LONG") > -1) return DbType.Int64; if (Name.IndexOf("TINYINT") > -1) return DbType.Byte; if (Name.IndexOf("INTEGER") > -1) return DbType.Int64; if (Name.IndexOf("INT") > -1) return DbType.Int32; if (Name.IndexOf("TEXT") > -1) return DbType.String; if (Name.IndexOf("DOUBLE") > -1) return DbType.Double; if (Name.IndexOf("FLOAT") > -1) return DbType.Double; if (Name.IndexOf("REAL") > -1) return DbType.Single; if (Name.IndexOf("BIT") > -1) return DbType.Boolean; if (Name.IndexOf("YESNO") > -1) return DbType.Boolean; if (Name.IndexOf("LOGICAL") > -1) return DbType.Boolean; if (Name.IndexOf("BOOL") > -1) return DbType.Boolean; if (Name.IndexOf("NUMERIC") > -1) return DbType.Decimal; if (Name.IndexOf("DECIMAL") > -1) return DbType.Decimal; if (Name.IndexOf("MONEY") > -1) return DbType.Decimal; if (Name.IndexOf("CURRENCY") > -1) return DbType.Decimal; if (Name.IndexOf("TIME") > -1) return DbType.DateTime; if (Name.IndexOf("DATE") > -1) return DbType.DateTime; if (Name.IndexOf("BLOB") > -1) return DbType.Binary; if (Name.IndexOf("BINARY") > -1) return DbType.Binary; if (Name.IndexOf("IMAGE") > -1) return DbType.Binary; if (Name.IndexOf("GENERAL") > -1) return DbType.Binary; if (Name.IndexOf("OLEOBJECT") > -1) return DbType.Binary; if (Name.IndexOf("GUID") > -1) return DbType.Guid; if (Name.IndexOf("UNIQUEIDENTIFIER") > -1) return DbType.Guid; if (Name.IndexOf("MEMO") > -1) return DbType.String; if (Name.IndexOf("NOTE") > -1) return DbType.String; if (Name.IndexOf("CHAR") > -1) return DbType.String; return DbType.Object; } #endregion } } |
Changes to System.Data.SQLite/SQLiteDataAdapter.cs.
1 2 3 4 5 6 7 8 9 10 11 12 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data; using System.Data.Common; | < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data; using System.Data.Common; /// <summary> /// SQLite implementation of DbDataAdapter. /// </summary> public sealed class SQLiteDataAdapter : DbDataAdapter { /// <overloads> /// This class is just a shell around the DbDataAdapter. Nothing from DbDataAdapter is overridden here, just a few constructors are defined. /// </overloads> /// <summary> /// Default constructor. /// </summary> public SQLiteDataAdapter() |
︙ | ︙ | |||
41 42 43 44 45 46 47 | { SelectCommand = cmd; } /// <summary> /// Constructs a data adapter with the supplied select command text and associated with the specified connection. /// </summary> | | | | | | | | | | < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | { SelectCommand = cmd; } /// <summary> /// Constructs a data adapter with the supplied select command text and associated with the specified connection. /// </summary> /// <param name="CommandText">The select command text to associate with the data adapter.</param> /// <param name="cnn">The connection to associate with the select command.</param> public SQLiteDataAdapter(string CommandText, SQLiteConnection cnn) { SelectCommand = new SQLiteCommand(CommandText, cnn); } /// <summary> /// Constructs a data adapter with the specified select command text, and using the specified database connection string. /// </summary> /// <param name="CommandText">The select command text to use to construct a select command.</param> /// <param name="ConnectionString">A connection string suitable for passing to a new SQLiteConnection, which is associated with the select command.</param> public SQLiteDataAdapter(string CommandText, string ConnectionString) { SQLiteConnection cnn = new SQLiteConnection(ConnectionString); SelectCommand = new SQLiteCommand(CommandText, cnn); } } } |
Changes to System.Data.SQLite/SQLiteDataReader.cs.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data; using System.Data.Common; using System.Collections.Generic; | | | > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data; using System.Data.Common; using System.Collections.Generic; internal struct SQLiteType { internal DbType Type; internal TypeAffinity Affinity; } /// <summary> /// SQLite implementation of DbDataReader. /// </summary> public sealed class SQLiteDataReader : DbDataReader { /// <summary> |
︙ | ︙ | |||
53 54 55 56 57 58 59 | private SQLiteType[] _fieldTypeArray; /// <summary> /// The behavior of the datareader /// </summary> private CommandBehavior _commandBehavior; | < < < < < | < < | < < < < > > | < < < < | | < < < < < < < < < | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | private SQLiteType[] _fieldTypeArray; /// <summary> /// The behavior of the datareader /// </summary> private CommandBehavior _commandBehavior; internal SQLiteDataReader(SQLiteCommand cmd, CommandBehavior behave) { _command = cmd; _commandBehavior = behave; Initialize(); } internal void Initialize() { _activeStatementIndex = -1; _activeStatement = null; _rowsAffected = -1; _fieldCount = -1; NextResult(); } /// <summary> /// Closes the datareader, potentially closing the connection as well if CommandBehavior.CloseConnection was specified. /// </summary> public override void Close() { if (_command != null) { while (NextResult()) ; _command.ClearDataReader(); } // If the datareader's behavior includes closing the connection, then do so here. if ((_commandBehavior & CommandBehavior.CloseConnection) != 0) _command.Connection.Close(); _command = null; } /// <summary> /// Disposes the datareader. Calls Close() to ensure everything is cleaned up. /// </summary> public override void Dispose() { Close(); GC.SuppressFinalize(this); } /// <summary> /// Throw an error if the datareader is closed /// </summary> private void CheckClosed() { if (_command == null) throw new InvalidOperationException("DataReader has been closed"); } /// <summary> /// Enumerator support /// </summary> /// <returns>Returns a DbEnumerator object.</returns> public override Collections.IEnumerator GetEnumerator() { return new DbEnumerator(this); } /// <summary> /// /// </summary> public override int Depth { get { CheckClosed(); return 0; } } /// <summary> /// /// </summary> public override int FieldCount { get { CheckClosed(); return _fieldCount; |
︙ | ︙ | |||
172 173 174 175 176 177 178 | /// This function attempts to verify that the type of data being requested of a column matches the datatype of the column. In /// the case of columns that are not backed into a table definition, we attempt to match up the affinity of a column (int, double, string or blob) /// to a set of known types that closely match that affinity. It's not an exact science, but its the best we can do. /// </summary> /// <returns> /// This function throws an InvalidTypeCast() exception if the requested type doesn't match the column's definition or affinity. /// </returns> | | | < | > > | | | | | | | | | | | | | | | | | | | | | | | | | > < | | | > | | | | | | > | | | | | | | | < | < < | > | | > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > | > > | | | > | | | | < < < < < | < < | > | | < > | | | < | < < | | | | | > | < | > > < < < < < < > | | | > > > > > > > > | | > | | | | > | | | | | | < < | < < < < < < < | | < | < < < < < < | < < < < | | | | > | | | | | | > | | | | | | > | | | | | | | | | | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 | /// This function attempts to verify that the type of data being requested of a column matches the datatype of the column. In /// the case of columns that are not backed into a table definition, we attempt to match up the affinity of a column (int, double, string or blob) /// to a set of known types that closely match that affinity. It's not an exact science, but its the best we can do. /// </summary> /// <returns> /// This function throws an InvalidTypeCast() exception if the requested type doesn't match the column's definition or affinity. /// </returns> /// <param name="ordinal">The index of the column to type-check</param> /// <param name="typ">The type we want to get out of the column</param> private void VerifyType(int ordinal, DbType typ) { SQLiteType t = GetSQLiteType(ordinal); if (t.Type == typ) return; if (t.Type != DbType.Object) { // Coercable type, usually a literal of some kind switch (_fieldTypeArray[ordinal].Affinity) { case TypeAffinity.Int64: if (typ == DbType.Int16) return; if (typ == DbType.Int32) return; if (typ == DbType.Int64) return; if (typ == DbType.Boolean) return; if (typ == DbType.Byte) return; break; case TypeAffinity.Double: if (typ == DbType.Single) return; if (typ == DbType.Double) return; if (typ == DbType.Decimal) return; break; case TypeAffinity.Text: if (typ == DbType.SByte) return; if (typ == DbType.String) return; if (typ == DbType.SByte) return; if (typ == DbType.Guid) return; if (typ == DbType.DateTime) return; break; case TypeAffinity.Blob: if (typ == DbType.String) return; if (typ == DbType.Binary) return; break; } } throw new InvalidCastException(); } /// <summary> /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override bool GetBoolean(int ordinal) { CheckClosed(); VerifyType(ordinal, DbType.Boolean); return Convert.ToBoolean(GetValue(ordinal)); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override byte GetByte(int ordinal) { CheckClosed(); VerifyType(ordinal, DbType.Byte); return Convert.ToByte(_activeStatement._sql.GetInt32(_activeStatement, ordinal)); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <param name="dataOffset"></param> /// <param name="buffer"></param> /// <param name="bufferOffset"></param> /// <param name="length"></param> /// <returns></returns> public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) { CheckClosed(); VerifyType(ordinal, DbType.Binary); return _activeStatement._sql.GetBytes(_activeStatement, ordinal, (int)dataOffset, buffer, bufferOffset, length); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override char GetChar(int ordinal) { CheckClosed(); VerifyType(ordinal, DbType.SByte); return Convert.ToChar(_activeStatement._sql.GetInt32(_activeStatement, ordinal)); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <param name="dataOffset"></param> /// <param name="buffer"></param> /// <param name="bufferOffset"></param> /// <param name="length"></param> /// <returns></returns> public override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length) { CheckClosed(); VerifyType(ordinal, DbType.String); return _activeStatement._sql.GetChars(_activeStatement, ordinal, (int)dataOffset, buffer, bufferOffset, length); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override string GetDataTypeName(int ordinal) { CheckClosed(); return _activeStatement._sql.ColumnName(_activeStatement, ordinal); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override DateTime GetDateTime(int ordinal) { CheckClosed(); VerifyType(ordinal, DbType.DateTime); return _activeStatement._sql.GetDateTime(_activeStatement, ordinal); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override decimal GetDecimal(int ordinal) { CheckClosed(); VerifyType(ordinal, DbType.Decimal); return Convert.ToDecimal(_activeStatement._sql.GetDouble(_activeStatement, ordinal)); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override double GetDouble(int ordinal) { CheckClosed(); VerifyType(ordinal, DbType.Double); return _activeStatement._sql.GetDouble(_activeStatement, ordinal); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override Type GetFieldType(int ordinal) { CheckClosed(); SQLiteType t = GetSQLiteType(ordinal); if (t.Type != DbType.Object) return SQLiteConvert.DbTypeToType(t.Type); switch (t.Affinity) { case TypeAffinity.Null: return typeof(DBNull); case TypeAffinity.Int64: return typeof(Int64); case TypeAffinity.Double: return typeof(Double); case TypeAffinity.Blob: return typeof(byte[]); default: return typeof(string); } } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override float GetFloat(int ordinal) { CheckClosed(); VerifyType(ordinal, DbType.Single); return Convert.ToSingle(_activeStatement._sql.GetDouble(_activeStatement, ordinal)); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override Guid GetGuid(int ordinal) { CheckClosed(); VerifyType(ordinal, DbType.Guid); return new Guid(_activeStatement._sql.GetText(_activeStatement, ordinal)); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override Int16 GetInt16(int ordinal) { CheckClosed(); VerifyType(ordinal, DbType.Int16); return Convert.ToInt16(_activeStatement._sql.GetInt32(_activeStatement, ordinal)); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override Int32 GetInt32(int ordinal) { CheckClosed(); VerifyType(ordinal, DbType.Int32); return _activeStatement._sql.GetInt32(_activeStatement, ordinal); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override Int64 GetInt64(int ordinal) { CheckClosed(); VerifyType(ordinal, DbType.Int64); return _activeStatement._sql.GetInt64(_activeStatement, ordinal); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override string GetName(int ordinal) { CheckClosed(); return _activeStatement._sql.ColumnName(_activeStatement, ordinal); } /// <summary> /// /// </summary> /// <param name="name"></param> /// <returns></returns> public override int GetOrdinal(string name) { CheckClosed(); return _activeStatement._sql.ColumnIndex(_activeStatement, name); } /// <summary> |
︙ | ︙ | |||
432 433 434 435 436 437 438 | /// original connection's existing statements or state. Any attached databases are re-attached to the new connection. /// </remarks> /// <returns>Returns a DataTable containing the schema information for the active SELECT statement being processed.</returns> public override DataTable GetSchemaTable() { CheckClosed(); | | < | | | | | | < < | < < | | | | | | | | | | | | | > | | | | | < | < < | | > | > > > > > | | | | > | | < > | | | > > | > | > > > | > | > > > < > | | > | | | | | | | | | | | | > > | | | | < < | < < < < < < < < | < < < < > < > < < < < < < < | < | | | | | | 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 | /// original connection's existing statements or state. Any attached databases are re-attached to the new connection. /// </remarks> /// <returns>Returns a DataTable containing the schema information for the active SELECT statement being processed.</returns> public override DataTable GetSchemaTable() { CheckClosed(); DataTable tbl = new DataTable("Schema"); string[] arName; string strTable; string strCatalog; DataRow row; tbl.Columns.Add(SchemaTableColumn.ColumnName, typeof(String)); tbl.Columns.Add(SchemaTableColumn.ColumnOrdinal, typeof(Int32)); tbl.Columns.Add(SchemaTableColumn.ColumnSize, typeof(Int32)); tbl.Columns.Add(SchemaTableColumn.NumericPrecision, typeof(Int32)); tbl.Columns.Add(SchemaTableColumn.NumericScale, typeof(Int32)); tbl.Columns.Add(SchemaTableColumn.DataType, typeof(Type)); tbl.Columns.Add(SchemaTableColumn.ProviderType, typeof(Int32)); tbl.Columns.Add(SchemaTableColumn.IsLong, typeof(Boolean)); tbl.Columns.Add(SchemaTableColumn.AllowDBNull, typeof(Boolean)); tbl.Columns.Add(SchemaTableOptionalColumn.IsReadOnly, typeof(Boolean)); tbl.Columns.Add(SchemaTableOptionalColumn.IsRowVersion, typeof(Boolean)); tbl.Columns.Add(SchemaTableColumn.IsUnique, typeof(Boolean)); tbl.Columns.Add(SchemaTableColumn.IsKey, typeof(Boolean)); tbl.Columns.Add(SchemaTableOptionalColumn.IsAutoIncrement, typeof(Boolean)); tbl.Columns.Add(SchemaTableColumn.BaseSchemaName, typeof(String)); tbl.Columns.Add(SchemaTableOptionalColumn.BaseCatalogName, typeof(String)); tbl.Columns.Add(SchemaTableColumn.BaseTableName, typeof(String)); tbl.Columns.Add(SchemaTableColumn.BaseColumnName, typeof(String)); tbl.Columns.Add(SchemaTableOptionalColumn.BaseColumnNamespace, typeof(string)); tbl.Columns.Add(SchemaTableOptionalColumn.DefaultValue, typeof(object)); tbl.BeginLoadData(); SQLiteConnection cnn = (SQLiteConnection)_command.Connection; try { cnn._sql.SetRealColNames(true); // Create a new command based on the original. The only difference being that this new command returns // fully-qualified Database.Table.Column column names because of the above pragma using (SQLiteCommand cmd = new SQLiteCommand(_activeStatement._sqlStatement, cnn)) { using (DbDataReader rd = cmd.ExecuteReader()) { // No need to Read() from this reader, we just want the column names for (int n = 0; n < FieldCount; n++) { strTable = ""; strCatalog = "main"; row = tbl.NewRow(); // Default settings for the column row[SchemaTableColumn.ColumnName] = GetName(n); row[SchemaTableColumn.ColumnOrdinal] = n; row[SchemaTableColumn.ColumnSize] = 0; row[SchemaTableColumn.NumericPrecision] = 0; row[SchemaTableColumn.NumericScale] = 0; row[SchemaTableColumn.DataType] = GetFieldType(n); row[SchemaTableColumn.ProviderType] = GetSQLiteType(n).Type; row[SchemaTableColumn.IsLong] = false; row[SchemaTableColumn.AllowDBNull] = true; row[SchemaTableOptionalColumn.IsReadOnly] = true; row[SchemaTableOptionalColumn.IsRowVersion] = false; row[SchemaTableColumn.IsUnique] = false; row[SchemaTableColumn.IsKey] = false; row[SchemaTableOptionalColumn.IsAutoIncrement] = false; row[SchemaTableOptionalColumn.IsReadOnly] = false; row[SchemaTableColumn.BaseColumnName] = GetName(n); // Try and extract the database, table and column from the datareader arName = rd.GetName(n).Split('.'); if (arName.Length > 1) strTable = arName[arName.Length - 2]; if (arName.Length > 2) strCatalog = arName[arName.Length - 3]; // If we have a table-bound column, extract the extra information from it if (arName.Length > 1) { using (SQLiteCommand cmdTable = new SQLiteCommand(String.Format("PRAGMA [{1}].TABLE_INFO([{0}])", strTable, strCatalog), cnn)) { if (arName.Length < 3) strCatalog = ""; using (DbDataReader rdTable = cmdTable.ExecuteReader()) { while (rdTable.Read()) { if (String.Compare(arName[arName.Length - 1], rdTable.GetString(1), true) == 0) { string strType = rdTable.GetString(2); string[] arSize = strType.Split('('); if (arSize.Length > 1) { arSize = arSize[1].Split(')'); if (arSize.Length > 1) row["ColumnSize"] = Convert.ToInt32(arSize[0]); } bool bNotNull = rdTable.GetBoolean(3); bool bPrimaryKey = rdTable.GetBoolean(5); row[SchemaTableColumn.BaseTableName] = strTable; row[SchemaTableColumn.BaseColumnName] = rdTable.GetString(1); if (strCatalog.Length > 0) { row[SchemaTableOptionalColumn.BaseColumnNamespace] = strCatalog; row[SchemaTableColumn.BaseSchemaName] = strCatalog; } row[SchemaTableColumn.AllowDBNull] = (!bNotNull && !bPrimaryKey); row[SchemaTableColumn.IsUnique] = bPrimaryKey; row[SchemaTableColumn.IsKey] = bPrimaryKey; row[SchemaTableOptionalColumn.IsAutoIncrement] = (bPrimaryKey && String.Compare(strType, "Integer", true) == 0); row[SchemaTableOptionalColumn.IsReadOnly] = !(bool)row[SchemaTableOptionalColumn.IsAutoIncrement]; if (rdTable.IsDBNull(4) == false) row[SchemaTableOptionalColumn.DefaultValue] = rdTable[4]; break; } } } } } tbl.Rows.Add(row); } } } } catch (Exception e) { throw (e); } finally { cnn._sql.SetRealColNames(false); } tbl.AcceptChanges(); tbl.EndLoadData(); return tbl; } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override string GetString(int ordinal) { CheckClosed(); VerifyType(ordinal, DbType.String); return _activeStatement._sql.GetText(_activeStatement, ordinal); } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override object GetValue(int ordinal) { CheckClosed(); if (IsDBNull(ordinal)) return DBNull.Value; if (GetFieldType(ordinal) == typeof(byte[])) { int n = (int)GetBytes(ordinal, 0, null, 0, 0); byte[] b = new byte[n]; GetBytes(ordinal, 0, b, 0, n); return b; } return Convert.ChangeType(_activeStatement._sql.GetText(_activeStatement, ordinal), GetFieldType(ordinal), null); } /// <summary> /// /// </summary> /// <param name="values"></param> /// <returns></returns> public override int GetValues(object[] values) { CheckClosed(); int nMax = FieldCount; if (values.Length < nMax) nMax = values.Length; for (int n = 0; n < nMax; n++) { values.SetValue(GetValue(n), n); } return nMax; } /// <summary> /// /// </summary> public override bool HasRows { get { CheckClosed(); return (_readingState != 2); } } /// <summary> /// /// </summary> public override bool IsClosed { get { return (_command == null); } } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override bool IsDBNull(int ordinal) { CheckClosed(); return _activeStatement._sql.IsNull(_activeStatement, ordinal); } /// <summary> /// /// </summary> /// <returns></returns> public override bool NextResult() { CheckClosed(); SQLiteStatement stmt; int fieldCount; while (true) { _readingState = 2; // HasRows() returns false, Read() returns false if (_activeStatement != null) { // Reset the previously-executed command _activeStatement._sql.Reset(_activeStatement); // If we're only supposed to return a single rowset, step through all remaining statements once until // they are all done and return false to indicate no more resultsets exist. if ((_commandBehavior & CommandBehavior.SingleResult) != 0) { while (_activeStatementIndex + 1 != _command._statementList.Length) { _activeStatementIndex++; stmt = _command._statementList[_activeStatementIndex]; stmt._sql.Step(stmt); stmt._sql.Reset(stmt); // Gotta reset after every step to release any locks and such! } return false; } } // If we've reached the end of the statements, return false, no more resultsets if (_activeStatementIndex + 1 == _command._statementList.Length) return false; _activeStatementIndex++; stmt = _command._statementList[_activeStatementIndex]; fieldCount = stmt._sql.ColumnCount(stmt); // If we're told to get schema information only, then don't perform an initial step() through the resultset if ((_commandBehavior & CommandBehavior.SchemaOnly) == 0 || fieldCount == 0) { if (stmt._sql.Step(stmt)) { _readingState = -1; } else if (fieldCount == 0) // No rows returned, if fieldCount is zero, skip to the next statement { stmt._sql.Reset(stmt); continue; // Skip this command and move to the next, it was not a row-returning resultset } else // No rows, fieldCount is non-zero so stop here { _readingState = 1; // This command returned columns but no rows, so return true, but HasRows = false and Read() returns false } } // Ahh, we found a row-returning resultset eligible to be returned! _activeStatement = stmt; _fieldCount = fieldCount; _fieldTypeArray = null; return true; } } private SQLiteType GetSQLiteType(int ordinal) { if (_fieldTypeArray == null) _fieldTypeArray = new SQLiteType[_fieldCount]; if (_fieldTypeArray[ordinal].Affinity == 0) _fieldTypeArray[ordinal].Type = SQLiteConvert.TypeNameToDbType(_activeStatement._sql.ColumnType(_activeStatement, ordinal, out _fieldTypeArray[ordinal].Affinity)); return _fieldTypeArray[ordinal]; } /// <summary> /// /// </summary> /// <returns></returns> public override bool Read() { CheckClosed(); if (_readingState == -1) // First step was already done at the NextResult() level, so don't step again, just return true. { _readingState = 0; |
︙ | ︙ | |||
770 771 772 773 774 775 776 | _readingState = 1; // Finished reading rows } return false; } /// <summary> | | | | | | | | | | | 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 | _readingState = 1; // Finished reading rows } return false; } /// <summary> /// /// </summary> public override int RecordsAffected { get { return _rowsAffected; } } /// <summary> /// /// </summary> /// <param name="name"></param> /// <returns></returns> public override object this[string name] { get { return GetValue(GetOrdinal(name)); } } /// <summary> /// /// </summary> /// <param name="ordinal"></param> /// <returns></returns> public override object this[int ordinal] { get { return GetValue(ordinal); } } } } |
Changes to System.Data.SQLite/SQLiteException.cs.
1 2 3 4 5 6 7 8 9 10 11 12 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Collections.Generic; using System.Text; | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > > | | < > | > | < < < < < < | | > | | < < < < < < < | < > | | > | < | < < | > | > | | < | < > | < < | | < > | < < | < | < < < < < < < < | | | > | | | | | > | < | | | > < < < < < < < < < < < < < < < | < | > | > | > | > | > | > | > | > | < > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Collections.Generic; using System.Text; /// <summary> /// SQLite exception class. /// </summary> public sealed class SQLiteException : Exception { internal SQLiteException(int nCode) : base(Initialize(nCode, null)) { HResult = (int)((uint)0x800F0000 | (uint)nCode); } internal SQLiteException(int nCode, string strMessage) : base(Initialize(nCode, strMessage)) { HResult = (int)((uint)0x800F0000 | (uint)nCode); } private static string Initialize(int nCode, string strMessage) { if (strMessage != null) { if (strMessage.Length > 0) strMessage = "\r\n\r\n" + strMessage; } switch (nCode) { case 1: return "SQLite error" + strMessage; case 2: return "An internal logic error in SQLite" + strMessage; case 3: return "Access permission denied" + strMessage; case 4: return "Callback routine requested an abort" + strMessage; case 5: return "The database file is locked" + strMessage; case 6: return "A table in the database is locked" + strMessage; case 7: return "A malloc() failed" + strMessage; case 8: return "Attempt to write a readonly database" + strMessage; case 9: return "Operation terminated by sqlite3_interrupt()" + strMessage; case 10: return "Some kind of disk I/O error occurred" + strMessage; case 11: return "The database disk image is malformed" + strMessage; case 12: return "Table or record not found" + strMessage; case 13: return "Insertion failed because database is full" + strMessage; case 14: return "Unable to open the database file" + strMessage; case 15: return "Database lock protocol error" + strMessage; case 16: return "Database is empty" + strMessage; case 17: return "The database schema changed" + strMessage; case 18: return "Too much data for one row of a table" + strMessage; case 19: return "Abort due to constraint violation" + strMessage; case 20: return "Data type mismatch" + strMessage; case 21: return "Library used incorrectly" + strMessage; case 22: return "Uses OS features not supported on host" + strMessage; case 23: return "Authorization denied" + strMessage; case 24: return "Auxiliary database format error" + strMessage; case 25: return "2nd parameter to sqlite3_bind() out of range" + strMessage; case 26: return "File opened that is not a database file" + strMessage; } return strMessage; } } } |
Changes to System.Data.SQLite/SQLiteFactory.cs.
︙ | ︙ | |||
16 17 18 19 20 21 22 23 24 25 26 27 28 29 | /// </summary> public sealed class SQLiteFactory : DbProviderFactory { /// <summary> /// Static instance member which returns an instanced SQLiteFactory class. /// </summary> public static readonly SQLiteFactory Instance = new SQLiteFactory(); /// <summary> /// Returns a new SQLiteCommand object. /// </summary> /// <returns>A SQLiteCommand object.</returns> public override DbCommand CreateCommand() { | > > > > > > > > > > > > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | /// </summary> public sealed class SQLiteFactory : DbProviderFactory { /// <summary> /// Static instance member which returns an instanced SQLiteFactory class. /// </summary> public static readonly SQLiteFactory Instance = new SQLiteFactory(); /// <summary> /// Returns the types of classes this factory supports /// </summary> [Obsolete] public override DbProviderSupportedClasses SupportedClasses { get { return (DbProviderSupportedClasses)0x3F; } } /// <summary> /// Returns a new SQLiteCommand object. /// </summary> /// <returns>A SQLiteCommand object.</returns> public override DbCommand CreateCommand() { |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteFunction.cs.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; /// <summary> /// The type of user-defined function to declare /// </summary> public enum FunctionType { /// <summary> |
︙ | ︙ | |||
67 68 69 70 71 72 73 | /// information in member variables of user-defined function classes. /// /// For aggregate functions, always create and store your per-statement data in the contextData object on the 1st step. This data will /// be automatically freed for you (and Dispose() called if the item supports IDisposable) when the statement completes. /// </remarks> public abstract class SQLiteFunction : IDisposable { | | < < < < < < < < > > > > < < < < < < < < < < < < > > > > > > > > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | /// information in member variables of user-defined function classes. /// /// For aggregate functions, always create and store your per-statement data in the contextData object on the 1st step. This data will /// be automatically freed for you (and Dispose() called if the item supports IDisposable) when the statement completes. /// </remarks> public abstract class SQLiteFunction : IDisposable { private SQLiteBase _base; private int _interopCookie; #if !PLATFORM_COMPACTFRAMEWORK private SortedList<int, object> _contextDataList; #else private SortedList _contextDataList; #endif private SQLiteCallback _InvokeFunc; private SQLiteCallback _StepFunc; private SQLiteCallback _FinalFunc; private SQLiteCollation _CompareFunc; /// <summary> /// This static list contains all the user-defined functions declared using the proper attributes. /// </summary> private static List<SQLiteFunctionAttribute> _registeredFunctions = new List<SQLiteFunctionAttribute>(); /// <summary> /// Internal constructor, initializes the function's internal variables. /// </summary> protected SQLiteFunction() { #if !PLATFORM_COMPACTFRAMEWORK _contextDataList = new SortedList<int, object>(); #else _contextDataList = new SortedList(); #endif _InvokeFunc = null; _StepFunc = null; _FinalFunc = null; _CompareFunc = null; } /// <summary> /// Returns a reference to the underlying connection's SQLiteConvert class, which can be used to convert /// strings and DateTime's into the current connection's encoding schema. /// </summary> public SQLiteConvert SQLiteConvert |
︙ | ︙ | |||
143 144 145 146 147 148 149 | return null; } /// <summary> /// Aggregate functions override this method to do their magic. /// </summary> /// <remarks> | > | | | | > > > > | 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | return null; } /// <summary> /// Aggregate functions override this method to do their magic. /// </summary> /// <remarks> /// Don't call the ReturnXXX functions of the context object during this function call. Save it for the Final() method. /// Typically you'll just be updating whatever you've placed in the contextData field and returning as quickly as possible. /// </remarks> /// <param name="args">The arguments for the command to process</param> /// <param name="nStep">The 1-based step number. This is incrememted each time the step method is called.</param> /// <param name="contextData">A placeholder for implementers to store contextual data pertaining to the current context.</param> public virtual void Step(object[] args, int nStep, ref object contextData) { } /// <summary> /// Aggregate functions override this method to finish their aggregate processing. /// </summary> /// <remarks> /// This is where you will call one of the ReturnXXX methods of the context class. If you implemented your aggregate properly, /// you've been recording and keeping track of your data in the contextData object provided, and now at this stage you should have /// all the information you need in there to figure out what to return. /// /// Parameters passed to this function have only an affinity for a certain data type, there is no underlying schema available /// to force them into a certain type. Therefore the only types you will ever see as parameters are /// DBNull.Value, Int64, Double, String or byte[] array. /// </remarks> /// <param name="contextData">Your own assigned contextData, provided for you so you can return your final results.</param> /// <returns>You may return most simple types as a return value, null or DBNull.Value to return null, DateTime, or /// you may return an Exception-derived class if you wish to return an error to SQLite. Do not actually throw the error, /// just return it! /// </returns> public virtual object Final(object contextData) |
︙ | ︙ | |||
243 244 245 246 247 248 249 | return parms; } /// <summary> /// Takes the return value from Invoke() and Final() and figures out how to return it to SQLite's context. /// </summary> /// <param name="context">The context the return value applies to</param> | | | | | | < < | | < < | | < | | | | | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | return parms; } /// <summary> /// Takes the return value from Invoke() and Final() and figures out how to return it to SQLite's context. /// </summary> /// <param name="context">The context the return value applies to</param> /// <param name="obj">The parameter to return to SQLite</param> void SetReturnValue(int context, object obj) { if (obj == null || obj == DBNull.Value) { _base.ReturnNull(context); return; } Type t = obj.GetType(); if (t == typeof(DateTime)) { _base.ReturnText(context, _base.ToString((DateTime)obj)); return; } else if (obj as Exception != null) { _base.ReturnError(context, ((Exception)obj).Message); return; } switch (SQLiteConvert.TypeToAffinity(t)) { case TypeAffinity.Null: _base.ReturnNull(context); return; case TypeAffinity.Int64: _base.ReturnInt64(context, Convert.ToInt64(obj)); return; case TypeAffinity.Double: _base.ReturnDouble(context, Convert.ToDouble(obj)); return; case TypeAffinity.Text: _base.ReturnText(context, obj.ToString()); return; case TypeAffinity.Blob: _base.ReturnBlob(context, (byte[])obj); return; } } /// <summary> /// Internal scalar callback function, which wraps the raw context pointer and calls the virtual Invoke() method. /// </summary> |
︙ | ︙ | |||
359 360 361 362 363 364 365 | IDisposable disp = obj as IDisposable; if (disp != null) disp.Dispose(); } /// <summary> /// Placeholder for a user-defined disposal routine /// </summary> | | | > > > > > > > > > < < < < < < < < < < < | < < < < < < < < | | | | | < | | 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 | IDisposable disp = obj as IDisposable; if (disp != null) disp.Dispose(); } /// <summary> /// Placeholder for a user-defined disposal routine /// </summary> /// <param name="bDisposing">True if the object is being disposed explicitly</param> protected virtual void Dispose(bool bDisposing) { } /// <summary> /// Disposes of any active contextData variables that were not automatically cleaned up. Sometimes this can happen if /// someone closes the connection while a DataReader is open. /// </summary> public void Dispose() { Dispose(true); _InvokeFunc = null; _StepFunc = null; _FinalFunc = null; _CompareFunc = null; IDisposable disp; #if !PLATFORM_COMPACTFRAMEWORK foreach (KeyValuePair<int, object> kv in _contextDataList) #else foreach (DictionaryEntry kv in _contextDataList) #endif { disp = kv.Value as IDisposable; if (disp != null) disp.Dispose(); } _contextDataList.Clear(); GC.SuppressFinalize(this); } /// <summary> /// Using reflection, enumerate all assemblies in the current appdomain looking for classes that /// have a SQLiteFunctionAttribute attribute, and registering them accordingly. /// </summary> static SQLiteFunction() { SQLiteFunctionAttribute at; System.Reflection.Assembly[] arAssemblies = System.AppDomain.CurrentDomain.GetAssemblies(); int w = arAssemblies.Length; for (int n = 0; n < w; n++) { Type[] arTypes = arAssemblies[n].GetTypes(); int v = arTypes.Length; for (int x = 0; x < v; x++) { object[] arAtt = arTypes[x].GetCustomAttributes(false); int u = arAtt.Length; for (int y = 0; y < u; y++) { at = arAtt[y] as SQLiteFunctionAttribute; if (at != null) { at.InstanceType = arTypes[x]; _registeredFunctions.Add(at); } } } } } /// <summary> /// Manual method of registering a function. The type must still have the SQLiteFunctionAttributes in order to work /// properly, but this is a workaround for the Compact Framework where enumerating assemblies is not currently supported. /// </summary> /// <param name="typ">The type of the function to register</param> public static void RegisterFunction(Type typ) { object[] arAtt = typ.GetCustomAttributes(false); int u = arAtt.Length; SQLiteFunctionAttribute at; for (int y = 0; y < u; y++) { at = arAtt[y] as SQLiteFunctionAttribute; if (at != null) { at.InstanceType = typ; _registeredFunctions.Add(at); } } } /// <summary> /// Called by SQLiteBase derived classes, this function binds all user-defined functions to a connection. /// It is done this way so that all user-defined functions will access the database using the same encoding scheme /// as the connection (UTF-8 or UTF-16). /// </summary> /// <remarks> /// The wrapper functions that interop with SQLite will create a unique cooke value, which internally is a pointer to /// all the wrapped callback functions. The interop function uses it to map CDecl callbacks to StdCall callbacks. /// </remarks> /// <param name="sqlbase">The base object on which the functions are to bind</param> /// <returns>Returns an array of functions which the connection object should retain until the connection is closed.</returns> internal static SQLiteFunction[] BindFunctions(SQLiteBase sqlbase) { SQLiteFunction f; List<SQLiteFunction> lFunctions = new List<SQLiteFunction>(); foreach (SQLiteFunctionAttribute pr in _registeredFunctions) { f = (SQLiteFunction)Activator.CreateInstance(pr.InstanceType); f._base = sqlbase; f._InvokeFunc = (pr.FuncType == FunctionType.Scalar) ? new SQLiteCallback(f.ScalarCallback) : null; f._StepFunc = (pr.FuncType == FunctionType.Aggregate) ? new SQLiteCallback(f.StepCallback) : null; f._FinalFunc = (pr.FuncType == FunctionType.Aggregate) ? new SQLiteCallback(f.FinalCallback) : null; f._CompareFunc = (pr.FuncType == FunctionType.Collation) ? new SQLiteCollation(f.CompareCallback) : null; if (pr.FuncType != FunctionType.Collation) |
︙ | ︙ | |||
512 513 514 515 516 517 518 | /// </remarks> /// <param name="sqlbase">The base SQLite connection object</param> /// <param name="ar">An array of user-defined functions for this object</param> internal static void UnbindFunctions(SQLiteBase sqlbase, SQLiteFunction[] ar) { if (ar == null) return; | < | | 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 | /// </remarks> /// <param name="sqlbase">The base SQLite connection object</param> /// <param name="ar">An array of user-defined functions for this object</param> internal static void UnbindFunctions(SQLiteBase sqlbase, SQLiteFunction[] ar) { if (ar == null) return; for (int n = 0; n < ar.Length; n++) { sqlbase.FreeFunction(ar[n]._interopCookie); ar[n].Dispose(); } } } } |
Changes to System.Data.SQLite/SQLiteFunctionAttribute.cs.
︙ | ︙ | |||
13 14 15 16 17 18 19 | /// <summary> /// A simple custom attribute to enable us to easily find user-defined functions in /// the loaded assemblies and initialize them in SQLite as connections are made. /// </summary> [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] public sealed class SQLiteFunctionAttribute : Attribute { | > > > | > > > | > > > | > | < | < < < < < < < < < < < < < < < < < < < < < < < < < | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | /// <summary> /// A simple custom attribute to enable us to easily find user-defined functions in /// the loaded assemblies and initialize them in SQLite as connections are made. /// </summary> [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] public sealed class SQLiteFunctionAttribute : Attribute { /// <summary> /// The function's name as it will be used in SQLite command text. /// </summary> public string Name; /// <summary> /// The number of arguments this function expects. -1 if the number of arguments is variable. /// </summary> public int Arguments; /// <summary> /// The type of function this implementation will be. /// </summary> public FunctionType FuncType; internal Type InstanceType; /// <summary> /// Default constructor, initializes the internal variables for the function. /// </summary> public SQLiteFunctionAttribute() { Name = ""; Arguments = -1; FuncType = FunctionType.Scalar; InstanceType = null; } } } |
Changes to System.Data.SQLite/SQLiteParameter.cs.
︙ | ︙ | |||
10 11 12 13 14 15 16 | using System; using System.Data; using System.Data.Common; /// <summary> /// SQLite implementation of DbParameter. /// </summary> | | < < < < < < < < < < < < < < < < < < | | | < | < < < < < < < < < < | | | | | | | | | | | | | < | < < < < < < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < < < | < | < < < | | < < < < > | | > | | < < < < < < < < | < < < < > | | | | | | | | | | | | | | | > > > > > > > > | > > | | > > > > > > > > > > > > > > | | | | | | | | | < < < < < < < | < < < < | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | using System; using System.Data; using System.Data.Common; /// <summary> /// SQLite implementation of DbParameter. /// </summary> public sealed class SQLiteParameter : DbParameter { private int _dbType; private DataRowVersion _rowVersion; private Object _objValue; private string _sourceColumn; private string _columnName; private int _dataSize; /// <summary> /// /// </summary> public SQLiteParameter() { Initialize(null, -1, 0, null, DataRowVersion.Current); } /// <summary> /// /// </summary> /// <param name="parameterName"></param> public SQLiteParameter(string parameterName) { Initialize(parameterName, -1, 0, null, DataRowVersion.Current); } /// <summary> /// /// </summary> /// <param name="parameterName"></param> /// <param name="dbType"></param> public SQLiteParameter(string parameterName, DbType dbType) { Initialize(parameterName, (int)dbType, 0, null, DataRowVersion.Current); } /// <summary> /// /// </summary> /// <param name="parameterName"></param> /// <param name="dbType"></param> /// <param name="sourceColumn"></param> public SQLiteParameter(string parameterName, DbType dbType, string sourceColumn) { Initialize(parameterName, (int)dbType, 0, sourceColumn, DataRowVersion.Current); } /// <summary> /// /// </summary> /// <param name="parameterName"></param> /// <param name="dbType"></param> /// <param name="sourceColumn"></param> /// <param name="rowVersion"></param> public SQLiteParameter(string parameterName, DbType dbType, string sourceColumn, DataRowVersion rowVersion) { Initialize(parameterName, (int)dbType, 0, sourceColumn, rowVersion); } /// <summary> /// /// </summary> /// <param name="dbType"></param> public SQLiteParameter(DbType dbType) { Initialize(null, (int)dbType, 0, null, DataRowVersion.Current); } /// <summary> /// /// </summary> /// <param name="dbType"></param> /// <param name="sourceColumn"></param> public SQLiteParameter(DbType dbType, string sourceColumn) { Initialize(null, (int)dbType, 0, sourceColumn, DataRowVersion.Current); } /// <summary> /// /// </summary> /// <param name="dbType"></param> /// <param name="sourceColumn"></param> /// <param name="rowVersion"></param> public SQLiteParameter(DbType dbType, string sourceColumn, DataRowVersion rowVersion) { Initialize(null, (int)dbType, 0, sourceColumn, rowVersion); } /// <summary> /// /// </summary> /// <param name="parameterName"></param> /// <param name="dbType"></param> /// <param name="nSize"></param> public SQLiteParameter(string parameterName, DbType dbType, int nSize) { Initialize(parameterName, (int)dbType, nSize, null, DataRowVersion.Current); } /// <summary> /// /// </summary> /// <param name="parameterName"></param> /// <param name="dbType"></param> /// <param name="nSize"></param> /// <param name="sourceColumn"></param> public SQLiteParameter(string parameterName, DbType dbType, int nSize, string sourceColumn) { Initialize(parameterName, (int)dbType, nSize, sourceColumn, DataRowVersion.Current); } /// <summary> /// /// </summary> /// <param name="parameterName"></param> /// <param name="dbType"></param> /// <param name="nSize"></param> /// <param name="sourceColumn"></param> /// <param name="rowVersion"></param> public SQLiteParameter(string parameterName, DbType dbType, int nSize, string sourceColumn, DataRowVersion rowVersion) { Initialize(parameterName, (int)dbType, nSize, sourceColumn, rowVersion); } /// <summary> /// /// </summary> /// <param name="dbType"></param> /// <param name="nSize"></param> public SQLiteParameter(DbType dbType, int nSize) { Initialize(null, (int)dbType, nSize, null, DataRowVersion.Current); } /// <summary> /// /// </summary> /// <param name="dbType"></param> /// <param name="nSize"></param> /// <param name="sourceColumn"></param> public SQLiteParameter(DbType dbType, int nSize, string sourceColumn) { Initialize(null, (int)dbType, nSize, sourceColumn, DataRowVersion.Current); } /// <summary> /// /// </summary> /// <param name="dbType"></param> /// <param name="nSize"></param> /// <param name="sourceColumn"></param> /// <param name="rowVersion"></param> public SQLiteParameter(DbType dbType, int nSize, string sourceColumn, DataRowVersion rowVersion) { Initialize(null, (int)dbType, nSize, sourceColumn, rowVersion); } /// <summary> /// /// </summary> /// <param name="parameterName"></param> /// <param name="dbType"></param> /// <param name="nSize"></param> /// <param name="sourceColumn"></param> /// <param name="rowVersion"></param> private void Initialize(string parameterName, int dbType, int nSize, string sourceColumn, DataRowVersion rowVersion) { _columnName = parameterName; _dbType = dbType; _sourceColumn = sourceColumn; _rowVersion = rowVersion; _objValue = null; _dataSize = nSize; } /// <summary> /// /// </summary> public override bool IsNullable { get { return true; } set { } } /// <summary> /// /// </summary> /// <param name="destination"></param> [Obsolete] public override void CopyTo(DbParameter destination) { throw new NotImplementedException(); } /// <summary> /// /// </summary> public override DbType DbType { get { if (_dbType == -1) return DbType.String; // Unassigned default value is String return (DbType)_dbType; } set { _dbType = (int)value; } } /// <summary> /// /// </summary> public override ParameterDirection Direction { get { return ParameterDirection.Input; } set { if (value != ParameterDirection.Input) throw new NotImplementedException(); } } /// <summary> /// /// </summary> public override int Offset { get { throw new NotImplementedException(); } set { } } /// <summary> /// /// </summary> public override string ParameterName { get { return _columnName; } set { _columnName = value; } } /// <summary> /// /// </summary> public override void ResetDbType() { throw new NotImplementedException(); } /// <summary> /// /// </summary> public override int Size { get { return _dataSize; } set { _dataSize = value; } } /// <summary> /// /// </summary> public override string SourceColumn { get { return _sourceColumn; } set { _sourceColumn = value; } } /// <summary> /// /// </summary> public override bool SourceColumnNullMapping { get { return false; } set { } } /// <summary> /// /// </summary> public override DataRowVersion SourceVersion { get { return _rowVersion; } set { _rowVersion = value; } } /// <summary> /// /// </summary> public override object Value { get { return _objValue; } set { _objValue = value; if (_dbType == -1 && _objValue != null && _objValue != DBNull.Value) // If the DbType has never been assigned, try to glean one from the value's datatype _dbType = (int)SQLiteConvert.TypeToDbType(_objValue.GetType()); } } } } |
Changes to System.Data.SQLite/SQLiteParameterCollection.cs.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data; using System.Data.Common; using System.Collections.Generic; | < < < < < < < < < < < < < < < < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | < < < < < < < < < < < < < | | < | | | < | > > > > > > > > > | > > | | | | | | | | | | > | | | > | | | | | | < | | < | | | | | | | | | | | | > | | | > | | | < < < | | < < | < < < < < < < < < | < | | < < | < < < < < < < < < < < < < < < < < < < | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data; using System.Data.Common; using System.Collections.Generic; /// <summary> /// SQLite implementation of DbParameterCollection. /// </summary> public sealed class SQLiteParameterCollection : DbParameterCollection { private SQLiteCommand _command; private List<SQLiteParameter> _parameterList; private bool _unboundFlag; internal SQLiteParameterCollection(SQLiteCommand cmd) { _command = cmd; _parameterList = new List<SQLiteParameter>(); _unboundFlag = true; } /// <summary> /// /// </summary> public override bool IsSynchronized { get { return true; } } /// <summary> /// /// </summary> public override bool IsFixedSize { get { return false; } } /// <summary> /// /// </summary> public override bool IsReadOnly { get { return false; } } /// <summary> /// /// </summary> public override object SyncRoot { get { return null; } } /// <summary> /// /// </summary> /// <returns></returns> public override System.Collections.IEnumerator GetEnumerator() { return _parameterList.GetEnumerator(); } /// <summary> /// /// </summary> /// <param name="paramName"></param> /// <param name="dbType"></param> /// <param name="nSize"></param> /// <param name="sourceColumn"></param> /// <returns></returns> public SQLiteParameter Add(string paramName, DbType dbType, int nSize, string sourceColumn) { SQLiteParameter param = new SQLiteParameter(paramName, dbType, nSize, sourceColumn); Add(param); return param; } /// <summary> /// /// </summary> /// <param name="paramName"></param> /// <param name="dbType"></param> /// <param name="nSize"></param> /// <returns></returns> public SQLiteParameter Add(string paramName, DbType dbType, int nSize) { SQLiteParameter param = new SQLiteParameter(paramName, dbType, nSize); Add(param); return param; } /// <summary> /// /// </summary> /// <param name="paramName"></param> /// <param name="dbType"></param> /// <returns></returns> public SQLiteParameter Add(string paramName, DbType dbType) { SQLiteParameter param = new SQLiteParameter(paramName, dbType); Add(param); return param; } /// <summary> /// /// </summary> /// <param name="p"></param> /// <returns></returns> public int Add(SQLiteParameter p) { int n = -1; if (p.ParameterName != null) { n = IndexOf(p.ParameterName); } if (n == -1) { n = _parameterList.Count; _parameterList.Add(p); } SetParameter(n, p); return n; } /// <summary> /// /// </summary> /// <param name="value"></param> /// <returns></returns> public override int Add(object value) { return Add((SQLiteParameter)value); } /// <summary> /// /// </summary> /// <param name="values"></param> public void AddRange(SQLiteParameter[] values) { for (int n = 0; n < values.Length; n++) Add(values[n]); } /// <summary> /// /// </summary> /// <param name="values"></param> public override void AddRange(Array values) { for (int n = 0; n < values.Length; n++) Add((SQLiteParameter)(values.GetValue(n))); } /// <summary> /// /// </summary> /// <param name="parameterName"></param> /// <returns></returns> [Obsolete] protected override int CheckName(string parameterName) { throw new NotImplementedException(); } /// <summary> /// /// </summary> public override void Clear() { _unboundFlag = true; _parameterList.Clear(); } /// <summary> /// /// </summary> /// <param name="value"></param> /// <returns></returns> public override bool Contains(string value) { return (IndexOf(value) != -1); } /// <summary> /// /// </summary> /// <param name="value"></param> /// <returns></returns> public override bool Contains(object value) { return _parameterList.Contains((SQLiteParameter)value); } /// <summary> /// /// </summary> /// <param name="array"></param> /// <param name="index"></param> public override void CopyTo(Array array, int index) { throw new NotImplementedException(); } /// <summary> /// /// </summary> public override int Count { get { return _parameterList.Count; } } #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// /// </summary> /// <param name="parameterName"></param> /// <returns></returns> protected override DbParameter GetParameter(string parameterName) { return GetParameter(IndexOf(parameterName)); } #endif /// <summary> /// /// </summary> /// <param name="index"></param> /// <returns></returns> protected override DbParameter GetParameter(int index) { return _parameterList[index]; } /// <summary> /// /// </summary> /// <param name="parameterName"></param> /// <returns></returns> public override int IndexOf(string parameterName) { for (int n = 0; n < _parameterList.Count; n++) { if (String.Compare(parameterName, _parameterList[n].ParameterName, true) == 0) return n; } return -1; } /// <summary> /// /// </summary> /// <param name="value"></param> /// <returns></returns> public override int IndexOf(object value) { return _parameterList.IndexOf((SQLiteParameter)value); } /// <summary> /// /// </summary> /// <param name="index"></param> /// <param name="value"></param> public override void Insert(int index, object value) { _unboundFlag = true; _parameterList.Insert(index, (SQLiteParameter)value); } /// <summary> /// /// </summary> /// <param name="value"></param> public override void Remove(object value) { _unboundFlag = true; _parameterList.Remove((SQLiteParameter)value); } /// <summary> /// /// </summary> /// <param name="parameterName"></param> public override void RemoveAt(string parameterName) { Remove(IndexOf(parameterName)); } /// <summary> /// /// </summary> /// <param name="index"></param> public override void RemoveAt(int index) { _unboundFlag = true; _parameterList.RemoveAt(index); } #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// /// </summary> /// <param name="parameterName"></param> /// <param name="value"></param> protected override void SetParameter(string parameterName, DbParameter value) { SetParameter(IndexOf(parameterName), value); } #endif /// <summary> /// /// </summary> /// <param name="index"></param> /// <param name="value"></param> protected override void SetParameter(int index, DbParameter value) { _unboundFlag = true; _parameterList[index] = (SQLiteParameter)value; } internal void Unbind() { _unboundFlag = true; } /// <summary> /// This function attempts to map all parameters in the collection to all statements in a Command. /// Since named parameters may span multiple statements, this function makes sure all statements are bound /// to the same named parameter. Unnamed parameters are bound in sequence. /// </summary> internal void MapParameters() { if (_unboundFlag == false || _parameterList.Count == 0) return; int nUnnamed = 0; string s; int n; SQLiteStatement stmt; foreach(SQLiteParameter p in _parameterList) { s = p.ParameterName; if (s == null) { s = String.Format(";{0}", nUnnamed); nUnnamed++; } for (n = 0; n < _command._statementList.Length; n++) { stmt = _command._statementList[n]; if (stmt._paramNames != null) { stmt.MapParameter(s, p); } } } _unboundFlag = false; } } } |
Changes to System.Data.SQLite/SQLiteStatement.cs.
1 2 3 4 5 6 7 8 9 10 11 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Collections.Generic; | < < < < | < < < | < < < | < < < | < < < < < < < < < < < < < < < < < | > > > > < < < < | | | < < < < < < < | | < | | | < < < < | < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Collections.Generic; /// <summary> /// Represents a single SQL statement in SQLite. /// </summary> internal sealed class SQLiteStatement : IDisposable { internal SQLiteBase _sql; internal string _sqlStatement; internal int _sqlite_stmt; internal int _unnamedParameterStart; internal string[] _paramNames; internal SQLiteParameter[] _paramValues; internal SQLiteStatement(SQLiteBase sqlbase, int stmt, string strCommand, ref int nCmdStart) { _paramNames = null; _paramValues = null; _unnamedParameterStart = nCmdStart; _sql = sqlbase; _sqlite_stmt = stmt; _sqlStatement = strCommand; // Determine parameters for this statement (if any) and prepare space for them. int n = _sql.Bind_ParamCount(this); int x; string s; if (n > 0) { _paramNames = new string[n]; _paramValues = new SQLiteParameter[n]; for (x = 0; x < n; x++) { s = _sql.Bind_ParamName(this, x); if (s == null || s == "") { s = String.Format(";{0}", nCmdStart); nCmdStart++; } _paramNames[x] = s; _paramValues[x] = null; } } } internal void MapParameter(string s, SQLiteParameter p) { if (_paramNames == null) return; for (int n = 0; n < _paramNames.Length; n++) { if (String.Compare(_paramNames[n], s, true) == 0) { _paramValues[n] = p; break; } } } #region IDisposable Members public void Dispose() { _sql.Finalize(this); _paramNames = null; _paramValues = null; GC.SuppressFinalize(this); } #endregion /// <summary> /// Bind all parameters, making sure the caller didn't miss any |
︙ | ︙ | |||
143 144 145 146 147 148 149 | /// <summary> /// Perform the bind operation for an individual parameter /// </summary> /// <param name="index">The index of the parameter to bind</param> /// <param name="param">The parameter we're binding</param> private void BindParameter(int index, SQLiteParameter param) { | < < < | | | | | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | /// <summary> /// Perform the bind operation for an individual parameter /// </summary> /// <param name="index">The index of the parameter to bind</param> /// <param name="param">The parameter we're binding</param> private void BindParameter(int index, SQLiteParameter param) { object obj = param.Value; if (Convert.IsDBNull(obj) || obj == null) { _sql.Bind_Null(this, index); return; } switch (param.DbType) { case DbType.Date: case DbType.Time: case DbType.DateTime: _sql.Bind_DateTime(this, index, Convert.ToDateTime(obj)); break; case DbType.Int64: case DbType.UInt64: _sql.Bind_Int64(this, index, Convert.ToInt64(obj)); break; case DbType.Boolean: case DbType.Int16: case DbType.Int32: case DbType.UInt16: case DbType.UInt32: case DbType.SByte: case DbType.Byte: _sql.Bind_Int32(this, index, Convert.ToInt32(obj)); break; case DbType.Single: case DbType.Double: case DbType.Currency: case DbType.Decimal: _sql.Bind_Double(this, index, Convert.ToDouble(obj)); break; case DbType.Binary: _sql.Bind_Blob(this, index, (byte[])obj); break; default: _sql.Bind_Text(this, index, obj.ToString()); break; } } } } |
Changes to System.Data.SQLite/SQLiteTransaction.cs.
︙ | ︙ | |||
12 13 14 15 16 17 18 | using System.Data.Common; /// <summary> /// SQLite implementation of DbTransaction. /// </summary> public sealed class SQLiteTransaction : DbTransaction { | < < < | < < < < < | < < < | < | | | | | < < < < < < < < | | < < < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | using System.Data.Common; /// <summary> /// SQLite implementation of DbTransaction. /// </summary> public sealed class SQLiteTransaction : DbTransaction { private SQLiteConnection _cnn; internal SQLiteTransaction(SQLiteConnection cnn) { try { cnn._sql.Execute("BEGIN"); _cnn = cnn; } catch (SQLiteException e) { BaseDispose(); throw (e); } } /// <summary> /// Commits the current transaction. /// </summary> public override void Commit() { if (_cnn == null) throw new ArgumentNullException(); try { _cnn._sql.Execute("COMMIT"); } catch (SQLiteException e) { BaseDispose(); throw (e); } BaseDispose(); } /// <summary> /// Returns the underlying connection to which this transaction applies. /// </summary> protected override DbConnection DbConnection { get { return _cnn; } } /// <summary> /// Disposes the transaction. If it is currently active, any changes are rolled back. /// </summary> public override void Dispose() { if (_cnn != null) Rollback(); GC.SuppressFinalize(this); } /// <summary> /// Gets the isolation level of the transaction. SQLite does not support isolation levels, so this always returns Unspecified. /// </summary> public override IsolationLevel IsolationLevel { |
︙ | ︙ | |||
109 110 111 112 113 114 115 | if (_cnn == null) throw new ArgumentNullException(); try { _cnn._sql.Execute("ROLLBACK"); } | | | | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | if (_cnn == null) throw new ArgumentNullException(); try { _cnn._sql.Execute("ROLLBACK"); } catch (SQLiteException e) { BaseDispose(); throw (e); } BaseDispose(); } private void BaseDispose() { _cnn._activeTransaction = null; _cnn = null; } } } |
Deleted System.Data.SQLite/SR.Designer.cs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted System.Data.SQLite/SR.resx.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted System.Data.SQLite/System.Data.SQLite.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted System.Data.SQLite/System.Data.SQLite.CF.snk.
cannot compute difference between binary files
Added System.Data.SQLite/System.Data.SQLite.csproj.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion>8.0.41202</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{AC139951-261A-4463-B6FA-AEBC25283A66}</ProjectGuid> <OutputType>Library</OutputType> <RootNamespace>System.Data.SQLite</RootNamespace> <AssemblyName>System.Data.SQLite</AssemblyName> <WarningLevel>4</WarningLevel> <SignAssembly>true</SignAssembly> <AssemblyOriginatorKeyFile>System.Data.SQLite.snk</AssemblyOriginatorKeyFile> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>.\bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> <PlatformTarget>x86</PlatformTarget> <DocumentationFile>bin\Debug\System.Data.SQLite.XML</DocumentationFile> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>pdbonly</DebugType> <Optimize>true</Optimize> <OutputPath>.\bin\Release\</OutputPath> <DefineConstants> </DefineConstants> <PlatformTarget>x86</PlatformTarget> <DebugSymbols>true</DebugSymbols> <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies> <NoStdLib>false</NoStdLib> <DocumentationFile>bin\Release\System.Data.SQLite.XML</DocumentationFile> </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.XML" /> </ItemGroup> <ItemGroup> <Compile Include="AssemblyInfo.cs" /> <None Include="System.Data.SQLite.snk" /> <Compile Include="SQLite3.cs" /> <Compile Include="SQLite3_UTF16.cs" /> <Compile Include="SQLiteBase.cs" /> <Compile Include="SQLiteCommand.cs"> <SubType>Component</SubType> </Compile> <Compile Include="SQLiteCommandBuilder.cs"> <SubType>Component</SubType> </Compile> <Compile Include="SQLiteConnectionStringBuilder.cs"> </Compile> <Compile Include="SQLiteConvert.cs" /> <Compile Include="SQLiteFactory.cs" /> <Compile Include="SQLiteFunction.cs" /> <Compile Include="SQLiteFunctionAttribute.cs" /> <Compile Include="SQLiteStatement.cs" /> <Compile Include="SQLiteConnection.cs"> <SubType>Component</SubType> </Compile> <Compile Include="SQLiteDataAdapter.cs"> <SubType>Component</SubType> </Compile> <Compile Include="SQLiteDataReader.cs" /> <Compile Include="SQLiteException.cs" /> <Compile Include="SQLiteParameter.cs" /> <Compile Include="SQLiteParameterCollection.cs" /> <Compile Include="SQLiteTransaction.cs" /> <Compile Include="UnsafeNativeMethods.cs" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> </Project> |
Added System.Data.SQLite/System.Data.SQLite.csproj.user.
> > > > > > > | 1 2 3 4 5 6 7 | <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <LastOpenVersion>8.0.41202</LastOpenVersion> <ProjectView>ProjectFiles</ProjectView> <ProjectTrust>0</ProjectTrust> </PropertyGroup> </Project> |
Changes to System.Data.SQLite/System.Data.SQLite.snk.
cannot compute difference between binary files
Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Security; using System.Runtime.InteropServices; | < < | < < < < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Security; using System.Runtime.InteropServices; [SuppressUnmanagedCodeSecurity] internal class UnsafeNativeMethods { private const string SQLITE_DLL = "SQLite.Interop.DLL"; [DllImport(SQLITE_DLL)] internal static extern IntPtr sqlite3_libversion_interop(out int len); [DllImport(SQLITE_DLL)] internal static extern void sqlite3_free_interop(IntPtr p); [DllImport(SQLITE_DLL)] internal static extern int sqlite3_open_interop(byte[] utf8Filename, out int db); [DllImport(SQLITE_DLL)] internal static extern int sqlite3_close_interop(int db); [DllImport(SQLITE_DLL)] internal static extern int sqlite3_exec_interop(int db, byte[] strSql, int pvCallback, int pvParam, out IntPtr errMsg, out int len); [DllImport(SQLITE_DLL)] |
︙ | ︙ | |||
182 183 184 185 186 187 188 | [DllImport(SQLITE_DLL)] internal static extern int sqlite3_aggregate_context_interop(int context, int nBytes); [DllImport(SQLITE_DLL)] internal static extern void sqlite3_realcolnames(int db, int bset); [DllImport(SQLITE_DLL)] | | | | | | | | < < | < < < < < < < < < < < < < < < < < < < | 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | [DllImport(SQLITE_DLL)] internal static extern int sqlite3_aggregate_context_interop(int context, int nBytes); [DllImport(SQLITE_DLL)] internal static extern void sqlite3_realcolnames(int db, int bset); [DllImport(SQLITE_DLL)] internal static extern IntPtr sqlite3_column_text16_interop(int stmt, int index); [DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)] internal static extern int sqlite3_open16_interop(string utf16Filename, out int db); [DllImport(SQLITE_DLL)] internal static extern IntPtr sqlite3_errmsg16_interop(int db); [DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)] internal static extern int sqlite3_prepare16_interop(int db, string strSql, int sqlLen, out int stmt, out IntPtr ptrRemain); [DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)] internal static extern int sqlite3_bind_text16_interop(int stmt, int index, string value, int nlen, int nTransient); [DllImport(SQLITE_DLL)] internal static extern IntPtr sqlite3_column_name16_interop(int stmt, int index); [DllImport(SQLITE_DLL)] internal static extern IntPtr sqlite3_column_decltype16_interop(int stmt, int index); [DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)] internal static extern int sqlite3_create_collation16_interop(int db, string strName, int nType, int nArgs, SQLiteCollation func, out int nCookie); [DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)] internal static extern int sqlite3_create_function16_interop(int db, string strName, int nArgs, int nType, SQLiteCallback func, SQLiteCallback funcstep, SQLiteCallback funcfinal, out int nCookie); [DllImport(SQLITE_DLL)] internal static extern IntPtr sqlite3_value_text16_interop(int p); [DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)] internal static extern void sqlite3_result_error16_interop(int context, string strName, int nLen); [DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)] internal static extern void sqlite3_result_text16_interop(int context, string strName, int nLen, int pvReserved); } } |
Deleted bin/CompactFramework/System.Data.SQLite.DLL.
cannot compute difference between binary files
Deleted bin/CompactFramework/System.Data.SQLite.dll.
cannot compute difference between binary files
Deleted bin/CompactFramework/testce.exe.
cannot compute difference between binary files
Deleted bin/Designer/Install.cmd.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted bin/Designer/Install.vbs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted bin/Designer/InstallVWDExpress.cmd.
|
| < < < |
Deleted bin/Designer/SQLite.Designer.dll.
cannot compute difference between binary files
Deleted bin/Designer/SQLiteDataObjectSupport.xml.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted bin/Designer/SQLiteDataViewSupport.xml.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted bin/Designer/SQLiteDesigner.reg.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted bin/Designer/readme.txt.
|
| < < < < < < < < |
Deleted bin/System.Data.SQLite.dll.
cannot compute difference between binary files
Deleted bin/itanium/System.Data.SQLite.DLL.
cannot compute difference between binary files
Deleted bin/test.exe.
cannot compute difference between binary files
Changes to bin/test.exe.config.
1 2 3 | <configuration> <system.data> <DbProviderFactories> | < | | 1 2 3 4 5 6 7 | <configuration> <system.data> <DbProviderFactories> <add name="SQLite Data Provider" invariant="System.Data.SQLite" support="3F" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /> </DbProviderFactories> </system.data> </configuration> |
Deleted bin/tools/mergebin.exe.
cannot compute difference between binary files
Deleted bin/x64/System.Data.SQLite.DLL.
cannot compute difference between binary files
Changes to readme.htm.
1 2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> | | | | | | | < | | | > > > | < | | | < | | < < < < < < < < < < < < < < < < < < < < < < | < | | | < | | < | < | | < | < | < < | < | > | | < | | < < < < < < < < < < < < < < < < | | > > | > | < | < < < < | < < < < < < < < < < < < | < < > | | < < < < > | | < | > | < < | < < < < < < < < < < < | < < < < < < < < > | | | | | | | < < < < < < < < < < < < < < < < < < | < | < | < < < < < | < < < < < < < | < < < | | < < < < < < > < | < > | > | < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | < < < < < < < < < | > > > | > > > > > > > | | | | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < < < < < < < < < < < < < < < < < < < < < | | < < < < < < < < < | < < < < < < | < < | > > > > > | < | < < < < < | < < | | < < < < < | | < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < | < < | > | < < < < < < < < < < | < < | < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < | < < | < < < > | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < | | | < | | < | | < | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title></title> </head> <body> ADO.NET 2.0 SQLite Data Provider<br /> Version 1.0.6 - Feb 28, 2005<br /> Written by Robert Simpson (<a href="mailto:robert@blackcastlesoft.com">robert@blackcastlesoft.com</a>)<br /> Released to the public domain, use at your own risk!<br /> <br /> This provider was written and verified using the Visual Studio 2005 November and December CTP's.<br /> <br /> The latest version can be downloaded <a href="http://www.blackcastlesoft.com/files/system.data.sqlite.zip">here</a> <br /> <br /> <b>Features:</b><br /> <ul> <li>DbProviderFactory support, just add the XML below at the machine.config and/or app.config level. </li> <li>Full support for ATTACH'ed databases. Exposed as <i>Catalogs</i> in the schema. When cloning a connection, all attached databases are automatically re-attached to the new connection.</li> <li>DbConnection.GetSchema(...) support includes the <i>MetaDataCollections</i>, <i> DataSourceInformation</i>, <i>Columns</i>, <i>Tables</i>, <i>Views</i>, <i>Catalogs</i> and <i>Indexes</i> keywords.</li> <li>Enhanced DbDataReader.GetSchemaTable() functionality returns catalog, namespace and detailed schema information even for complex queries.</li> <li>Named and unnamed parameters.</li> <li>Full UTF-8 and UTF-16 support.</li> <li>Multiple simultaneous DataReaders (one DataReader per Command however).</li> <li>Full support for user-defined scalar and aggregate functions, encapsulated into an easy-to-use base class in which only a couple of overrides are necessary to implement new SQL functions.</li> <li>Full support for user-defined collating sequences, every bit as simple to implement as user-defined functions and uses the same base class.</li></ul> In order to use the SQLiteFactory and have the SQLite data provider enumerated in the DbProviderFactories methods, you must add the following segment into either your application's app.config or the system's machine.config located in the %SystemRoot%\Microsoft.Net\Framework\v2.xxxx\Config folder:<br /> <br /> <pre> <configuration> <system.data> <DbProviderFactories> <add name="SQLite Data Provider" invariant="System.Data.SQLite" support="3F" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /> </DbProviderFactories> </system.data> </configuration> </pre> <br /> <b>Development Notes Regarding the SQLite 3 Source Code<br /> </b>*** At this time, the necessary changes to the DLL to support Windows CE have not been completed. All function calls that return or pass a 64-bit value have been wrapped, but the necessary OS changes have not been finished.<br /> <br /> <p></p> <p> Steps for merging the sqlite3 core codebase:</p> <ol> <li>Download the latest sqlite3 source from <a href="http://www.sqlite.org/download.html"> http://www.sqlite.org/download.html</a></li> <li>Extract the source code to the <b>SQLite.Interop\src</b> directory of this project</li> <li>Open the <b>src\select.c</b> file.</li> <li>Add <b>#include "../interop.h" </b>to the top of the file where the other include's are.</li> <li>Scroll down the <b>select.c</b> file to around line <b>748</b>. Change the name of the function <b>static void generateColumnNames </b>to <b>static void _generateColumnNames</b> (<i>note the underscore in front of the name</i>).</li> <li>Compile it.</li> </ol> <b>Version History<br /> 1.06 - Feb 28, 2005<br /> </b> <ul> <li>Speed-ups to SQLiteDataReader. It was interop'ing every time it tried to fetch a field due to a logic error.</li> <li>Changed/Added some code to SQLiteConvert's internal DbType, Type and TypeAffinity functions.</li> <li>Fixed the SQLiteDataReader to obey the flags set in the optional CommandBehavior flag from SQLiteCommand.ExecuteReader().</li> <li>Changed the default page size to 1024 to reflect the defaults of SQLite. Ignores the "Page Size" connection string option for memory databases, as tests revealed that changing it resulted in memory corruption errors.</li> <li>Performance enhancements to the SQLiteCommand and SQLiteStatement classes which reduced the 100,000 row insert execution time as well as the various Function execution times significantly.</li> </ul> <b> <br /> 1.05 - Feb 25, 2005</b> <ul> <li>Fixed the SQLite3 C# class step/reset functions to accomodate schema changes that invalidate a prepared statement. Statements are recompiled transparently.</li> <li>Moved all native DLL declarations to an UnsafeNativeMethods class.</li> <li>Split several classes into their own modules for readability.</li> <li>Renamed many internal variables, reviewed access to variables marked as internal and altered their protection levels accordingly.</li> <li>Due to the presence of the altered sqlite3 codebase and so many added interop functions, I decided to rename the sqlite3 C project and the DLL to SQLite.Interop.DLL. This is the same core sqlite3 codebase but designed specifically for this ADO.NET provider. This eliminates any possibility of someone dropping another build of sqlite3.dll into the system and rendering the provider inoperable. In the future if the folks at sqlite.org finally introduce a method of retrieving column usage for an arbitrary prepared statement, I'll retool this library to be a lightweight function call wrapper around the core binary distribution.</li> <li>Added [SuppressUnmanagedCodeSecurity] attribute to the UnsafeNativeMethods class which brings VS2005 November CTP execution speeds inline with the December CTP.</li> <li>Added a <b>bin</b> directory to the project root where pre-compiled binaries can be found.</li> <li>Added a <b>doc</b> directory where preliminary documentation on the class library can be found.</li> <li>Documented a lot more of the classes internally.</li> </ul> <b> <br /> 1.04 - Feb 24, 2005</b> <ul> <li>Removed the SQLiteContext class and revamped the way UserFunctions work to simplify the imlementation.</li> <li>Fixed a counting bug in the TestCases class, specifically in the function tests where I wasn't resetting the counter and it was consequently reporting intrinsic and raw select calls as being much much faster than they actually were. The numbers are now much closer to what I expected for performance, with .NET user-functions still being the slowest, but only by a small margin.</li> <li>Small performance tweaks to SQLiteDataReader.</li> <li>Added PageSize to the SQLiteConnectionStringBuilder and subsequently to the SQLiteConnection</li> <li>Added a PRAGMA encoding=XXX execution statement to the SQLiteConnection after opening a connection.</li> </ul> <b> 1.03 - Feb 23, 2005</b> <ul> <li>Fixed up SQLiteCommandBuilder to correct implementation errors, which resulted in an enormous performance boost in the InsertMany test. 10,000 row insert that executed in 1500ms now executes in 500ms.</li> <li>Fixed several errors in the SQLite3_UTF16 class. ToString() was working incorrectly and the Open() method failed to register user defined functions and collations.</li> <li>Fixed a bug in SQLiteCommand.ClearCommands() whereby only the first statement was being properly cleaned up.</li> <li>Fixed a bug in SQLiteDataReader whereby calling NextResult() would not properly reset the previously-executed command in the sequence.</li> <li>Added an InsertManyWithIdentityFetch test, which appends a select clause to populate the ID of the last inserted row into the InsertCommand, demonstrating ADO.NET's ability to auto-fetch identity columns on insert.</li> </ul> <p> <b> 1.02 - Feb 21, 2005</b></p> <ul> <li>Tweaks to the xxx_interop functions that return char *'s, so they also return the length. Saves an interop call to get the UTF-8 string length during conversion to a .NET string.</li> <li>Reworked the whole interop.c thing into interop.h and reduced the code required to merge the main sqlite3 codebase.</li> <li>Added support for user-defined collations.</li> </ul> </body> </html> |
Changes to test/Program.cs.
1 2 3 4 5 6 7 8 9 10 11 12 | using System; using System.Data; using System.Text; using System.Data.Common; using System.Data.SQLite; namespace test { class Program { static void Main(string[] args) { | | | | > > < > | | > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | using System; using System.Data; using System.Text; using System.Data.Common; using System.Data.SQLite; namespace test { class Program { static void Main(string[] args) { DbProviderFactory fact; // = DbProviderFactories.GetFactory("System.Data.OleDb"); DbConnection cnn; // = fact.CreateConnection(); // cnn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Temp\\db.mdb;Persist Security Info=False"; // cnn.ConnectionString = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=DirectLink;Data Source=MASTER"; // cnn.Open(); // TestCases.Run(fact, cnn); fact = DbProviderFactories.GetFactory("System.Data.SQLite"); using (cnn = fact.CreateConnection()) { cnn.ConnectionString = "Data Source=test.db3"; cnn.Open(); TestCases.Run(fact, cnn); } System.IO.File.Delete("test.db3"); Console.ReadKey(); } } } |
Changes to test/TestCases.cs.
︙ | ︙ | |||
78 79 80 81 82 83 84 | try { CoersionTest(cnn); Console.WriteLine("FAIL - CoersionTest"); } catch (Exception) { Console.WriteLine("SUCCESS - CoersionTest"); } try { ParameterizedInsert(cnn); Console.WriteLine("SUCCESS - ParameterizedInsert"); } catch (Exception) { Console.WriteLine("FAIL - ParameterizedInsert"); } | | < < < | | < < < | | | < < < | | | | < | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | try { CoersionTest(cnn); Console.WriteLine("FAIL - CoersionTest"); } catch (Exception) { Console.WriteLine("SUCCESS - CoersionTest"); } try { ParameterizedInsert(cnn); Console.WriteLine("SUCCESS - ParameterizedInsert"); } catch (Exception) { Console.WriteLine("FAIL - ParameterizedInsert"); } try { BinaryInsert(cnn); Console.WriteLine("SUCCESS - BinaryInsert"); } catch (Exception) { Console.WriteLine("FAIL - BinaryInsert"); } try { VerifyBinaryData(cnn); Console.WriteLine("SUCCESS - VerifyBinaryData"); } catch (Exception) { Console.WriteLine("FAIL - VerifyBinaryData"); } try { ParameterizedInsertMissingParams(cnn); Console.WriteLine("FAIL - ParameterizedInsertMissingParams"); } catch (Exception) { Console.WriteLine("SUCCESS - ParameterizedInsertMissingParams"); } try { InsertMany(fact, cnn, false); Console.WriteLine("SUCCESS - InsertMany"); } catch (Exception) { Console.WriteLine("FAIL - InsertMany"); } try { InsertMany(fact, cnn, true); Console.WriteLine("SUCCESS - InsertManyWithIdentityFetch"); } catch (Exception) { Console.WriteLine("FAIL - InsertManyWithIdentityFetch"); } try { IterationTest(cnn); Console.WriteLine("SUCCESS - Iteration Test"); } catch (Exception) { Console.WriteLine("FAIL - Iteration Test"); } try { UserFunction(cnn); Console.WriteLine("SUCCESS - UserFunction"); } catch (Exception) { Console.WriteLine("FAIL - UserFunction"); } try { UserAggregate(cnn); Console.WriteLine("SUCCESS - UserAggregate"); } catch (Exception) { Console.WriteLine("FAIL - UserAggregate"); } try { UserCollation(cnn); Console.WriteLine("SUCCESS - UserCollation"); } catch (Exception) { Console.WriteLine("FAIL - UserCollation"); } try { DropTable(cnn); Console.WriteLine("SUCCESS - DropTable"); } catch (Exception) { Console.WriteLine("FAIL - DropTable"); } Console.WriteLine("\r\nTests Finished."); } internal static void CreateTable(DbConnection cnn) { using (DbCommand cmd = cnn.CreateCommand()) { cmd.CommandText = "CREATE TABLE TestCase (ID integer primary key autoincrement, Field1 Integer, Field2 Float, Field3 VARCHAR(50), Field4 CHAR(10), Field5 DateTime, Field6 Image)"; cmd.ExecuteNonQuery(); } } internal static void DropTable(DbConnection cnn) { using (DbCommand cmd = cnn.CreateCommand()) |
︙ | ︙ | |||
174 175 176 177 178 179 180 | if (Field4 != "Field4") throw new ArgumentOutOfRangeException("Non-Match on Field4"); if (Field5.CompareTo(DateTime.Parse("2005-01-01 13:49:00")) != 0) throw new ArgumentOutOfRangeException("Non-Match on Field5"); } else throw new ArgumentOutOfRangeException("No data in table"); } } } | | | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | if (Field4 != "Field4") throw new ArgumentOutOfRangeException("Non-Match on Field4"); if (Field5.CompareTo(DateTime.Parse("2005-01-01 13:49:00")) != 0) throw new ArgumentOutOfRangeException("Non-Match on Field5"); } else throw new ArgumentOutOfRangeException("No data in table"); } } } internal static void CoersionTest(DbConnection cnn) { using (DbCommand cmd = cnn.CreateCommand()) { cmd.CommandText = "SELECT Field1, Field2, Field3, Field4, Field5, 'A', 1, 1 + 1, 3.14159 FROM TestCase"; using (DbDataReader rd = cmd.ExecuteReader()) { |
︙ | ︙ | |||
241 242 243 244 245 246 247 | cmd.Parameters.Add(Field4); cmd.Parameters.Add(Field5); cmd.ExecuteNonQuery(); } } | < | < | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | cmd.Parameters.Add(Field4); cmd.Parameters.Add(Field5); cmd.ExecuteNonQuery(); } } internal static void BinaryInsert(DbConnection cnn) { using (DbCommand cmd = cnn.CreateCommand()) { cmd.CommandText = "INSERT INTO TestCase(Field6) VALUES(?)"; DbParameter Field6 = cmd.CreateParameter(); byte[] b = new byte[4000]; b[0] = 1; b[100] = 2; b[1000] = 3; b[2000] = 4; b[3000] = 5; Field6.Value = b; cmd.Parameters.Add(Field6); cmd.ExecuteNonQuery(); } } |
︙ | ︙ | |||
287 288 289 290 291 292 293 | if (b[1000] != 3) throw new ArgumentException(); if (b[2000] != 4) throw new ArgumentException(); if (b[3000] != 5) throw new ArgumentException(); } } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | if (b[1000] != 3) throw new ArgumentException(); if (b[2000] != 4) throw new ArgumentException(); if (b[3000] != 5) throw new ArgumentException(); } } } internal static void ParameterizedInsertMissingParams(DbConnection cnn) { using (DbCommand cmd = cnn.CreateCommand()) { cmd.CommandText = "INSERT INTO TestCase(Field1, Field2, Field3, Field4, Field5) VALUES(?,?,?,?,?)"; DbParameter Field1 = cmd.CreateParameter(); DbParameter Field2 = cmd.CreateParameter(); |
︙ | ︙ | |||
362 363 364 365 366 367 368 | cmd.Parameters.Add(Field4); // Assertion here, not enough parameters cmd.ExecuteNonQuery(); } } | < | < < | | | < | | | | | < | | | | | | | | | < < < < < < < < < < < < < < < < < | < < | < < < < | > > | | < | > | < | < | | < < < < < | | < < < | | < < < < < | | | | | | | | | | | | | | | | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | cmd.Parameters.Add(Field4); // Assertion here, not enough parameters cmd.ExecuteNonQuery(); } } // Utilizes the SQLiteCommandBuilder, which in turn utilizes SQLiteDataReader's GetSchemaTable() functionality internal static void InsertMany(DbProviderFactory fact, DbConnection cnn, bool bWithIdentity) { using (DbTransaction dbTrans = cnn.BeginTransaction()) { using (DbDataAdapter adp = fact.CreateDataAdapter()) { using (DbCommand cmd = cnn.CreateCommand()) { cmd.Transaction = dbTrans; cmd.CommandText = "SELECT * FROM TestCase WHERE 1=2"; adp.SelectCommand = cmd; using (DbCommandBuilder bld = fact.CreateCommandBuilder()) { bld.DataAdapter = adp; adp.InsertCommand = bld.GetInsertCommand(); if (bWithIdentity) { adp.InsertCommand.CommandText += ";SELECT [ID] FROM TestCase WHERE RowID = last_insert_rowid()"; adp.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord; } using (DataTable tbl = new DataTable()) { adp.Fill(tbl); for (int n = 0; n < 100000; n++) { DataRow row = tbl.NewRow(); row[1] = n + 10000; tbl.Rows.Add(row); } Console.Write(String.Format(" InsertMany{0} (100000 rows) Begins ... ", (bWithIdentity == true) ? "WithIdentityFetch":" ")); long dtStart = DateTime.Now.Ticks; adp.Update(tbl); long dtEnd = DateTime.Now.Ticks; dtEnd -= dtStart; Console.Write(String.Format("Ends in {0} ms ... ", (dtEnd / 10000))); dtStart = DateTime.Now.Ticks; dbTrans.Commit(); dtEnd = DateTime.Now.Ticks; dtEnd -= dtStart; Console.WriteLine(String.Format("Commits in {0} ms", (dtEnd / 10000))); } } } } } } // Causes the user-defined function to be called internal static void UserFunction(DbConnection cnn) { using (DbCommand cmd = cnn.CreateCommand()) { int nTimes; long dtStart; nTimes = 0; cmd.CommandText = "SELECT Foo('ee','foo')"; dtStart = DateTime.Now.Ticks; while (DateTime.Now.Ticks - dtStart < 10000000) { cmd.ExecuteNonQuery(); nTimes++; } Console.WriteLine(String.Format(" User (text) command executed {0} times in 1 second.", nTimes)); nTimes = 0; cmd.CommandText = "SELECT Foo(10,11)"; dtStart = DateTime.Now.Ticks; while (DateTime.Now.Ticks - dtStart < 10000000) { cmd.ExecuteNonQuery(); nTimes++; } Console.WriteLine(String.Format(" UserFunction command executed {0} times in 1 second.", nTimes)); nTimes = 0; cmd.CommandText = "SELECT ABS(1)"; dtStart = DateTime.Now.Ticks; while (DateTime.Now.Ticks - dtStart < 10000000) { cmd.ExecuteNonQuery(); nTimes++; } Console.WriteLine(String.Format(" Intrinsic command executed {0} times in 1 second.", nTimes)); nTimes = 0; cmd.CommandText = "SELECT lower('FOO')"; dtStart = DateTime.Now.Ticks; while (DateTime.Now.Ticks - dtStart < 10000000) { cmd.ExecuteNonQuery(); nTimes++; } Console.WriteLine(String.Format(" Intrin (txt) command executed {0} times in 1 second.", nTimes)); nTimes = 0; cmd.CommandText = "SELECT 1"; dtStart = DateTime.Now.Ticks; while (DateTime.Now.Ticks - dtStart < 10000000) { cmd.ExecuteNonQuery(); nTimes++; } Console.WriteLine(String.Format(" Raw Value command executed {0} times in 1 second.", nTimes)); } } internal static void IterationTest(DbConnection cnn) { using (DbCommand cmd = cnn.CreateCommand()) { long dtStart; long dtEnd; int nCount; long n; cmd.CommandText = "SELECT Foo(ID, ID) FROM TestCase"; cmd.Prepare(); dtStart = DateTime.Now.Ticks; nCount = 0; using (DbDataReader rd = cmd.ExecuteReader()) { while (rd.Read()) { n = rd.GetInt64(0); nCount++; } dtEnd = DateTime.Now.Ticks; } Console.WriteLine(String.Format(" User Function iteration of {0} records in {1} ms", nCount, (dtEnd - dtStart) / 10000)); cmd.CommandText = "SELECT ID FROM TestCase"; cmd.Prepare(); dtStart = DateTime.Now.Ticks; nCount = 0; using (DbDataReader rd = cmd.ExecuteReader()) { while (rd.Read()) { n = rd.GetInt64(0); nCount++; } dtEnd = DateTime.Now.Ticks; } Console.WriteLine(String.Format(" Raw iteration of {0} records in {1} ms", nCount, (dtEnd - dtStart) / 10000)); cmd.CommandText = "SELECT ABS(ID) FROM TestCase"; cmd.Prepare(); dtStart = DateTime.Now.Ticks; nCount = 0; using (DbDataReader rd = cmd.ExecuteReader()) { while (rd.Read()) { n = rd.GetInt64(0); nCount++; } dtEnd = DateTime.Now.Ticks; } Console.WriteLine(String.Format(" Intrinsic Function iteration of {0} records in {1} ms", nCount, (dtEnd - dtStart) / 10000)); } } // Causes the user-defined aggregate to be iterated through internal static void UserAggregate(DbConnection cnn) { using (DbCommand cmd = cnn.CreateCommand()) { long dtStart; int n = 0; int nCount; cmd.CommandText = "SELECT MyCount(*) FROM TestCase"; nCount = 0; dtStart = DateTime.Now.Ticks; while (DateTime.Now.Ticks - dtStart < 10000000) { n = Convert.ToInt32(cmd.ExecuteScalar()); nCount++; } if (n != 200003) throw new ArgumentOutOfRangeException("Unexpected count"); Console.WriteLine(String.Format(" UserAggregate executed {0} times in 1 second.", nCount)); } } // Causes the user-defined collation sequence to be iterated through internal static void UserCollation(DbConnection cnn) { |
︙ | ︙ |
Changes to test/app.config.
1 2 3 | <configuration> <system.data> <DbProviderFactories> | < | | 1 2 3 4 5 6 7 | <configuration> <system.data> <DbProviderFactories> <add name="SQLite Data Provider" invariant="System.Data.SQLite" support="3F" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /> </DbProviderFactories> </system.data> </configuration> |
Changes to test/test.csproj.
1 2 3 4 | <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | | | 1 2 3 4 5 6 7 8 9 10 11 12 | <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion>8.0.41202</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}</ProjectGuid> <OutputType>Exe</OutputType> <RootNamespace>test</RootNamespace> <AssemblyName>test</AssemblyName> <WarningLevel>4</WarningLevel> <IsWebBootstrapper>true</IsWebBootstrapper> |
︙ | ︙ | |||
23 24 25 26 27 28 29 | <ApplicationVersion>1.0.0.*</ApplicationVersion> <BootstrapperEnabled>true</BootstrapperEnabled> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> | | | | | | < < < < < < | | | | < | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | <ApplicationVersion>1.0.0.*</ApplicationVersion> <BootstrapperEnabled>true</BootstrapperEnabled> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>.\bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> <PlatformTarget>x86</PlatformTarget> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>pdbonly</DebugType> <Optimize>true</Optimize> <OutputPath>.\bin\Release\</OutputPath> <DefineConstants> </DefineConstants> <PlatformTarget>x86</PlatformTarget> </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <None Include="app.config" /> <Compile Include="Program.cs" /> <Compile Include="AssemblyInfo.cs" /> <Compile Include="TestCases.cs" /> </ItemGroup> <ItemGroup> <BootstrapperFile Include="Microsoft.Net.Framework.2.0"> <InProject>False</InProject> <ProductName>.NET Framework 2.0</ProductName> <Install>true</Install> </BootstrapperFile> </ItemGroup> <ItemGroup> <ProjectReference Include="..\System.Data.SQLite\System.Data.SQLite.csproj"> <Project>{AC139951-261A-4463-B6FA-AEBC25283A66}</Project> <Name>System.Data.SQLite</Name> </ProjectReference> </ItemGroup> <ItemGroup> <Folder Include="Properties\" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> </Project> |
Changes to test/test.csproj.user.
1 2 | <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> | | > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <LastOpenVersion>8.0.41202</LastOpenVersion> <ProjectView>ProjectFiles</ProjectView> <ProjectTrust>0</ProjectTrust> <PublishUrlHistory>http://localhost/test||||</PublishUrlHistory> <InstallUrlHistory>||||</InstallUrlHistory> <SupportUrlHistory>||||</SupportUrlHistory> <UpdateUrlHistory>||||</UpdateUrlHistory> <BootstrapperUrlHistory>||||</BootstrapperUrlHistory> <ApplicationRevision>0</ApplicationRevision> <FallbackCulture>en-US</FallbackCulture> <VerifyUploadedFiles>true</VerifyUploadedFiles> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging> </PropertyGroup> </Project> |
Deleted testce/AssemblyInfo.cs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted testce/Form1.Designer.cs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted testce/Form1.cs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted testce/Form1.resx.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted testce/Program.cs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted testce/TestCases.cs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted testce/testce.csproj.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/MetaData.cpp.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/MetaData.h.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/MetaDataTables.cpp.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/MetaDataTables.h.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/PEFile.cpp.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/PEFile.h.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/ReadMe.txt.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/StreamTable.cpp.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/StreamTable.h.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/TableData.cpp.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/TableData.h.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/mergebin.cpp.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/mergebin.sln.
|
| < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/mergebin.vcproj.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/mergebin/stdafx.cpp.
|
| < < < < < < < < |
Deleted tools/mergebin/stdafx.h.
|
| < < < < < < < < < < < < < < < < |