DELETED Doc/SQLite.NET.Internal.chm
Index: Doc/SQLite.NET.Internal.chm
==================================================================
--- Doc/SQLite.NET.Internal.chm
+++ /dev/null
cannot compute difference between binary files
DELETED Doc/SQLite.NET.Internal.ndoc
Index: Doc/SQLite.NET.Internal.ndoc
==================================================================
--- Doc/SQLite.NET.Internal.ndoc
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Index: Doc/SQLite.NET.chm
==================================================================
--- Doc/SQLite.NET.chm
+++ Doc/SQLite.NET.chm
cannot compute difference between binary files
Index: Doc/SQLite.NET.ndoc
==================================================================
--- Doc/SQLite.NET.ndoc
+++ Doc/SQLite.NET.ndoc
@@ -1,8 +1,8 @@
-
+
DELETED Doc/System.Data.SQLite.XML
Index: Doc/System.Data.SQLite.XML
==================================================================
--- Doc/System.Data.SQLite.XML
+++ /dev/null
@@ -1,2935 +0,0 @@
-
-
-
- System.Data.SQLite
-
-
-
-
- SQLite implementation of DbProviderFactory.
-
-
-
-
- Static instance member which returns an instanced SQLiteFactory class.
-
-
-
-
- Returns a new SQLiteCommand object.
-
- A SQLiteCommand object.
-
-
-
- Returns a new SQLiteCommandBuilder object.
-
- A SQLiteCommandBuilder object.
-
-
-
- Creates a new SQLiteConnection.
-
- A SQLiteConnection object.
-
-
-
- Creates a new SQLiteConnectionStringBuilder.
-
- A SQLiteConnectionStringBuilder object.
-
-
-
- Creates a new SQLiteDataAdapter.
-
- A SQLiteDataAdapter object.
-
-
-
- Creates a new SQLiteParameter.
-
- A SQLiteParameter object.
-
-
-
- SQLite implementation of DbDataReader.
-
-
-
-
- Underlying command this reader is attached to
-
-
-
-
- Index of the current statement in the command being processed
-
-
-
-
- Current statement being Read()
-
-
-
-
- State of the current statement being processed.
- -1 = First Step() executed, so the first Read() will be ignored
- 0 = Actively reading
- 1 = Finished reading
- 2 = Non-row-returning statement, no records
-
-
-
-
- Number of records affected by the insert/update statements executed on the command
-
-
-
-
- Count of fields (columns) in the row-returning statement currently being processed
-
-
-
-
- Datatypes of active fields (columns) in the current statement, used for type-restricting data
-
-
-
-
- The behavior of the datareader
-
-
-
-
- Internal constructor, initializes the datareader and sets up to begin executing statements
-
- The SQLiteCommand this data reader is for
- The expected behavior of the data reader
-
-
-
- Initializes and resets the datareader's member variables
-
-
-
-
- Closes the datareader, potentially closing the connection as well if CommandBehavior.CloseConnection was specified.
-
-
-
-
- Disposes the datareader. Calls Close() to ensure everything is cleaned up.
-
-
-
-
- Throw an error if the datareader is closed
-
-
-
-
- Throw an error if a row is not loaded
-
-
-
-
- Enumerator support
-
- Returns a DbEnumerator object.
-
-
-
- SQLite is inherently un-typed. All datatypes in SQLite are natively strings. The definition of the columns of a table
- and the affinity of returned types are all we have to go on to type-restrict data in the reader.
-
- 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.
-
-
- This function throws an InvalidTypeCast() exception if the requested type doesn't match the column's definition or affinity.
-
- The index of the column to type-check
- The type we want to get out of the column
-
-
-
- Retrieves the column as a boolean value
-
- The index of the column to retrieve
- bool
-
-
-
- Retrieves the column as a single byte value
-
- The index of the column to retrieve
- byte
-
-
-
- Retrieves a column as an array of bytes (blob)
-
- The index of the column to retrieve
- The zero-based index of where to begin reading the data
- The buffer to write the bytes into
- The zero-based index of where to begin writing into the array
- The number of bytes to retrieve
- The actual number of bytes written into the array
-
- To determine the number of bytes in the column, pass a null value for the buffer. The total length will be returned.
-
-
-
-
- Returns the column as a single character
-
- The index of the column to retrieve
- char
-
-
-
- Retrieves a column as an array of chars (blob)
-
- The index of the column to retrieve
- The zero-based index of where to begin reading the data
- The buffer to write the characters into
- The zero-based index of where to begin writing into the array
- The number of bytes to retrieve
- The actual number of characters written into the array
-
- To determine the number of characters in the column, pass a null value for the buffer. The total length will be returned.
-
-
-
-
- Retrieves the name of the back-end datatype of the column
-
- The index of the column to retrieve
- string
-
-
-
- Retrieve the column as a date/time value
-
- The index of the column to retrieve
- DateTime
-
-
-
- Retrieve the column as a decimal value
-
- The index of the column to retrieve
- decimal
-
-
-
- Returns the column as a double
-
- The index of the column to retrieve
- double
-
-
-
- Returns the .NET type of a given column
-
- The index of the column to retrieve
- Type
-
-
-
- Returns a column as a float value
-
- The index of the column to retrieve
- float
-
-
-
- Returns the column as a Guid
-
- The index of the column to retrieve
- Guid
-
-
-
- Returns the column as a short
-
- The index of the column to retrieve
- Int16
-
-
-
- Retrieves the column as an int
-
- The index of the column to retrieve
- Int32
-
-
-
- Retrieves the column as a long
-
- The index of the column to retrieve
- Int64
-
-
-
- Retrieves the name of the column
-
- The index of the column to retrieve
- string
-
-
-
- Retrieves the i of a column, given its name
-
- The name of the column to retrieve
- The int i of the column
-
-
-
- Schema information in SQLite is an iffy-business. We've extended the native SQLite3.DLL to include a special pragma called
- PRAGMA real_column_names
- When enabled, the pragma causes all column aliases to be ignored, and the full Database.Table.ColumnName to be returned for
- each column of a SELECT statement. Using this information it is then possible to query each database and table for the
- matching column, and associate it with the active statement.
-
-
- The current connection is cloned for the sake of executing this statement, so as to avoid any possibility of corrupting the
- original connection's existing statements or state. Any attached databases are re-attached to the new connection.
-
- Returns a DataTable containing the schema information for the active SELECT statement being processed.
-
-
-
- Retrieves the column as a string
-
- The index of the column to retrieve
- string
-
-
-
- Retrieves the column as an object corresponding to the underlying datatype of the column
-
- The index of the column to retrieve
- object
-
-
-
- Retreives the values of multiple columns, up to the size of the supplied array
-
- The array to fill with values from the columns in the current resultset
- The number of columns retrieved
-
-
-
- Returns True if the specified column is null
-
- The index of the column to retrieve
- True or False
-
-
-
- Moves to the next resultset in multiple row-returning SQL command.
-
- True if the command was successful and a new resultset is available, False otherwise.
-
-
-
- Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls.
-
- The index of the column to retrieve
- A SQLiteType structure
-
-
-
- Reads the next row from the resultset
-
- True if a new row was successfully loaded and is ready for processing
-
-
-
- Not implemented. Returns 0
-
-
-
-
- Returns the number of columns in the current resultset
-
-
-
-
- Returns True if the resultset has rows that can be fetched
-
-
-
-
- Returns True if the data reader is closed
-
-
-
-
- Retrieve the count of records affected by an update/insert command. Only valid once the data reader is closed!
-
-
-
-
- Indexer to retrieve data from a column given its name
-
- The name of the column to retrieve data for
- The value contained in the column
-
-
-
- Indexer to retrieve data from a column given its i
-
- The index of the column to retrieve
- The value contained in the column
-
-
-
- The type of user-defined function to declare
-
-
-
-
- Scalar functions are designed to be called and return a result immediately. Examples include ABS(), Upper(), Lower(), etc.
-
-
-
-
- Aggregate functions are designed to accumulate data until the end of a call and then return a result gleaned from the accumulated data.
- Examples include SUM(), COUNT(), AVG(), etc.
-
-
-
-
- Collation sequences are used to sort textual data in a custom manner, and appear in an ORDER BY clause. Typically text in an ORDER BY is
- sorted using a straight case-insensitive comparison function. Custom collating sequences can be used to alter the behavior of text sorting
- in a user-defined manner.
-
-
-
-
- An internal callback delegate declaration.
-
- Raw context pointer for the user function
- Count of arguments to the function
- A pointer to the array of argument pointers
-
-
-
- Internal callback delegate for implementing collation sequences
-
- Length of the string pv1
- Pointer to the first string to compare
- Length of the string pv2
- Pointer to the second string to compare
- Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater
- than the second.
-
-
-
- This abstract class is designed to handle user-defined functions easily. An instance of the derived class is made for each
- connection to the database.
-
-
- Although there is one instance of a class derived from SQLiteFunction per database connection, the derived class has no access
- to the underlying connection. This is necessary to deter implementers from thinking it would be a good idea to make database
- calls during processing.
-
- It is important to distinguish between a per-connection instance, and a per-SQL statement context. One instance of this class
- services all SQL statements being stepped through on that connection, and there can be many. One should never store per-statement
- 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.
-
-
-
-
- The base connection this function is attached to
-
-
-
-
- Used internally to keep track of memory allocated for aggregate functions
-
-
-
-
- Internal array used to keep track of aggregate function context data
-
-
-
-
- Holds a reference to the callback function for user functions
-
-
-
-
- Holds a reference to the callbakc function for stepping in an aggregate function
-
-
-
-
- Holds a reference to the callback function for finalizing an aggregate function
-
-
-
-
- Holds a reference to the callback function for collation sequences
-
-
-
-
- This static list contains all the user-defined functions declared using the proper attributes.
-
-
-
-
- Internal constructor, initializes the function's internal variables.
-
-
-
-
- Scalar functions override this method to do their magic.
-
-
- Parameters passed to functions 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.
-
- The arguments for the command to process
- 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!
-
-
-
- Aggregate functions override this method to do their magic.
-
-
- Typically you'll be updating whatever you've placed in the contextData field and returning as quickly as possible.
-
- The arguments for the command to process
- The 1-based step number. This is incrememted each time the step method is called.
- A placeholder for implementers to store contextual data pertaining to the current context.
-
-
-
- Aggregate functions override this method to finish their aggregate processing.
-
-
- If you implemented your aggregate function 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.
-
- Your own assigned contextData, provided for you so you can return your final results.
- 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!
-
-
-
-
- User-defined collation sequences override this method to provide a custom string sorting algorithm.
-
- The first string to compare
- The second strnig to compare
- 1 if param1 is greater than param2, 0 if they are equal, or -1 if param1 is less than param2
-
-
-
- Converts an IntPtr array of context arguments to an object array containing the resolved parameters the pointers point to.
-
-
- Parameters passed to functions 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.
-
- The number of arguments
- A pointer to the array of arguments
- An object array of the arguments once they've been converted to .NET values
-
-
-
- Takes the return value from Invoke() and Final() and figures out how to return it to SQLite's context.
-
- The context the return value applies to
- The parameter to return to SQLite
-
-
-
- Internal scalar callback function, which wraps the raw context pointer and calls the virtual Invoke() method.
-
- A raw context pointer
- Number of arguments passed in
- A pointer to the array of arguments
-
-
-
- Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function.
-
- Length of the string pv1
- Pointer to the first string to compare
- Length of the string pv2
- Pointer to the second string to compare
- Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater
- than the second.
-
-
-
- The internal aggregate Step function callback, which wraps the raw context pointer and calls the virtual Step() method.
-
-
- This function takes care of doing the lookups and getting the important information put together to call the Step() function.
- That includes pulling out the user's contextData and updating it after the call is made. We use a sorted list for this so
- binary searches can be done to find the data.
-
- A raw context pointer
- Number of arguments passed in
- A pointer to the array of arguments
-
-
-
- An internal aggregate Final function callback, which wraps the context pointer and calls the virtual Final() method.
-
- A raw context pointer
- Not used, always zero
- Not used, always zero
-
-
-
- Placeholder for a user-defined disposal routine
-
- True if the object is being disposed explicitly
-
-
-
- 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.
-
-
-
-
- Using reflection, enumerate all assemblies in the current appdomain looking for classes that
- have a SQLiteFunctionAttribute attribute, and registering them accordingly.
-
-
-
-
- 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).
-
-
- 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.
-
- The base object on which the functions are to bind
- Returns an array of functions which the connection object should retain until the connection is closed.
-
-
-
- Issued after the base connection is closed, this function cleans up all user-defined functions and disposes of them.
-
-
- Cleaning up here is done mainly because of the interop wrapper. It allocated memory to hold a reference to all the
- delegates, and now must free that memory.
- Freeing is done after the connection is closed to ensure no callbacks get hit after we've freed the cookie.
-
- The base SQLite connection object
- An array of user-defined functions for this object
-
-
-
- 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.
-
-
-
-
- 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.
-
-
-
-
- Not used
-
-
-
-
- All integers in SQLite default to Int64
-
-
-
-
- All floating point numbers in SQLite default to double
-
-
-
-
- The default data type of SQLite is text
-
-
-
-
- Typically blob types are only seen when returned from a function
-
-
-
-
- Null types can be returned from functions
-
-
-
-
- Used internally by this provider
-
-
-
-
- Used internally
-
-
-
-
- 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.
-
-
-
-
- Using ticks is more accurate but less compatible with other viewers and utilities that access your database.
-
-
-
-
- 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.
-
-
-
-
- Struct used internally to determine the datatype of a column in a resultset
-
-
-
-
- The DbType of the column, or DbType.Object if it cannot be determined
-
-
-
-
- The affinity of a column, used for expressions or when Type is DbType.Object
-
-
-
-
- This base class provides datatype conversion services for the SQLite provider.
-
-
-
-
- An array of ISO8601 datetime formats we support conversion from
-
-
-
-
- An UTF-8 Encoding instance, so we can convert strings to and from UTF-8
-
-
-
-
- The default DateTime format for this instance
-
-
-
-
- Initializes the conversion class
-
- The default date/time format to use for this instance
-
-
-
- Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character.
-
- The string to convert to UTF-8
- A byte array containing the converted string plus an extra 0 terminating byte at the end of the array.
-
-
-
- Convert a DateTime to a UTF-8 encoded, zero-terminated byte array.
-
-
- This function is a convenience function, which first calls ToString() on the DateTime, and then calls ToUTF8() with the
- string result.
-
- The DateTime to convert.
- The UTF-8 encoded string, including a 0 terminating byte at the end of the array.
-
-
-
- Converts a UTF-8 encoded IntPtr of the specified length into a .NET string
-
- The pointer to the memory where the UTF-8 string is encoded
- The number of bytes to decode
- A string containing the translated character(s)
-
-
-
- Converts a string into a DateTime, using the current DateTimeFormat specified for the connection when it was opened.
-
-
- Acceptable ISO8601 DateTime formats are:
- yyyy-MM-dd HH:mm:ss
- yyyyMMddHHmmss
- yyyyMMddTHHmmssfffffff
- yyyy-MM-dd
- yy-MM-dd
- yyyyMMdd
- HH:mm:ss
- THHmmss
-
- The string containing either a Tick value or an ISO8601-format string
- A DateTime value
-
-
-
- Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened.
-
- The DateTime value to convert
- Either a string consisting of the tick count for DateTimeFormat.Ticks, or a date/time in ISO8601 format.
-
-
-
- Internal function to convert a UTF-8 encoded IntPtr of the specified length to a DateTime.
-
-
- This is a convenience function, which first calls ToString() on the IntPtr to convert it to a string, then calls
- ToDateTime() on the string to return a DateTime.
-
- A pointer to the UTF-8 encoded string
- The length in bytes of the string
- The parsed DateTime value
-
-
-
- Smart method of splitting a string. Skips quoted elements, removes the quotes.
-
-
- This split function works somewhat like the String.Split() function in that it breaks apart a string into
- pieces and returns the pieces as an array. The primary differences are:
-
- - Only one character can be provided as a separator character
- - Quoted text inside the string is skipped over when searching for the separator, and the quotes are removed.
-
- Thus, if splitting the following string looking for a comma:
- One,Two, "Three, Four", Five
-
- The resulting array would contain
- [0] One
- [1] Two
- [2] Three, Four
- [3] Five
-
- Note that the leading and trailing spaces were removed from each item during the split.
-
- Source string to split apart
- Separator character
- A string array of the split up elements
-
-
-
- Determines the data type of a column in a statement
-
- The statement to retrieve information for
- The column to retrieve type information on
- Returns a SQLiteType struct
-
-
-
- Converts a SQLiteType to a .NET Type object
-
- The SQLiteType to convert
- Returns a .NET Type object
-
-
-
- For a given intrinsic type, return a DbType
-
- The native type to convert
- The corresponding (closest match) DbType
-
-
-
- Convert a DbType to a Type
-
- The DbType to convert from
- The closest-match .NET type
-
-
-
- For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types.
-
- The type to evaluate
- The SQLite type affinity for that type.
-
-
-
- For a given type name, return a closest-match .NET type
-
- The name of the type to match
- The .NET DBType the text evaluates to.
-
-
-
- A strongly-typed resource class, for looking up localized strings, etc.
-
-
-
-
- Returns the cached ResourceManager instance used by this class.
-
-
-
-
- Overrides the current thread's CurrentUICulture property for all
- resource lookups using this strongly typed resource class.
-
-
-
-
- Looks up a localized string similar to <?xml version="1.0" standalone="yes"?>
- <DocumentElement>
- <DataTypes>
- <TypeName>System.Int16</TypeName>
- <ProviderDbType>10</ProviderDbType>
- <ColumnSize>5</ColumnSize>
- <DataType>System.Int16</DataType>
- <IsAutoIncrementable>false</IsAutoIncrementable>
- <IsCaseSensitive>false</IsCaseSensitive>
- <IsFixedLength>true</IsFixedLength>
- <IsFixedPrecisionScale>true</IsFixedPrecisionScale>
- <IsLong>false</IsLong>
- <IsNullable>true</IsNullable>
- <IsSearchable>true</Is [rest of string was truncated]";.
-
-
-
-
- Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?>
- <DocumentElement>
- <MetaDataCollections>
- <CollectionName>MetaDataCollections</CollectionName>
- <NumberOfRestrictions>0</NumberOfRestrictions>
- <NumberOfIdentifierParts>0</NumberOfIdentifierParts>
- </MetaDataCollections>
- <MetaDataCollections>
- <CollectionName>DataSourceInformation</CollectionName>
- <NumberOfRestrictions>0</NumberOfRestrictions>
- <NumberOfIdentifierParts>0</NumberOfIdentifierParts>
- </MetaDataCollections>
- <MetaDataC [rest of string was truncated]";.
-
-
-
-
- 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.
-
-
-
-
- Default constructor, initializes the internal variables for the function.
-
-
-
-
- The function's name as it will be used in SQLite command text.
-
-
-
-
- The number of arguments this function expects. -1 if the number of arguments is variable.
-
-
-
-
- The type of function this implementation will be.
-
-
-
-
- SQLite error codes
-
-
-
-
- Success
-
-
-
-
- SQL error or missing database
-
-
-
-
- Internal logic error in SQLite
-
-
-
-
- Access permission denied
-
-
-
-
- Callback routine requested an abort
-
-
-
-
- The database file is locked
-
-
-
-
- A table in the database is locked
-
-
-
-
- malloc() failed
-
-
-
-
- Attempt to write a read-only database
-
-
-
-
- Operation terminated by sqlite3_interrupt()
-
-
-
-
- Some kind of disk I/O error occurred
-
-
-
-
- The database disk image is malformed
-
-
-
-
- Table or record not found
-
-
-
-
- Insertion failed because database is full
-
-
-
-
- Unable to open the database file
-
-
-
-
- Database lock protocol error
-
-
-
-
- Database is empty
-
-
-
-
- The database schema changed
-
-
-
-
- Too much data for one row of a table
-
-
-
-
- Abort due to constraint violation
-
-
-
-
- Data type mismatch
-
-
-
-
- Library used incorrectly
-
-
-
-
- Uses OS features not supported on host
-
-
-
-
- Authorization denied
-
-
-
-
- Auxiliary database format error
-
-
-
-
- 2nd parameter to sqlite3_bind out of range
-
-
-
-
- File opened that is not a database file
-
-
-
-
- sqlite3_step() has another row ready
-
-
-
-
- sqlite3_step() has finished executing
-
-
-
-
- SQLite exception class.
-
-
-
-
- Public constructor for generating a SQLite error given the base error code
-
- The SQLite error code to report
- Extra text to go along with the error message text
-
-
-
- Various public constructors that just pass along to the base Exception
-
- Passed verbatim to Exception
-
-
-
- Various public constructors that just pass along to the base Exception
-
-
-
-
- Various public constructors that just pass along to the base Exception
- Passed to Exception
- Passed to Exception
-
-
-
-
- Initializes the exception class with the SQLite error code.
-
- The SQLite error code
- A detailed error message
- An error message string
-
-
-
- Retrieves the underlying SQLite error code for this exception
-
-
-
-
- This class implements SQLiteBase completely, and is the guts of the code that interop's SQLite with .NET
-
-
-
-
- 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.
-
-
-
-
- Opens a database.
-
-
- Implementers should call SQLiteFunction.BindFunctions() and save the array after opening a connection
- to bind all attributed user-defined functions and collating sequences to the new connection.
-
- The filename of the database to open. SQLite automatically creates it if it doesn't exist.
-
-
-
- Closes the currently-open database.
-
-
- After the database has been closed implemeters should call SQLiteFunction.UnbindFunctions() to deallocate all interop allocated
- memory associated with the user-defined functions and collating sequences tied to the closed connection.
-
-
-
-
- Sets the busy timeout on the connection. SQLiteCommand will call this before executing any command.
-
- The number of milliseconds to wait before returning SQLITE_BUSY
-
-
-
- Quick execute of a SQL command. This is only executed internally, usually by SQLiteConnection when the connection
- is first opened to set the necessary startup pragmas.
-
- The SQL command text to execute
-
-
-
- Returns the text of the last error issued by SQLite
-
-
-
-
-
- Prepares a SQL statement for execution.
-
- The SQL command text to prepare
- The previous statement in a multi-statement command, or null if no previous statement exists
- 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.
- Returns an initialized SQLiteStatement.
-
-
-
- Steps through a prepared statement.
-
- The SQLiteStatement to step through
- True if a row was returned, False if not.
-
-
-
- Finalizes a prepared statement.
-
- The statement to finalize
-
-
-
- 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.
-
- The statement to reset
- Returns -1 if the schema changed while resetting, 0 if the reset was sucessful or 6 (SQLITE_LOCKED) if the reset failed due to a lock
-
-
-
- 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.
-
-
- All statements prepared on this connection after this flag is changed are affected. Existing statements are not.
-
- Set to True to enable real column names, false to disable them.
-
-
-
- Helper function to retrieve a column of data from an active statement.
-
- The statement being step()'d through
- The column index to retrieve
- The type of data contained in the column. If Uninitialized, this function will retrieve the datatype information.
- Returns the data in the column
-
-
-
- Returns a string representing the active version of SQLite
-
-
-
-
- Returns the number of changes the last executing insert/update caused.
-
-
-
-
- The opaque pointer returned to us by the sqlite provider
-
-
-
-
- The user-defined functions registered on this connection
-
-
-
-
- Represents a single SQL statement in SQLite.
-
-
-
-
- The underlying SQLite object this statement is bound to
-
-
-
-
- The command text of this SQL statement
-
-
-
-
- The actual statement pointer
-
-
-
-
- An index from which unnamed parameters begin
-
-
-
-
- Names of the parameters as SQLite understands them to be
-
-
-
-
- Parameters for this statement
-
-
-
-
- Command this statement belongs to (if any)
-
-
-
-
- Initializes the statement and attempts to get all information about parameters in the statement
-
- The base SQLite object
- The statement
- The command text for this statement
- The previous command in a multi-statement command
-
-
-
- Called by SQLiteParameterCollection, this function determines if the specified parameter name belongs to
- this statement, and if so, keeps a reference to the parameter so it can be bound later.
-
- The parameter name to map
- The parameter to assign it
-
-
-
- Disposes and finalizes the statement
-
-
-
-
- Bind all parameters, making sure the caller didn't miss any
-
-
-
-
- Perform the bind operation for an individual parameter
-
- The index of the parameter to bind
- The parameter we're binding
-
-
-
- SQLite implementation of DbDataAdapter.
-
-
-
-
- This class is just a shell around the DbDataAdapter. Nothing from DbDataAdapter is overridden here, just a few constructors are defined.
-
-
- Default constructor.
-
-
-
-
- Constructs a data adapter using the specified select command.
-
- The select command to associate with the adapter.
-
-
-
- Constructs a data adapter with the supplied select command text and associated with the specified connection.
-
- The select command text to associate with the data adapter.
- The connection to associate with the select command.
-
-
-
- Constructs a data adapter with the specified select command text, and using the specified database connection string.
-
- The select command text to use to construct a select command.
- A connection string suitable for passing to a new SQLiteConnection, which is associated with the select command.
-
-
-
- Raised by the underlying DbDataAdapter when a row is being updated
-
- The event's specifics
-
-
-
- Raised by DbDataAdapter after a row is updated
-
- The event's specifics
-
-
-
- Row updating event handler
-
-
-
-
- Row updated event handler
-
-
-
-
- Gets/sets the select command for this DataAdapter
-
-
-
-
- Gets/sets the insert command for this DataAdapter
-
-
-
-
- Gets/sets the update command for this DataAdapter
-
-
-
-
- Gets/sets the delete command for this DataAdapter
-
-
-
-
- SQLite implementation of DbCommand.
-
-
-
-
- The command text this command is based on
-
-
-
-
- The connection the command is associated with
-
-
-
-
- Indicates whether or not a DataReader is active on the command.
-
-
-
-
- The timeout for the command, kludged because SQLite doesn't support per-command timeout values
-
-
-
-
- Designer support
-
-
-
-
- Used by DbDataAdapter to determine updating behavior
-
-
-
-
- The collection of parameters for the command
-
-
-
-
- The SQL command text, broken into individual SQL statements as they are executed
-
-
-
-
- Unprocessed SQL text that has not been executed
-
-
-
-
- Constructs a new SQLiteCommand
-
-
- Default constructor
-
-
-
-
- Initializes the command with the given command text
-
- The SQL command text
-
-
-
- Initializes the command with the given SQL command text and attach the command to the specified
- connection.
-
- The SQL command text
- The connection to associate with the command
-
-
-
- Initializes the command and associates it with the specified connection.
-
- The connection to associate with the command
-
-
-
- Initializes a command with the given SQL, connection and transaction
-
- The SQL command text
- The connection to associate with the command
- The transaction the command should be associated with
-
-
-
- Initializes the command class
-
- The SQL command text
- A connection to associate with the command
-
-
-
- Disposes of the command and clears all member variables
-
- Whether or not the class is being explicitly or implicitly disposed
-
-
-
- Clears and destroys all statements currently prepared
-
-
-
-
- Builds an array of prepared statements for each complete SQL statement in the command text
-
-
-
-
- Not implemented
-
-
-
-
- Forwards to the local CreateParameter() function
-
-
-
-
-
- Create a new parameter
-
-
-
-
-
- This function ensures there are no active readers, that we have a valid connection,
- that the connection is open, that all statements are prepared and all parameters are assigned
- in preparation for allocating a data reader.
-
-
-
-
- Creates a new SQLiteDataReader to execute/iterate the array of SQLite prepared statements
-
- The behavior the data reader should adopt
- Returns a SQLiteDataReader object
-
-
-
- Overrides the default behavior to return a SQLiteDataReader specialization class
-
- The flags to be associated with the reader
- A SQLiteDataReader
-
-
-
- Overrides the default behavior of DbDataReader to return a specialized SQLiteDataReader class
-
- A SQLiteDataReader
-
-
-
- Called by the SQLiteDataReader when the data reader is closed.
-
-
-
-
- Execute the command and return the number of rows inserted/updated affected by it.
-
-
-
-
-
- Execute the command and return the first column of the first row of the resultset
- (if present), or null if no resultset was returned.
-
- The first column of the first row of the first resultset from the query
-
-
-
- Does nothing. Commands are prepared as they are executed the first time, and kept in prepared state afterwards.
-
-
-
-
- Clones a command, including all its parameters
-
- A new SQLiteCommand with the same commandtext, connection and parameters
-
-
-
- The SQL command text associated with the command
-
-
-
-
- The amount of time to wait for the connection to become available before erroring out
-
-
-
-
- The type of the command. SQLite only supports CommandType.Text
-
-
-
-
- The connection associated with this command
-
-
-
-
- Forwards to the local Connection property
-
-
-
-
- Returns the SQLiteParameterCollection for the given command
-
-
-
-
- Forwards to the local Parameters property
-
-
-
-
- The transaction associated with this command. SQLite only supports one transaction per connection, so this property forwards to the
- command's underlying connection.
-
-
-
-
- Forwards to the local Transaction property
-
-
-
-
- Sets the method the SQLiteCommandBuilder uses to determine how to update inserted or updated rows in a DataTable.
-
-
-
-
- Determines if the command is visible at design time. Defaults to True.
-
-
-
-
- SQLite implementation of DbTransaction.
-
-
-
-
- The connection to which this transaction is bound
-
-
-
-
- Constructs the transaction object, binding it to the supplied connection
-
- The connection to open a transaction on
- TRUE to defer the writelock, or FALSE to lock immediately
-
-
-
- Commits the current transaction.
-
-
-
-
- Disposes the transaction. If it is currently active, any changes are rolled back.
-
-
-
-
- Rolls back the active transaction.
-
-
-
-
- Returns the underlying connection to which this transaction applies.
-
-
-
-
- Forwards to the local Connection property
-
-
-
-
- Gets the isolation level of the transaction. SQLite does not support isolation levels, so this always returns Unspecified.
-
-
-
-
- The I/O file cache flushing behavior for the connection
-
-
-
-
- Normal file flushing at critical sections of the code
-
-
-
-
- Full file flushing after every write operation
-
-
-
-
- Use the default operating system's file flushing, SQLite does not explicitly flush the file buffers after writing
-
-
-
-
- SQLite implentation of DbConnection.
-
-
- The ConnectionString property of the SQLiteConnection class can contain the following parameter(s), delimited with a semi-colon:
-
-
- Parameter
- Values
- Required
- Default
-
- -
- Data Source
- {filename}
- Y
-
-
- -
- Version
- 3
- N
- 3
-
- -
- UseUTF16Encoding
- True
False
- N
- False
-
- -
- DateTimeFormat
- Ticks - Use DateTime.Ticks
ISO8601 - Use ISO8601 DateTime format
- N
- ISO8601
-
- -
- Cache Size
- {size in bytes}
- N
- 2000
-
- -
- Synchronous
- Normal - Normal file flushing behavior
Full - Full flushing after all writes
Off - Underlying OS flushes I/O's
- N
- Normal
-
- -
- Page Size
- {size in bytes}
- N
- 1024
-
- -
- Password
- {password}
- N
-
-
-
-
-
-
-
- State of the current connection
-
-
-
-
- The connection string
-
-
-
-
- One transaction allowed per connection please!
-
-
-
-
- The base SQLite object to interop with
-
-
-
-
- Commands associated with this connection
-
-
-
-
- The database filename minus path and extension
-
-
-
-
- Constructs a new SQLiteConnection object
-
-
- Default constructor
-
-
-
-
- Initializes the connection with the specified connection string
-
- The connection string to use on the connection
-
-
-
- Clones the settings and connection string from an existing connection. If the existing connection is already open, this
- function will open its own connection, enumerate any attached databases of the original connection, and automatically
- attach to them.
-
-
-
-
-
- Creates a clone of the connection. All attached databases and user-defined functions are cloned. If the existing connection is open, the cloned connection
- will also be opened.
-
-
-
-
-
- Disposes of the SQLiteConnection, closing it if it is active.
-
- True if the connection is being explicitly closed.
-
-
-
- Creates a database file. This just creates a zero-byte file which SQLite
- will turn into a database when the file is opened properly.
-
- The file to create
-
-
-
- On NTFS volumes, this function turns on the compression attribute for the given file.
- It must not be open or referenced at the time of the function call.
-
- The file to compress
-
-
-
- On NTFS volumes, this function removes the compression attribute for the given file.
- It must not be open or referenced at the time of the function call.
-
- The file to decompress
-
-
-
- On NTFS volumes, this function turns on the EFS (Encrypted File System) attribute
- for the given file, which causes the file to be encrypted.
- For a full description of EFS, see the MSDN documentation.
-
-
- Requires Win2K and above, plus a valid EFS certificate (which is beyond the scope
- of this function description).
-
- The file to encrypt
-
-
-
- On NTFS volumes, this function removes the encryption attribute from the file,
- causing the file to be decrypted. See the MSDN documentation for full details on
- EFS (Encrypted File System).
-
-
- Requires Win2K and above, plus a valid EFS certificate (which is beyond the scope
- of this function description).
-
- The file to decrypt
-
-
-
- Returns true if the file is encrypted, or false otherwise.
-
-
- Requires Win2K and above, plus a valid EFS certificate (which is beyond the scope
- of this function description).
-
- The file to check
- true if the file is encrypted
-
-
-
- Raises the state change event when the state of the connection changes
-
- The new state. If it is different from the previous state, an event is raised.
-
-
-
- Creates a new SQLiteTransaction if one isn't already active on the connection.
-
- SQLite doesn't support varying isolation levels, so this parameter is ignored.
- When TRUE, SQLite defers obtaining a write lock until a write operation is requested.
- When FALSE, a writelock is obtained immediately. The default is TRUE, but in a multi-threaded multi-writer
- environment, one may instead choose to lock the database immediately to avoid any possible writer deadlock.
- Returns a SQLiteTransaction object.
-
-
-
- Creates a new SQLiteTransaction if one isn't already active on the connection.
-
- When TRUE, SQLite defers obtaining a write lock until a write operation is requested.
- When FALSE, a writelock is obtained immediately. The default is TRUE, but in a multi-threaded multi-writer
- environment, one may instead choose to lock the database immediately to avoid any possible writer deadlock.
- Returns a SQLiteTransaction object.
-
-
-
- Creates a new SQLiteTransaction if one isn't already active on the connection.
-
- SQLite doesn't support varying isolation levels, so this parameter is ignored.
- Returns a SQLiteTransaction object.
-
-
-
- Creates a new SQLiteTransaction if one isn't already active on the connection.
-
- Returns a SQLiteTransaction object.
-
-
-
- Forwards to the local BeginTransaction() function
-
-
-
-
-
-
- Not implemented
-
-
-
-
-
- When the database connection is closed, all commands linked to this connection are automatically reset.
-
-
-
-
- Create a new SQLiteCommand and associate it with this connection.
-
- Returns an instantiated SQLiteCommand object already assigned to this connection.
-
-
-
- Forwards to the local CreateCommand() function
-
-
-
-
-
- Parses the connection string into component parts
-
- An array of key-value pairs representing each parameter of the connection string
-
-
-
- Looks for a key in the array of key/values of the parameter string. If not found, return the specified default value
-
- The Key/Value pair array to look in
- The key to find
- The default value to return if the key is not found
- The value corresponding to the specified key, or the default value if not found.
-
-
-
- Opens the connection using the parameters found in the ConnectionString
-
-
-
-
- Change the password (or assign a password) to an open database.
-
-
- No readers or writers may be active for this process. The database must already be open
- and if it already was password protected, the existing password must already have been supplied.
-
- The new password to assign to the database
-
-
-
- Change the password (or assign a password) to an open database.
-
-
- No readers or writers may be active for this process. The database must already be open
- and if it already was password protected, the existing password must already have been supplied.
-
- The new password to assign to the database
-
-
-
- Sets the password for a password-protected database. A password-protected database is
- unusable for any operation until the password has been set.
-
- The password for the database
-
-
-
- Sets the password for a password-protected database. A password-protected database is
- unusable for any operation until the password has been set.
-
- The password for the database
-
-
-
- The following commands are used to extract schema information out of the database. Valid schema types are:
-
- -
- MetaDataCollections
-
- -
- DataSourceInformation
-
- -
- Columns
-
- -
- Indexes
-
- -
- Tables
-
- -
- Views
-
- -
- Catalogs
-
-
-
-
- Returns the MetaDataCollections schema
-
- A DataTable of the MetaDataCollections schema
-
-
-
- Returns schema information of the specified collection
-
- The schema collection to retrieve
- A DataTable of the specified collection
-
-
-
- Retrieves schema information using the specified constraint(s) for the specified collection
-
- The collection to retrieve
- The restrictions to impose
- A DataTable of the specified collection
-
-
-
- Builds a MetaDataCollections schema datatable
-
- DataTable
-
-
-
- Builds a DataSourceInformation datatable
-
- DataTable
-
-
-
- Build a Columns schema
-
- The catalog (attached database) to query, can be null
- The table to retrieve schema information for, must not be null
- The column to retrieve schema information for, can be null
- DataTable
-
-
-
- Returns index information for the given database and catalog
-
- The catalog (attached database) to query, can be null
- The name of the index to retrieve information for, can be null
- The table to retrieve index information for, can be null
- DataTable
-
-
-
- Retrieves table schema information for the database and catalog
-
- The catalog (attached database) to retrieve tables on
- The table to retrieve, can be null
- The table type, can be null
- DataTable
-
-
-
- Retrieves view schema information for the database
-
- The catalog (attached database) to retrieve views on
- The view name, can be null
- DataTable
-
-
-
- Retrieves catalog (attached databases) schema information for the database
-
- The catalog to retrieve, can be null
- DataTable
-
-
-
- Returns the base column information for indexes in a database
-
- The catalog to retrieve indexes for (can be null)
- The table to restrict index information by (can be null)
- The index to restrict index information by (can be null)
- The source column to restrict index information by (can be null)
- A DataTable containing the results
-
-
-
- Returns detailed column information for a specified view
-
- The catalog to retrieve columns for (can be null)
- The view to restrict column information by (can be null)
- The source column to restrict column information by (can be null)
- A DataTable containing the results
-
-
-
- Retrieves foreign key information from the specified set of filters
-
- An optional catalog to restrict results on
- An optional table to restrict results on
- An optional foreign key name to restrict results on
- A DataTable with the results of the query
-
-
-
-
- This event is raised whenever the database is opened or closed.
-
-
-
-
- The connection string containing the parameters for the connection
-
-
-
-
- Parameter
- Values
- Required
- Default
-
- -
- Data Source
- {filename}
- Y
-
-
- -
- Version
- 3
- N
- 3
-
- -
- UseUTF16Encoding
- True
False
- N
- False
-
- -
- DateTimeFormat
- Ticks - Use DateTime.Ticks
ISO8601 - Use ISO8601 DateTime format
- N
- ISO8601
-
- -
- Cache Size
- {size in bytes}
- N
- 2000
-
- -
- Synchronous
- Normal - Normal file flushing behavior
Full - Full flushing after all writes
Off - Underlying OS flushes I/O's
- N
- Normal
-
- -
- Page Size
- {size in bytes}
- N
- 1024
-
- -
- Password
- {password}
- N
-
-
-
-
-
-
-
- Returns the filename without extension or path
-
-
-
-
- Returns an empty string
-
-
-
-
- Returns the version of the underlying SQLite database engine
-
-
-
-
- Returns the state of the connection.
-
-
-
-
- SQLite implementation of DbCommandBuilder.
-
-
-
-
- Default constructor
-
-
-
-
- Initializes the command builder and associates it with the specified data adapter.
-
-
-
-
-
- Not implemented, this function does nothing.
-
- The parameter to use in applying custom behaviors to a row
- The row to apply the parameter to
- The type of statement
- Whether the application of the parameter is part of a WHERE clause
-
-
-
- Not implemented. Throws a NotImplementedException() if called.
-
-
- Not implemented.
-
- The name of the parameter
- Error
-
-
-
- Not implemented.
-
- The i of the parameter
- Error
-
-
-
- Returns a placeholder character for the specified parameter i.
-
- The index of the parameter to provide a placeholder for
- Returns a "?" character, used for all placeholders.
-
-
-
- Sets the handler for receiving row updating events. Used by the DbCommandBuilder to autogenerate SQL
- statements that may not have previously been generated.
-
- A data adapter to receive events on.
-
-
-
- Returns the automatically-generated SQLite command to delete rows from the database
-
-
-
-
-
- Returns the automatically-generated SQLite command to delete rows from the database
-
-
-
-
-
-
- Returns the automatically-generated SQLite command to update rows in the database
-
-
-
-
-
- Returns the automatically-generated SQLite command to update rows in the database
-
-
-
-
-
-
- Returns the automatically-generated SQLite command to insert rows into the database
-
-
-
-
-
- Returns the automatically-generated SQLite command to insert rows into the database
-
-
-
-
-
-
- Gets/sets the DataAdapter for this CommandBuilder
-
-
-
-
- Overridden to hide its property from the designer
-
-
-
-
- Overridden to hide its property from the designer
-
-
-
-
- Overridden to hide its property from the designer
-
-
-
-
- Overridden to hide its property from the designer
-
-
-
-
- Overridden to hide its property from the designer
-
-
-
-
- Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode)
-
-
-
-
- Overrides SQLiteConvert.ToString() to marshal UTF-16 strings instead of UTF-8
-
- A pointer to a UTF-16 string
- The length (IN BYTES) of the string
- A .NET string
-
-
-
- SQLite implementation of DbParameterCollection.
-
-
-
-
- The underlying command to which this collection belongs
-
-
-
-
- The internal array of parameters in this collection
-
-
-
-
- Determines whether or not all parameters have been bound to their statement(s)
-
-
-
-
- Initializes the collection
-
- The command to which the collection belongs
-
-
-
- Retrieves an enumerator for the collection
-
- An enumerator for the underlying array
-
-
-
- Adds a parameter to the collection
-
- The parameter name
- The data type
- The size of the value
- The source column
- A SQLiteParameter object
-
-
-
- Adds a parameter to the collection
-
- The parameter name
- The data type
- The size of the value
- A SQLiteParameter object
-
-
-
- Adds a parameter to the collection
-
- The parameter name
- The data type
- A SQLiteParameter object
-
-
-
- Adds a parameter to the collection
-
- The parameter to add
- A zero-based index of where the parameter is located in the array
-
-
-
- Adds a parameter to the collection
-
- The parameter to add
- A zero-based index of where the parameter is located in the array
-
-
-
- Adds a named/unnamed parameter and its value to the parameter collection.
-
- Name of the parameter, or null to indicate an unnamed parameter
- The initial value of the parameter
- Returns the SQLiteParameter object created during the call.
-
-
-
- Adds an array of parameters to the collection
-
- The array of parameters to add
-
-
-
- Adds an array of parameters to the collection
-
- The array of parameters to add
-
-
-
- Clears the array and resets the collection
-
-
-
-
- Determines if the named parameter exists in the collection
-
- The name of the parameter to check
- True if the parameter is in the collection
-
-
-
- Determines if the parameter exists in the collection
-
- The SQLiteParameter to check
- True if the parameter is in the collection
-
-
-
- Not implemented
-
-
-
-
-
-
- Retrieve a parameter by name from the collection
-
- The name of the parameter to fetch
- A DbParameter object
-
-
-
- Retrieves a parameter by its index in the collection
-
- The index of the parameter to retrieve
- A DbParameter object
-
-
-
- Returns the index of a parameter given its name
-
- The name of the parameter to find
- -1 if not found, otherwise a zero-based index of the parameter
-
-
-
- Returns the index of a parameter
-
- The parameter to find
- -1 if not found, otherwise a zero-based index of the parameter
-
-
-
- Inserts a parameter into the array at the specified location
-
- The zero-based index to insert the parameter at
- The parameter to insert
-
-
-
- Removes a parameter from the collection
-
- The parameter to remove
-
-
-
- Removes a parameter from the collection given its name
-
- The name of the parameter to remove
-
-
-
- Removes a parameter from the collection given its index
-
- The zero-based parameter index to remove
-
-
-
- Re-assign the named parameter to a new parameter object
-
- The name of the parameter to replace
- The new parameter
-
-
-
- Re-assign a parameter at the specified index
-
- The zero-based index of the parameter to replace
- The new parameter
-
-
-
- Un-binds all parameters from their statements
-
-
-
-
- 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.
-
-
-
-
- Returns true
-
-
-
-
- Returns false
-
-
-
-
- Returns false
-
-
-
-
- Returns null
-
-
-
-
- Returns a count of parameters in the collection
-
-
-
-
- SQLite implementation of DbParameter.
-
-
-
-
- The data type of the parameter
-
-
-
-
- The version information for mapping the parameter
-
-
-
-
- The value of the data in the parameter
-
-
-
-
- The source column for the parameter
-
-
-
-
- The column name
-
-
-
-
- The data size, unused by SQLite
-
-
-
-
- Default constructor
-
-
-
-
- Constructs a named parameter given the specified parameter name
-
- The parameter name
-
-
-
- Constructs a named parameter given the specified parameter name and initial value
-
- The parameter name
- The initial value of the parameter
-
-
-
- Constructs a named parameter of the specified type
-
- The parameter name
- The datatype of the parameter
-
-
-
- Constructs a named parameter of the specified type and source column reference
-
- The parameter name
- The data type
- The source column
-
-
-
- Constructs a named parameter of the specified type, source column and row version
-
- The parameter name
- The data type
- The source column
- The row version information
-
-
-
- Constructs an unnamed parameter of the specified data type
-
- The datatype of the parameter
-
-
-
- Constructs an unnamed parameter of the specified data type and sets the initial value
-
- The datatype of the parameter
- The initial value of the parameter
-
-
-
- Constructs an unnamed parameter of the specified data type and source column
-
- The datatype of the parameter
- The source column
-
-
-
- Constructs an unnamed parameter of the specified data type, source column and row version
-
- The data type
- The source column
- The row version information
-
-
-
- Constructs a named parameter of the specified type and size
-
- The parameter name
- The data type
- The size of the parameter
-
-
-
- Constructs a named parameter of the specified type, size and source column
-
- The name of the parameter
- The data type
- The size of the parameter
- The source column
-
-
-
- Constructs a named parameter of the specified type, size, source column and row version
-
- The name of the parameter
- The data type
- The size of the parameter
- The source column
- The row version information
-
-
-
- Constructs a named parameter of the specified type, size, source column and row version
-
- The name of the parameter
- The data type
- The size of the parameter
- Only input parameters are supported in SQLite
- Ignored
- Ignored
- Ignored
- The source column
- The row version information
- The initial value to assign the parameter
-
-
-
- Constructs an unnamed parameter of the specified type and size
-
- The data type
- The size of the parameter
-
-
-
- Constructs an unnamed parameter of the specified type, size, and source column
-
- The data type
- The size of the parameter
- The source column
-
-
-
- Constructs an unnamed parameter of the specified type, size, source column and row version
-
- The data type
- The size of the parameter
- The source column
- The row version information
-
-
-
- Initializes the parameter member variables
-
- The parameter name
- The data type
- The size
- The source column
- The row version
-
-
-
- Not implemented
-
-
-
-
- Clones a parameter
-
- A new, unassociated SQLiteParameter
-
-
-
- Returns True.
-
-
-
-
- Returns the datatype of the parameter
-
-
-
-
- Supports only input parameters
-
-
-
-
- Returns the parameter name
-
-
-
-
- Returns the size of the parameter
-
-
-
-
- Gets/sets the source column
-
-
-
-
- Returns false, ignores any set value
-
-
-
-
- Gets and sets the row version
-
-
-
-
- Gets and sets the parameter value. If no datatype was specified, the datatype will assume the type from the value given.
-
-
-
-
- SQLite implementation of DbConnectionStringBuilder.
-
-
-
-
- Properties of this class
-
-
-
-
- Constructs a new instance of the class
-
-
- Default constructor
-
-
-
-
- Constructs a new instance of the class using the specified connection string.
-
- The connection string to parse
-
-
-
- Private initializer, which assigns the connection string and resets the builder
-
- The connection string to assign
-
-
-
- Helper function for retrieving values from the connectionstring
-
- The keyword to retrieve settings for
- The resulting parameter value
- Returns true if the value was found and returned
-
-
-
- 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.
-
-
-
-
- Gets/Sets the synchronous mode of the connection string. Default is "Normal".
-
-
-
-
- Gets/Sets the encoding for the connection string. The default is "False" which indicates UTF-8 encoding.
-
-
-
-
- Gets/Sets the filename to open on the connection string.
-
-
-
-
- Gets/sets the database encryption password
-
-
-
-
- Gets/Sets the page size for the connection.
-
-
-
-
- Gets/Sets the cache size for the connection.
-
-
-
-
- Gets/Sets the datetime format for the connection.
-
-
-
-
Index: Doc/ndoc.log
==================================================================
--- Doc/ndoc.log
+++ Doc/ndoc.log
@@ -25,11 +25,10 @@
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.SQLiteCommandConstructor5.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
@@ -89,10 +88,11 @@
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
@@ -142,10 +142,12 @@
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
@@ -161,10 +163,11 @@
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
@@ -186,13 +189,10 @@
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.SQLiteParameterConstructor15.html
-System.Data.SQLite.SQLiteParameterConstructor16.html
-System.Data.SQLite.SQLiteParameterConstructor17.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
@@ -201,10 +201,11 @@
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
@@ -252,16 +253,16 @@
Compiling c:\src\SQLite.NET\Doc\ndoc_msdn_temp\SQLite.NET.chm
Compile time: 0 minutes, 3 seconds
-232 Topics
-1,341 Local links
+233 Topics
+1,346 Local links
0 Internet links
8 Graphics
-Created c:\src\SQLite.NET\Doc\ndoc_msdn_temp\SQLite.NET.chm, 142,903 bytes
-Compression decreased file by 746,084 bytes.
+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
Index: SQLite.Designer/AssemblyInfo.cs
==================================================================
--- SQLite.Designer/AssemblyInfo.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using System;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.ConstrainedExecution;
-
-// 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("SQLite.Designer")]
-[assembly: AssemblyDescription("ADO.NET 2.0 Data Designer for SQLite")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("http://sourceforge.net/projects/sqlite-dotnet2")]
-[assembly: AssemblyProduct("SQLite.Designer")]
-[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)]
-[assembly: CLSCompliant(true)]
-[assembly: ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
-
-// 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.24.5")]
-[assembly: AssemblyFileVersion("1.0.24.5")]
-[assembly:AssemblyDelaySignAttribute(false)]
-[assembly:AssemblyKeyFileAttribute("..\\System.Data.SQLite\\System.Data.SQLite.snk")]
-[assembly:AssemblyKeyNameAttribute("")]
DELETED SQLite.Designer/SQLite.Designer.csproj
Index: SQLite.Designer/SQLite.Designer.csproj
==================================================================
--- SQLite.Designer/SQLite.Designer.csproj
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
- Debug
- AnyCPU
- 8.0.50727
- 2.0
- {9B4A5CF6-5BE5-4926-ACC7-B729A8C05198}
- Library
- Properties
- SQLite.Designer
- SQLite.Designer
- false
-
-
-
-
- true
- full
- false
- ..\bin\Designer\
- DEBUG;TRACE
- prompt
- 4
- 1701;1702;1699
-
-
- none
- true
- ..\bin\Designer\
-
-
- prompt
- 4
- 1701;1702;1699
-
-
-
- False
- C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\Microsoft.VisualStudio.Data.dll
- False
-
-
- False
-
-
-
-
-
-
-
-
-
-
- True
- True
- SR.resx
-
-
-
-
- ResXFileCodeGenerator
- SR.Designer.cs
-
-
-
-
-
-
-
DELETED SQLite.Designer/SQLiteDataObjectIdentifierResolver.cs
Index: SQLite.Designer/SQLiteDataObjectIdentifierResolver.cs
==================================================================
--- SQLite.Designer/SQLiteDataObjectIdentifierResolver.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-/********************************************************
- * 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 SQLite.Designer
-{
- using System;
- using System.Collections.Generic;
- using System.Text;
- using Microsoft.VisualStudio.Data;
- using Microsoft.VisualStudio.OLE.Interop;
-
- internal class SQLiteDataObjectIdentifierResolver : DataObjectIdentifierResolver, IObjectWithSite
- {
- private DataConnection _connection;
-
- public SQLiteDataObjectIdentifierResolver()
- {
- }
-
- protected override object[] QuickExpandIdentifier(string typeName, object[] partialIdentifier)
- {
- if (typeName == null)
- {
- throw new ArgumentNullException("typeName");
- }
-
- // Create an identifier array of the correct full length based on
- // the object type
- object[] identifier = null;
- int length = 0;
-
- switch (typeName.ToLowerInvariant())
- {
- case "":
- length = 0;
- break;
- case "table":
- case "view":
- length = 3;
- break;
- case "column":
- case "index":
- case "foreignkey":
- case "viewcolumn":
- length = 4;
- break;
- case "indexcolumn":
- case "foreignkeycolumn":
- length = 5;
- break;
- default:
- throw new NotSupportedException();
- }
- identifier = new object[length];
-
- // If the input identifier is not null, copy it to the full
- // identifier array. If the input identifier's length is less
- // than the full length we assume the more specific parts are
- // specified and thus copy into the rightmost portion of the
- // full identifier array.
- if (partialIdentifier != null)
- {
- if (partialIdentifier.Length > length)
- {
- throw new InvalidOperationException();
- }
- partialIdentifier.CopyTo(identifier, length - partialIdentifier.Length);
- }
-
- if (length > 0)
- {
- // Fill in the current database if not specified
- if (!(identifier[0] is string))
- {
- identifier[0] = _connection.SourceInformation[DataSourceInformation.DefaultCatalog] as string;
- }
- }
-
- if (length > 1)
- {
- identifier[1] = null;
- }
-
- return identifier;
- }
-
- protected override object[] QuickContractIdentifier(string typeName, object[] fullIdentifier)
- {
- int length = fullIdentifier.Length;
- object[] identifier = new object[length];
-
- fullIdentifier.CopyTo(identifier, 0);
-
- if (length > 0)
- {
- if (!(identifier[0] is string))
- identifier[0] = null;
- }
-
- if (length > 1)
- {
- identifier[1] = null;
- }
-
- return identifier;
- }
-
- ///
- /// GetSite does not need to be implemented since
- /// DDEX only calls SetSite to site the object.
- ///
- void IObjectWithSite.GetSite(ref Guid riid, out IntPtr ppvSite)
- {
- ppvSite = IntPtr.Zero;
- throw new NotImplementedException();
- }
-
- void IObjectWithSite.SetSite(object pUnkSite)
- {
- _connection = (DataConnection)pUnkSite;
- }
- }
-}
DELETED SQLite.Designer/SQLiteDataSourceInformation.cs
Index: SQLite.Designer/SQLiteDataSourceInformation.cs
==================================================================
--- SQLite.Designer/SQLiteDataSourceInformation.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-/********************************************************
- * 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 SQLite.Designer
-{
- using System;
- using System.Collections.Generic;
- using System.Text;
- using Microsoft.VisualStudio.Data;
-
- internal class SQLiteDataSourceInformation : DataSourceInformation
- {
- public SQLiteDataSourceInformation()
- {
- Initialize();
- }
-
- public SQLiteDataSourceInformation(DataConnection connection) : base(connection)
- {
- Initialize();
- }
-
- private void Initialize()
- {
- AddProperty(DefaultSchema);
- AddProperty(DefaultCatalog, "main");
- AddProperty(SupportsAnsi92Sql, true);
- AddProperty(SupportsQuotedIdentifierParts, true);
- AddProperty(IdentifierOpenQuote, "[");
- AddProperty(IdentifierCloseQuote, "]");
- AddProperty(CatalogSeparator, ".");
- AddProperty(CatalogSupported, true);
- AddProperty(CatalogSupportedInDml, true);
- AddProperty(SchemaSupported, false);
- AddProperty(SchemaSupportedInDml, false);
- AddProperty(SchemaSeparator, "");
- AddProperty(ParameterPrefix, "$");
- AddProperty(ParameterPrefixInName, true);
- }
- }
-}
DELETED SQLite.Designer/SR.Designer.cs
Index: SQLite.Designer/SR.Designer.cs
==================================================================
--- SQLite.Designer/SR.Designer.cs
+++ /dev/null
@@ -1,101 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-// Runtime Version:2.0.50215.44
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-[assembly: global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope="member", Target="SQLite.Designer.SR.get_ResourceManager():System.Resources.ResourceManager")]
-[assembly: global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope="member", Target="SQLite.Designer.SR.get_Culture():System.Globalization.CultureInfo")]
-[assembly: global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope="member", Target="SQLite.Designer.SR.set_Culture(System.Globalization.CultureInfo):Void")]
-
-namespace SQLite.Designer {
-
-
- ///
- /// A strongly-typed resource class, for looking up localized strings, etc.
- ///
- // This class was auto-generated by the StronglyTypedResourceBuilder
- // class via a tool like ResGen or Visual Studio.
- // To add or remove a member, edit your .ResX file then rerun ResGen
- // with the /str option, or rebuild your VS project.
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class SR {
-
- private static global::System.Resources.ResourceManager resourceMan;
-
- private static global::System.Globalization.CultureInfo resourceCulture;
-
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal SR() {
- }
-
- ///
- /// Returns the cached ResourceManager instance used by this class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
- get {
- if ((resourceMan == null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SQLite.Designer.SR", typeof(SR).Assembly);
- resourceMan = temp;
- }
- return resourceMan;
- }
- }
-
- ///
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
- get {
- return resourceCulture;
- }
- set {
- resourceCulture = value;
- }
- }
-
- ///
- /// Looks up a localized string similar to .NET Data Provider for SQLite.
- ///
- internal static string DataProvider_SQLite {
- get {
- return ResourceManager.GetString("DataProvider_SQLite", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Description of the SQLite Data Provider goes here.
- ///
- internal static string DataProvider_SQLite_Description {
- get {
- return ResourceManager.GetString("DataProvider_SQLite_Description", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Service Provider string.
- ///
- internal static string DataProvider_SQLite_ServiceProvider {
- get {
- return ResourceManager.GetString("DataProvider_SQLite_ServiceProvider", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to SQLite Database File.
- ///
- internal static string DataProvider_SQLite_Short {
- get {
- return ResourceManager.GetString("DataProvider_SQLite_Short", resourceCulture);
- }
- }
- }
-}
DELETED SQLite.Designer/SR.resx
Index: SQLite.Designer/SR.resx
==================================================================
--- SQLite.Designer/SR.resx
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- .NET Data Provider for SQLite
-
-
- Description of the SQLite Data Provider goes here
-
-
- Service Provider string
-
-
- SQLite Database File
-
-
DELETED SQLite.Interop/AssemblyInfo.cpp
Index: SQLite.Interop/AssemblyInfo.cpp
==================================================================
--- SQLite.Interop/AssemblyInfo.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-using namespace System::Reflection;
-using namespace System::Runtime::CompilerServices;
-using namespace 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:AssemblyTitleAttribute("System.Data.SQLite")];
-[assembly:AssemblyDescriptionAttribute("http://sourceforge.net/projects/sqlite-dotnet2")];
-[assembly:AssemblyConfigurationAttribute("")];
-[assembly:AssemblyCompanyAttribute("")];
-[assembly:AssemblyProductAttribute("System.Data.SQLite")];
-[assembly:AssemblyCopyrightAttribute("Released to the public domain")];
-[assembly:AssemblyTrademarkAttribute("")];
-[assembly:AssemblyCultureAttribute("")];
-
-//
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the value or you can default the Revision and Build Numbers
-// by using the '*' as shown below:
-
-[assembly:AssemblyVersionAttribute("1.0.17.0")];
-[assembly:AssemblyFileVersionAttribute("1.0.17.0")];
-
-//
-// In order to sign your assembly you must specify a key to use. Refer to the
-// Microsoft CLR Framework documentation for more information on assembly signing.
-//
-// You can use the attributes below to control which key is used for signing.
-// You can also use the project property page for signing under Common Properties
-// to set the same information.
-//
-// Notes:
-// (*) If no key is specified, the assembly is not signed.
-// (*) KeyName refers to a key that has been installed in the Crypto Service
-// Provider (CSP) on your machine. KeyFile refers to a file which contains
-// a key.
-// (*) If the KeyFile and the KeyName values are both specified, the
-// following processing occurs:
-// (1) If the KeyName can be found in the CSP, that key is used.
-// (2) If the KeyName does not exist and the KeyFile does exist, the key
-// in the KeyFile is installed into the CSP and used.
-// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
-// When specifying the KeyFile, the location of the KeyFile should be
-// relative to the project directory.
-// (*) Delay Signing is an advanced option - see the Microsoft CLR Framework
-// documentation for more information on this.
-//
-[assembly:AssemblyDelaySignAttribute(false)];
-
-#ifdef _WIN64
-#ifdef _M_IA64 // Itanium
-[assembly:AssemblyKeyFileAttribute("..\\System.Data.SQLite\\System.Data.SQLite.IA64.snk")];
-#else // AMD64
-[assembly:AssemblyKeyFileAttribute("..\\System.Data.SQLite\\System.Data.SQLite.X64.snk")];
-#endif
-#else
-[assembly:AssemblyKeyFileAttribute("..\\System.Data.SQLite\\System.Data.SQLite.snk")];
-#endif
-[assembly:AssemblyKeyNameAttribute("")];
-
-[assembly:ComVisible(false)];
-
DELETED SQLite.Interop/SQLite.Interop.rc
Index: SQLite.Interop/SQLite.Interop.rc
==================================================================
--- SQLite.Interop/SQLite.Interop.rc
+++ /dev/null
@@ -1,102 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,24,5
- PRODUCTVERSION 1,0,0,0
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "Comments", "http://sourceforge.net/projects/sqlite-dotnet2"
- VALUE "FileDescription", "SQLite.NET Interop Library"
- VALUE "FileVersion", "1.0.24.5"
- VALUE "InternalName", "SQLite.Interop.DLL"
- VALUE "LegalCopyright", "Released to the public domain"
- VALUE "OriginalFilename", "SQLite3.DLL 3.3.1 alpha"
- VALUE "ProductName", "SQLite.NET"
- VALUE "ProductVersion", "1.0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
Index: SQLite.Interop/SQLite.Interop.vcproj
==================================================================
--- SQLite.Interop/SQLite.Interop.vcproj
+++ SQLite.Interop/SQLite.Interop.vcproj
@@ -9,36 +9,23 @@
>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -735,18 +203,10 @@
>
-
-
-
-
@@ -781,96 +241,28 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -879,78 +271,18 @@
>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -983,14 +315,10 @@
>
-
-
@@ -1003,33 +331,18 @@
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
-
-
-
-
-
-
-
-
DELETED SQLite.Interop/crypt.c
Index: SQLite.Interop/crypt.c
==================================================================
--- SQLite.Interop/crypt.c
+++ /dev/null
@@ -1,396 +0,0 @@
-#ifdef SQLITE_HAS_CODEC
- void sqlite3pager_free_codecarg(void *pArg);
-#endif
-
-#include "src/pager.c"
-
-#ifndef SQLITE_OMIT_DISKIO
-#ifdef SQLITE_HAS_CODEC
-
-#include
-#include
-
-typedef struct _CRYPTBLOCK
-{
- HCRYPTKEY hReadKey; // Key used to read from the database and write to the journal
- HCRYPTKEY hWriteKey; // Key used to write to the database
- DWORD dwPageSize; // Size of pages
- LPVOID pvCrypt; // A buffer for encrypting/decrypting (if necessary)
- DWORD dwCryptSize; // Equal to or greater than dwPageSize. If larger, pvCrypt is valid and this is its size
-} CRYPTBLOCK, *LPCRYPTBLOCK;
-
-HCRYPTPROV g_hProvider = 0; // Global instance of the cryptographic provider
-
-#define SQLITECRYPTERROR_PROVIDER "Cryptographic provider not available"
-
-// Needed for re-keying
-static void * sqlite3pager_get_codecarg(Pager *pPager)
-{
- return (pPager->xCodec) ? pPager->pCodecArg: NULL;
-}
-
-// Create a cryptographic context. Use the enhanced provider because it is available on
-// most platforms
-static BOOL InitializeProvider()
-{
- if (g_hProvider) return TRUE;
-
- if (!CryptAcquireContext(&g_hProvider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
- {
- if(!CryptAcquireContext(&g_hProvider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET))
- {
- return FALSE;
- }
- }
- return TRUE;
-}
-
-// Create or update a cryptographic context for a pager.
-// This function will automatically determine if the encryption algorithm requires
-// extra padding, and if it does, will create a temp buffer big enough to provide
-// space to hold it.
-static LPCRYPTBLOCK CreateCryptBlock(HCRYPTKEY hKey, Pager *pager, LPCRYPTBLOCK pExisting)
-{
- LPCRYPTBLOCK pBlock;
-
- if (!pExisting) // Creating a new cryptblock
- {
- pBlock = malloc(sizeof(CRYPTBLOCK));
- ZeroMemory(pBlock, sizeof(CRYPTBLOCK));
- pBlock->hReadKey = hKey;
- pBlock->hWriteKey = hKey;
- }
- else // Updating an existing cryptblock
- {
- pBlock = pExisting;
- }
-
- pBlock->dwPageSize = (DWORD)pager->pageSize;
- pBlock->dwCryptSize = pBlock->dwPageSize;
-
- // Existing cryptblocks may have a buffer, if so, delete it
- if (pBlock->pvCrypt)
- {
- free(pBlock->pvCrypt);
- pBlock->pvCrypt = NULL;
- }
-
- // Figure out if this cryptographic key requires extra buffer space, and if so, allocate
- // enough room for it
- if (CryptEncrypt(hKey, 0, TRUE, 0, NULL, &pBlock->dwCryptSize, pBlock->dwCryptSize * 2))
- {
- if (pBlock->dwCryptSize > pBlock->dwPageSize)
- {
- pBlock->pvCrypt = malloc(pBlock->dwCryptSize);
- }
- }
- return pBlock;
-}
-
-// Destroy a cryptographic context and any buffers and keys allocated therein
-static void DestroyCryptBlock(LPCRYPTBLOCK pBlock)
-{
- // Destroy the read key if there is one
- if (pBlock->hReadKey)
- {
- CryptDestroyKey(pBlock->hReadKey);
- }
-
- // If there's a writekey and its not equal to the readkey, destroy it
- if (pBlock->hWriteKey && pBlock->hWriteKey != pBlock->hReadKey)
- {
- CryptDestroyKey(pBlock->hWriteKey);
- }
-
- // If there's extra buffer space allocated, free it as well
- if (pBlock->pvCrypt)
- {
- free(pBlock->pvCrypt);
- }
-
- // All done with this cryptblock
- free(pBlock);
-}
-
-// Encrypt/Decrypt functionality, called by pager.c
-void sqlite3Codec(void *pArg, void *data, Pgno nPageNum, int nMode)
-{
- LPCRYPTBLOCK pBlock = (LPCRYPTBLOCK)pArg;
- DWORD dwPageSize;
- LPVOID pvTemp;
-
- if (!pBlock) return;
-
- // Make sure the page size for the pager is still the same as the page size
- // for the cryptblock. If the user changed it, we need to adjust!
- if (nMode != 2)
- {
- PgHdr *pageHeader;
- pageHeader = DATA_TO_PGHDR(data);
- if (pageHeader->pPager->pageSize != pBlock->dwPageSize)
- {
- // Update the cryptblock to reflect the new page size
- CreateCryptBlock(0, pageHeader->pPager, pBlock);
- }
- }
-
- /* Block ciphers often need to write extra padding beyond the
- data block. We don't have that luxury for a given page of data so
- we must copy the page data to a buffer that IS large enough to hold
- the padding. We then encrypt the block and write the buffer back to
- the page without the unnecessary padding.
- We only use the special block of memory if its absolutely necessary. */
- if (pBlock->pvCrypt)
- {
- CopyMemory(pBlock->pvCrypt, data, pBlock->dwPageSize);
- pvTemp = data;
- data = pBlock->pvCrypt;
- }
-
- switch(nMode)
- {
- case 0: // Undo a "case 7" journal file encryption
- case 2: // Reload a page
- case 3: // Load a page
- if (!pBlock->hReadKey) break;
- dwPageSize = pBlock->dwCryptSize;
- CryptDecrypt(pBlock->hReadKey, 0, TRUE, 0, (LPBYTE)data, &dwPageSize);
- break;
- case 6: // Encrypt a page for the main database file
- if (!pBlock->hWriteKey) break;
- dwPageSize = pBlock->dwPageSize;
- CryptEncrypt(pBlock->hWriteKey, 0, TRUE, 0, (LPBYTE)data, &dwPageSize, pBlock->dwCryptSize);
- break;
- case 7: // Encrypt a page for the journal file
- /* Under normal circumstances, the readkey is the same as the writekey. However,
- when the database is being rekeyed, the readkey is not the same as the writekey.
- The rollback journal must be written using the original key for the
- database file because it is, by nature, a rollback journal.
- Therefore, for case 7, when the rollback is being written, always encrypt using
- the database's readkey, which is guaranteed to be the same key that was used to
- read the original data.
- */
- if (!pBlock->hReadKey) break;
- dwPageSize = pBlock->dwPageSize;
- CryptEncrypt(pBlock->hReadKey, 0, TRUE, 0, (LPBYTE)data, &dwPageSize, pBlock->dwCryptSize);
- break;
- }
-
- // If the encryption algorithm required extra padding and we were forced to encrypt or
- // decrypt a copy of the page data to a temp buffer, then write the contents of the temp
- // buffer back to the page data minus any padding applied.
- if (pBlock->pvCrypt)
- {
- CopyMemory(pvTemp, data, pBlock->dwPageSize);
- }
-}
-
-// Derive an encryption key from a user-supplied buffer
-static HCRYPTKEY DeriveKey(const void *pKey, int nKeyLen)
-{
- HCRYPTHASH hHash = 0;
- HCRYPTKEY hKey;
-
- if (!pKey || !nKeyLen) return 0;
-
- if (!InitializeProvider())
- {
- return MAXDWORD;
- }
-
- if (CryptCreateHash(g_hProvider, CALG_SHA1, 0, 0, &hHash))
- {
- if (CryptHashData(hHash, (LPBYTE)pKey, nKeyLen, 0))
- {
- CryptDeriveKey(g_hProvider, CALG_RC4, hHash, 0, &hKey);
- }
- CryptDestroyHash(hHash);
- }
- return hKey;
-}
-
-// Called by sqlite and sqlite3_key_interop to attach a key to a database.
-int sqlite3CodecAttach(sqlite3 *db, int nDb, const void *pKey, int nKeyLen)
-{
- int rc = SQLITE_ERROR;
- HCRYPTKEY hKey = 0;
-
- // No key specified, could mean either use the main db's encryption or no encryption
- if (!pKey || !nKeyLen)
- {
- if (!nDb)
- {
- return SQLITE_OK; // Main database, no key specified so not encrypted
- }
- else // Attached database, use the main database's key
- {
- // Get the encryption block for the main database and attempt to duplicate the key
- // for use by the attached database
- LPCRYPTBLOCK pBlock = (LPCRYPTBLOCK)sqlite3pager_get_codecarg(sqlite3BtreePager(db->aDb[0].pBt));
-
- if (!pBlock) return SQLITE_OK; // Main database is not encrypted so neither will be any attached database
- if (!pBlock->hReadKey) return SQLITE_OK; // Not encrypted
-
- if (!CryptDuplicateKey(pBlock->hReadKey, NULL, 0, &hKey))
- return rc; // Unable to duplicate the key
- }
- }
- else // User-supplied passphrase, so create a cryptographic key out of it
- {
- hKey = DeriveKey(pKey, nKeyLen);
- if (hKey == MAXDWORD)
- {
- sqlite3Error(db, rc, SQLITECRYPTERROR_PROVIDER);
- return rc;
- }
- }
-
- // Create a new encryption block and assign the codec to the new attached database
- if (hKey)
- {
- LPCRYPTBLOCK pBlock = CreateCryptBlock(hKey, sqlite3BtreePager(db->aDb[nDb].pBt), NULL);
- sqlite3pager_set_codec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, pBlock);
- rc = SQLITE_OK;
- }
- return rc;
-}
-
-void sqlite3pager_free_codecarg(void *pArg)
-{
- LPCRYPTBLOCK pBlock = (LPCRYPTBLOCK)pArg;
-
- if (pBlock)
- {
- if (pBlock->hReadKey)
- CryptDestroyKey(pBlock->hReadKey);
- if (pBlock->hWriteKey)
- CryptDestroyKey(pBlock->hWriteKey);
-
- if (pBlock->pvCrypt)
- free(pBlock->pvCrypt);
- }
- free(pBlock);
-}
-
-// Once a password has been supplied and a key created, we don't keep the
-// original password for security purposes. Therefore return NULL.
-void sqlite3CodecGetKey(sqlite3 *db, int nDb, void **ppKey, int *pnKeyLen)
-{
- *ppKey = NULL;
- *pnKeyLen = 0;
-}
-
-// We do not attach this key to the temp store, only the main database.
-__declspec(dllexport) int __stdcall sqlite3_key_interop(sqlite3 *db, const void *pKey, int nKeySize)
-{
- return sqlite3CodecAttach(db, 0, pKey, nKeySize);
-}
-
-// Changes the encryption key for an existing database.
-__declspec(dllexport) int __stdcall sqlite3_rekey_interop(sqlite3 *db, const void *pKey, int nKeySize)
-{
- Btree *pbt = db->aDb[0].pBt;
- Pager *p = sqlite3BtreePager(pbt);
- LPCRYPTBLOCK pBlock = (LPCRYPTBLOCK)sqlite3pager_get_codecarg(p);
- HCRYPTKEY hKey = DeriveKey(pKey, nKeySize);
- int rc = SQLITE_ERROR;
-
- if (hKey == MAXDWORD)
- {
- sqlite3Error(db, rc, SQLITECRYPTERROR_PROVIDER);
- return rc;
- }
-
- if (!pBlock && !hKey) return SQLITE_OK; // Wasn't encrypted to begin with
-
- // To rekey a database, we change the writekey for the pager. The readkey remains
- // the same
- if (!pBlock) // Encrypt an unencrypted database
- {
- pBlock = CreateCryptBlock(hKey, p, NULL);
- pBlock->hReadKey = 0; // Original database is not encrypted
- sqlite3pager_set_codec(sqlite3BtreePager(pbt), sqlite3Codec, pBlock);
- }
- else // Change the writekey for an already-encrypted database
- {
- pBlock->hWriteKey = hKey;
- }
-
- // Start a transaction
- rc = sqlite3BtreeBeginTrans(pbt, 1);
-
- if (!rc)
- {
- // Rewrite all the pages in the database using the new encryption key
- int nPage = sqlite3pager_pagecount(p);
- void *pPage;
- int n;
-
- for(n = 1; rc == SQLITE_OK && n <= nPage; n ++)
- {
- rc = sqlite3pager_get(p, n, &pPage);
- if(!rc)
- {
- rc = sqlite3pager_write(pPage);
- sqlite3pager_unref(pPage);
- }
- }
- }
-
- // If we succeeded, try and commit the transaction
- if (!rc)
- {
- rc = sqlite3BtreeCommit(pbt);
- }
-
- // If we failed, rollback
- if (rc)
- {
- sqlite3BtreeRollback(pbt);
- }
-
- // If we succeeded, destroy any previous read key this database used
- // and make the readkey equal to the writekey
- if (!rc)
- {
- if (pBlock->hReadKey)
- {
- CryptDestroyKey(pBlock->hReadKey);
- }
- pBlock->hReadKey = pBlock->hWriteKey;
- }
- // We failed. Destroy the new writekey (if there was one) and revert it back to
- // the original readkey
- else
- {
- if (pBlock->hWriteKey)
- {
- CryptDestroyKey(pBlock->hWriteKey);
- }
- pBlock->hWriteKey = pBlock->hReadKey;
- }
-
- // If the readkey and writekey are both empty, there's no need for a codec on this
- // pager anymore. Destroy the crypt block and remove the codec from the pager.
- if (!pBlock->hReadKey && !pBlock->hWriteKey)
- {
- sqlite3pager_set_codec(p, NULL, NULL);
- DestroyCryptBlock(pBlock);
- }
-
- return rc;
-}
-
-int sqlite3_key(sqlite3 *db, const void *pKey, int nKey)
-{
- return sqlite3_key_interop(db, pKey, nKey);
-}
-
-int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey)
-{
- return sqlite3_rekey_interop(db, pKey, nKey);
-}
-
-#endif // SQLITE_HAS_CODEC
-
-#endif // SQLITE_OMIT_DISKIO
DELETED SQLite.Interop/fixsource.vbs
Index: SQLite.Interop/fixsource.vbs
==================================================================
--- SQLite.Interop/fixsource.vbs
+++ /dev/null
@@ -1,60 +0,0 @@
-' VBScript source code
-Main
-
-Sub Main()
- Dim WshShell
- Set WshShell = WScript.CreateObject("WScript.Shell")
-
- Dim fso
- Set fso = WScript.CreateObject("Scripting.FileSystemObject")
-
- Dim srcFile
- Dim srcFileContents
- dim newFileContents
-
- ' Changes the name of the function so we can get first crack at it in interop.h to provide GetSchemaTable() support
- '
- Set srcFile = fso.OpenTextFile("src\select.c", 1)
- srcFileContents = srcFile.ReadAll()
- srcFile.Close()
- newFileContents = Replace(srcFileContents, "static void generateColumnNames(", "static void _generateColumnNames(")
- If (newFileContents <> srcFileContents) Then
- WScript.StdOut.WriteLine "Updating select.c"
- Set srcFile = fso.CreateTextFile("src\select.c", true)
- srcFile.Write(newFileContents)
- srcFile.Close()
- End If
-
- ' SQLite supports : and $ for named parameters, but we add support for @ as well here
- '
- Set srcFile = fso.OpenTextFile("src\tokenize.c", 1)
- srcFileContents = srcFile.ReadAll()
- srcFile.Close()
- If InStr(1, srcFileContents, " case '@':", 1) = 0 Then
- newFileContents = Replace(srcFileContents, " case ':': {", " case '@':" & Chr(10) & " case ':': {")
- If (newFileContents <> srcFileContents) Then
- WScript.StdOut.WriteLine "Updating tokenize.c"
- Set srcFile = fso.CreateTextFile("src\tokenize.c", true)
- srcFile.Write(newFileContents)
- srcFile.Close()
- End If
- End If
-
- ' In order to support encryption, we need to know when the pager is being destroyed so we can destroy our encryption
- ' objects. This modification adds code to support that.
- '
- Set srcFile = fso.OpenTextFile("src\pager.c", 1)
- srcFileContents = srcFile.ReadAll()
- srcFile.Close()
- If InStr(1, srcFileContents, "sqlite3pager_free_codecarg", 1) = 0 Then
- newFileContents = Replace(srcFileContents, Chr(10) & " sqliteFree(pPager);", Chr(10) & "#ifdef SQLITE_HAS_CODEC" & Chr(10) & " sqlite3pager_free_codecarg(pPager->pCodecArg);" & Chr(10) & "#endif" & Chr(10) & " sqliteFree(pPager);")
- If (newFileContents <> srcFileContents) Then
- WScript.StdOut.WriteLine "Updating pager.c"
- Set srcFile = fso.CreateTextFile("src\pager.c", true)
- srcFile.Write(newFileContents)
- srcFile.Close()
- End If
- End If
-
-End Sub
-
DELETED SQLite.Interop/interop.c
Index: SQLite.Interop/interop.c
==================================================================
--- SQLite.Interop/interop.c
+++ /dev/null
@@ -1,768 +0,0 @@
-/*
- 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 "src/sqliteint.h"
-#include "src\os.h"
-
-#if _WIN32_WCE && NDEBUG
-#include "merge.h"
-#endif
-
-// Forward declare this function, we're implementing it later
-static void generateColumnNames(
- Parse *pParse, /* Parser context */
- SrcList *pTabList, /* List of tables */
- ExprList *pEList /* Expressions defining the result set */
-);
-
-#include "src\select.c"
-
-/*
-** 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 || sqlite3ThreadData()->mallocFailed ) 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; inExpr; 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; jnSrc && pTabList->a[j].iCursor!=p->iTable; j++){}
- assert( jnSrc );
- pTab = pTabList->a[j].pTab;
- if( iCol<0 ) iCol = pTab->iPKey;
- assert( iCol==-1 || (iCol>=0 && iColnCol) );
- if( iCol<0 ){
- zCol = "rowid";
- }else{
- zCol = pTab->aCol[iCol].zName;
- }
- if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){
- sqlite3VdbeSetColName(v, i, (char*)p->span.z, p->span.n);
- }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){
- char *zName = 0;
- char *zTab;
- char *zDb = 0; /*** ADDED - SQLite.Interop ***/
- int iDb;
-
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
-
- zTab = pTabList->a[j].zAlias;
- if( fullNames || zTab==0 ){
- if (iDb > 1) zDb = db->aDb[iDb].zName; /*** ADDED - SQLite.Interop ***/
- zTab = pTab->zName;
- }
- if (!zDb || !realNames) sqlite3SetString(&zName, zTab, "\x01", zCol, 0); /*** CHANGED - SQLite.Interop ***/
- else sqlite3SetString(&zName, zDb, "\x01", zTab, "\x01", 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, (char*)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
-
-#include
-
-typedef void (__stdcall *SQLITEUSERFUNC)(void *, int, void **);
-typedef int (__stdcall *SQLITECOLLATION)(int, const void *, int, const void*);
-
-typedef int (__stdcall *ENCRYPTFILEW)(const wchar_t *);
-typedef int (__stdcall *ENCRYPTEDSTATUSW)(const wchar_t *, unsigned long *);
-typedef int (__stdcall *DECRYPTFILEW)(const wchar_t *, unsigned long);
-
-typedef HANDLE (__stdcall *CREATEFILEW)(
- LPCWSTR,
- DWORD,
- DWORD,
- LPSECURITY_ATTRIBUTES,
- DWORD,
- DWORD,
- HANDLE);
-
-// 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, (void **)pv);
-}
-
-void sqlite3_interop_step(sqlite3_context *pctx, int n, sqlite3_value **pv)
-{
- SQLITEUSERFUNC *pf = (SQLITEUSERFUNC *)sqlite3_user_data(pctx);
- pf[1](pctx, n, (void **)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_sleep_interop(int milliseconds)
-{
- Sleep(milliseconds);
-}
-
-__declspec(dllexport) int sqlite3_encryptfile(const wchar_t *pwszFilename)
-{
- HMODULE hMod = LoadLibrary(_T("ADVAPI32"));
- ENCRYPTFILEW pfunc;
- int n;
-
- if (hMod == NULL)
- {
- SetLastError(ERROR_NOT_SUPPORTED);
- return 0;
- }
-
- pfunc = (ENCRYPTFILEW)GetProcAddress(hMod, _T("EncryptFileW"));
- if (pfunc == NULL)
- {
- SetLastError(ERROR_NOT_SUPPORTED);
- return 0;
- }
-
- n = pfunc(pwszFilename);
-
- FreeLibrary(hMod);
-
- return n;
-}
-
-__declspec(dllexport) int sqlite3_decryptfile(const wchar_t *pwszFilename)
-{
- HMODULE hMod = LoadLibrary(_T("ADVAPI32"));
- DECRYPTFILEW pfunc;
- int n;
-
- if (hMod == NULL)
- {
- SetLastError(ERROR_NOT_SUPPORTED);
- return 0;
- }
-
- pfunc = (DECRYPTFILEW)GetProcAddress(hMod, _T("DecryptFileW"));
- if (pfunc == NULL)
- {
- SetLastError(ERROR_NOT_SUPPORTED);
- return 0;
- }
-
- n = pfunc(pwszFilename, 0);
-
- FreeLibrary(hMod);
-
- return n;
-}
-
-__declspec(dllexport) unsigned long sqlite3_encryptedstatus(const wchar_t *pwszFilename, unsigned long *pdwStatus)
-{
- HMODULE hMod = LoadLibrary(_T("ADVAPI32"));
- ENCRYPTEDSTATUSW pfunc;
- int n;
-
- if (hMod == NULL)
- {
- SetLastError(ERROR_NOT_SUPPORTED);
- return 0;
- }
-
- pfunc = (ENCRYPTEDSTATUSW)GetProcAddress(hMod, _T("FileEncryptionStatusW"));
- if (pfunc == NULL)
- {
- SetLastError(ERROR_NOT_SUPPORTED);
- return 0;
- }
-
- n = pfunc(pwszFilename, pdwStatus);
-
- FreeLibrary(hMod);
-
- return n;
-}
-
-int SetCompression(const wchar_t *pwszFilename, unsigned short ufLevel)
-{
-#ifdef FSCTL_SET_COMPRESSION
- HMODULE hMod = GetModuleHandle(_T("KERNEL32"));
- CREATEFILEW pfunc;
- HANDLE hFile;
- unsigned long dw = 0;
- int n;
-
- if (hMod == NULL)
- {
- SetLastError(ERROR_NOT_SUPPORTED);
- return 0;
- }
-
- pfunc = (CREATEFILEW)GetProcAddress(hMod, _T("CreateFileW"));
- if (pfunc == NULL)
- {
- SetLastError(ERROR_NOT_SUPPORTED);
- return 0;
- }
-
- hFile = pfunc(pwszFilename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile == NULL)
- return 0;
-
- n = DeviceIoControl(hFile, FSCTL_SET_COMPRESSION, &ufLevel, sizeof(ufLevel), NULL, 0, &dw, NULL);
-
- CloseHandle(hFile);
-
- return n;
-#else
- SetLastError(ERROR_NOT_SUPPORTED);
- return 0;
-#endif
-}
-
-__declspec(dllexport) int __stdcall sqlite3_compressfile(const wchar_t *pwszFilename)
-{
- return SetCompression(pwszFilename, COMPRESSION_FORMAT_DEFAULT);
-}
-
-__declspec(dllexport) int __stdcall sqlite3_decompressfile(const wchar_t *pwszFilename)
-{
- return SetCompression(pwszFilename, COMPRESSION_FORMAT_NONE);
-}
-
-__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, int *plen)
-{
- const void *pval = sqlite3_errmsg16(db);
- *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t): 0;
- return pval;
-}
-
-__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 nchars, sqlite3_stmt **ppstmt, const void **pztail, int *plen)
-{
- int n = sqlite3_prepare16(db, sql, nchars * sizeof(wchar_t), ppstmt, pztail);
- *plen = (*pztail != 0) ? wcslen((wchar_t *)*pztail) * sizeof(wchar_t) : 0;
- return n;
-}
-
-__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, int *plen)
-{
- const void *pval = sqlite3_column_name16(stmt, iCol);
- *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
- return pval;
-}
-
-__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, int *plen)
-{
- const void *pval = sqlite3_column_decltype16(stmt, iCol);
- *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
- return pval;
-}
-
-__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((char *)pval) : 0;
- return pval;
-}
-
-__declspec(dllexport) const void * __stdcall sqlite3_column_text16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
-{
- const void *pval = sqlite3_column_text16(stmt, iCol);
- *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t): 0;
- return pval;
-}
-
-__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 = (SQLITEUSERFUNC *)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 = (SQLITEUSERFUNC *)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 = (SQLITECOLLATION *)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 = (SQLITECOLLATION *)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((char *)pval) : 0;
- return pval;
-}
-
-__declspec(dllexport) const void * __stdcall sqlite3_value_text16_interop(sqlite3_value *val, int *plen)
-{
- const void *pval = sqlite3_value_text16(val);
- *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
- return pval;
-}
-
-__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
ADDED SQLite.Interop/interop.h
Index: SQLite.Interop/interop.h
==================================================================
--- /dev/null
+++ SQLite.Interop/interop.h
@@ -0,0 +1,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; inExpr; 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; jnSrc && pTabList->a[j].iCursor!=p->iTable; j++){}
+ assert( jnSrc );
+ pTab = pTabList->a[j].pTab;
+ if( iCol<0 ) iCol = pTab->iPKey;
+ assert( iCol==-1 || (iCol>=0 && iColnCol) );
+ 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
Index: SQLite.Interop/merge.h
==================================================================
--- SQLite.Interop/merge.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// This code was automatically generated from assembly
-// C:\src\SQLite.NET\System.Data.SQLite\bin\System.Data.SQLite.dll
-
-#include
-
-#pragma data_seg(".clr")
-#pragma comment(linker, "/SECTION:.clr,ER")
- char __ph[85184] = {0}; // The number of bytes to reserve
-#pragma data_seg()
-
-#pragma comment(lib, "mscoree")
-
-extern BOOL WINAPI _CorDllMain(HANDLE, DWORD, LPVOID);
-__declspec(dllexport) BOOL WINAPI _CorDllMainStub(HANDLE hModule, DWORD dwReason, LPVOID pvReserved)
-{
- return _CorDllMain(hModule, dwReason, pvReserved);
-}
DELETED SQLite.Interop/resource.h
Index: SQLite.Interop/resource.h
==================================================================
--- SQLite.Interop/resource.h
+++ /dev/null
@@ -1,14 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by SQLite.Interop.rc
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 101
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1001
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
Index: SQLite.Interop/src/alter.c
==================================================================
--- SQLite.Interop/src/alter.c
+++ SQLite.Interop/src/alter.c
@@ -10,14 +10,13 @@
**
*************************************************************************
** This file contains C code routines that used to generate VDBE code
** that implements the ALTER TABLE command.
**
-** $Id: alter.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $
+** $Id: alter.c,v 1.1 2005/03/01 16:04:26 rmsimpson Exp $
*/
#include "sqliteInt.h"
-#include
/*
** The code in this file only exists if we are not omitting the
** ALTER TABLE logic from the build.
*/
@@ -45,11 +44,11 @@
unsigned char const *zSql = sqlite3_value_text(argv[0]);
unsigned char const *zTableName = sqlite3_value_text(argv[1]);
int token;
Token tname;
- unsigned char const *zCsr = zSql;
+ 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
@@ -94,11 +93,11 @@
unsigned char const *zTableName = sqlite3_value_text(argv[1]);
int token;
Token tname;
int dist = 3;
- unsigned char const *zCsr = zSql;
+ 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
@@ -165,91 +164,10 @@
sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
}
}
-/*
-** Generate the text of a WHERE expression which can be used to select all
-** temporary triggers on table pTab from the sqlite_temp_master table. If
-** table pTab has no temporary triggers, or is itself stored in the
-** temporary database, NULL is returned.
-*/
-static char *whereTempTriggers(Parse *pParse, Table *pTab){
- Trigger *pTrig;
- char *zWhere = 0;
- char *tmp = 0;
- const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */
-
- /* If the table is not located in the temp-db (in which case NULL is
- ** returned, loop through the tables list of triggers. For each trigger
- ** that is not part of the temp-db schema, add a clause to the WHERE
- ** expression being built up in zWhere.
- */
- if( pTab->pSchema!=pTempSchema ){
- for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){
- if( pTrig->pSchema==pTempSchema ){
- if( !zWhere ){
- zWhere = sqlite3MPrintf("name=%Q", pTrig->name);
- }else{
- tmp = zWhere;
- zWhere = sqlite3MPrintf("%s OR name=%Q", zWhere, pTrig->name);
- sqliteFree(tmp);
- }
- }
- }
- }
- return zWhere;
-}
-
-/*
-** Generate code to drop and reload the internal representation of table
-** pTab from the database, including triggers and temporary triggers.
-** Argument zName is the name of the table in the database schema at
-** the time the generated code is executed. This can be different from
-** pTab->zName if this function is being called to code part of an
-** "ALTER TABLE RENAME TO" statement.
-*/
-static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
- Vdbe *v;
- char *zWhere;
- int iDb; /* Index of database containing pTab */
-#ifndef SQLITE_OMIT_TRIGGER
- Trigger *pTrig;
-#endif
-
- v = sqlite3GetVdbe(pParse);
- if( !v ) return;
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- assert( iDb>=0 );
-
-#ifndef SQLITE_OMIT_TRIGGER
- /* Drop any table triggers from the internal schema. */
- for(pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext){
- int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
- assert( iTrigDb==iDb || iTrigDb==1 );
- sqlite3VdbeOp3(v, OP_DropTrigger, iTrigDb, 0, pTrig->name, 0);
- }
-#endif
-
- /* Drop the table and index from the internal schema */
- sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
-
- /* Reload the table, index and permanent trigger schemas. */
- zWhere = sqlite3MPrintf("tbl_name=%Q", zName);
- if( !zWhere ) return;
- sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
-
-#ifndef SQLITE_OMIT_TRIGGER
- /* Now, if the table is not stored in the temp database, reload any temp
- ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
- */
- if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
- sqlite3VdbeOp3(v, OP_ParseSchema, 1, 0, zWhere, P3_DYNAMIC);
- }
-#endif
-}
-
/*
** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
** command.
*/
void sqlite3AlterRenameTable(
@@ -259,22 +177,22 @@
){
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 *zWhere = 0; /* Where clause to locate temp triggers */
+ char *zTempTrig = 0; /* Where clause to locate temp triggers */
#endif
- if( sqlite3ThreadDataReadOnly()->mallocFailed ) goto exit_rename_table;
assert( pSrc->nSrc==1 );
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
if( !pTab ) goto exit_rename_table;
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ 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;
@@ -335,11 +253,11 @@
"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,
+zName,
#endif
zName, strlen(pTab->zName), pTab->zName
);
#ifndef SQLITE_OMIT_AUTOINCREMENT
@@ -356,199 +274,61 @@
#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( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
- sqlite3NestedParse(pParse,
- "UPDATE sqlite_temp_master SET "
- "sql = sqlite_rename_trigger(sql, %Q), "
- "tbl_name = %Q "
- "WHERE %s;", zName, zName, zWhere);
- sqliteFree(zWhere);
+ 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 and reload the internal table schema. */
- reloadTableSchema(pParse, pTab, zName);
+ /* 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);
}
-
-
-/*
-** This function is called after an "ALTER TABLE ... ADD" statement
-** has been parsed. Argument pColDef contains the text of the new
-** column definition.
-**
-** The Table structure pParse->pNewTable was extended to include
-** the new column during parsing.
-*/
-void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
- Table *pNew; /* Copy of pParse->pNewTable */
- Table *pTab; /* Table being altered */
- int iDb; /* Database number */
- const char *zDb; /* Database name */
- const char *zTab; /* Table name */
- char *zCol; /* Null-terminated column definition */
- Column *pCol; /* The new column */
- Expr *pDflt; /* Default value for the new column */
-
- if( pParse->nErr ) return;
- pNew = pParse->pNewTable;
- assert( pNew );
-
- iDb = sqlite3SchemaToIndex(pParse->db, pNew->pSchema);
- zDb = pParse->db->aDb[iDb].zName;
- zTab = pNew->zName;
- pCol = &pNew->aCol[pNew->nCol-1];
- pDflt = pCol->pDflt;
- pTab = sqlite3FindTable(pParse->db, zTab, zDb);
- assert( pTab );
-
- /* If the default value for the new column was specified with a
- ** literal NULL, then set pDflt to 0. This simplifies checking
- ** for an SQL NULL default below.
- */
- if( pDflt && pDflt->op==TK_NULL ){
- pDflt = 0;
- }
-
- /* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
- ** If there is a NOT NULL constraint, then the default value for the
- ** column must not be NULL.
- */
- if( pCol->isPrimKey ){
- sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
- return;
- }
- if( pNew->pIndex ){
- sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
- return;
- }
- if( pCol->notNull && !pDflt ){
- sqlite3ErrorMsg(pParse,
- "Cannot add a NOT NULL column with default value NULL");
- return;
- }
-
- /* Ensure the default expression is something that sqlite3ValueFromExpr()
- ** can handle (i.e. not CURRENT_TIME etc.)
- */
- if( pDflt ){
- sqlite3_value *pVal;
- if( sqlite3ValueFromExpr(pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
- /* malloc() has failed */
- return;
- }
- if( !pVal ){
- sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
- return;
- }
- sqlite3ValueFree(pVal);
- }
-
- /* Modify the CREATE TABLE statement. */
- zCol = sqliteStrNDup((char*)pColDef->z, pColDef->n);
- if( zCol ){
- char *zEnd = &zCol[pColDef->n-1];
- while( (zEnd>zCol && *zEnd==';') || isspace(*(unsigned char *)zEnd) ){
- *zEnd-- = '\0';
- }
- sqlite3NestedParse(pParse,
- "UPDATE %Q.%s SET "
- "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d,length(sql)) "
- "WHERE type = 'table' AND name = %Q",
- zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
- zTab
- );
- sqliteFree(zCol);
- }
-
- /* If the default value of the new column is NULL, then set the file
- ** format to 2. If the default value of the new column is not NULL,
- ** the file format becomes 3.
- */
- sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2);
-
- /* Reload the schema of the modified table. */
- reloadTableSchema(pParse, pTab, pTab->zName);
-}
-
-/*
-** This function is called by the parser after the table-name in
-** an "ALTER TABLE ADD" statement is parsed. Argument
-** pSrc is the full-name of the table being altered.
-**
-** This routine makes a (partial) copy of the Table structure
-** for the table being altered and sets Parse.pNewTable to point
-** to it. Routines called by the parser as the column definition
-** is parsed (i.e. sqlite3AddColumn()) add the new Column data to
-** the copy. The copy of the Table structure is deleted by tokenize.c
-** after parsing is finished.
-**
-** Routine sqlite3AlterFinishAddColumn() will be called to complete
-** coding the "ALTER TABLE ... ADD" statement.
-*/
-void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
- Table *pNew;
- Table *pTab;
- Vdbe *v;
- int iDb;
- int i;
- int nAlloc;
-
- /* Look up the table being altered. */
- assert( pParse->pNewTable==0 );
- if( sqlite3ThreadDataReadOnly()->mallocFailed ) goto exit_begin_add_column;
- pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
- if( !pTab ) goto exit_begin_add_column;
-
- /* Make sure this is not an attempt to ALTER a view. */
- if( pTab->pSelect ){
- sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
- goto exit_begin_add_column;
- }
-
- assert( pTab->addColOffset>0 );
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
-
- /* Put a copy of the Table struct in Parse.pNewTable for the
- ** sqlite3AddColumn() function and friends to modify.
- */
- pNew = (Table *)sqliteMalloc(sizeof(Table));
- if( !pNew ) goto exit_begin_add_column;
- pParse->pNewTable = pNew;
- pNew->nRef = 1;
- pNew->nCol = pTab->nCol;
- assert( pNew->nCol>0 );
- nAlloc = (((pNew->nCol-1)/8)*8)+8;
- assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
- pNew->aCol = (Column *)sqliteMalloc(sizeof(Column)*nAlloc);
- pNew->zName = sqliteStrDup(pTab->zName);
- if( !pNew->aCol || !pNew->zName ){
- goto exit_begin_add_column;
- }
- memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
- for(i=0; inCol; i++){
- Column *pCol = &pNew->aCol[i];
- pCol->zName = sqliteStrDup(pCol->zName);
- pCol->zType = 0;
- pCol->pDflt = 0;
- }
- pNew->pSchema = pParse->db->aDb[iDb].pSchema;
- pNew->addColOffset = pTab->addColOffset;
- pNew->nRef = 1;
-
- /* Begin a transaction and increment the schema cookie. */
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- v = sqlite3GetVdbe(pParse);
- if( !v ) goto exit_begin_add_column;
- sqlite3ChangeCookie(pParse->db, v, iDb);
-
-exit_begin_add_column:
- sqlite3SrcListDelete(pSrc);
- return;
-}
#endif /* SQLITE_ALTER_TABLE */
DELETED SQLite.Interop/src/analyze.c
Index: SQLite.Interop/src/analyze.c
==================================================================
--- SQLite.Interop/src/analyze.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
-** 2005 July 8
-**
-** 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 associated with the ANALYZE command.
-**
-** @(#) $Id: analyze.c,v 1.9 2006/01/16 15:51:47 rmsimpson Exp $
-*/
-#ifndef SQLITE_OMIT_ANALYZE
-#include "sqliteInt.h"
-
-/*
-** This routine generates code that opens the sqlite_stat1 table on cursor
-** iStatCur.
-**
-** If the sqlite_stat1 tables does not previously exist, it is created.
-** If it does previously exist, all entires associated with table zWhere
-** are removed. If zWhere==0 then all entries are removed.
-*/
-static void openStatTable(
- Parse *pParse, /* Parsing context */
- int iDb, /* The database we are looking in */
- int iStatCur, /* Open the sqlite_stat1 table on this cursor */
- const char *zWhere /* Delete entries associated with this table */
-){
- sqlite3 *db = pParse->db;
- Db *pDb;
- int iRootPage;
- Table *pStat;
- Vdbe *v = sqlite3GetVdbe(pParse);
-
- pDb = &db->aDb[iDb];
- if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){
- /* The sqlite_stat1 tables does not exist. Create it.
- ** Note that a side-effect of the CREATE TABLE statement is to leave
- ** the rootpage of the new table on the top of the stack. This is
- ** important because the OpenWrite opcode below will be needing it. */
- sqlite3NestedParse(pParse,
- "CREATE TABLE %Q.sqlite_stat1(tbl,idx,stat)",
- pDb->zName
- );
- iRootPage = 0; /* Cause rootpage to be taken from top of stack */
- }else if( zWhere ){
- /* The sqlite_stat1 table exists. Delete all entries associated with
- ** the table zWhere. */
- sqlite3NestedParse(pParse,
- "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q",
- pDb->zName, zWhere
- );
- iRootPage = pStat->tnum;
- }else{
- /* The sqlite_stat1 table already exists. Delete all rows. */
- iRootPage = pStat->tnum;
- sqlite3VdbeAddOp(v, OP_Clear, pStat->tnum, iDb);
- }
-
- /* Open the sqlite_stat1 table for writing. Unless it was created
- ** by this vdbe program, lock it for writing at the shared-cache level.
- ** If this vdbe did create the sqlite_stat1 table, then it must have
- ** already obtained a schema-lock, making the write-lock redundant.
- */
- if( iRootPage>0 ){
- sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1");
- }
- sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
- sqlite3VdbeAddOp(v, OP_OpenWrite, iStatCur, iRootPage);
- sqlite3VdbeAddOp(v, OP_SetNumColumns, iStatCur, 3);
-}
-
-/*
-** Generate code to do an analysis of all indices associated with
-** a single table.
-*/
-static void analyzeOneTable(
- Parse *pParse, /* Parser context */
- Table *pTab, /* Table whose indices are to be analyzed */
- int iStatCur, /* Cursor that writes to the sqlite_stat1 table */
- int iMem /* Available memory locations begin here */
-){
- Index *pIdx; /* An index to being analyzed */
- int iIdxCur; /* Cursor number for index being analyzed */
- int nCol; /* Number of columns in the index */
- Vdbe *v; /* The virtual machine being built up */
- int i; /* Loop counter */
- int topOfLoop; /* The top of the loop */
- int endOfLoop; /* The end of the loop */
- int addr; /* The address of an instruction */
- int iDb; /* Index of database containing pTab */
-
- v = sqlite3GetVdbe(pParse);
- if( pTab==0 || pTab->pIndex==0 ){
- /* Do no analysis for tables that have no indices */
- return;
- }
-
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- assert( iDb>=0 );
-#ifndef SQLITE_OMIT_AUTHORIZATION
- if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
- pParse->db->aDb[iDb].zName ) ){
- return;
- }
-#endif
-
- /* Establish a read-lock on the table at the shared-cache level. */
- sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
-
- iIdxCur = pParse->nTab;
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
-
- /* Open a cursor to the index to be analyzed
- */
- assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) );
- sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
- VdbeComment((v, "# %s", pIdx->zName));
- sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum,
- (char *)pKey, P3_KEYINFO_HANDOFF);
- nCol = pIdx->nColumn;
- if( iMem+nCol*2>=pParse->nMem ){
- pParse->nMem = iMem+nCol*2+1;
- }
- sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, nCol+1);
-
- /* Memory cells are used as follows:
- **
- ** mem[iMem]: The total number of rows in the table.
- ** mem[iMem+1]: Number of distinct values in column 1
- ** ...
- ** mem[iMem+nCol]: Number of distinct values in column N
- ** mem[iMem+nCol+1] Last observed value of column 1
- ** ...
- ** mem[iMem+nCol+nCol]: Last observed value of column N
- **
- ** Cells iMem through iMem+nCol are initialized to 0. The others
- ** are initialized to NULL.
- */
- for(i=0; i<=nCol; i++){
- sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem+i);
- }
- for(i=0; i0 then it is always the case the D>0 so division by zero
- ** is never possible.
- */
- sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
- addr = sqlite3VdbeAddOp(v, OP_IfNot, 0, 0);
- sqlite3VdbeAddOp(v, OP_NewRowid, iStatCur, 0);
- sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
- sqlite3VdbeOp3(v, OP_String8, 0, 0, pIdx->zName, 0);
- sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
- sqlite3VdbeOp3(v, OP_String8, 0, 0, " ", 0);
- for(i=0; idb;
- Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */
- HashElem *k;
- int iStatCur;
- int iMem;
-
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- iStatCur = pParse->nTab++;
- openStatTable(pParse, iDb, iStatCur, 0);
- iMem = pParse->nMem;
- for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
- Table *pTab = (Table*)sqliteHashData(k);
- analyzeOneTable(pParse, pTab, iStatCur, iMem);
- }
- loadAnalysis(pParse, iDb);
-}
-
-/*
-** Generate code that will do an analysis of a single table in
-** a database.
-*/
-static void analyzeTable(Parse *pParse, Table *pTab){
- int iDb;
- int iStatCur;
-
- assert( pTab!=0 );
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- iStatCur = pParse->nTab++;
- openStatTable(pParse, iDb, iStatCur, pTab->zName);
- analyzeOneTable(pParse, pTab, iStatCur, pParse->nMem);
- loadAnalysis(pParse, iDb);
-}
-
-/*
-** Generate code for the ANALYZE command. The parser calls this routine
-** when it recognizes an ANALYZE command.
-**
-** ANALYZE -- 1
-** ANALYZE -- 2
-** ANALYZE ?.? -- 3
-**
-** Form 1 causes all indices in all attached databases to be analyzed.
-** Form 2 analyzes all indices the single database named.
-** Form 3 analyzes all indices associated with the named table.
-*/
-void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
- sqlite3 *db = pParse->db;
- int iDb;
- int i;
- char *z, *zDb;
- Table *pTab;
- Token *pTableName;
-
- /* Read the database schema. If an error occurs, leave an error message
- ** and code in pParse and return NULL. */
- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
- return;
- }
-
- if( pName1==0 ){
- /* Form 1: Analyze everything */
- for(i=0; inDb; i++){
- if( i==1 ) continue; /* Do not analyze the TEMP database */
- analyzeDatabase(pParse, i);
- }
- }else if( pName2==0 || pName2->n==0 ){
- /* Form 2: Analyze the database or table named */
- iDb = sqlite3FindDb(db, pName1);
- if( iDb>=0 ){
- analyzeDatabase(pParse, iDb);
- }else{
- z = sqlite3NameFromToken(pName1);
- pTab = sqlite3LocateTable(pParse, z, 0);
- sqliteFree(z);
- if( pTab ){
- analyzeTable(pParse, pTab);
- }
- }
- }else{
- /* Form 3: Analyze the fully qualified table name */
- iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
- if( iDb>=0 ){
- zDb = db->aDb[iDb].zName;
- z = sqlite3NameFromToken(pTableName);
- pTab = sqlite3LocateTable(pParse, z, zDb);
- sqliteFree(z);
- if( pTab ){
- analyzeTable(pParse, pTab);
- }
- }
- }
-}
-
-/*
-** Used to pass information from the analyzer reader through to the
-** callback routine.
-*/
-typedef struct analysisInfo analysisInfo;
-struct analysisInfo {
- sqlite3 *db;
- const char *zDatabase;
-};
-
-/*
-** This callback is invoked once for each index when reading the
-** sqlite_stat1 table.
-**
-** argv[0] = name of the index
-** argv[1] = results of analysis - on integer for each column
-*/
-static int analysisLoader(void *pData, int argc, char **argv, char **azNotUsed){
- analysisInfo *pInfo = (analysisInfo*)pData;
- Index *pIndex;
- int i, c;
- unsigned int v;
- const char *z;
-
- assert( argc==2 );
- if( argv==0 || argv[0]==0 || argv[1]==0 ){
- return 0;
- }
- pIndex = sqlite3FindIndex(pInfo->db, argv[0], pInfo->zDatabase);
- if( pIndex==0 ){
- return 0;
- }
- z = argv[1];
- for(i=0; *z && i<=pIndex->nColumn; i++){
- v = 0;
- while( (c=z[0])>='0' && c<='9' ){
- v = v*10 + c - '0';
- z++;
- }
- pIndex->aiRowEst[i] = v;
- if( *z==' ' ) z++;
- }
- return 0;
-}
-
-/*
-** Load the content of the sqlite_stat1 table into the index hash tables.
-*/
-void sqlite3AnalysisLoad(sqlite3 *db, int iDb){
- analysisInfo sInfo;
- HashElem *i;
- char *zSql;
-
- /* Clear any prior statistics */
- for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
- Index *pIdx = sqliteHashData(i);
- sqlite3DefaultRowEst(pIdx);
- }
-
- /* Check to make sure the sqlite_stat1 table existss */
- sInfo.db = db;
- sInfo.zDatabase = db->aDb[iDb].zName;
- if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){
- return;
- }
-
-
- /* Load new statistics out of the sqlite_stat1 table */
- zSql = sqlite3MPrintf("SELECT idx, stat FROM %Q.sqlite_stat1",
- sInfo.zDatabase);
- sqlite3SafetyOff(db);
- sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
- sqlite3SafetyOn(db);
- sqliteFree(zSql);
-}
-
-
-#endif /* SQLITE_OMIT_ANALYZE */
Index: SQLite.Interop/src/attach.c
==================================================================
--- SQLite.Interop/src/attach.c
+++ SQLite.Interop/src/attach.c
@@ -9,346 +9,191 @@
** 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.15 2006/01/16 15:51:47 rmsimpson Exp $
+** $Id: attach.c,v 1.1 2005/03/01 16:04:26 rmsimpson Exp $
*/
#include "sqliteInt.h"
/*
-** Resolve an expression that was part of an ATTACH or DETACH statement. This
-** is slightly different from resolving a normal SQL expression, because simple
-** identifiers are treated as strings, not possible column names or aliases.
-**
-** i.e. if the parser sees:
-**
-** ATTACH DATABASE abc AS def
-**
-** it treats the two expressions as literal strings 'abc' and 'def' instead of
-** looking for columns of the same name.
-**
-** This only applies to the root node of pExpr, so the statement:
-**
-** ATTACH DATABASE abc||def AS 'db2'
-**
-** will fail because neither abc or def can be resolved.
-*/
-int resolveAttachExpr(NameContext *pName, Expr *pExpr)
-{
- int rc = SQLITE_OK;
- if( pExpr ){
- if( pExpr->op!=TK_ID ){
- rc = sqlite3ExprResolveNames(pName, pExpr);
- }else{
- pExpr->op = TK_STRING;
- }
- }
- return rc;
-}
-
-/*
-** An SQL user-function registered to do the work of an ATTACH statement. The
-** three arguments to the function come directly from an attach statement:
-**
-** ATTACH DATABASE x AS y KEY z
-**
-** SELECT sqlite_attach(x, y, z)
-**
-** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the
-** third argument.
-*/
-static void attachFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int i;
- int rc = 0;
- sqlite3 *db = sqlite3_user_data(context);
- const char *zName;
- const char *zFile;
- Db *aNew;
- char zErr[128];
- char *zErrDyn = 0;
-
- zFile = (const char *)sqlite3_value_text(argv[0]);
- zName = (const char *)sqlite3_value_text(argv[1]);
-
- /* Check for the following errors:
- **
- ** * Too many attached databases,
- ** * Transaction currently open
- ** * Specified database name already being used.
- */
- if( db->nDb>=MAX_ATTACHED+2 ){
- sqlite3_snprintf(
- 127, zErr, "too many attached databases - max %d", MAX_ATTACHED
- );
- goto attach_error;
- }
- if( !db->autoCommit ){
- strcpy(zErr, "cannot ATTACH database within transaction");
- goto attach_error;
- }
+** 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; inDb; i++){
char *z = db->aDb[i].zName;
if( z && sqlite3StrICmp(z, zName)==0 ){
- sqlite3_snprintf(127, zErr, "database %s is already in use", zName);
- goto attach_error;
+ sqlite3ErrorMsg(pParse, "database %z is already in use", zName);
+ pParse->rc = SQLITE_ERROR;
+ sqliteFree(zFile);
+ return;
}
}
- /* Allocate the new entry in the db->aDb[] array and initialise the schema
- ** hash tables.
- */
if( db->aDb==db->aDbStatic ){
aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
- if( aNew==0 ){
- return;
- }
+ 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;
- }
+ if( aNew==0 ) return;
}
db->aDb = aNew;
aNew = &db->aDb[db->nDb++];
memset(aNew, 0, sizeof(*aNew));
-
- /* Open the database file. If the btree is successfully opened, use
- ** it to obtain the database schema. At this point the schema may
- ** or may not be initialised.
- */
+ 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==SQLITE_OK ){
- aNew->pSchema = sqlite3SchemaGet(aNew->pBt);
- if( !aNew->pSchema ){
- rc = SQLITE_NOMEM;
- }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
- strcpy(zErr,
- "attached databases must use the same text encoding as main database");
- goto attach_error;
- }
- }
- aNew->zName = sqliteStrDup(zName);
- aNew->safety_level = 3;
-
+ if( rc ){
+ sqlite3ErrorMsg(pParse, "unable to open database: %s", zFile);
+ }
#if SQLITE_HAS_CODEC
{
extern int sqlite3CodecAttach(sqlite3*, int, void*, int);
- extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
+ char *zKey;
int nKey;
- char *zKey;
- int t = sqlite3_value_type(argv[2]);
- switch( t ){
- case SQLITE_INTEGER:
- case SQLITE_FLOAT:
- zErrDyn = sqliteStrDup("Invalid key value");
- rc = SQLITE_ERROR;
- break;
-
- case SQLITE_TEXT:
- case SQLITE_BLOB:
- nKey = sqlite3_value_bytes(argv[2]);
- zKey = (char *)sqlite3_value_blob(argv[2]);
- sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
- break;
-
- case SQLITE_NULL:
- /* No key specified. Use the key from the main database */
- sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
- sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
- break;
+ 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
-
- /* If the file was opened successfully, read the schema for the new database.
- ** If this fails, or if opening the file failed, then close the file and
- ** remove the entry from the db->aDb[] array. i.e. put everything back the way
- ** we found it.
- */
- if( rc==SQLITE_OK ){
- sqlite3SafetyOn(db);
- rc = sqlite3Init(db, &zErrDyn);
- sqlite3SafetyOff(db);
+ 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;
- db->aDb[i].pSchema = 0;
- }
- sqlite3ResetInternalSchema(db, 0);
- db->nDb = i;
- sqlite3_snprintf(127, zErr, "unable to open database: %s", zFile);
- goto attach_error;
- }
-
- return;
-
-attach_error:
- /* Return an error if we get here */
- if( zErrDyn ){
- sqlite3_result_error(context, zErrDyn, -1);
- sqliteFree(zErrDyn);
- }else{
- zErr[sizeof(zErr)-1] = 0;
- sqlite3_result_error(context, zErr, -1);
- }
-}
-
-/*
-** An SQL user-function registered to do the work of an DETACH statement. The
-** three arguments to the function come directly from a detach statement:
-**
-** DETACH DATABASE x
-**
-** SELECT sqlite_detach(x)
-*/
-static void detachFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *zName = (const char *)sqlite3_value_text(argv[0]);
- sqlite3 *db = sqlite3_user_data(context);
- int i;
- Db *pDb = 0;
- char zErr[128];
-
- assert(zName);
- for(i=0; inDb; i++){
- pDb = &db->aDb[i];
- if( pDb->pBt==0 ) continue;
- if( sqlite3StrICmp(pDb->zName, zName)==0 ) break;
- }
-
- if( i>=db->nDb ){
- sqlite3_snprintf(sizeof(zErr), zErr, "no such database: %s", zName);
- goto detach_error;
- }
- if( i<2 ){
- sqlite3_snprintf(sizeof(zErr), zErr, "cannot detach database %s", zName);
- goto detach_error;
- }
- if( !db->autoCommit ){
- strcpy(zErr, "cannot DETACH database within transaction");
- goto detach_error;
- }
-
- sqlite3BtreeClose(pDb->pBt);
- pDb->pBt = 0;
- pDb->pSchema = 0;
- sqlite3ResetInternalSchema(db, 0);
- return;
-
-detach_error:
- sqlite3_result_error(context, zErr, -1);
-}
-
-/*
-** This procedure generates VDBE code for a single invocation of either the
-** sqlite_detach() or sqlite_attach() SQL user functions.
-*/
-static void codeAttach(
- Parse *pParse, /* The parser context */
- int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */
- const char *zFunc, /* Either "sqlite_attach" or "sqlite_detach */
- int nFunc, /* Number of args to pass to zFunc */
- Expr *pAuthArg, /* Expression to pass to authorization callback */
- Expr *pFilename, /* Name of database file */
- Expr *pDbname, /* Name of the database to use internally */
- Expr *pKey /* Database key for encryption extension */
-){
- int rc;
- NameContext sName;
- Vdbe *v;
- FuncDef *pFunc;
- sqlite3* db = pParse->db;
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
- assert( sqlite3ThreadDataReadOnly()->mallocFailed || pAuthArg );
- if( pAuthArg ){
- char *zAuthArg = sqlite3NameFromToken(&pAuthArg->span);
- if( !zAuthArg ){
- goto attach_end;
- }
- rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
- sqliteFree(zAuthArg);
- if(rc!=SQLITE_OK ){
- goto attach_end;
- }
- }
-#endif /* SQLITE_OMIT_AUTHORIZATION */
-
- memset(&sName, 0, sizeof(NameContext));
- sName.pParse = pParse;
-
- if(
- SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
- SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
- SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
- ){
- pParse->nErr++;
- goto attach_end;
- }
-
- v = sqlite3GetVdbe(pParse);
- sqlite3ExprCode(pParse, pFilename);
- sqlite3ExprCode(pParse, pDbname);
- sqlite3ExprCode(pParse, pKey);
-
- assert(v || sqlite3ThreadDataReadOnly()->mallocFailed);
- if( v ){
- sqlite3VdbeAddOp(v, OP_Function, 0, nFunc);
- pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0);
- sqlite3VdbeChangeP3(v, -1, (char *)pFunc, P3_FUNCDEF);
-
- /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
- ** statement only). For DETACH, set it to false (expire all existing
- ** statements).
- */
- sqlite3VdbeAddOp(v, OP_Expire, (type==SQLITE_ATTACH), 0);
- }
-
-attach_end:
- sqlite3ExprDelete(pFilename);
- sqlite3ExprDelete(pDbname);
- sqlite3ExprDelete(pKey);
-}
-
-/*
-** Called by the parser to compile a DETACH statement.
-**
-** DETACH pDbname
-*/
-void sqlite3Detach(Parse *pParse, Expr *pDbname){
- codeAttach(pParse, SQLITE_DETACH, "sqlite_detach", 1, pDbname, 0, 0, pDbname);
-}
-
-/*
-** Called by the parser to compile an ATTACH statement.
-**
-** ATTACH p AS pDbname KEY pKey
-*/
-void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
- codeAttach(pParse, SQLITE_ATTACH, "sqlite_attach", 3, p, p, pDbname, pKey);
-}
-
-/*
-** Register the functions sqlite_attach and sqlite_detach.
-*/
-void sqlite3AttachFunctions(sqlite3 *db){
- static const int enc = SQLITE_UTF8;
- sqlite3_create_function(db, "sqlite_attach", 3, enc, db, attachFunc, 0, 0);
- sqlite3_create_function(db, "sqlite_detach", 1, enc, db, detachFunc, 0, 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; inDb; 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.
Index: SQLite.Interop/src/auth.c
==================================================================
--- SQLite.Interop/src/auth.c
+++ SQLite.Interop/src/auth.c
@@ -12,11 +12,11 @@
** 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.15 2006/01/16 15:51:47 rmsimpson Exp $
+** $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
@@ -110,21 +110,13 @@
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 */
- int iDb; /* The index of the database the expression refers to */
if( db->xAuth==0 ) return;
- if( pExpr->op==TK_AS ) return;
assert( pExpr->op==TK_COLUMN );
- iDb = sqlite3SchemaToIndex(pParse->db, pExpr->pSchema);
- if( iDb<0 ){
- /* An attempt to read a column out of a subquery or other
- ** temporary table. */
- return;
- }
for(iSrc=0; pTabList && iSrcnSrc; iSrc++){
if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
}
if( iSrc>=0 && pTabList && iSrcnSrc ){
pTab = pTabList->a[iSrc].pTab;
@@ -145,18 +137,18 @@
assert( pTab->iPKeynCol );
zCol = pTab->aCol[pTab->iPKey].zName;
}else{
zCol = "ROWID";
}
- assert( iDb>=0 && iDbnDb );
- zDBase = db->aDb[iDb].zName;
+ assert( pExpr->iDbnDb );
+ 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 || iDb!=0 ){
+ 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);
}
Index: SQLite.Interop/src/btree.c
==================================================================
--- SQLite.Interop/src/btree.c
+++ SQLite.Interop/src/btree.c
@@ -7,11 +7,11 @@
** 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.17 2006/01/16 15:51:47 rmsimpson Exp $
+** $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:
@@ -209,15 +209,15 @@
#include "pager.h"
#include "btree.h"
#include "os.h"
#include
-/* Round up a number to the next larger multiple of 8. This is used
-** to force 8-byte alignment on 64-bit architectures.
+/*
+** 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 ROUND8(x) ((x+7)&~7)
-
+#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)
@@ -228,28 +228,16 @@
*/
#define MX_CELL(pBt) ((pBt->pageSize-8)/3)
/* Forward declarations */
typedef struct MemPage MemPage;
-typedef struct BtLock BtLock;
/*
** This is a magic string that appears at the beginning of every
** SQLite database in order to identify the file as a real database.
-**
-** You can change this value at compile-time by specifying a
-** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The
-** header must be exactly 16 bytes including the zero-terminator so
-** the string itself should be 15 characters long. If you change
-** the header, then your custom library will not be able to read
-** databases generated by the standard tools and the standard tools
-** will not be able to read databases created by your custom library.
-*/
-#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */
-# define SQLITE_FILE_HEADER "SQLite format 3"
-#endif
-static const char zMagicHeader[] = SQLITE_FILE_HEADER;
+** 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.
*/
@@ -284,14 +272,14 @@
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 */
+ u8 *pCell; /* Pointers to the body of the overflow cell */
+ u16 idx; /* Insert this cell before idx-th non-overflow cell */
} aOvfl[5];
- BtShared *pBt; /* Pointer back to BTree structure */
+ 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 */
};
@@ -300,36 +288,18 @@
** to the end. EXTRA_SIZE is the number of bytes of space needed to hold
** that extra information.
*/
#define EXTRA_SIZE sizeof(MemPage)
-/* Btree handle */
-struct Btree {
- sqlite3 *pSqlite;
- BtShared *pBt;
- u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
-};
-
-/*
-** Btree.inTrans may take one of the following values.
-**
-** If the shared-data extension is enabled, there may be multiple users
-** of the Btree structure. At most one of these may open a write transaction,
-** but any number may have active read transactions. Variable Btree.pDb
-** points to the handle that owns any current write-transaction.
-*/
-#define TRANS_NONE 0
-#define TRANS_READ 1
-#define TRANS_WRITE 2
-
/*
** Everything we need to know about an open database
*/
-struct BtShared {
+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 */
@@ -336,26 +306,25 @@
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 */
- BusyHandler *pBusyHandler; /* Callback for when there is lock contention */
- u8 inTransaction; /* Transaction state */
- int nRef; /* Number of references to this structure */
- int nTransaction; /* Number of open transactions (read + write) */
- void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
- void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
-#ifndef SQLITE_OMIT_SHARED_CACHE
- BtLock *pLock; /* List of locks held on this shared-btree struct */
- BtShared *pNext; /* Next in ThreadData.pBtree linked list */
-#endif
};
+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.
@@ -375,51 +344,22 @@
** 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 *pBtree; /* The Btree to which this cursor belongs */
+ 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 eState; /* One of the CURSOR_XXX constants (see below) */
-#ifndef SQLITE_OMIT_SHARED_CACHE
- void *pKey;
- i64 nKey;
- int skip; /* (skip<0) -> Prev() is a no-op. (skip>0) -> Next() is */
-#endif
+ u8 isValid; /* TRUE if points to a valid entry */
};
-/*
-** Potential values for BtCursor.eState. The first two values (VALID and
-** INVALID) may occur in any build. The third (REQUIRESEEK) may only occur
-** if sqlite was compiled without the OMIT_SHARED_CACHE symbol defined.
-**
-** CURSOR_VALID:
-** Cursor points to a valid entry. getPayload() etc. may be called.
-**
-** CURSOR_INVALID:
-** Cursor does not point to a valid entry. This can happen (for example)
-** because the table is empty or because BtreeCursorFirst() has not been
-** called.
-**
-** CURSOR_REQUIRESEEK:
-** The table that this cursor was opened on still exists, but has been
-** modified since the cursor was last used. The cursor position is saved
-** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
-** this state, restoreOrClearCursorPosition() can be called to attempt to seek
-** the cursor to the saved position.
-*/
-#define CURSOR_INVALID 0
-#define CURSOR_VALID 1
-#define CURSOR_REQUIRESEEK 2
-
/*
** The TRACE macro will print high-level status information about the
** btree operation when the global variable sqlite3_btree_trace is
** enabled.
*/
@@ -432,11 +372,11 @@
int sqlite3_btree_trace=0; /* True to enable tracing */
/*
** Forward declaration
*/
-static int checkReadLocks(BtShared*,Pgno,BtCursor*);
+static int checkReadLocks(Btree*,Pgno,BtCursor*);
/*
** Read or write a two- and four-byte big-endian integer values.
*/
static u32 get2byte(unsigned char *p){
@@ -469,278 +409,10 @@
** 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)
-/*
-** A linked list of the following structures is stored at BtShared.pLock.
-** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor
-** is opened on the table with root page BtShared.iTable. Locks are removed
-** from this list when a transaction is committed or rolled back, or when
-** a btree handle is closed.
-*/
-struct BtLock {
- Btree *pBtree; /* Btree handle holding this lock */
- Pgno iTable; /* Root page of table */
- u8 eLock; /* READ_LOCK or WRITE_LOCK */
- BtLock *pNext; /* Next in BtShared.pLock list */
-};
-
-/* Candidate values for BtLock.eLock */
-#define READ_LOCK 1
-#define WRITE_LOCK 2
-
-#ifdef SQLITE_OMIT_SHARED_CACHE
- /*
- ** The functions queryTableLock(), lockTable() and unlockAllTables()
- ** manipulate entries in the BtShared.pLock linked list used to store
- ** shared-cache table level locks. If the library is compiled with the
- ** shared-cache feature disabled, then there is only ever one user
- ** of each BtShared structure and so this locking is not necessary.
- ** So define the lock related functions as no-ops.
- */
- #define queryTableLock(a,b,c) SQLITE_OK
- #define lockTable(a,b,c) SQLITE_OK
- #define unlockAllTables(a)
- #define restoreOrClearCursorPosition(a,b) SQLITE_OK
- #define saveAllCursors(a,b,c) SQLITE_OK
-
-#else
-
-/*
-** Save the current cursor position in the variables BtCursor.nKey
-** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
-*/
-static int saveCursorPosition(BtCursor *pCur){
- int rc = SQLITE_OK;
-
- assert( CURSOR_VALID==pCur->eState|| CURSOR_INVALID==pCur->eState );
- assert( 0==pCur->pKey );
-
- if( pCur->eState==CURSOR_VALID ){
- rc = sqlite3BtreeKeySize(pCur, &pCur->nKey);
-
- /* If this is an intKey table, then the above call to BtreeKeySize()
- ** stores the integer key in pCur->nKey. In this case this value is
- ** all that is required. Otherwise, if pCur is not open on an intKey
- ** table, then malloc space for and store the pCur->nKey bytes of key
- ** data.
- */
- if( rc==SQLITE_OK && 0==pCur->pPage->intKey){
- void *pKey = sqliteMalloc(pCur->nKey);
- if( pKey ){
- rc = sqlite3BtreeKey(pCur, 0, pCur->nKey, pKey);
- if( rc==SQLITE_OK ){
- pCur->pKey = pKey;
- }else{
- sqliteFree(pKey);
- }
- }else{
- rc = SQLITE_NOMEM;
- }
- }
- assert( !pCur->pPage->intKey || !pCur->pKey );
-
- /* Todo: Should we drop the reference to pCur->pPage here? */
-
- if( rc==SQLITE_OK ){
- pCur->eState = CURSOR_REQUIRESEEK;
- }
- }
-
- return rc;
-}
-
-/*
-** Save the positions of all cursors except pExcept open on the table
-** with root-page iRoot. Usually, this is called just before cursor
-** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()).
-*/
-static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
- BtCursor *p;
- if( sqlite3ThreadDataReadOnly()->useSharedData ){
- for(p=pBt->pCursor; p; p=p->pNext){
- if( p!=pExcept && p->pgnoRoot==iRoot && p->eState==CURSOR_VALID ){
- int rc = saveCursorPosition(p);
- if( SQLITE_OK!=rc ){
- return rc;
- }
- }
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Restore the cursor to the position it was in (or as close to as possible)
-** when saveCursorPosition() was called. Note that this call deletes the
-** saved position info stored by saveCursorPosition(), so there can be
-** at most one effective restoreOrClearCursorPosition() call after each
-** saveCursorPosition().
-**
-** If the second argument argument - doSeek - is false, then instead of
-** returning the cursor to it's saved position, any saved position is deleted
-** and the cursor state set to CURSOR_INVALID.
-*/
-static int restoreOrClearCursorPositionX(BtCursor *pCur, int doSeek){
- int rc = SQLITE_OK;
- assert( sqlite3ThreadDataReadOnly()->useSharedData );
- assert( pCur->eState==CURSOR_REQUIRESEEK );
- if( doSeek ){
- rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, &pCur->skip);
- }else{
- pCur->eState = CURSOR_INVALID;
- }
- if( rc==SQLITE_OK ){
- sqliteFree(pCur->pKey);
- pCur->pKey = 0;
- assert( CURSOR_VALID==pCur->eState || CURSOR_INVALID==pCur->eState );
- }
- return rc;
-}
-
-#define restoreOrClearCursorPosition(p,x) \
- (p->eState==CURSOR_REQUIRESEEK?restoreOrClearCursorPositionX(p,x):SQLITE_OK)
-
-/*
-** Query to see if btree handle p may obtain a lock of type eLock
-** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return
-** SQLITE_OK if the lock may be obtained (by calling lockTable()), or
-** SQLITE_LOCKED if not.
-*/
-static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){
- BtShared *pBt = p->pBt;
- BtLock *pIter;
-
- /* This is a no-op if the shared-cache is not enabled */
- if( 0==sqlite3ThreadDataReadOnly()->useSharedData ){
- return SQLITE_OK;
- }
-
- /* This (along with lockTable()) is where the ReadUncommitted flag is
- ** dealt with. If the caller is querying for a read-lock and the flag is
- ** set, it is unconditionally granted - even if there are write-locks
- ** on the table. If a write-lock is requested, the ReadUncommitted flag
- ** is not considered.
- **
- ** In function lockTable(), if a read-lock is demanded and the
- ** ReadUncommitted flag is set, no entry is added to the locks list
- ** (BtShared.pLock).
- **
- ** To summarize: If the ReadUncommitted flag is set, then read cursors do
- ** not create or respect table locks. The locking procedure for a
- ** write-cursor does not change.
- */
- if(
- !p->pSqlite ||
- 0==(p->pSqlite->flags&SQLITE_ReadUncommitted) ||
- eLock==WRITE_LOCK ||
- iTab==MASTER_ROOT
- ){
- for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
- if( pIter->pBtree!=p && pIter->iTable==iTab &&
- (pIter->eLock!=eLock || eLock!=READ_LOCK) ){
- return SQLITE_LOCKED;
- }
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Add a lock on the table with root-page iTable to the shared-btree used
-** by Btree handle p. Parameter eLock must be either READ_LOCK or
-** WRITE_LOCK.
-**
-** SQLITE_OK is returned if the lock is added successfully. SQLITE_BUSY and
-** SQLITE_NOMEM may also be returned.
-*/
-static int lockTable(Btree *p, Pgno iTable, u8 eLock){
- BtShared *pBt = p->pBt;
- BtLock *pLock = 0;
- BtLock *pIter;
-
- /* This is a no-op if the shared-cache is not enabled */
- if( 0==sqlite3ThreadDataReadOnly()->useSharedData ){
- return SQLITE_OK;
- }
-
- assert( SQLITE_OK==queryTableLock(p, iTable, eLock) );
-
- /* If the read-uncommitted flag is set and a read-lock is requested,
- ** return early without adding an entry to the BtShared.pLock list. See
- ** comment in function queryTableLock() for more info on handling
- ** the ReadUncommitted flag.
- */
- if(
- (p->pSqlite) &&
- (p->pSqlite->flags&SQLITE_ReadUncommitted) &&
- (eLock==READ_LOCK) &&
- iTable!=MASTER_ROOT
- ){
- return SQLITE_OK;
- }
-
- /* First search the list for an existing lock on this table. */
- for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
- if( pIter->iTable==iTable && pIter->pBtree==p ){
- pLock = pIter;
- break;
- }
- }
-
- /* If the above search did not find a BtLock struct associating Btree p
- ** with table iTable, allocate one and link it into the list.
- */
- if( !pLock ){
- pLock = (BtLock *)sqliteMalloc(sizeof(BtLock));
- if( !pLock ){
- return SQLITE_NOMEM;
- }
- pLock->iTable = iTable;
- pLock->pBtree = p;
- pLock->pNext = pBt->pLock;
- pBt->pLock = pLock;
- }
-
- /* Set the BtLock.eLock variable to the maximum of the current lock
- ** and the requested lock. This means if a write-lock was already held
- ** and a read-lock requested, we don't incorrectly downgrade the lock.
- */
- assert( WRITE_LOCK>READ_LOCK );
- if( eLock>pLock->eLock ){
- pLock->eLock = eLock;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Release all the table locks (locks obtained via calls to the lockTable()
-** procedure) held by Btree handle p.
-*/
-static void unlockAllTables(Btree *p){
- BtLock **ppIter = &p->pBt->pLock;
-
- /* If the shared-cache extension is not enabled, there should be no
- ** locks in the BtShared.pLock list, making this procedure a no-op. Assert
- ** that this is the case.
- */
- assert( sqlite3ThreadDataReadOnly()->useSharedData || 0==*ppIter );
-
- while( *ppIter ){
- BtLock *pLock = *ppIter;
- if( pLock->pBtree==p ){
- *ppIter = pLock->pNext;
- sqliteFree(pLock);
- }else{
- ppIter = &pLock->pNext;
- }
- }
-}
-#endif /* SQLITE_OMIT_SHARED_CACHE */
-
#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
@@ -801,19 +473,19 @@
**
** 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(BtShared *pBt, Pgno key, u8 eType, Pgno parent){
+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_BKPT;
+ return SQLITE_CORRUPT;
}
iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key);
rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap);
if( rc!=SQLITE_OK ){
return rc;
@@ -838,11 +510,11 @@
**
** 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(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
+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;
@@ -855,11 +527,11 @@
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_BKPT;
+ if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT;
return SQLITE_OK;
}
#endif /* SQLITE_OMIT_AUTOVACUUM */
@@ -1039,11 +711,11 @@
u8 *used;
used = sqliteMallocRaw( pPage->pBt->pageSize );
if( used==0 ) return;
usableSize = pPage->pBt->usableSize;
- assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->pageSize] );
+ 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 ){
@@ -1105,24 +777,14 @@
#define pageIntegrity(X) _pageIntegrity(X)
#else
# define pageIntegrity(X)
#endif
-/* A bunch of assert() statements to check the transaction state variables
-** of handle p (type Btree*) are internally consistent.
-*/
-#define btreeIntegrity(p) \
- assert( p->inTrans!=TRANS_NONE || p->pBt->nTransactionpBt->nRef ); \
- assert( p->pBt->nTransaction<=p->pBt->nRef ); \
- assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \
- assert( p->pBt->inTransaction>=p->inTrans );
-
/*
** Defragment the page given. All Cells are moved to the
-** end of the page and all free space is collected into one
-** big FreeBlk that occurs in between the header and cell
-** pointer array and the cell content area.
+** 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 */
@@ -1302,11 +964,11 @@
/*
** 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){
- BtShared *pBt; /* A copy of pPage->pBt */
+ 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;
@@ -1342,24 +1004,24 @@
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 */
- BtShared *pBt; /* The main btree structure */
+ 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->pageSize] );
+ 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;
+ return SQLITE_CORRUPT; /* bkpt-CORRUPT */
}
if( pPage->isInit ) return SQLITE_OK;
if( pPage->pParent==0 && pParent!=0 ){
pPage->pParent = pParent;
sqlite3pager_ref(pParent->aData);
@@ -1373,39 +1035,39 @@
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;
+ 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;
+ 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;
+ 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;
+ 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;
+ return SQLITE_CORRUPT; /* bkpt-CORRUPT */
}
pPage->isInit = 1;
pageIntegrity(pPage);
return SQLITE_OK;
@@ -1415,16 +1077,16 @@
** 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;
- BtShared *pBt = pPage->pBt;
+ Btree *pBt = pPage->pBt;
int hdr = pPage->hdrOffset;
int first;
assert( sqlite3pager_pagenumber(data)==pPage->pgno );
- assert( &data[pBt->pageSize] == (unsigned char*)pPage );
+ 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);
@@ -1443,17 +1105,17 @@
/*
** Get a page from the pager. Initialize the MemPage.pBt and
** MemPage.aData elements if needed.
*/
-static int getPage(BtShared *pBt, Pgno pgno, MemPage **ppPage){
+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->pageSize];
+ pPage = (MemPage*)&aData[pBt->psAligned];
pPage->aData = aData;
pPage->pBt = pBt;
pPage->pgno = pgno;
pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
*ppPage = pPage;
@@ -1464,18 +1126,18 @@
** 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(
- BtShared *pBt, /* The database file */
+ 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;
+ return SQLITE_CORRUPT; /* bkpt-CORRUPT */
}
rc = getPage(pBt, pgno, ppPage);
if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){
rc = initPage(*ppPage, pParent);
}
@@ -1488,11 +1150,11 @@
*/
static void releasePage(MemPage *pPage){
if( pPage ){
assert( pPage->aData );
assert( pPage->pBt );
- assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage );
+ assert( &pPage->aData[pPage->pBt->psAligned]==(unsigned char*)pPage );
sqlite3pager_unref(pPage->aData);
}
}
/*
@@ -1499,13 +1161,11 @@
** 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;
- assert( (pageSize & 7)==0 );
- pPage = (MemPage*)&((char*)pData)[pageSize];
+ MemPage *pPage = (MemPage*)&((char*)pData)[FORCE_ALIGNMENT(pageSize)];
if( pPage->pParent ){
MemPage *pParent = pPage->pParent;
pPage->pParent = 0;
releasePage(pParent);
}
@@ -1519,13 +1179,11 @@
**
** 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;
- assert( (pageSize & 7)==0 );
- pPage = (MemPage*)&((char*)pData)[pageSize];
+ MemPage *pPage = (MemPage*)&((char*)pData)[FORCE_ALIGNMENT(pageSize)];
if( pPage->isInit ){
pPage->isInit = 0;
initPage(pPage, pPage->pParent);
}
}
@@ -1537,65 +1195,17 @@
** 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 */
- sqlite3 *pSqlite, /* Associated database handle */
Btree **ppBtree, /* Pointer to new Btree object written here */
int flags /* Options */
){
- BtShared *pBt; /* Shared part of btree structure */
- Btree *p; /* Handle to return */
+ Btree *pBt;
int rc;
int nReserve;
unsigned char zDbHeader[100];
-#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
- const ThreadData *pTsdro;
-#endif
-
- /* Set the variable isMemdb to true for an in-memory database, or
- ** false for a file-based database. This symbol is only required if
- ** either of the shared-data or autovacuum features are compiled
- ** into the library.
- */
-#if !defined(SQLITE_OMIT_SHARED_CACHE) || !defined(SQLITE_OMIT_AUTOVACUUM)
- #ifdef SQLITE_OMIT_MEMORYDB
- const int isMemdb = !zFilename;
- #else
- const int isMemdb = !zFilename || (strcmp(zFilename, ":memory:")?0:1);
- #endif
-#endif
-
- p = sqliteMalloc(sizeof(Btree));
- if( !p ){
- return SQLITE_NOMEM;
- }
- p->inTrans = TRANS_NONE;
- p->pSqlite = pSqlite;
-
- /* Try to find an existing Btree structure opened on zFilename. */
-#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
- pTsdro = sqlite3ThreadDataReadOnly();
- if( pTsdro->useSharedData && zFilename && !isMemdb ){
- char *zFullPathname = sqlite3OsFullPathname(zFilename);
- if( !zFullPathname ){
- sqliteFree(p);
- return SQLITE_NOMEM;
- }
- for(pBt=pTsdro->pBtree; pBt; pBt=pBt->pNext){
- assert( pBt->nRef>0 );
- if( 0==strcmp(zFullPathname, sqlite3pager_filename(pBt->pPager)) ){
- p->pBt = pBt;
- *ppBtree = p;
- pBt->nRef++;
- sqliteFree(zFullPathname);
- return SQLITE_OK;
- }
- }
- sqliteFree(zFullPathname);
- }
-#endif
/*
** 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.
@@ -1603,36 +1213,33 @@
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;
- sqliteFree(p);
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);
- sqliteFree(p);
*ppBtree = 0;
return rc;
}
- p->pBt = pBt;
-
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-1)&pBt->pageSize)!=0 ){
+ 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
@@ -1640,11 +1247,15 @@
** 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.
*/
- if( zFilename && !isMemdb ){
+#ifndef SQLITE_OMIT_MEMORYDB
+ if( zFilename && strcmp(zFilename,":memory:") ){
+#else
+ if( zFilename ){
+#endif
pBt->autoVacuum = SQLITE_DEFAULT_AUTOVACUUM;
}
#endif
nReserve = 0;
}else{
@@ -1656,94 +1267,32 @@
#ifndef SQLITE_OMIT_AUTOVACUUM
pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0);
#endif
}
pBt->usableSize = pBt->pageSize - nReserve;
- assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */
+ pBt->psAligned = FORCE_ALIGNMENT(pBt->pageSize);
sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize);
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
- /* Add the new btree to the linked list starting at ThreadData.pBtree */
- if( pTsdro->useSharedData && zFilename && !isMemdb ){
- pBt->pNext = pTsdro->pBtree;
- sqlite3ThreadData()->pBtree = pBt;
- }
-#endif
- pBt->nRef = 1;
- *ppBtree = p;
+ *ppBtree = pBt;
return SQLITE_OK;
}
/*
** Close an open database and invalidate all cursors.
*/
-int sqlite3BtreeClose(Btree *p){
- BtShared *pBt = p->pBt;
- BtCursor *pCur;
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
- ThreadData *pTsd;
-#endif
-
- /* Drop any table-locks */
- unlockAllTables(p);
-
- /* Close all cursors opened via this handle. */
- pCur = pBt->pCursor;
- while( pCur ){
- BtCursor *pTmp = pCur;
- pCur = pCur->pNext;
- if( pTmp->pBtree==p ){
- sqlite3BtreeCloseCursor(pTmp);
- }
- }
-
- /* Rollback any active transaction and free the handle structure */
- sqlite3BtreeRollback(p);
- sqliteFree(p);
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
- /* If there are still other outstanding references to the shared-btree
- ** structure, return now. The remainder of this procedure cleans
- ** up the shared-btree.
- */
- assert( pBt->nRef>0 );
- pBt->nRef--;
- if( pBt->nRef ){
- return SQLITE_OK;
- }
-
- /* Remove the shared-btree from the thread wide list */
- pTsd = sqlite3ThreadData();
- if( pTsd->pBtree==pBt ){
- pTsd->pBtree = pBt->pNext;
- }else{
- BtShared *pPrev;
- for(pPrev=pTsd->pBtree; pPrev && pPrev->pNext!=pBt; pPrev=pPrev->pNext);
- if( pPrev ){
- pPrev->pNext = pBt->pNext;
- }
- }
-#endif
-
- /* Close the pager and free the shared-btree structure */
- assert( !pBt->pCursor );
- sqlite3pager_close(pBt->pPager);
- if( pBt->xFreeSchema && pBt->pSchema ){
- pBt->xFreeSchema(pBt->pSchema);
- }
- sqliteFree(pBt->pSchema);
+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 *p, BusyHandler *pHandler){
- BtShared *pBt = p->pBt;
- pBt->pBusyHandler = pHandler;
+int sqlite3BtreeSetBusyHandler(Btree *pBt, BusyHandler *pHandler){
sqlite3pager_set_busyhandler(pBt->pPager, pHandler);
return SQLITE_OK;
}
/*
@@ -1759,12 +1308,11 @@
** 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 *p, int mxPage){
- BtShared *pBt = p->pBt;
+int sqlite3BtreeSetCacheSize(Btree *pBt, int mxPage){
sqlite3pager_set_cachesize(pBt->pPager, mxPage);
return SQLITE_OK;
}
/*
@@ -1774,27 +1322,16 @@
** 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 *p, int level){
- BtShared *pBt = p->pBt;
+int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){
sqlite3pager_set_safety_level(pBt->pPager, level);
return SQLITE_OK;
}
#endif
-/*
-** Return TRUE if the given btree is set to safety level 1. In other
-** words, return TRUE if no sync() occurs on the disk files.
-*/
-int sqlite3BtreeSyncDisabled(Btree *p){
- BtShared *pBt = p->pBt;
- assert( pBt && pBt->pPager );
- return sqlite3pager_nosync(pBt->pPager);
-}
-
#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
@@ -1807,47 +1344,45 @@
** 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 *p, int pageSize, int nReserve){
- BtShared *pBt = p->pBt;
+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 ){
- assert( (pageSize & 7)==0 );
- assert( !pBt->pPage1 && !pBt->pCursor );
- pBt->pageSize = sqlite3pager_set_pagesize(pBt->pPager, pageSize);
+ 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 *p){
- return p->pBt->pageSize;
+int sqlite3BtreeGetPageSize(Btree *pBt){
+ return pBt->pageSize;
}
-int sqlite3BtreeGetReserve(Btree *p){
- return p->pBt->pageSize - p->pBt->usableSize;
+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 *p, int autoVacuum){
- BtShared *pBt = p->pBt;;
+int sqlite3BtreeSetAutoVacuum(Btree *pBt, int autoVacuum){
#ifdef SQLITE_OMIT_AUTOVACUUM
return SQLITE_READONLY;
#else
if( pBt->pageSizeFixed ){
return SQLITE_READONLY;
@@ -1859,15 +1394,15 @@
/*
** Return the value of the 'auto-vacuum' property. If auto-vacuum is
** enabled 1 is returned. Otherwise 0.
*/
-int sqlite3BtreeGetAutoVacuum(Btree *p){
+int sqlite3BtreeGetAutoVacuum(Btree *pBt){
#ifdef SQLITE_OMIT_AUTOVACUUM
return 0;
#else
- return p->pBt->autoVacuum;
+ return pBt->autoVacuum;
#endif
}
/*
@@ -1878,12 +1413,12 @@
** 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(BtShared *pBt){
- int rc, pageSize;
+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;
@@ -1898,20 +1433,16 @@
goto page1_init_failed;
}
if( page1[18]>1 || page1[19]>1 ){
goto page1_init_failed;
}
- pageSize = get2byte(&page1[16]);
- if( ((pageSize-1)&pageSize)!=0 ){
- goto page1_init_failed;
- }
- assert( (pageSize & 7)==0 );
- pBt->pageSize = pageSize;
- pBt->usableSize = pageSize - page1[20];
+ 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);
@@ -1946,31 +1477,10 @@
releasePage(pPage1);
pBt->pPage1 = 0;
return rc;
}
-/*
-** This routine works like lockBtree() except that it also invokes the
-** busy callback if there is lock contention.
-*/
-static int lockBtreeWithRetry(Btree *pRef){
- int rc = SQLITE_OK;
- if( pRef->inTrans==TRANS_NONE ){
- u8 inTransaction = pRef->pBt->inTransaction;
- btreeIntegrity(pRef);
- rc = sqlite3BtreeBeginTrans(pRef, 0);
- pRef->pBt->inTransaction = inTransaction;
- pRef->inTrans = TRANS_NONE;
- if( rc==SQLITE_OK ){
- pRef->pBt->nTransaction--;
- }
- btreeIntegrity(pRef);
- }
- 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.
@@ -1977,15 +1487,15 @@
**
** 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(BtShared *pBt){
- if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){
+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 = &((u8*)pPage)[-pBt->pageSize];
+ pPage->aData = &((char*)pPage)[-pBt->psAligned];
pPage->pBt = pBt;
pPage->pgno = 1;
}
releasePage(pBt->pPage1);
pBt->pPage1 = 0;
@@ -1995,11 +1505,11 @@
/*
** Create a new database by initializing the first page of the
** file.
*/
-static int newDatabase(BtShared *pBt){
+static int newDatabase(Btree *pBt){
MemPage *pP1;
unsigned char *data;
int rc;
if( sqlite3pager_pagecount(pBt->pPager)>0 ) return SQLITE_OK;
pP1 = pBt->pPage1;
@@ -2031,11 +1541,11 @@
** 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
-** upgraded to exclusive by calling this routine a second time - the
+** 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:
@@ -2046,82 +1556,47 @@
** sqlite3BtreeDropTable()
** sqlite3BtreeInsert()
** sqlite3BtreeDelete()
** sqlite3BtreeUpdateMeta()
**
-** If an initial attempt to acquire the lock fails because of lock contention
-** and the database was previously unlocked, then invoke the busy handler
-** if there is one. But if there was previously a read-lock, do not
-** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is
-** returned when there is already a read-lock in order to avoid a deadlock.
-**
-** Suppose there are two processes A and B. A has a read lock and B has
-** a reserved lock. B tries to promote to exclusive but is blocked because
-** of A's read lock. A tries to promote to reserved but is blocked by B.
-** One or the other of the two processes must give way or there can be
-** no progress. By returning SQLITE_BUSY and not invoking the busy callback
-** when A already has a read lock, we encourage A to give up and let B
-** proceed.
+** 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 *p, int wrflag){
- BtShared *pBt = p->pBt;
+int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){
int rc = SQLITE_OK;
- btreeIntegrity(p);
-
/* 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( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
+ if( pBt->inTrans==TRANS_WRITE ||
+ (pBt->inTrans==TRANS_READ && !wrflag) ){
return SQLITE_OK;
}
-
- /* Write transactions are not possible on a read-only database */
if( pBt->readOnly && wrflag ){
return SQLITE_READONLY;
}
- /* If another database handle has already opened a write transaction
- ** on this shared-btree structure and a second write transaction is
- ** requested, return SQLITE_BUSY.
- */
- if( pBt->inTransaction==TRANS_WRITE && wrflag ){
- return SQLITE_BUSY;
- }
-
- do {
- 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 ){
- if( wrflag ) pBt->inStmt = 0;
- }else{
- unlockBtreeIfUnused(pBt);
- }
- }while( rc==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
- sqlite3InvokeBusyHandler(pBt->pBusyHandler) );
-
- if( rc==SQLITE_OK ){
- if( p->inTrans==TRANS_NONE ){
- pBt->nTransaction++;
- }
- p->inTrans = (wrflag?TRANS_WRITE:TRANS_READ);
- if( p->inTrans>pBt->inTransaction ){
- pBt->inTransaction = p->inTrans;
- }
- }
-
- btreeIntegrity(p);
+ 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
@@ -2132,11 +1607,11 @@
*/
static int setChildPtrmaps(MemPage *pPage){
int i; /* Counter variable */
int nCell; /* Number of cells in page pPage */
int rc = SQLITE_OK; /* Return code */
- BtShared *pBt = pPage->pBt;
+ Btree *pBt = pPage->pBt;
int isInitOrig = pPage->isInit;
Pgno pgno = pPage->pgno;
initPage(pPage, 0);
nCell = pPage->nCell;
@@ -2183,11 +1658,11 @@
*/
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_BKPT;
+ return SQLITE_CORRUPT;
}
put4byte(pPage->aData, iTo);
}else{
int isInitOrig = pPage->isInit;
int i;
@@ -2216,11 +1691,11 @@
}
if( i==nCell ){
if( eType!=PTRMAP_BTREE ||
get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT;
}
put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
}
pPage->isInit = isInitOrig;
@@ -2232,11 +1707,11 @@
/*
** Move the open database page pDbPage to location iFreePage in the
** database. The pDbPage reference remains valid.
*/
static int relocatePage(
- BtShared *pBt, /* Btree */
+ 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 */
){
@@ -2302,23 +1777,23 @@
}
return rc;
}
/* Forward declaration required by autoVacuumCommit(). */
-static int allocatePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
+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(BtShared *pBt, Pgno *nTrunc){
+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 */
+ 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 */
@@ -2329,11 +1804,11 @@
int nRef = *sqlite3pager_stats(pPager);
#endif
assert( pBt->autoVacuum );
if( PTRMAP_ISPAGE(pgsz, sqlite3pager_pagecount(pPager)) ){
- return SQLITE_CORRUPT_BKPT;
+ 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.
*/
@@ -2344,11 +1819,11 @@
}
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) ){
+ if( origSize>PENDING_BYTE_PAGE(pBt) && finSize<=PENDING_BYTE_PAGE(pBt) ){
finSize--;
if( PTRMAP_ISPAGE(pBt->usableSize, finSize) ){
finSize--;
}
}
@@ -2366,14 +1841,11 @@
continue;
}
rc = ptrmapGet(pBt, iDbPage, &eType, &iPtrPage);
if( rc!=SQLITE_OK ) goto autovacuum_out;
- if( eType==PTRMAP_ROOTPAGE ){
- rc = SQLITE_CORRUPT_BKPT;
- goto autovacuum_out;
- }
+ assert( eType!=PTRMAP_ROOTPAGE );
/* If iDbPage is free, do not swap it. */
if( eType==PTRMAP_FREEPAGE ){
continue;
}
@@ -2397,16 +1869,10 @@
assert( iFreePage<=origSize );
}while( iFreePage>finSize );
releasePage(pFreeMemPage);
pFreeMemPage = 0;
- /* Relocate the page into the body of the file. Note that although the
- ** page has moved within the database file, the pDbMemPage pointer
- ** remains valid. This means that this function can run without
- ** invalidating cursors open on the btree. This is important in
- ** shared-cache mode.
- */
rc = relocatePage(pBt, pDbMemPage, eType, iPtrPage, iFreePage);
releasePage(pDbMemPage);
if( rc!=SQLITE_OK ) goto autovacuum_out;
}
@@ -2434,80 +1900,50 @@
** 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 *p){
+int sqlite3BtreeCommit(Btree *pBt){
int rc = SQLITE_OK;
- BtShared *pBt = p->pBt;
-
- btreeIntegrity(p);
- unlockAllTables(p);
-
- /* If the handle has a write-transaction open, commit the shared-btrees
- ** transaction and set the shared state to TRANS_READ.
- */
- if( p->inTrans==TRANS_WRITE ){
- assert( pBt->inTransaction==TRANS_WRITE );
- assert( pBt->nTransaction>0 );
+ if( pBt->inTrans==TRANS_WRITE ){
rc = sqlite3pager_commit(pBt->pPager);
- pBt->inTransaction = TRANS_READ;
- pBt->inStmt = 0;
- }
-
- /* If the handle has any kind of transaction open, decrement the transaction
- ** count of the shared btree. If the transaction count reaches 0, set
- ** the shared state to TRANS_NONE. The unlockBtreeIfUnused() call below
- ** will unlock the pager.
- */
- if( p->inTrans!=TRANS_NONE ){
- pBt->nTransaction--;
- if( 0==pBt->nTransaction ){
- pBt->inTransaction = TRANS_NONE;
- }
- }
-
- /* Set the handles current transaction state to TRANS_NONE and unlock
- ** the pager if this call closed the only read or write transaction.
- */
- p->inTrans = TRANS_NONE;
- unlockBtreeIfUnused(pBt);
-
- btreeIntegrity(p);
+ }
+ 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(BtShared *pBt){
+static int countWriteCursors(Btree *pBt){
BtCursor *pCur;
int r = 0;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
- if( pCur->wrFlag ) r++;
+ if( pCur->wrFlag ) r++;
}
return r;
}
#endif
#ifdef SQLITE_TEST
/*
** Print debugging information about all cursors to standard output.
*/
-void sqlite3BtreeCursorList(Btree *p){
+void sqlite3BtreeCursorList(Btree *pBt){
BtCursor *pCur;
- BtShared *pBt = p->pBt;
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->eState==CURSOR_VALID) ? "" : " eof"
+ pCur->isValid ? "" : " eof"
);
}
}
#endif
@@ -2518,45 +1954,26 @@
** 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 *p){
+int sqlite3BtreeRollback(Btree *pBt){
int rc = SQLITE_OK;
- BtShared *pBt = p->pBt;
MemPage *pPage1;
-
- btreeIntegrity(p);
- unlockAllTables(p);
-
- if( p->inTrans==TRANS_WRITE ){
- assert( TRANS_WRITE==pBt->inTransaction );
-
+ 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->inTransaction = TRANS_READ;
- }
-
- if( p->inTrans!=TRANS_NONE ){
- assert( pBt->nTransaction>0 );
- pBt->nTransaction--;
- if( 0==pBt->nTransaction ){
- pBt->inTransaction = TRANS_NONE;
- }
- }
-
- p->inTrans = TRANS_NONE;
+ }
+ pBt->inTrans = TRANS_NONE;
pBt->inStmt = 0;
unlockBtreeIfUnused(pBt);
-
- btreeIntegrity(p);
return rc;
}
/*
** Start a statement subtransaction. The subtransaction can
@@ -2571,17 +1988,15 @@
** 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 *p){
+int sqlite3BtreeBeginStmt(Btree *pBt){
int rc;
- BtShared *pBt = p->pBt;
- if( (p->inTrans!=TRANS_WRITE) || pBt->inStmt ){
+ if( (pBt->inTrans!=TRANS_WRITE) || pBt->inStmt ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
- assert( pBt->inTransaction==TRANS_WRITE );
rc = pBt->readOnly ? SQLITE_OK : sqlite3pager_stmt_begin(pBt->pPager);
pBt->inStmt = 1;
return rc;
}
@@ -2588,13 +2003,12 @@
/*
** Commit the statment subtransaction currently in progress. If no
** subtransaction is active, this is a no-op.
*/
-int sqlite3BtreeCommitStmt(Btree *p){
+int sqlite3BtreeCommitStmt(Btree *pBt){
int rc;
- BtShared *pBt = p->pBt;
if( pBt->inStmt && !pBt->readOnly ){
rc = sqlite3pager_stmt_commit(pBt->pPager);
}else{
rc = SQLITE_OK;
}
@@ -2608,13 +2022,12 @@
**
** 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 *p){
+int sqlite3BtreeRollbackStmt(Btree *pBt){
int rc;
- BtShared *pBt = p->pBt;
if( pBt->inStmt==0 || pBt->readOnly ) return SQLITE_OK;
rc = sqlite3pager_stmt_rollback(pBt->pPager);
assert( countWriteCursors(pBt)==0 );
pBt->inStmt = 0;
return rc;
@@ -2678,20 +2091,19 @@
** 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 *p, /* The btree */
+ 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;
- BtShared *pBt = p->pBt;
*ppCur = 0;
if( wrFlag ){
if( pBt->readOnly ){
return SQLITE_READONLY;
@@ -2698,49 +2110,48 @@
}
if( checkReadLocks(pBt, iTable, 0) ){
return SQLITE_LOCKED;
}
}
-
if( pBt->pPage1==0 ){
- rc = lockBtreeWithRetry(p);
+ rc = lockBtree(pBt);
if( rc!=SQLITE_OK ){
return rc;
}
}
- pCur = sqliteMalloc( sizeof(*pCur) );
+ 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;
}
-
- /* Now that no other errors can occur, finish filling in the BtCursor
- ** variables, link the cursor into the BtShared list and set *ppCur (the
- ** output argument to this function).
- */
pCur->xCompare = xCmp ? xCmp : dfltCompare;
pCur->pArg = pArg;
- pCur->pBtree = p;
+ 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->eState = CURSOR_INVALID;
+ pCur->isValid = 0;
*ppCur = pCur;
-
return SQLITE_OK;
+
create_cursor_exception:
if( pCur ){
releasePage(pCur->pPage);
sqliteFree(pCur);
}
@@ -2765,12 +2176,11 @@
/*
** Close a cursor. The read lock on the database file is released
** when the last cursor is closed.
*/
int sqlite3BtreeCloseCursor(BtCursor *pCur){
- BtShared *pBt = pCur->pBtree->pBt;
- restoreOrClearCursorPosition(pCur, 0);
+ Btree *pBt = pCur->pBt;
if( pCur->pPrev ){
pCur->pPrev->pNext = pCur->pNext;
}else{
pBt->pCursor = pCur->pNext;
}
@@ -2833,21 +2243,17 @@
**
** 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){
- int rc = restoreOrClearCursorPosition(pCur, 1);
- if( rc==SQLITE_OK ){
- assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID );
- if( pCur->eState==CURSOR_INVALID ){
- *pSize = 0;
- }else{
- getCellInfo(pCur);
- *pSize = pCur->info.nKey;
- }
- }
- return rc;
+ 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.
@@ -2854,22 +2260,18 @@
** 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){
- int rc = restoreOrClearCursorPosition(pCur, 1);
- if( rc==SQLITE_OK ){
- assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID );
- if( pCur->eState==CURSOR_INVALID ){
- /* Not pointing at a valid entry - set *pSize to 0. */
- *pSize = 0;
- }else{
- getCellInfo(pCur);
- *pSize = pCur->info.nData;
- }
- }
- return rc;
+ 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
@@ -2888,22 +2290,23 @@
){
unsigned char *aPayload;
Pgno nextPage;
int rc;
MemPage *pPage;
- BtShared *pBt;
+ Btree *pBt;
int ovflSize;
u32 nKey;
assert( pCur!=0 && pCur->pPage!=0 );
- assert( pCur->eState==CURSOR_VALID );
- pBt = pCur->pBtree->pBt;
+ assert( pCur->isValid );
+ pBt = pCur->pBt;
pPage = pCur->pPage;
pageIntegrity(pPage);
assert( pCur->idx>=0 && pCur->idxnCell );
getCellInfo(pCur);
- aPayload = pCur->info.pCell + pCur->info.nHeader;
+ aPayload = pCur->info.pCell;
+ aPayload += pCur->info.nHeader;
if( pPage->intKey ){
nKey = 0;
}else{
nKey = pCur->info.nKey;
}
@@ -2953,11 +2356,11 @@
sqlite3pager_unref(aPayload);
}
}
if( amt>0 ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT; /* bkpt-CORRUPT */
}
return SQLITE_OK;
}
/*
@@ -2968,22 +2371,15 @@
** 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){
- int rc = restoreOrClearCursorPosition(pCur, 1);
- if( rc==SQLITE_OK ){
- assert( pCur->eState==CURSOR_VALID );
- assert( pCur->pPage!=0 );
- if( pCur->pPage->intKey ){
- return SQLITE_CORRUPT_BKPT;
- }
- assert( pCur->pPage->intKey==0 );
- assert( pCur->idx>=0 && pCur->idxpPage->nCell );
- rc = getPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
- }
- return rc;
+ assert( pCur->isValid );
+ assert( pCur->pPage!=0 );
+ assert( pCur->pPage->intKey==0 );
+ assert( pCur->idx>=0 && pCur->idxpPage->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
@@ -2992,18 +2388,14 @@
** 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){
- int rc = restoreOrClearCursorPosition(pCur, 1);
- if( rc==SQLITE_OK ){
- assert( pCur->eState==CURSOR_VALID );
- assert( pCur->pPage!=0 );
- assert( pCur->idx>=0 && pCur->idxpPage->nCell );
- rc = getPayload(pCur, offset, amt, pBuf, 1);
- }
- return rc;
+ assert( pCur->isValid );
+ assert( pCur->pPage!=0 );
+ assert( pCur->idx>=0 && pCur->idxpPage->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
@@ -3028,15 +2420,17 @@
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->eState==CURSOR_VALID );
+ assert( pCur->isValid );
+ pBt = pCur->pBt;
pPage = pCur->pPage;
pageIntegrity(pPage);
assert( pCur->idx>=0 && pCur->idxnCell );
getCellInfo(pCur);
aPayload = pCur->info.pCell;
@@ -3070,20 +2464,14 @@
**
** 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){
- if( pCur->eState==CURSOR_VALID ){
- return (const void*)fetchPayload(pCur, pAmt, 0);
- }
- return 0;
+ return (const void*)fetchPayload(pCur, pAmt, 0);
}
const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){
- if( pCur->eState==CURSOR_VALID ){
- return (const void*)fetchPayload(pCur, pAmt, 1);
- }
- return 0;
+ return (const void*)fetchPayload(pCur, pAmt, 1);
}
/*
** Move the cursor down to a new child page. The newPgno argument is the
@@ -3091,13 +2479,13 @@
*/
static int moveToChild(BtCursor *pCur, u32 newPgno){
int rc;
MemPage *pNewPage;
MemPage *pOldPage;
- BtShared *pBt = pCur->pBtree->pBt;
+ Btree *pBt = pCur->pBt;
- assert( pCur->eState==CURSOR_VALID );
+ assert( pCur->isValid );
rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage);
if( rc ) return rc;
pageIntegrity(pNewPage);
pNewPage->idxParent = pCur->idx;
pOldPage = pCur->pPage;
@@ -3105,11 +2493,11 @@
releasePage(pOldPage);
pCur->pPage = pNewPage;
pCur->idx = 0;
pCur->info.nSize = 0;
if( pNewPage->nCell<1 ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT; /* bkpt-CORRUPT */
}
return SQLITE_OK;
}
/*
@@ -3136,24 +2524,26 @@
** 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->eState==CURSOR_VALID );
+ 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;
@@ -3162,56 +2552,45 @@
/*
** Move the cursor to the root page
*/
static int moveToRoot(BtCursor *pCur){
MemPage *pRoot;
- int rc = SQLITE_OK;
- BtShared *pBt = pCur->pBtree->pBt;
-
- restoreOrClearCursorPosition(pCur, 0);
- assert( pCur->pPage );
- pRoot = pCur->pPage;
- if( pRoot->pgno==pCur->pgnoRoot ){
- assert( pRoot->isInit );
- }else{
- if(
- SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0))
- ){
- pCur->eState = CURSOR_INVALID;
- return rc;
- }
- releasePage(pCur->pPage);
- pageIntegrity(pRoot);
- pCur->pPage = 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->eState = CURSOR_VALID;
+ pCur->isValid = 1;
rc = moveToChild(pCur, subpage);
}
- pCur->eState = ((pCur->pPage->nCell>0)?CURSOR_VALID:CURSOR_INVALID);
+ 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.
-**
-** The left-most leaf is the one with the smallest key - the first
-** in ascending order.
*/
static int moveToLeftmost(BtCursor *pCur){
Pgno pgno;
int rc;
MemPage *pPage;
- assert( pCur->eState==CURSOR_VALID );
+ assert( pCur->isValid );
while( !(pPage = pCur->pPage)->leaf ){
assert( pCur->idx>=0 && pCur->idxnCell );
pgno = get4byte(findCell(pPage, pCur->idx));
rc = moveToChild(pCur, pgno);
if( rc ) return rc;
@@ -3223,20 +2602,17 @@
** 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*.
-**
-** The right-most entry is the one with the largest key - the last
-** key in ascending order.
*/
static int moveToRightmost(BtCursor *pCur){
Pgno pgno;
int rc;
MemPage *pPage;
- assert( pCur->eState==CURSOR_VALID );
+ 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;
@@ -3252,11 +2628,11 @@
*/
int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
int rc;
rc = moveToRoot(pCur);
if( rc ) return rc;
- if( pCur->eState==CURSOR_INVALID ){
+ if( pCur->isValid==0 ){
assert( pCur->pPage->nCell==0 );
*pRes = 1;
return SQLITE_OK;
}
assert( pCur->pPage->nCell>0 );
@@ -3271,16 +2647,16 @@
*/
int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
int rc;
rc = moveToRoot(pCur);
if( rc ) return rc;
- if( CURSOR_INVALID==pCur->eState ){
+ if( pCur->isValid==0 ){
assert( pCur->pPage->nCell==0 );
*pRes = 1;
return SQLITE_OK;
}
- assert( pCur->eState==CURSOR_VALID );
+ assert( pCur->isValid );
*pRes = 0;
rc = moveToRightmost(pCur);
return rc;
}
@@ -3287,11 +2663,11 @@
/* 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 pKey. The comparison function specified when the cursor was
+** 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
@@ -3311,17 +2687,15 @@
** *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;
- int tryRightmost;
rc = moveToRoot(pCur);
if( rc ) return rc;
assert( pCur->pPage );
assert( pCur->pPage->isInit );
- tryRightmost = pCur->pPage->intKey;
- if( pCur->eState==CURSOR_INVALID ){
+ if( pCur->isValid==0 ){
*pRes = -1;
assert( pCur->pPage->nCell==0 );
return SQLITE_OK;
}
for(;;){
@@ -3330,41 +2704,30 @@
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_BKPT;
+ 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 ){
- u8 *pCell;
- if( tryRightmost ){
- pCur->idx = upr;
- }
- pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize;
- if( pPage->hasData ){
- int dummy;
- pCell += getVarint32(pCell, &dummy);
- }
- getVarint(pCell, &nCellKey);
if( nCellKeynKey ){
c = +1;
- tryRightmost = 0;
}else{
c = 0;
}
}else{
int available;
pCellKey = (void *)fetchPayload(pCur, &available, 0);
- nCellKey = pCur->info.nKey;
if( available>=nCellKey ){
c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey);
}else{
pCellKey = sqliteMallocRaw( nCellKey );
if( pCellKey==0 ) return SQLITE_NOMEM;
@@ -3420,15 +2783,11 @@
** 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){
- /* TODO: What if the cursor is in CURSOR_REQUIRESEEK but all table entries
- ** have been deleted? This API will need to change to return an error code
- ** as well as the boolean result value.
- */
- return (CURSOR_VALID!=pCur->eState);
+ return pCur->isValid==0;
}
/*
** Advance the cursor to the next entry in the database. If
** successful then set *pRes=0. If the cursor
@@ -3437,25 +2796,12 @@
*/
int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
int rc;
MemPage *pPage = pCur->pPage;
-#ifndef SQLITE_OMIT_SHARED_CACHE
- rc = restoreOrClearCursorPosition(pCur, 1);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- if( pCur->skip>0 ){
- pCur->skip = 0;
- *pRes = 0;
- return SQLITE_OK;
- }
- pCur->skip = 0;
-#endif
-
assert( pRes!=0 );
- if( CURSOR_INVALID==pCur->eState ){
+ if( pCur->isValid==0 ){
*pRes = 1;
return SQLITE_OK;
}
assert( pPage->isInit );
assert( pCur->idxnCell );
@@ -3471,11 +2817,11 @@
return rc;
}
do{
if( isRootPage(pPage) ){
*pRes = 1;
- pCur->eState = CURSOR_INVALID;
+ pCur->isValid = 0;
return SQLITE_OK;
}
moveToParent(pCur);
pPage = pCur->pPage;
}while( pCur->idx>=pPage->nCell );
@@ -3503,25 +2849,11 @@
*/
int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
int rc;
Pgno pgno;
MemPage *pPage;
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
- rc = restoreOrClearCursorPosition(pCur, 1);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- if( pCur->skip<0 ){
- pCur->skip = 0;
- *pRes = 0;
- return SQLITE_OK;
- }
- pCur->skip = 0;
-#endif
-
- if( CURSOR_INVALID==pCur->eState ){
+ if( pCur->isValid==0 ){
*pRes = 1;
return SQLITE_OK;
}
pPage = pCur->pPage;
@@ -3533,11 +2865,11 @@
if( rc ) return rc;
rc = moveToRightmost(pCur);
}else{
while( pCur->idx==0 ){
if( isRootPage(pPage) ){
- pCur->eState = CURSOR_INVALID;
+ pCur->isValid = 0;
*pRes = 1;
return SQLITE_OK;
}
moveToParent(pCur);
pPage = pCur->pPage;
@@ -3574,11 +2906,11 @@
** 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(
- BtShared *pBt,
+ Btree *pBt,
MemPage **ppPage,
Pgno *pPgno,
Pgno nearby,
u8 exact
){
@@ -3657,11 +2989,11 @@
*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;
+ 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.
*/
@@ -3732,11 +3064,11 @@
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;
+ 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( closestpBt;
+ Btree *pBt = pPage->pBt;
MemPage *pPage1 = pBt->pPage1;
int rc, n, k;
/* Prepare the page for freeing */
assert( pPage->pgno>1 );
@@ -3860,11 +3192,11 @@
/*
** Free any overflow pages associated with the given Cell.
*/
static int clearCell(MemPage *pPage, unsigned char *pCell){
- BtShared *pBt = pPage->pBt;
+ Btree *pBt = pPage->pBt;
CellInfo info;
Pgno ovflPgno;
int rc;
parseCellPtr(pPage, pCell, &info);
@@ -3873,18 +3205,18 @@
}
ovflPgno = get4byte(&pCell[info.iOverflow]);
while( ovflPgno!=0 ){
MemPage *pOvfl;
if( ovflPgno>sqlite3pager_pagecount(pBt->pPager) ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT;
}
rc = getPage(pBt, ovflPgno, &pOvfl);
if( rc ) return rc;
ovflPgno = get4byte(pOvfl->aData);
rc = freePage(pOvfl);
- sqlite3pager_unref(pOvfl->aData);
if( rc ) return rc;
+ sqlite3pager_unref(pOvfl->aData);
}
return SQLITE_OK;
}
/*
@@ -3912,11 +3244,11 @@
int spaceLeft;
MemPage *pOvfl = 0;
MemPage *pToRelease = 0;
unsigned char *pPrior;
unsigned char *pPayload;
- BtShared *pBt = pPage->pBt;
+ Btree *pBt = pPage->pBt;
Pgno pgnoOvfl = 0;
int nHeader;
CellInfo info;
/* Fill in the header. */
@@ -4001,19 +3333,19 @@
/*
** 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(BtShared *pBt, Pgno pgno, MemPage *pNewParent, int idx){
+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->pageSize];
+ 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;
@@ -4044,11 +3376,11 @@
** This routine gets called after you memcpy() one page into
** another.
*/
static int reparentChildPages(MemPage *pPage){
int i;
- BtShared *pBt = pPage->pBt;
+ Btree *pBt = pPage->pBt;
int rc = SQLITE_OK;
if( pPage->leaf ) return SQLITE_OK;
for(i=0; inCell; i++){
@@ -4152,12 +3484,11 @@
top = get2byte(&data[hdr+5]);
cellOffset = pPage->cellOffset;
end = cellOffset + 2*pPage->nCell + 2;
ins = cellOffset + 2*i;
if( end > top - sz ){
- int rc = defragmentPage(pPage);
- if( rc!=SQLITE_OK ) return rc;
+ defragmentPage(pPage);
top = get2byte(&data[hdr+5]);
assert( end + sz <= top );
}
idx = allocateSpace(pPage, sz);
assert( idx>0 );
@@ -4218,23 +3549,21 @@
assert( pPage->nCell==0 );
cellptr = pPage->cellOffset;
data = pPage->aData;
hdr = pPage->hdrOffset;
put2byte(&data[hdr+3], nCell);
- if( nCell ){
- cellbody = allocateSpace(pPage, totalSize);
- assert( cellbody>0 );
- assert( pPage->nFree >= 2*nCell );
- pPage->nFree -= 2*nCell;
- for(i=0; ipBt->usableSize );
- }
+ cellbody = allocateSpace(pPage, totalSize);
+ assert( cellbody>0 );
+ assert( pPage->nFree >= 2*nCell );
+ pPage->nFree -= 2*nCell;
+ for(i=0; ipBt->usableSize );
pPage->nCell = nCell;
}
/*
** The following parameters determine how many adjacent pages get involved
@@ -4277,11 +3606,11 @@
MemPage *pNew;
Pgno pgnoNew;
u8 *pCell;
int szCell;
CellInfo info;
- BtShared *pBt = pPage->pBt;
+ 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
@@ -4386,13 +3715,12 @@
** 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 */
- BtShared *pBt; /* The whole database */
- int nCell = 0; /* Number of cells in apCell[] */
- int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */
+ 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[] */
@@ -4402,19 +3730,21 @@
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 = 0; /* All cells begin balanced */
+ 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;
@@ -4433,11 +3763,11 @@
#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)
- ** and the new entry is the right-most entry in the tree (it has the
+ ** 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 &&
@@ -4454,10 +3784,35 @@
*/
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; ipsAligned+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
*/
@@ -4498,10 +3853,11 @@
nxDiv = 0;
}
nDiv = 0;
for(i=0, k=nxDiv; inCell ){
+ idxDiv[i] = k;
apDiv[i] = findCell(pParent, k);
nDiv++;
assert( !pParent->leaf );
pgnoOld[i] = get4byte(apDiv[i]);
}else if( k==pParent->nCell ){
@@ -4513,59 +3869,23 @@
if( rc ) goto balance_cleanup;
apOld[i]->idxParent = k;
apCopy[i] = 0;
assert( i==nOld );
nOld++;
- nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
- }
-
- /* Make nMaxCells a multiple of 2 in order to preserve 8-byte
- ** alignment */
- nMaxCells = (nMaxCells + 1)&~1;
-
- /*
- ** Allocate space for memory structures
- */
- apCell = sqliteMallocRaw(
- nMaxCells*sizeof(u8*) /* apCell */
- + nMaxCells*sizeof(int) /* szCell */
- + ROUND8(sizeof(MemPage))*NB /* aCopy */
- + pBt->pageSize*(5+NB) /* aSpace */
- + (ISAUTOVACUUM ? nMaxCells : 0) /* aFrom */
- );
- if( apCell==0 ){
- rc = SQLITE_NOMEM;
- goto balance_cleanup;
- }
- szCell = (int*)&apCell[nMaxCells];
- aCopy[0] = (u8*)&szCell[nMaxCells];
- assert( ((aCopy[0] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */
- for(i=1; ipageSize+ROUND8(sizeof(MemPage))];
- assert( ((aCopy[i] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */
- }
- aSpace = &aCopy[NB-1][pBt->pageSize+ROUND8(sizeof(MemPage))];
- assert( ((aSpace - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum ){
- aFrom = &aSpace[5*pBt->pageSize];
- }
-#endif
-
+ }
+
/*
** 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; ipageSize];
- p->aData = &((u8*)p)[-pBt->pageSize];
- memcpy(p->aData, apOld[i]->aData, pBt->pageSize + sizeof(MemPage));
- /* The memcpy() above changes the value of p->aData so we have to
- ** set it again. */
- p->aData = &((u8*)p)[-pBt->pageSize];
+ 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
@@ -4587,11 +3907,10 @@
leafData = pPage->leafData && pPage->leaf;
for(i=0; inCell+pOld->nOverflow;
for(j=0; jautoVacuum ){
int a;
@@ -4615,15 +3934,14 @@
** added to apCell[] because they are duplicates of child cells.
*/
dropCell(pParent, nxDiv, sz);
}else{
u8 *pTemp;
- assert( nCellpageSize*5 );
+ assert( iSpace<=pBt->psAligned*5 );
memcpy(pTemp, apDiv[i], sz);
apCell[nCell] = pTemp+leafCorrection;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
aFrom[nCell] = 0xFF;
@@ -4661,11 +3979,10 @@
** usableSpace: Number of bytes of space available on each sibling.
**
*/
usableSpace = pBt->usableSize - 12 + leafCorrection;
for(subtotal=k=i=0; i usableSpace ){
szNew[k] = subtotal - szCell[i];
cntNew[k] = i;
if( leafData ){ i--; }
@@ -4693,12 +4010,10 @@
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;
- assert( d0) or we are the
- ** a virtual root page. A virtual root page is when the real root
- ** page is page 1 and we are the only child of that page.
- */
- assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) );
+ assert( cntNew[0]>0 );
/*
** Allocate k new pages. Reuse old pages where possible.
*/
assert( pPage->pgno>1 );
@@ -4796,14 +4106,13 @@
*/
j = 0;
for(i=0; ipgno==pgnoNew[i] );
assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]);
- assert( pNew->nCell>0 || (nNew==1 && cntNew[0]==0) );
+ 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
@@ -4810,11 +4119,10 @@
** children of cells, the right-child of the page, or overflow pages
** pointed to by cells.
*/
if( pBt->autoVacuum ){
for(k=j; kpgno!=pNew->pgno ){
rc = ptrmapPutOvfl(pNew, k-j);
if( rc!=SQLITE_OK ){
goto balance_cleanup;
}
@@ -4830,12 +4138,10 @@
*/
if( ileaf ){
memcpy(&pNew->aData[8], pCell, 4);
pTemp = 0;
@@ -4849,17 +4155,17 @@
j--;
parseCellPtr(pNew, apCell[j], &info);
pCell = &aSpace[iSpace];
fillInCell(pParent, pCell, 0, info.nKey, 0, 0, &sz);
iSpace += sz;
- assert( iSpace<=pBt->pageSize*5 );
+ assert( iSpace<=pBt->psAligned*5 );
pTemp = 0;
}else{
pCell -= 4;
pTemp = &aSpace[iSpace];
iSpace += sz;
- assert( iSpace<=pBt->pageSize*5 );
+ 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
@@ -4935,11 +4241,11 @@
*/
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 */
- BtShared *pBt; /* The main BTree structure */
+ 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 );
@@ -5037,11 +4343,11 @@
*/
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 */
- BtShared *pBt; /* The BTree */
+ 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 */
@@ -5059,11 +4365,11 @@
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 ) goto balancedeeper_out;
+ 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;
}
@@ -5073,22 +4379,20 @@
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 ) goto balancedeeper_out;
+ if( rc ) return rc;
for(i=0; inCell; i++){
rc = ptrmapPutOvfl(pChild, i);
if( rc!=SQLITE_OK ){
return rc;
}
}
}
#endif
rc = balance_nonroot(pChild);
-
-balancedeeper_out:
releasePage(pChild);
return rc;
}
/*
@@ -5126,16 +4430,14 @@
** 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(BtShared *pBt, Pgno pgnoRoot, BtCursor *pExclude){
+static int checkReadLocks(Btree *pBt, Pgno pgnoRoot, BtCursor *pExclude){
BtCursor *p;
for(p=pBt->pCursor; p; p=p->pNext){
- u32 flags = (p->pBtree->pSqlite ? p->pBtree->pSqlite->flags : 0);
if( p->pgnoRoot!=pgnoRoot || p==pExclude ) continue;
- if( p->wrFlag==0 && flags&SQLITE_ReadUncommitted ) continue;
if( p->wrFlag==0 ) return SQLITE_LOCKED;
if( p->pPage->pgno!=p->pgnoRoot ){
moveToRoot(p);
}
}
@@ -5158,15 +4460,15 @@
){
int rc;
int loc;
int szNew;
MemPage *pPage;
- BtShared *pBt = pCur->pBtree->pBt;
+ Btree *pBt = pCur->pBt;
unsigned char *oldCell;
unsigned char *newCell = 0;
- if( pBt->inTransaction!=TRANS_WRITE ){
+ 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 ){
@@ -5173,20 +4475,12 @@
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 */
}
-
- /* Save the positions of any other cursors open on this table */
- restoreOrClearCursorPosition(pCur, 0);
- if(
- SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
- SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, &loc))
- ){
- return rc;
- }
-
+ 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,
@@ -5198,11 +4492,11 @@
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 && CURSOR_VALID==pCur->eState ){
+ if( loc==0 && pCur->isValid ){
int szOld;
assert( pCur->idx>=0 && pCur->idxnCell );
oldCell = findCell(pPage, pCur->idx);
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
@@ -5238,14 +4532,14 @@
int sqlite3BtreeDelete(BtCursor *pCur){
MemPage *pPage = pCur->pPage;
unsigned char *pCell;
int rc;
Pgno pgnoChild = 0;
- BtShared *pBt = pCur->pBtree->pBt;
+ Btree *pBt = pCur->pBt;
assert( pPage->isInit );
- if( pBt->inTransaction!=TRANS_WRITE ){
+ 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 ){
@@ -5255,23 +4549,12 @@
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 */
}
-
- /* Restore the current cursor position (a no-op if the cursor is not in
- ** CURSOR_REQUIRESEEK state) and save the positions of any other cursors
- ** open on the same table. Then call sqlite3pager_write() on the page
- ** that the entry will be deleted from.
- */
- if(
- (rc = restoreOrClearCursorPosition(pCur, 1)) ||
- (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
- (rc = sqlite3pager_write(pPage->aData))
- ){
- return rc;
- }
+ 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.
*/
@@ -5292,56 +4575,46 @@
*/
BtCursor leafCur;
unsigned char *pNext;
int szNext;
int notUsed;
- unsigned char *tempCell = 0;
+ 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;
- }
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3pager_write(leafCur.pPage->aData);
- }
- if( rc==SQLITE_OK ){
- 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 ){
- rc = SQLITE_NOMEM;
- }
- }
- if( rc==SQLITE_OK ){
- rc = insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell, 0);
- }
- if( rc==SQLITE_OK ){
- put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild);
- rc = balance(pPage, 0);
- }
- if( rc==SQLITE_OK ){
- dropCell(leafCur.pPage, leafCur.idx, szNext);
- rc = balance(leafCur.pPage, 0);
- }
+ 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);
}
- if( rc==SQLITE_OK ){
- moveToRoot(pCur);
- }
+ moveToRoot(pCur);
return rc;
}
/*
** Create a new BTree table. Write into *piTable the page
@@ -5352,16 +4625,15 @@
** flags might not work:
**
** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys
** BTREE_ZERODATA Used for SQL indices
*/
-int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
- BtShared *pBt = p->pBt;
+int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){
MemPage *pRoot;
Pgno pgnoRoot;
int rc;
- if( pBt->inTransaction!=TRANS_WRITE ){
+ if( pBt->inTrans!=TRANS_WRITE ){
/* Must start a transaction first */
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
assert( !pBt->readOnly );
@@ -5384,11 +4656,11 @@
/* 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(p, 4, &pgnoRoot);
+ 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.
@@ -5416,17 +4688,12 @@
rc = getPage(pBt, pgnoRoot, &pRoot);
if( rc!=SQLITE_OK ){
return rc;
}
rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
- if( rc!=SQLITE_OK || eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){
- releasePage(pRoot);
- return rc;
- }
assert( eType!=PTRMAP_ROOTPAGE );
assert( eType!=PTRMAP_FREEPAGE );
- rc = sqlite3pager_write(pRoot->aData);
if( rc!=SQLITE_OK ){
releasePage(pRoot);
return rc;
}
rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove);
@@ -5451,11 +4718,11 @@
rc = ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0);
if( rc ){
releasePage(pRoot);
return rc;
}
- rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot);
+ rc = sqlite3BtreeUpdateMeta(pBt, 4, pgnoRoot);
if( rc ){
releasePage(pRoot);
return rc;
}
@@ -5474,48 +4741,46 @@
/*
** Erase the given database page and all its children. Return
** the page to the freelist.
*/
static int clearDatabasePage(
- BtShared *pBt, /* The BTree that contains the table */
+ 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 = 0;
+ MemPage *pPage;
int rc;
unsigned char *pCell;
int i;
if( pgno>sqlite3pager_pagecount(pBt->pPager) ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT;
}
rc = getAndInitPage(pBt, pgno, &pPage, pParent);
- if( rc ) goto cleardatabasepage_out;
+ if( rc ) return rc;
rc = sqlite3pager_write(pPage->aData);
- if( rc ) goto cleardatabasepage_out;
+ if( rc ) return rc;
for(i=0; inCell; i++){
pCell = findCell(pPage, i);
if( !pPage->leaf ){
rc = clearDatabasePage(pBt, get4byte(pCell), pPage->pParent, 1);
- if( rc ) goto cleardatabasepage_out;
+ if( rc ) return rc;
}
rc = clearCell(pPage, pCell);
- if( rc ) goto cleardatabasepage_out;
+ if( rc ) return rc;
}
if( !pPage->leaf ){
rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), pPage->pParent, 1);
- if( rc ) goto cleardatabasepage_out;
+ if( rc ) return rc;
}
if( freePageFlag ){
rc = freePage(pPage);
}else{
zeroPage(pPage, pPage->aData[0] | PTF_LEAF);
}
-
-cleardatabasepage_out:
releasePage(pPage);
return rc;
}
/*
@@ -5525,29 +4790,26 @@
**
** 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 *p, int iTable){
+int sqlite3BtreeClearTable(Btree *pBt, int iTable){
int rc;
BtCursor *pCur;
- BtShared *pBt = p->pBt;
- if( p->inTrans!=TRANS_WRITE ){
+ 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 0
if( rc ){
sqlite3BtreeRollback(pBt);
}
-#endif
return rc;
}
/*
** Erase all information in a table and add the root of the table to
@@ -5567,16 +4829,15 @@
** 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 *p, int iTable, int *piMoved){
+int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){
int rc;
MemPage *pPage = 0;
- BtShared *pBt = p->pBt;
- if( p->inTrans!=TRANS_WRITE ){
+ 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
@@ -5588,15 +4849,12 @@
return SQLITE_LOCKED;
}
rc = getPage(pBt, (Pgno)iTable, &pPage);
if( rc ) return rc;
- rc = sqlite3BtreeClearTable(p, iTable);
- if( rc ){
- releasePage(pPage);
- return rc;
- }
+ rc = sqlite3BtreeClearTable(pBt, iTable);
+ if( rc ) return rc;
*piMoved = 0;
if( iTable>1 ){
#ifdef SQLITE_OMIT_AUTOVACUUM
@@ -5603,11 +4861,11 @@
rc = freePage(pPage);
releasePage(pPage);
#else
if( pBt->autoVacuum ){
Pgno maxRootPgno;
- rc = sqlite3BtreeGetMeta(p, 4, &maxRootPgno);
+ rc = sqlite3BtreeGetMeta(pBt, 4, &maxRootPgno);
if( rc!=SQLITE_OK ){
releasePage(pPage);
return rc;
}
@@ -5660,11 +4918,11 @@
if( maxRootPgno==PTRMAP_PAGENO(pBt->usableSize, maxRootPgno) ){
maxRootPgno--;
}
assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) );
- rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno);
+ rc = sqlite3BtreeUpdateMeta(pBt, 4, maxRootPgno);
}else{
rc = freePage(pPage);
releasePage(pPage);
}
#endif
@@ -5685,24 +4943,13 @@
**
** 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 *p, int idx, u32 *pMeta){
+int sqlite3BtreeGetMeta(Btree *pBt, int idx, u32 *pMeta){
int rc;
unsigned char *pP1;
- BtShared *pBt = p->pBt;
-
- /* Reading a meta-data value requires a read-lock on page 1 (and hence
- ** the sqlite_master table. We grab this lock regardless of whether or
- ** not the SQLITE_ReadUncommitted flag is set (the table rooted at page
- ** 1 is treated as a special case by queryTableLock() and lockTable()).
- */
- rc = queryTableLock(p, 1, READ_LOCK);
- if( rc!=SQLITE_OK ){
- return rc;
- }
assert( idx>=0 && idx<=15 );
rc = sqlite3pager_get(pBt->pPager, 1, (void**)&pP1);
if( rc ) return rc;
*pMeta = get4byte(&pP1[36 + idx*4]);
@@ -5713,25 +4960,22 @@
*/
#ifdef SQLITE_OMIT_AUTOVACUUM
if( idx==4 && *pMeta>0 ) pBt->readOnly = 1;
#endif
- /* Grab the read-lock on page 1. */
- rc = lockTable(p, 1, READ_LOCK);
- return rc;
+ return SQLITE_OK;
}
/*
** Write meta-information back into the database. Meta[0] is
** read-only and may not be written.
*/
-int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
- BtShared *pBt = p->pBt;
+int sqlite3BtreeUpdateMeta(Btree *pBt, int idx, u32 iMeta){
unsigned char *pP1;
int rc;
assert( idx>=1 && idx<=15 );
- if( p->inTrans!=TRANS_WRITE ){
+ if( pBt->inTrans!=TRANS_WRITE ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
assert( pBt->pPage1!=0 );
pP1 = pBt->pPage1->aData;
rc = sqlite3pager_write(pP1);
@@ -5743,23 +4987,20 @@
/*
** Return the flag byte at the beginning of the page that the cursor
** is currently pointing to.
*/
int sqlite3BtreeFlags(BtCursor *pCur){
- /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call
- ** restoreOrClearCursorPosition() here.
- */
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(BtShared *pBt, int pgno, int recursive, MemPage *pParent){
+static int btreePageDump(Btree *pBt, int pgno, int recursive, MemPage *pParent){
int rc;
MemPage *pPage;
int i, j, c;
int nFree;
u16 idx;
@@ -5851,12 +5092,12 @@
pPage->isInit = isInit;
sqlite3pager_unref(data);
fflush(stdout);
return SQLITE_OK;
}
-int sqlite3BtreePageDump(Btree *p, int pgno, int recursive){
- return btreePageDump(p->pBt, pgno, recursive, 0);
+int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
+ return btreePageDump(pBt, pgno, recursive, 0);
}
#endif
#ifdef SQLITE_TEST
/*
@@ -5879,15 +5120,10 @@
int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){
int cnt, idx;
MemPage *pPage = pCur->pPage;
BtCursor tmpCur;
- int rc = restoreOrClearCursorPosition(pCur, 1);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
pageIntegrity(pPage);
assert( pPage->isInit );
getTempCursor(pCur, &tmpCur);
while( upCnt-- ){
moveToParent(&tmpCur);
@@ -5930,21 +5166,21 @@
/*
** Return the pager associated with a BTree. This routine is used for
** testing and debugging only.
*/
-Pager *sqlite3BtreePager(Btree *p){
- return p->pBt->pPager;
+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 {
- BtShared *pBt; /* The tree being checked out */
+ 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. */
};
@@ -6131,37 +5367,40 @@
MemPage *pPage;
int i, rc, depth, d2, pgno, cnt;
int hdr, cellStart;
int nCell;
u8 *data;
- BtShared *pBt;
- int usableSize;
+ BtCursor cur;
+ Btree *pBt;
+ int maxLocal, usableSize;
char zContext[100];
char *hit;
sprintf(zContext, "Page %d: ", iPage);
/* Check that the page exists
*/
- pBt = pCheck->pBt;
+ 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; inCell; i++){
u8 *pCell;
int sz;
CellInfo info;
@@ -6273,18 +5512,17 @@
** 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 *p, int *aRoot, int nRoot){
+char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
int i;
int nRef;
IntegrityCk sCheck;
- BtShared *pBt = p->pBt;
nRef = *sqlite3pager_stats(pBt->pPager);
- if( lockBtreeWithRetry(p)!=SQLITE_OK ){
+ 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);
@@ -6362,31 +5600,31 @@
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
/*
** Return the full pathname of the underlying database file.
*/
-const char *sqlite3BtreeGetFilename(Btree *p){
- assert( p->pBt->pPager!=0 );
- return sqlite3pager_filename(p->pBt->pPager);
+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 *p){
- assert( p->pBt->pPager!=0 );
- return sqlite3pager_dirname(p->pBt->pPager);
+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 *p){
- assert( p->pBt->pPager!=0 );
- return sqlite3pager_journalname(p->pBt->pPager);
+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
@@ -6393,36 +5631,30 @@
** 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 *pTo, Btree *pFrom){
- int rc = SQLITE_OK;
- Pgno i, nPage, nToPage, iSkip;
-
- BtShared *pBtTo = pTo->pBt;
- BtShared *pBtFrom = pFrom->pBt;
-
- if( pTo->inTrans!=TRANS_WRITE || pFrom->inTrans!=TRANS_WRITE ){
+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);
- iSkip = PENDING_BYTE_PAGE(pBtTo);
for(i=1; rc==SQLITE_OK && i<=nPage; i++){
void *pPage;
- if( i==iSkip ) continue;
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;
- if( i==iSkip ) continue;
rc = sqlite3pager_get(pBtTo->pPager, i, &pPage);
if( rc ) break;
rc = sqlite3pager_write(pPage);
sqlite3pager_unref(pPage);
sqlite3pager_dont_write(pBtTo->pPager, i);
@@ -6429,28 +5661,28 @@
}
if( !rc && nPagepPager, nPage);
}
if( rc ){
- sqlite3BtreeRollback(pTo);
+ sqlite3BtreeRollback(pBtTo);
}
return rc;
}
#endif /* SQLITE_OMIT_VACUUM */
/*
** Return non-zero if a transaction is active.
*/
-int sqlite3BtreeIsInTrans(Btree *p){
- return (p && (p->inTrans==TRANS_WRITE));
+int sqlite3BtreeIsInTrans(Btree *pBt){
+ return (pBt && (pBt->inTrans==TRANS_WRITE));
}
/*
** Return non-zero if a statement transaction is active.
*/
-int sqlite3BtreeIsInStmt(Btree *p){
- return (p->pBt && p->pBt->inStmt);
+int sqlite3BtreeIsInStmt(Btree *pBt){
+ return (pBt && pBt->inStmt);
}
/*
** This call is a no-op if no write-transaction is currently active on pBt.
**
@@ -6463,13 +5695,12 @@
** 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 *p, const char *zMaster){
- if( p->inTrans==TRANS_WRITE ){
- BtShared *pBt = p->pBt;
+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;
@@ -6478,78 +5709,5 @@
#endif
return sqlite3pager_sync(pBt->pPager, zMaster, 0);
}
return SQLITE_OK;
}
-
-/*
-** This function returns a pointer to a blob of memory associated with
-** a single shared-btree. The memory is used by client code for it's own
-** purposes (for example, to store a high-level schema associated with
-** the shared-btree). The btree layer manages reference counting issues.
-**
-** The first time this is called on a shared-btree, nBytes bytes of memory
-** are allocated, zeroed, and returned to the caller. For each subsequent
-** call the nBytes parameter is ignored and a pointer to the same blob
-** of memory returned.
-**
-** Just before the shared-btree is closed, the function passed as the
-** xFree argument when the memory allocation was made is invoked on the
-** blob of allocated memory. This function should not call sqliteFree()
-** on the memory, the btree layer does that.
-*/
-void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
- BtShared *pBt = p->pBt;
- if( !pBt->pSchema ){
- pBt->pSchema = sqliteMalloc(nBytes);
- pBt->xFreeSchema = xFree;
- }
- return pBt->pSchema;
-}
-
-/*
-** Return true if another user of the same shared btree as the argument
-** handle holds an exclusive lock on the sqlite_master table.
-*/
-int sqlite3BtreeSchemaLocked(Btree *p){
- return (queryTableLock(p, MASTER_ROOT, READ_LOCK)!=SQLITE_OK);
-}
-
-int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){
- int rc = SQLITE_OK;
-#ifndef SQLITE_OMIT_SHARED_CACHE
- u8 lockType = (isWriteLock?WRITE_LOCK:READ_LOCK);
- rc = queryTableLock(p, iTab, lockType);
- if( rc==SQLITE_OK ){
- rc = lockTable(p, iTab, lockType);
- }
-#endif
- return rc;
-}
-
-/*
-** The following debugging interface has to be in this file (rather
-** than in, for example, test1.c) so that it can get access to
-** the definition of BtShared.
-*/
-#if defined(SQLITE_TEST) && defined(TCLSH)
-#include
-int sqlite3_shared_cache_report(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const ThreadData *pTd = sqlite3ThreadDataReadOnly();
- if( pTd->useSharedData ){
- BtShared *pBt;
- Tcl_Obj *pRet = Tcl_NewObj();
- for(pBt=pTd->pBtree; pBt; pBt=pBt->pNext){
- const char *zFile = sqlite3pager_filename(pBt->pPager);
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zFile, -1));
- Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(pBt->nRef));
- }
- Tcl_SetObjResult(interp, pRet);
- }
- return TCL_OK;
-}
-#endif
Index: SQLite.Interop/src/btree.h
==================================================================
--- SQLite.Interop/src/btree.h
+++ SQLite.Interop/src/btree.h
@@ -11,11 +11,11 @@
*************************************************************************
** 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.16 2006/01/16 15:51:47 rmsimpson Exp $
+** @(#) $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
@@ -34,16 +34,14 @@
/*
** Forward declarations of structure
*/
typedef struct Btree Btree;
typedef struct BtCursor BtCursor;
-typedef struct BtShared BtShared;
int sqlite3BtreeOpen(
const char *zFilename, /* Name of database file to open */
- sqlite3 *db, /* Associated database connection */
Btree **, /* Return open Btree* here */
int flags /* Flags */
);
/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
@@ -58,11 +56,10 @@
int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*);
int sqlite3BtreeSetCacheSize(Btree*,int);
int sqlite3BtreeSetSafetyLevel(Btree*,int);
-int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree*,int,int);
int sqlite3BtreeGetPageSize(Btree*);
int sqlite3BtreeGetReserve(Btree*);
int sqlite3BtreeSetAutoVacuum(Btree *, int);
int sqlite3BtreeGetAutoVacuum(Btree *);
@@ -74,13 +71,10 @@
int sqlite3BtreeRollbackStmt(Btree*);
int sqlite3BtreeCreateTable(Btree*, int*, int flags);
int sqlite3BtreeIsInTrans(Btree*);
int sqlite3BtreeIsInStmt(Btree*);
int sqlite3BtreeSync(Btree*, const char *zMaster);
-void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
-int sqlite3BtreeSchemaLocked(Btree *);
-int sqlite3BtreeLockTable(Btree *, int, u8);
const char *sqlite3BtreeGetFilename(Btree *);
const char *sqlite3BtreeGetDirname(Btree *);
const char *sqlite3BtreeGetJournalname(Btree *);
int sqlite3BtreeCopyFile(Btree *, Btree *);
Index: SQLite.Interop/src/build.c
==================================================================
--- SQLite.Interop/src/build.c
+++ SQLite.Interop/src/build.c
@@ -20,11 +20,11 @@
** creating ID lists
** BEGIN TRANSACTION
** COMMIT
** ROLLBACK
**
-** $Id: build.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $
+** $Id: build.c,v 1.1 2005/03/01 16:04:28 rmsimpson Exp $
*/
#include "sqliteInt.h"
#include
/*
@@ -34,90 +34,10 @@
void sqlite3BeginParse(Parse *pParse, int explainFlag){
pParse->explain = explainFlag;
pParse->nVar = 0;
}
-#ifndef SQLITE_OMIT_SHARED_CACHE
-/*
-** The TableLock structure is only used by the sqlite3TableLock() and
-** codeTableLocks() functions.
-*/
-struct TableLock {
- int iDb;
- int iTab;
- u8 isWriteLock;
- const char *zName;
-};
-
-/*
-** Have the compiled statement lock the table with rootpage iTab in database
-** iDb at the shared-cache level when executed. The isWriteLock argument
-** is zero for a read-lock, or non-zero for a write-lock.
-**
-** The zName parameter should point to the unqualified table name. This is
-** used to provide a more informative error message should the lock fail.
-*/
-void sqlite3TableLock(
- Parse *pParse,
- int iDb,
- int iTab,
- u8 isWriteLock,
- const char *zName
-){
- int i;
- int nBytes;
- TableLock *p;
-
- if( 0==sqlite3ThreadDataReadOnly()->useSharedData || iDb<0 ){
- return;
- }
-
- for(i=0; inTableLock; i++){
- p = &pParse->aTableLock[i];
- if( p->iDb==iDb && p->iTab==iTab ){
- p->isWriteLock = (p->isWriteLock || isWriteLock);
- return;
- }
- }
-
- nBytes = sizeof(TableLock) * (pParse->nTableLock+1);
- sqliteReallocOrFree((void **)&pParse->aTableLock, nBytes);
- if( pParse->aTableLock ){
- p = &pParse->aTableLock[pParse->nTableLock++];
- p->iDb = iDb;
- p->iTab = iTab;
- p->isWriteLock = isWriteLock;
- p->zName = zName;
- }
-}
-
-/*
-** Code an OP_TableLock instruction for each table locked by the
-** statement (configured by calls to sqlite3TableLock()).
-*/
-static void codeTableLocks(Parse *pParse){
- int i;
- Vdbe *pVdbe;
- assert( sqlite3ThreadDataReadOnly()->useSharedData || pParse->nTableLock==0 );
-
- if( 0==(pVdbe = sqlite3GetVdbe(pParse)) ){
- return;
- }
-
- for(i=0; inTableLock; i++){
- TableLock *p = &pParse->aTableLock[i];
- int p1 = p->iDb;
- if( p->isWriteLock ){
- p1 = -1*(p1+1);
- }
- sqlite3VdbeOp3(pVdbe, OP_TableLock, p1, p->iTab, p->zName, P3_STATIC);
- }
-}
-#else
- #define codeTableLocks(x)
-#endif
-
/*
** 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
@@ -128,11 +48,11 @@
*/
void sqlite3FinishCoding(Parse *pParse){
sqlite3 *db;
Vdbe *v;
- if( sqlite3ThreadDataReadOnly()->mallocFailed ) return;
+ if( sqlite3_malloc_failed ) return;
if( pParse->nested ) return;
if( !pParse->pVdbe ){
if( pParse->rc==SQLITE_OK && pParse->nErr ){
pParse->rc = SQLITE_ERROR;
}
@@ -154,44 +74,36 @@
** on each used database.
*/
if( pParse->cookieGoto>0 ){
u32 mask;
int iDb;
- sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
+ sqlite3VdbeChangeP2(v, pParse->cookieGoto-1, sqlite3VdbeCurrentAddr(v));
for(iDb=0, mask=1; iDbnDb; 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]);
}
-
- /* Once all the cookies have been verified and transactions opened,
- ** obtain the required table-locks. This is a no-op unless the
- ** shared-cache feature is enabled.
- */
- codeTableLocks(pParse);
sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->cookieGoto);
}
-#ifndef SQLITE_OMIT_TRACE
/* 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);
-#endif /* SQLITE_OMIT_TRACE */
}
/* 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->explain);
+ 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;
}
@@ -216,10 +128,11 @@
** 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 */
@@ -230,11 +143,11 @@
return; /* A malloc must have failed */
}
pParse->nested++;
memcpy(saveBuf, &pParse->nVar, SAVE_SZ);
memset(&pParse->nVar, 0, SAVE_SZ);
- sqlite3RunParser(pParse, zSql, 0);
+ rc = sqlite3RunParser(pParse, zSql, 0);
sqliteFree(zSql);
memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
pParse->nested--;
}
@@ -252,14 +165,15 @@
*/
Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
Table *p = 0;
int i;
assert( zName!=0 );
- for(i=OMIT_TEMPDB; inDb; i++){
+ assert( (db->flags & SQLITE_Initialized) || db->init.busy );
+ for(i=0; inDb; 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].pSchema->tblHash, zName, strlen(zName)+1);
+ p = sqlite3HashFind(&db->aDb[j].tblHash, zName, strlen(zName)+1);
if( p ) break;
}
return p;
}
@@ -284,10 +198,13 @@
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;
}
@@ -307,18 +224,15 @@
** using the ATTACH command.
*/
Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
Index *p = 0;
int i;
- for(i=OMIT_TEMPDB; inDb; i++){
+ assert( (db->flags & SQLITE_Initialized) || db->init.busy );
+ for(i=0; inDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- Schema *pSchema = db->aDb[j].pSchema;
if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue;
- assert( pSchema || (j==1 && !db->aDb[1].pBt) );
- if( pSchema ){
- p = sqlite3HashFind(&pSchema->idxHash, zName, strlen(zName)+1);
- }
+ p = sqlite3HashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1);
if( p ) break;
}
return p;
}
@@ -338,30 +252,32 @@
** 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;
- const char *zName = p->zName;
- pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName, strlen( zName)+1, 0);
- assert( pOld==0 || pOld==p );
+ 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);
}
/*
-** For the index called zIdxName which is found in the database iDb,
-** unlike that index from its Table then remove the index from
-** the index hash table and free all memory structures associated
-** with the index.
+** 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;
- Hash *pHash = &db->aDb[iDb].pSchema->idxHash;
len = strlen(zIdxName);
- pIndex = sqlite3HashInsert(pHash, zIdxName, len+1, 0);
+ 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;
@@ -385,25 +301,43 @@
** 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 && iDbnDb );
+ db->flags &= ~SQLITE_Initialized;
for(i=iDb; inDb; i++){
Db *pDb = &db->aDb[i];
- if( pDb->pSchema ){
- sqlite3SchemaFree(pDb->pSchema);
+ 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 them from the auxiliary database list. We take the
+ ** 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; inDb; i++){
@@ -457,19 +391,16 @@
*/
static void sqliteResetColumnNames(Table *pTable){
int i;
Column *pCol;
assert( pTable!=0 );
- if( (pCol = pTable->aCol)!=0 ){
- for(i=0; inCol; i++, pCol++){
- sqliteFree(pCol->zName);
- sqlite3ExprDelete(pCol->pDflt);
- sqliteFree(pCol->zType);
- sqliteFree(pCol->zColl);
- }
- sqliteFree(pTable->aCol);
- }
+ for(i=0, pCol=pTable->aCol; inCol; i++, pCol++){
+ sqliteFree(pCol->zName);
+ sqlite3ExprDelete(pCol->pDflt);
+ sqliteFree(pCol->zType);
+ }
+ sqliteFree(pTable->aCol);
pTable->aCol = 0;
pTable->nCol = 0;
}
/*
@@ -489,36 +420,28 @@
*/
void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
Index *pIndex, *pNext;
FKey *pFKey, *pNextFKey;
- db = 0;
-
if( pTable==0 ) return;
- /* Do not delete the table until the reference count reaches zero. */
- pTable->nRef--;
- if( pTable->nRef>0 ){
- return;
- }
- assert( pTable->nRef==0 );
-
/* Delete all indices associated with this table
*/
for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
pNext = pIndex->pNext;
- assert( pIndex->pSchema==pTable->pSchema );
+ 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( sqlite3HashFind(&pTable->pSchema->aFKey,
+ assert( pTable->iDbnDb );
+ assert( sqlite3HashFind(&db->aDb[pTable->iDb].aFKey,
pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
sqliteFree(pFKey);
}
#endif
@@ -526,13 +449,10 @@
*/
sqliteResetColumnNames(pTable);
sqliteFree(pTable->zName);
sqliteFree(pTable->zColAff);
sqlite3SelectDelete(pTable->pSelect);
-#ifndef SQLITE_OMIT_CHECK
- sqlite3ExprDelete(pTable->pCheck);
-#endif
sqliteFree(pTable);
}
/*
** Unlink the given table from the hash tables and the delete the
@@ -545,18 +465,18 @@
assert( db!=0 );
assert( iDb>=0 && iDbnDb );
assert( zTabName && zTabName[0] );
pDb = &db->aDb[iDb];
- p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, strlen(zTabName)+1,0);
+ 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->pSchema->aFKey, pF1->zTo, nTo);
+ pF2 = sqlite3HashFind(&pDb->aFKey, pF1->zTo, nTo);
if( pF2==pF1 ){
- sqlite3HashInsert(&pDb->pSchema->aFKey, pF1->zTo, nTo, pF1->pNextTo);
+ sqlite3HashInsert(&pDb->aFKey, pF1->zTo, nTo, pF1->pNextTo);
}else{
while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
if( pF2 ){
pF2->pNextTo = pF1->pNextTo;
}
@@ -572,18 +492,18 @@
** 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 often just pointers into the original SQL text and so
+** 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((char*)pName->z, pName->n);
+ zName = sqliteStrNDup(pName->z, pName->n);
sqlite3Dequote(zName);
}else{
zName = 0;
}
return zName;
@@ -591,13 +511,11 @@
/*
** Open the sqlite_master table stored in database number iDb for
** writing. The table is opened using cursor 0.
*/
-void sqlite3OpenMasterTable(Parse *p, int iDb){
- Vdbe *v = sqlite3GetVdbe(p);
- sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
+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 */
}
@@ -605,22 +523,21 @@
** 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.
*/
-int sqlite3FindDb(sqlite3 *db, Token *pName){
+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( (!OMIT_TEMPDB || i!=1 ) && n==strlen(pDb->zName) &&
- 0==sqlite3StrICmp(pDb->zName, zName) ){
+ if( n==strlen(pDb->zName) && 0==sqlite3StrICmp(pDb->zName, zName) ){
break;
}
}
sqliteFree(zName);
}
@@ -653,11 +570,11 @@
sqlite3 *db = pParse->db;
if( pName2 && pName2->n>0 ){
assert( !db->init.busy );
*pUnqual = pName2;
- iDb = sqlite3FindDb(db, pName1);
+ iDb = findDb(db, pName1);
if( iDb<0 ){
sqlite3ErrorMsg(pParse, "unknown database %T", pName1);
pParse->nErr++;
return -1;
}
@@ -676,11 +593,10 @@
** "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
- && (pParse->db->flags & SQLITE_WriteSchema)==0
&& 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
return SQLITE_ERROR;
}
return SQLITE_OK;
@@ -707,14 +623,14 @@
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 */
- int noErr /* Do nothing if table already exists */
+ 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 */
@@ -736,16 +652,16 @@
** 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( !OMIT_TEMPDB && isTemp && iDb>1 ){
+ 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( !OMIT_TEMPDB && isTemp ) iDb = 1;
+ if( isTemp ) iDb = 1;
pParse->sNameToken = *pName;
zName = sqlite3NameFromToken(pName);
if( zName==0 ) return;
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
@@ -759,17 +675,17 @@
char *zDb = db->aDb[iDb].zName;
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
goto begin_table_error;
}
if( isView ){
- if( !OMIT_TEMPDB && isTemp ){
+ if( isTemp ){
code = SQLITE_CREATE_TEMP_VIEW;
}else{
code = SQLITE_CREATE_VIEW;
}
}else{
- if( !OMIT_TEMPDB && isTemp ){
+ if( isTemp ){
code = SQLITE_CREATE_TEMP_TABLE;
}else{
code = SQLITE_CREATE_TABLE;
}
}
@@ -786,16 +702,15 @@
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto begin_table_error;
}
pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName);
if( pTable ){
- if( !noErr ){
- sqlite3ErrorMsg(pParse, "table %T already exists", pName);
- }
+ sqlite3ErrorMsg(pParse, "table %T already exists", pName);
goto begin_table_error;
}
- if( sqlite3FindIndex(db, zName, 0)!=0 && (iDb==0 || !db->init.busy) ){
+ 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 ){
@@ -806,22 +721,21 @@
pTable->zName = zName;
pTable->nCol = 0;
pTable->aCol = 0;
pTable->iPKey = -1;
pTable->pIndex = 0;
- pTable->pSchema = db->aDb[iDb].pSchema;
- pTable->nRef = 1;
+ 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( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){
- pTable->pSchema->pSeqTab = pTable;
+ 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
@@ -831,24 +745,21 @@
** indices. Hence, the record number for the table must be allocated
** now.
*/
if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){
int lbl;
- int fileFormat;
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);
- fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ?
- 1 : SQLITE_DEFAULT_FILE_FORMAT;
- sqlite3VdbeAddOp(v, OP_Integer, fileFormat, 0);
+ sqlite3VdbeAddOp(v, OP_Integer, db->file_format, 0);
sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1);
- sqlite3VdbeAddOp(v, OP_Integer, ENC(db), 0);
+ 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
@@ -864,15 +775,15 @@
}else
#endif
{
sqlite3VdbeAddOp(v, OP_CreateTable, iDb, 0);
}
- sqlite3OpenMasterTable(pParse, iDb);
- sqlite3VdbeAddOp(v, OP_NewRowid, 0, 0);
+ sqlite3OpenMasterTable(v, iDb);
+ sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
- sqlite3VdbeAddOp(v, OP_Null, 0, 0);
- sqlite3VdbeAddOp(v, OP_Insert, 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. */
@@ -921,14 +832,11 @@
}
}
if( (p->nCol & 0x7)==0 ){
Column *aNew;
aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0]));
- if( aNew==0 ){
- sqliteFree(z);
- return;
- }
+ if( aNew==0 ) return;
p->aCol = aNew;
}
pCol = &p->aCol[p->nCol];
memset(pCol, 0, sizeof(p->aCol[0]));
pCol->zName = z;
@@ -936,10 +844,11 @@
/* 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
@@ -971,22 +880,19 @@
** 'INT' | SQLITE_AFF_INTEGER
** 'CHAR' | SQLITE_AFF_TEXT
** 'CLOB' | SQLITE_AFF_TEXT
** 'TEXT' | SQLITE_AFF_TEXT
** 'BLOB' | SQLITE_AFF_NONE
-** 'REAL' | SQLITE_AFF_REAL
-** 'FLOA' | SQLITE_AFF_REAL
-** 'DOUB' | SQLITE_AFF_REAL
**
** If none of the substrings in the above table are found,
** SQLITE_AFF_NUMERIC is returned.
*/
-char sqlite3AffinityType(const Token *pType){
+static char sqlite3AffinityType(const char *zType, int nType){
u32 h = 0;
char aff = SQLITE_AFF_NUMERIC;
- const unsigned char *zIn = pType->z;
- const unsigned char *zEnd = &pType->z[pType->n];
+ 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 */
@@ -994,25 +900,14 @@
}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_REAL) ){
+ && aff==SQLITE_AFF_NUMERIC ){
aff = SQLITE_AFF_NONE;
-#ifndef SQLITE_OMIT_FLOATING_POINT
- }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
- && aff==SQLITE_AFF_NUMERIC ){
- aff = SQLITE_AFF_REAL;
- }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */
- && aff==SQLITE_AFF_NUMERIC ){
- aff = SQLITE_AFF_REAL;
- }else if( h==(('d'<<24)+('o'<<16)+('u'<<8)+'b') /* DOUB */
- && aff==SQLITE_AFF_NUMERIC ){
- aff = SQLITE_AFF_REAL;
-#endif
}else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */
- aff = SQLITE_AFF_INTEGER;
+ aff = SQLITE_AFF_INTEGER;
break;
}
}
return aff;
@@ -1025,22 +920,34 @@
** 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 *pType){
+void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
Table *p;
- int i;
+ 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];
- sqliteFree(pCol->zType);
- pCol->zType = sqlite3NameFromToken(pType);
- pCol->affinity = sqlite3AffinityType(pType);
+ 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; iaffinity = sqlite3AffinityType(z, n);
}
/*
** The expression is the default value for the most recently added column
** of the table currently under construction.
@@ -1052,19 +959,18 @@
** parsing a CREATE TABLE statement.
*/
void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
Table *p;
Column *pCol;
- if( (p = pParse->pNewTable)!=0 ){
- pCol = &(p->aCol[p->nCol-1]);
- if( !sqlite3ExprIsConstantOrFunction(pExpr) ){
- sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
- pCol->zName);
- }else{
- sqlite3ExprDelete(pCol->pDflt);
- pCol->pDflt = sqlite3ExprDup(pExpr);
- }
+ 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);
}
/*
@@ -1087,12 +993,11 @@
*/
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 */
- int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */
+ 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;
@@ -1110,84 +1015,217 @@
for(iCol=0; iColnCol; iCol++){
if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){
break;
}
}
- if( iColnCol ){
- pTab->aCol[iCol].isPrimKey = 1;
- }
+ if( iColnCol ) pTab->aCol[iCol].isPrimKey = 1;
}
if( pList->nExpr>1 ) iCol = -1;
}
if( iCol>=0 && iColnCol ){
zType = pTab->aCol[iCol].zType;
}
- if( zType && sqlite3StrICmp(zType, "INTEGER")==0
- && sortOrder==SQLITE_SO_ASC ){
+ 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, sortOrder, 0);
+ sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0);
pList = 0;
}
primary_key_exit:
sqlite3ExprListDelete(pList);
return;
}
-/*
-** Add a new CHECK constraint to the table currently under construction.
-*/
-void sqlite3AddCheckConstraint(
- Parse *pParse, /* Parsing context */
- Expr *pCheckExpr /* The check expression */
-){
-#ifndef SQLITE_OMIT_CHECK
- Table *pTab = pParse->pNewTable;
- if( pTab ){
- /* The CHECK expression must be duplicated so that tokens refer
- ** to malloced space and not the (ephemeral) text of the CREATE TABLE
- ** statement */
- pTab->pCheck = sqlite3ExprAnd(pTab->pCheck, sqlite3ExprDup(pCheckExpr));
- }
-#endif
- sqlite3ExprDelete(pCheckExpr);
-}
-
/*
** 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;
- if( sqlite3LocateCollSeq(pParse, zType, nType) ){
- Index *pIdx;
- p->aCol[i].zColl = sqliteStrNDup(zType, nType);
-
- /* If the column is declared as " PRIMARY KEY COLLATE ",
- ** then an index may have been created on this column before the
- ** collation type was added. Correct this if it is the case.
+ pColl = sqlite3LocateCollSeq(pParse, zType, nType);
+ p->aCol[i].pColl = pColl;
+
+ /* If the column is declared as " PRIMARY KEY COLLATE ",
+ ** 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.
*/
- for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
- assert( pIdx->nColumn==1 );
- if( pIdx->aiColumn[0]==i ){
- pIdx->azColl[0] = p->aCol[i].zColl;
+ 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; inColumn; 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.
@@ -1201,27 +1239,37 @@
** 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){
- sqlite3 *db = pParse->db;
- u8 enc = ENC(db);
- u8 initbusy = db->init.busy;
- CollSeq *pColl;
+ 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;
+ }
+ }
+ }
- pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy);
+ /* If nothing has been found, write the error message into pParse */
if( !initbusy && (!pColl || !pColl->xCmp) ){
- pColl = sqlite3GetCollSeq(db, pColl, zName, nName);
- if( !pColl ){
- if( nName<0 ){
- nName = strlen(zName);
- }
+ if( pParse->nErr==0 ){
sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", nName, zName);
- pColl = 0;
}
+ pColl = 0;
}
-
return pColl;
}
/*
@@ -1239,11 +1287,11 @@
** 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].pSchema->schema_cookie+1, 0);
+ 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
@@ -1287,11 +1335,11 @@
/*
** 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 isTemp){
+static char *createTableStmt(Table *p){
int i, k, n;
char *zStmt;
char *zSep, *zSep2, *zEnd, *z;
Column *pCol;
n = 0;
@@ -1313,11 +1361,11 @@
zEnd = "\n)";
}
n += 35 + 6*p->nCol;
zStmt = sqliteMallocRaw( n );
if( zStmt==0 ) return 0;
- strcpy(zStmt, !OMIT_TEMPDB&&isTemp ? "CREATE TEMP TABLE ":"CREATE TABLE ");
+ 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; inCol; i++, pCol++){
strcpy(&zStmt[k], zSep);
@@ -1344,61 +1392,28 @@
**
** 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 changed, so the entry for this table already exists in
+** 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, /* Parse context */
- Token *pCons, /* The ',' token after the last column defn. */
- Token *pEnd, /* The final ')' token in the CREATE TABLE */
- Select *pSelect /* Select from a "CREATE ... AS SELECT" */
-){
+void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
Table *p;
sqlite3 *db = pParse->db;
- int iDb;
- if( (pEnd==0 && pSelect==0) ||
- pParse->nErr || sqlite3ThreadDataReadOnly()->mallocFailed ) {
- return;
- }
+ if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite3_malloc_failed ) return;
p = pParse->pNewTable;
if( p==0 ) return;
assert( !db->init.busy || !pSelect );
- iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
-
-#ifndef SQLITE_OMIT_CHECK
- /* Resolve names in all CHECK constraint expressions.
- */
- if( p->pCheck ){
- SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
- NameContext sNC; /* Name context for pParse->pNewTable */
-
- memset(&sNC, 0, sizeof(sNC));
- memset(&sSrc, 0, sizeof(sSrc));
- sSrc.nSrc = 1;
- sSrc.a[0].zName = p->zName;
- sSrc.a[0].pTab = p;
- sSrc.a[0].iCursor = -1;
- sNC.pParse = pParse;
- sNC.pSrcList = &sSrc;
- sNC.isCheck = 1;
- if( sqlite3ExprResolveNames(&sNC, p->pCheck) ){
- return;
- }
- }
-#endif /* !defined(SQLITE_OMIT_CHECK) */
-
/* 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.)
@@ -1430,15 +1445,17 @@
** 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
}
@@ -1447,20 +1464,15 @@
** 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.
- **
- ** A shared-cache write-lock is not required to write to the new table,
- ** as a schema-lock must have already been obtained to create it. Since
- ** a schema-lock excludes all other database users, the write-lock would
- ** be redundant.
*/
if( pSelect ){
Table *pSelTab;
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
- sqlite3VdbeAddOp(v, OP_Integer, iDb, 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 ){
@@ -1475,13 +1487,13 @@
}
}
/* Compute the complete text of the CREATE statement */
if( pSelect ){
- zStmt = createTableStmt(p, p->pSchema==pParse->db->aDb[1].pSchema);
+ zStmt = createTableStmt(p);
}else{
- n = pEnd->z - pParse->sNameToken.z + 1;
+ 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
@@ -1491,70 +1503,61 @@
*/
sqlite3NestedParse(pParse,
"UPDATE %Q.%s "
"SET type='%s', name=%Q, tbl_name=%Q, rootpage=#0, sql=%Q "
"WHERE rowid=#1",
- db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
+ db->aDb[p->iDb].zName, SCHEMA_TABLE(p->iDb),
zType,
p->zName,
p->zName,
zStmt
);
sqliteFree(zStmt);
- sqlite3ChangeCookie(db, v, iDb);
+ 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[iDb];
- if( pDb->pSchema->pSeqTab==0 ){
+ 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, iDb, 0,
+ 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;
- Schema *pSchema = p->pSchema;
- pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, strlen(p->zName)+1,p);
+ 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(&pSchema->aFKey, pFKey->zTo, nTo);
- sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey);
+ 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_ALTERTABLE
- if( !p->pSelect ){
- const unsigned char *zName = pParse->sNameToken.z;
- assert( !pSelect && pCons && pEnd );
- if( pCons->z==0 ) pCons = pEnd;
- p->addColOffset = 13 + sqlite3utf8CharLen(zName, pCons->z - zName);
- }
-#endif
}
}
#ifndef SQLITE_OMIT_VIEW
/*
@@ -1572,26 +1575,19 @@
int n;
const unsigned char *z;
Token sEnd;
DbFixer sFix;
Token *pName;
- int iDb;
-
- if( pParse->nVar>0 ){
- sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
- sqlite3SelectDelete(pSelect);
- return;
- }
- sqlite3StartTable(pParse, pBegin, pName1, pName2, isTemp, 1, 0);
+
+ sqlite3StartTable(pParse, pBegin, pName1, pName2, isTemp, 1);
p = pParse->pNewTable;
if( p==0 || pParse->nErr ){
sqlite3SelectDelete(pSelect);
return;
}
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
- iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
- if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName)
+ if( sqlite3FixInit(&sFix, pParse, p->iDb, "view", pName)
&& sqlite3FixSelect(&sFix, pSelect)
){
sqlite3SelectDelete(pSelect);
return;
}
@@ -1601,13 +1597,10 @@
** 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( sqlite3ThreadDataReadOnly()->mallocFailed ){
- return;
- }
if( !pParse->db->init.busy ){
sqlite3ViewGetColumnNames(pParse, p);
}
/* Locate the end of the CREATE VIEW statement. Make sEnd point to
@@ -1623,11 +1616,11 @@
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, 0, &sEnd, 0);
+ sqlite3EndTable(pParse, &sEnd, 0);
return;
}
#endif /* SQLITE_OMIT_VIEW */
#ifndef SQLITE_OMIT_VIEW
@@ -1657,17 +1650,14 @@
** 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 0
if( pTable->nCol<0 ){
sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName);
return 1;
}
-#endif
- assert( pTable->nCol>=0 );
/* 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
@@ -1674,32 +1664,28 @@
** 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);
- if( pSel ){
- 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);
- pTable->pSchema->flags |= DB_UnresetViews;
- }else{
- pTable->nCol = 0;
- nErr++;
- }
- sqlite3SelectDelete(pSel);
- } else {
- nErr++;
- }
+ 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
@@ -1707,11 +1693,11 @@
** 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].pSchema->tblHash); i;i=sqliteHashNext(i)){
+ for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){
Table *pTab = sqliteHashData(i);
if( pTab->pSelect ){
sqliteResetColumnNames(pTab);
}
}
@@ -1728,22 +1714,19 @@
** to iTo.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){
HashElem *pElem;
- Hash *pHash;
-
- pHash = &pDb->pSchema->tblHash;
- for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){
+
+ for(pElem=sqliteHashFirst(&pDb->tblHash); pElem; pElem=sqliteHashNext(pElem)){
Table *pTab = sqliteHashData(pElem);
if( pTab->tnum==iFrom ){
pTab->tnum = iTo;
return;
}
}
- pHash = &pDb->pSchema->idxHash;
- for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){
+ for(pElem=sqliteHashFirst(&pDb->idxHash); pElem; pElem=sqliteHashNext(pElem)){
Index *pIdx = sqliteHashData(pElem);
if( pIdx->tnum==iFrom ){
pIdx->tnum = iTo;
return;
}
@@ -1783,14 +1766,13 @@
** is also added (this can happen with an auto-vacuum database).
*/
static void destroyTable(Parse *pParse, Table *pTab){
#ifdef SQLITE_OMIT_AUTOVACUUM
Index *pIdx;
- int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- destroyRootPage(pParse, pTab->tnum, iDb);
+ destroyRootPage(pParse, pTab->tnum, pTab->iDb);
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- destroyRootPage(pParse, pIdx->tnum, iDb);
+ 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
@@ -1817,66 +1799,55 @@
if( iDestroyed==0 || iTabpIndex; pIdx; pIdx=pIdx->pNext){
int iIdx = pIdx->tnum;
- assert( pIdx->pSchema==pTab->pSchema );
+ assert( pIdx->iDb==pTab->iDb );
if( (iDestroyed==0 || (iIdxiLargest ){
iLargest = iIdx;
}
}
- if( iLargest==0 ){
- return;
- }else{
- int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- destroyRootPage(pParse, iLargest, iDb);
- iDestroyed = iLargest;
- }
+ 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, int noErr){
+void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
Table *pTab;
Vdbe *v;
sqlite3 *db = pParse->db;
int iDb;
- if( pParse->nErr || sqlite3ThreadDataReadOnly()->mallocFailed ){
- goto exit_drop_table;
- }
+ 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 ){
- if( noErr ){
- sqlite3ErrorClear(pParse);
- }
- goto exit_drop_table;
- }
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ if( pTab==0 ) goto exit_drop_table;
+ iDb = pTab->iDb;
assert( iDb>=0 && iDbnDb );
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code;
- const char *zTab = SCHEMA_TABLE(iDb);
- const char *zDb = db->aDb[iDb].zName;
+ 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( !OMIT_TEMPDB && iDb==1 ){
+ if( iDb==1 ){
code = SQLITE_DROP_TEMP_VIEW;
}else{
code = SQLITE_DROP_VIEW;
}
}else{
- if( !OMIT_TEMPDB && iDb==1 ){
+ if( iDb==1 ){
code = SQLITE_DROP_TEMP_TABLE;
}else{
code = SQLITE_DROP_TABLE;
}
}
@@ -1886,11 +1857,11 @@
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
goto exit_drop_table;
}
}
#endif
- if( pTab->readOnly || pTab==db->aDb[iDb].pSchema->pSeqTab ){
+ 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
@@ -1911,21 +1882,21 @@
** 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->pSchema==pTab->pSchema ||
- pTrigger->pSchema==db->aDb[1].pSchema );
+ assert( pTrigger->iDb==iDb || pTrigger->iDb==1 );
sqlite3DropTriggerPtr(pParse, pTrigger, 1);
pTrigger = pTrigger->pNext;
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
@@ -2117,52 +2088,51 @@
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 */
- KeyInfo *pKey; /* KeyInfo for index */
- int iDb = sqlite3SchemaToIndex(pParse->db, pIndex->pSchema);
+ int isUnique; /* True for a unique index */
#ifndef SQLITE_OMIT_AUTHORIZATION
if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
- pParse->db->aDb[iDb].zName ) ){
+ 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;
}
-#endif
-
- /* Require a write-lock on the table to perform this operation */
- sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
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, iDb);
+ sqlite3VdbeAddOp(v, OP_Clear, tnum, pIndex->iDb);
}
- sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
- pKey = sqlite3IndexKeyinfo(pParse, pIndex);
- sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum, (char *)pKey, P3_KEYINFO_HANDOFF);
- sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
+ 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);
- if( pIndex->onError!=OE_None ){
- int curaddr = sqlite3VdbeCurrentAddr(v);
- int addr2 = curaddr+4;
- sqlite3VdbeChangeP2(v, curaddr-1, addr2);
- sqlite3VdbeAddOp(v, OP_Rowid, iTab, 0);
- sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
- sqlite3VdbeAddOp(v, OP_IsUnique, iIdx, addr2);
- sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort,
- "indexed columns are not unique", P3_STATIC);
- assert( addr2==sqlite3VdbeCurrentAddr(v) );
- }
- sqlite3VdbeAddOp(v, OP_IdxInsert, iIdx, 0);
+ 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);
- sqlite3VdbeJumpHere(v, addr1);
+ sqlite3VdbeChangeP2(v, addr1, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeAddOp(v, OP_Close, iTab, 0);
sqlite3VdbeAddOp(v, OP_Close, iIdx, 0);
}
/*
@@ -2183,34 +2153,25 @@
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 */
- int sortOrder, /* Sort order of primary key when pList==NULL */
- int ifNotExist /* Omit error if index already exists */
+ 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; /* Name of the index */
- int nName; /* Number of characters in zName */
+ 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 sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */
+ 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;
- Db *pDb; /* The specific table containing the indexed database */
- int iDb; /* Index of the database that is being written */
- Token *pName = 0; /* Unqualified name of the index to create */
- struct ExprList_item *pListItem; /* For looping over pList */
- int nCol;
- int nExtra = 0;
- char *zExtra;
-
- if( pParse->nErr || sqlite3ThreadDataReadOnly()->mallocFailed ){
- goto exit_create_index;
- }
+
+ 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 ){
@@ -2221,38 +2182,32 @@
*/
assert( pName1 && pName2 );
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
if( iDb<0 ) goto exit_create_index;
-#ifndef SQLITE_OMIT_TEMPDB
/* 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->pSchema==db->aDb[1].pSchema ){
+ if( pName2 && pName2->n==0 && pTab && pTab->iDb==1 ){
iDb = 1;
}
-#endif
if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
sqlite3FixSrcList(&sFix, pTblName)
){
- /* Because the parser constructs pTblName from a single identifier,
- ** sqlite3FixSrcList can never fail. */
- assert(0);
+ goto exit_create_index;
}
pTab = sqlite3LocateTable(pParse, pTblName->a[0].zName,
pTblName->a[0].zDatabase);
if( !pTab ) goto exit_create_index;
- assert( db->aDb[iDb].pSchema==pTab->pSchema );
+ assert( iDb==pTab->iDb );
}else{
assert( pName==0 );
- pTab = pParse->pNewTable;
- if( !pTab ) goto exit_create_index;
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ pTab = pParse->pNewTable;
+ iDb = pTab->iDb;
}
- pDb = &db->aDb[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;
@@ -2261,10 +2216,11 @@
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.
**
@@ -2283,18 +2239,18 @@
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( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){
- if( !ifNotExist ){
- sqlite3ErrorMsg(pParse, "index %s already exists", zName);
- }
+ if( (pISameName = sqlite3FindIndex(db, zName, db->aDb[iDb].zName))!=0 ){
+ sqlite3ErrorMsg(pParse, "index %s already exists", zName);
goto exit_create_index;
}
- if( sqlite3FindTable(db, zName, 0)!=0 ){
+ if( (pTSameName = sqlite3FindTable(db, zName, 0))!=0 ){
sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
goto exit_create_index;
}
}
}else{
@@ -2310,16 +2266,16 @@
/* Check for authorization to create an index.
*/
#ifndef SQLITE_OMIT_AUTHORIZATION
{
- const char *zDb = pDb->zName;
- if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){
+ 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( !OMIT_TEMPDB && iDb==1 ) i = SQLITE_CREATE_TEMP_INDEX;
+ if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
if( sqlite3AuthCheck(pParse, i, zName, pTab->zName, zDb) ){
goto exit_create_index;
}
}
#endif
@@ -2327,101 +2283,59 @@
/* 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 = (u8*)pTab->aCol[pTab->nCol-1].zName;
- nullId.n = strlen((char*)nullId.z);
+ 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;
- pList->a[0].sortOrder = sortOrder;
- }
-
- /* Figure out how many bytes of space are required to store explicitly
- ** specified collation sequence names.
- */
- for(i=0; inExpr; i++){
- Expr *pExpr = pList->a[i].pExpr;
- if( pExpr ){
- nExtra += (1 + strlen(pExpr->pColl->zName));
- }
}
/*
** Allocate the index structure.
*/
- nName = strlen(zName);
- nCol = pList->nExpr;
- pIndex = sqliteMalloc(
- sizeof(Index) + /* Index structure */
- sizeof(int)*nCol + /* Index.aiColumn */
- sizeof(int)*(nCol+1) + /* Index.aiRowEst */
- sizeof(char *)*nCol + /* Index.azColl */
- sizeof(u8)*nCol + /* Index.aSortOrder */
- nName + 1 + /* Index.zName */
- nExtra /* Collation sequence names */
- );
- if( sqlite3ThreadDataReadOnly()->mallocFailed ) goto exit_create_index;
- pIndex->aiColumn = (int *)(&pIndex[1]);
- pIndex->aiRowEst = (int *)(&pIndex->aiColumn[nCol]);
- pIndex->azColl = (char **)(&pIndex->aiRowEst[nCol+1]);
- pIndex->aSortOrder = (u8 *)(&pIndex->azColl[nCol]);
- pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]);
- zExtra = (char *)(&pIndex->zName[nName+1]);
+ 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->pSchema = db->aDb[iDb].pSchema;
-
- /* Check to see if we should honor DESC requests on index columns
- */
- if( pDb->pSchema->file_format>=4 ){
- sortOrderMask = -1; /* Honor DESC */
- }else{
- sortOrderMask = 0; /* Ignore DESC */
- }
+ 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, pListItem=pList->a; inExpr; i++, pListItem++){
- const char *zColName = pListItem->zName;
- Column *pTabCol;
- int requestedSortOrder;
- char *zColl; /* Collation sequence */
-
- for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){
- if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
+ for(i=0; inExpr; i++){
+ for(j=0; jnCol; 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, zColName);
+ pTab->zName, pList->a[i].zName);
goto exit_create_index;
}
pIndex->aiColumn[i] = j;
- if( pListItem->pExpr ){
- assert( pListItem->pExpr->pColl );
- zColl = zExtra;
- strcpy(zExtra, pListItem->pExpr->pColl->zName);
- zExtra += (strlen(zColl) + 1);
+ if( pList->a[i].pExpr ){
+ assert( pList->a[i].pExpr->pColl );
+ pIndex->keyInfo.aColl[i] = pList->a[i].pExpr->pColl;
}else{
- zColl = pTab->aCol[j].zColl;
- if( !zColl ){
- zColl = db->pDfltColl->zName;
- }
+ pIndex->keyInfo.aColl[i] = pTab->aCol[j].pColl;
}
- if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl, -1) ){
+ assert( pIndex->keyInfo.aColl[i] );
+ if( !db->init.busy &&
+ sqlite3CheckCollSeq(pParse, pIndex->keyInfo.aColl[i])
+ ){
goto exit_create_index;
}
- pIndex->azColl[i] = zColl;
- requestedSortOrder = pListItem->sortOrder & sortOrderMask;
- pIndex->aSortOrder[i] = requestedSortOrder;
}
- sqlite3DefaultRowEst(pIndex);
+ 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.
@@ -2442,15 +2356,12 @@
assert( pIdx->autoIndex );
assert( pIndex->onError!=OE_None );
if( pIdx->nColumn!=pIndex->nColumn ) continue;
for(k=0; knColumn; k++){
- const char *z1 = pIdx->azColl[k];
- const char *z2 = pIndex->azColl[k];
if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break;
- if( pIdx->aSortOrder[k]!=pIndex->aSortOrder[k] ) break;
- if( z1!=z2 && sqlite3StrICmp(z1, z2) ) 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.
@@ -2475,11 +2386,11 @@
/* Link the new Index structure to its table and to the other
** in-memory database structures.
*/
if( db->init.busy ){
Index *p;
- p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
+ 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;
}
@@ -2510,11 +2421,10 @@
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);
@@ -2524,11 +2434,11 @@
*/
if( pStart && pEnd ){
/* A named index with an explicit CREATE INDEX statement */
zStmt = sqlite3MPrintf("CREATE%s INDEX %.*s",
onError==OE_None ? "" : " UNIQUE",
- pEnd->z - pName->z + 1,
+ 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;
@@ -2588,107 +2498,53 @@
sqlite3SrcListDelete(pTblName);
sqliteFree(zName);
return;
}
-/*
-** Generate code to make sure the file format number is at least minFormat.
-** The generated code will increase the file format number if necessary.
-*/
-void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){
- Vdbe *v;
- v = sqlite3GetVdbe(pParse);
- if( v ){
- sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1);
- sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0);
- sqlite3VdbeAddOp(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3);
- sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0);
- sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1);
- }
-}
-
-/*
-** Fill the Index.aiRowEst[] array with default information - information
-** to be used when we have not run the ANALYZE command.
-**
-** aiRowEst[0] is suppose to contain the number of elements in the index.
-** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the
-** number of rows in the table that match any particular value of the
-** first column of the index. aiRowEst[2] is an estimate of the number
-** of rows that match any particular combiniation of the first 2 columns
-** of the index. And so forth. It must always be the case that
-*
-** aiRowEst[N]<=aiRowEst[N-1]
-** aiRowEst[N]>=1
-**
-** Apart from that, we have little to go on besides intuition as to
-** how aiRowEst[] should be initialized. The numbers generated here
-** are based on typical values found in actual indices.
-*/
-void sqlite3DefaultRowEst(Index *pIdx){
- unsigned *a = pIdx->aiRowEst;
- int i;
- assert( a!=0 );
- a[0] = 1000000;
- for(i=pIdx->nColumn; i>=1; i--){
- a[i] = 10;
- }
- if( pIdx->onError!=OE_None ){
- a[pIdx->nColumn] = 1;
- }
-}
-
/*
** This routine will drop an existing named index. This routine
** implements the DROP INDEX statement.
*/
-void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
+void sqlite3DropIndex(Parse *pParse, SrcList *pName){
Index *pIndex;
Vdbe *v;
sqlite3 *db = pParse->db;
- int iDb;
- if( pParse->nErr || sqlite3ThreadDataReadOnly()->mallocFailed ){
- goto exit_drop_index;
- }
+ if( pParse->nErr || sqlite3_malloc_failed ) return;
assert( pName->nSrc==1 );
- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
- goto exit_drop_index;
- }
+ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) return;
pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
if( pIndex==0 ){
- if( !ifExists ){
- sqlite3ErrorMsg(pParse, "no such index: %S", pName, 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;
}
- iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_DROP_INDEX;
Table *pTab = pIndex->pTable;
- const char *zDb = db->aDb[iDb].zName;
- const char *zTab = SCHEMA_TABLE(iDb);
+ 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( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_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
);
@@ -2699,97 +2555,36 @@
exit_drop_index:
sqlite3SrcListDelete(pName);
}
-/*
-** ppArray points into a structure where there is an array pointer
-** followed by two integers. The first integer is the
-** number of elements in the structure array. The second integer
-** is the number of allocated slots in the array.
-**
-** In other words, the structure looks something like this:
-**
-** struct Example1 {
-** struct subElem *aEntry;
-** int nEntry;
-** int nAlloc;
-** }
-**
-** The pnEntry parameter points to the equivalent of Example1.nEntry.
-**
-** This routine allocates a new slot in the array, zeros it out,
-** and returns its index. If malloc fails a negative number is returned.
-**
-** szEntry is the sizeof of a single array entry. initSize is the
-** number of array entries allocated on the initial allocation.
-*/
-int sqlite3ArrayAllocate(void **ppArray, int szEntry, int initSize){
- char *p;
- int *an = (int*)&ppArray[1];
- if( an[0]>=an[1] ){
- void *pNew;
- int newSize;
- newSize = an[1]*2 + initSize;
- pNew = sqliteRealloc(*ppArray, newSize*szEntry);
- if( pNew==0 ){
- return -1;
- }
- an[1] = newSize;
- *ppArray = pNew;
- }
- p = *ppArray;
- memset(&p[an[0]*szEntry], 0, szEntry);
- return an[0]++;
-}
-
/*
** 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){
- int i;
if( pList==0 ){
pList = sqliteMalloc( sizeof(IdList) );
if( pList==0 ) return 0;
pList->nAlloc = 0;
}
- i = sqlite3ArrayAllocate((void**)&pList->a, sizeof(pList->a[0]), 5);
- if( i<0 ){
- sqlite3IdListDelete(pList);
- return 0;
- }
- pList->a[i].zName = sqlite3NameFromToken(pToken);
- return pList;
-}
-
-/*
-** Delete an IdList.
-*/
-void sqlite3IdListDelete(IdList *pList){
- int i;
- if( pList==0 ) return;
- for(i=0; inId; 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; inId; i++){
- if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i;
- }
- return -1;
+ 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.
@@ -2854,18 +2649,15 @@
** Assign cursors to all tables in a SrcList
*/
void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
struct SrcList_item *pItem;
- assert(pList || sqlite3ThreadDataReadOnly()->mallocFailed);
- if( pList ){
- for(i=0, pItem=pList->a; inSrc; i++, pItem++){
- if( pItem->iCursor>=0 ) break;
- pItem->iCursor = pParse->nTab++;
- if( pItem->pSelect ){
- sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
- }
+ for(i=0, pItem=pList->a; inSrc; i++, pItem++){
+ if( pItem->iCursor>=0 ) break;
+ pItem->iCursor = pParse->nTab++;
+ if( pItem->pSelect ){
+ sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
}
}
}
/*
@@ -2874,10 +2666,36 @@
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; inId; 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; inId; 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){
@@ -2886,11 +2704,13 @@
if( pList==0 ) return;
for(pItem=pList->a, i=0; inSrc; i++, pItem++){
sqliteFree(pItem->zDatabase);
sqliteFree(pItem->zName);
sqliteFree(pItem->zAlias);
- sqlite3DeleteTable(0, pItem->pTab);
+ if( pItem->pTab && pItem->pTab->isTransient ){
+ sqlite3DeleteTable(0, pItem->pTab);
+ }
sqlite3SelectDelete(pItem->pSelect);
sqlite3ExprDelete(pItem->pOn);
sqlite3IdListDelete(pItem->pUsing);
}
sqliteFree(pList);
@@ -2903,11 +2723,11 @@
sqlite3 *db;
Vdbe *v;
int i;
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
- if( pParse->nErr || sqlite3ThreadDataReadOnly()->mallocFailed ) 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 ){
@@ -2924,11 +2744,11 @@
void sqlite3CommitTransaction(Parse *pParse){
sqlite3 *db;
Vdbe *v;
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
- if( pParse->nErr || sqlite3ThreadDataReadOnly()->mallocFailed ) 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);
@@ -2941,11 +2761,11 @@
void sqlite3RollbackTransaction(Parse *pParse){
sqlite3 *db;
Vdbe *v;
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
- if( pParse->nErr || sqlite3ThreadDataReadOnly()->mallocFailed ) 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);
@@ -2973,11 +2793,10 @@
"the temporary database file");
pParse->rc = rc;
return 1;
}
}
- assert( db->aDb[1].pSchema );
}
return 0;
}
/*
@@ -3018,12 +2837,12 @@
assert( db->aDb[iDb].pBt!=0 || iDb==1 );
assert( iDb<32 );
mask = 1<cookieMask & mask)==0 ){
pParse->cookieMask |= mask;
- pParse->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
- if( !OMIT_TEMPDB && iDb==1 ){
+ pParse->cookieValue[iDb] = db->aDb[iDb].schema_cookie;
+ if( iDb==1 ){
sqlite3OpenTempDatabase(pParse);
}
}
}
}
@@ -3052,27 +2871,39 @@
sqlite3CodeVerifySchema(pParse, iDb);
pParse->writeMask |= 1<nested==0 ){
sqlite3VdbeAddOp(v, OP_Statement, iDb, 0);
}
- if( (OMIT_TEMPDB || iDb!=1) && pParse->db->aDb[1].pBt!=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(const char *zColl, Index *pIndex){
- int i;
- for(i=0; inColumn; i++){
- const char *z = pIndex->azColl[i];
- if( z==zColl || (z && zColl && 0==sqlite3StrICmp(z, zColl)) ){
- return 1;
- }
+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
@@ -3079,17 +2910,16 @@
/*
** Recompute all indices of pTab that use the collating sequence pColl.
** If pColl==0 then recompute all indices of pTab.
*/
#ifndef SQLITE_OMIT_REINDEX
-static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
+void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){
Index *pIndex; /* An index associated with pTab */
for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
- if( zColl==0 || collationMatch(zColl, pIndex) ){
- int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- sqlite3BeginWriteOperation(pParse, 0, iDb);
+ if( pColl==0 || collationMatch(pColl,pIndex) ){
+ sqlite3BeginWriteOperation(pParse, 0, pTab->iDb);
sqlite3RefillIndex(pParse, pIndex, -1);
}
}
}
#endif
@@ -3098,22 +2928,22 @@
** 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
-static void reindexDatabases(Parse *pParse, char const *zColl){
+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; iDbnDb; iDb++, pDb++){
if( pDb==0 ) continue;
- for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){
+ for(k=sqliteHashFirst(&pDb->tblHash); k; k=sqliteHashNext(k)){
pTab = (Table*)sqliteHashData(k);
- reindexTable(pParse, pTab, zColl);
+ reindexTable(pParse, pTab, pColl);
}
}
}
#endif
@@ -3149,18 +2979,13 @@
if( pName1==0 || pName1->z==0 ){
reindexDatabases(pParse, 0);
return;
}else if( pName2==0 || pName2->z==0 ){
- assert( pName1->z );
- pColl = sqlite3FindCollSeq(db, ENC(db), (char*)pName1->z, pName1->n, 0);
+ pColl = sqlite3FindCollSeq(db, db->enc, pName1->z, pName1->n, 0);
if( pColl ){
- char *z = sqliteStrNDup(pName1->z, pName1->n);
- if( z ){
- reindexDatabases(pParse, z);
- sqliteFree(z);
- }
+ reindexDatabases(pParse, pColl);
return;
}
}
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName);
if( iDb<0 ) return;
@@ -3180,40 +3005,5 @@
return;
}
sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed");
}
#endif
-
-/*
-** Return a dynamicly allocated KeyInfo structure that can be used
-** with OP_OpenRead or OP_OpenWrite to access database index pIdx.
-**
-** If successful, a pointer to the new structure is returned. In this case
-** the caller is responsible for calling sqliteFree() on the returned
-** pointer. If an error occurs (out of memory or missing collation
-** sequence), NULL is returned and the state of pParse updated to reflect
-** the error.
-*/
-KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
- int i;
- int nCol = pIdx->nColumn;
- int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol;
- KeyInfo *pKey = (KeyInfo *)sqliteMalloc(nBytes);
-
- if( pKey ){
- pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]);
- assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) );
- for(i=0; iazColl[i];
- assert( zColl );
- pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl, -1);
- pKey->aSortOrder[i] = pIdx->aSortOrder[i];
- }
- pKey->nField = nCol;
- }
-
- if( pParse->nErr ){
- sqliteFree(pKey);
- pKey = 0;
- }
- return pKey;
-}
DELETED SQLite.Interop/src/callback.c
Index: SQLite.Interop/src/callback.c
==================================================================
--- SQLite.Interop/src/callback.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
-** 2005 May 23
-**
-** 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 functions used to access the internal hash tables
-** of user defined functions and collation sequences.
-**
-** $Id: callback.c,v 1.11 2006/01/16 15:51:47 rmsimpson Exp $
-*/
-
-#include "sqliteInt.h"
-
-/*
-** 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)ENC(db), zExternal);
- sqliteFree(zExternal);
- }
-#ifndef SQLITE_OMIT_UTF16
- if( db->xCollNeeded16 ){
- char const *zExternal;
- sqlite3_value *pTmp = sqlite3ValueNew();
- sqlite3ValueSetStr(pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC);
- zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE);
- if( zExternal ){
- db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal);
- }
- sqlite3ValueFree(pTmp);
- }
-#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(sqlite3 *db, CollSeq *pColl){
- CollSeq *pColl2;
- char *z = pColl->zName;
- int n = strlen(z);
- 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;
- }
- }
- return SQLITE_ERROR;
-}
-
-/*
-** This function is responsible for invoking the collation factory callback
-** or substituting a collation sequence of a different encoding when the
-** requested collation sequence is not available in the database native
-** encoding.
-**
-** If it is not NULL, then pColl must point to the database native encoding
-** collation sequence with name zName, length nName.
-**
-** The return value is either the collation sequence to be used in database
-** db for collation type name zName, length nName, or NULL, if no collation
-** sequence can be found.
-*/
-CollSeq *sqlite3GetCollSeq(
- sqlite3* db,
- CollSeq *pColl,
- const char *zName,
- int nName
-){
- CollSeq *p;
-
- p = pColl;
- if( !p ){
- p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0);
- }
- if( !p || !p->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(db, zName, nName);
- p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0);
- }
- if( p && !p->xCmp && synthCollSeq(db, p) ){
- p = 0;
- }
- assert( !p || p->xCmp );
- return p;
-}
-
-/*
-** 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 ){
- const char *zName = pColl->zName;
- CollSeq *p = sqlite3GetCollSeq(pParse->db, pColl, zName, -1);
- if( !p ){
- if( pParse->nErr==0 ){
- sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
- }
- pParse->nErr++;
- return SQLITE_ERROR;
- }
- assert( p==pColl );
- }
- return SQLITE_OK;
-}
-
-
-
-/*
-** 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 ){
- CollSeq *pDel = 0;
- 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;
- pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);
-
- /* If a malloc() failure occured in sqlite3HashInsert(), it will
- ** return the pColl pointer to be deleted (because it wasn't added
- ** to the hash table).
- */
- assert( !pDel ||
- (sqlite3ThreadDataReadOnly()->mallocFailed && pDel==pColl) );
- sqliteFree(pDel);
- }
- }
- 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;
- if( zName ){
- pColl = findCollSeqEntry(db, zName, nName, create);
- }else{
- pColl = db->pDfltColl;
- }
- assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
- assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
- if( pColl ) pColl += enc-1;
- return pColl;
-}
-
-/*
-** 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))!=0 ){
- pBest->nArg = nArg;
- pBest->pNext = pFirst;
- 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;
-}
DELETED SQLite.Interop/src/complete.c
Index: SQLite.Interop/src/complete.c
==================================================================
--- SQLite.Interop/src/complete.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
-** 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.
-**
-*************************************************************************
-** An tokenizer for SQL
-**
-** This file contains C code that implements the sqlite3_complete() API.
-** This code used to be part of the tokenizer.c source file. But by
-** separating it out, the code will be automatically omitted from
-** static links that do not use it.
-**
-** $Id: complete.c,v 1.9 2006/01/16 15:51:47 rmsimpson Exp $
-*/
-#include "sqliteInt.h"
-#ifndef SQLITE_OMIT_COMPLETE
-
-/*
-** This is defined in tokenize.c. We just have to import the definition.
-*/
-extern const char sqlite3IsIdChar[];
-#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsIdChar[c-0x20]))
-
-
-/*
-** 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 '`': /* Grave-accent quoted symbols used by MySQL */
- 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);
- }else if( zSql ){
- rc = SQLITE_NOMEM;
- sqlite3MallocClearFailed();
- }
- sqlite3ValueFree(pVal);
- return rc;
-}
-#endif /* SQLITE_OMIT_UTF16 */
-#endif /* SQLITE_OMIT_COMPLETE */
ADDED SQLite.Interop/src/config.h
Index: SQLite.Interop/src/config.h
==================================================================
--- /dev/null
+++ SQLite.Interop/src/config.h
@@ -0,0 +1,1 @@
+#define SQLITE_PTR_SZ 4
Index: SQLite.Interop/src/date.c
==================================================================
--- SQLite.Interop/src/date.c
+++ SQLite.Interop/src/date.c
@@ -14,11 +14,11 @@
**
** 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.16 2006/01/16 15:51:47 rmsimpson Exp $
+** $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
@@ -103,32 +103,34 @@
nextC = va_arg(ap, int);
pVal = va_arg(ap, int*);
val = 0;
while( N-- ){
if( !isdigit(*(u8*)zDate) ){
- goto end_getDigits;
+ return cnt;
}
val = val*10 + *zDate - '0';
zDate++;
}
if( valmax || (nextC!=0 && nextC!=*zDate) ){
- goto end_getDigits;
+ return cnt;
}
*pVal = val;
zDate++;
cnt++;
}while( nextC );
- va_end(ap);
-end_getDigits:
return cnt;
}
/*
** Read text from z[] and convert into a floating point number. Return
** the number of digits converted.
*/
-#define getValue sqlite3AtoF
+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:
**
@@ -236,11 +238,11 @@
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->rJD += p->tz*60/86400.0;
p->validHMS = 0;
p->validTZ = 0;
}
}
}
@@ -268,11 +270,11 @@
}
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) || 'T'==*(u8*)zDate ){ zDate++; }
+ while( isspace(*(u8*)zDate) ){ zDate++; }
if( parseHhMmSs(zDate, p)==0 ){
/* We got the time */
}else if( *zDate==0 ){
p->validHMS = 0;
}else{
@@ -316,11 +318,11 @@
sqlite3OsCurrentTime(&r);
p->rJD = r;
p->validJD = 1;
return 0;
}else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){
- getValue(zDate, &p->rJD);
+ p->rJD = sqlite3AtoF(zDate, 0);
p->validJD = 1;
return 0;
}
return 1;
}
@@ -639,14 +641,14 @@
*/
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((char*)sqlite3_value_text(argv[0]), p) ) return 1;
+ parseDateOrTime(sqlite3_value_text(argv[0]), p) ) return 1;
for(i=1; ia; inSrc; i++, pItem++){
pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase);
- sqlite3DeleteTable(pParse->db, pItem->pTab);
pItem->pTab = pTab;
- if( pTab ){
- pTab->nRef++;
- }
}
return pTab;
}
/*
@@ -57,23 +53,18 @@
}
/*
** Generate code that will open a table for reading.
*/
-void sqlite3OpenTable(
- Parse *p, /* Generate code into this VDBE */
+void sqlite3OpenTableForReading(
+ Vdbe *v, /* Generate code into this VDBE */
int iCur, /* The cursor number of the table */
- int iDb, /* The database index in sqlite3.aDb[] */
- Table *pTab, /* The table to be opened */
- int opcode /* OP_OpenRead or OP_OpenWrite */
+ Table *pTab /* The table to be opened */
){
- Vdbe *v = sqlite3GetVdbe(p);
- assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
- sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName);
- sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
+ sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
+ sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
VdbeComment((v, "# %s", pTab->zName));
- sqlite3VdbeAddOp(v, opcode, iCur, pTab->tnum);
sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol);
}
/*
@@ -98,19 +89,19 @@
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 */
- int iDb;
#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 || sqlite3ThreadDataReadOnly()->mallocFailed ){
+ if( pParse->nErr || sqlite3_malloc_failed ){
+ pTabList = 0;
goto delete_from_cleanup;
}
db = pParse->db;
assert( pTabList->nSrc==1 );
@@ -138,13 +129,12 @@
#endif
if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
goto delete_from_cleanup;
}
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- assert( iDbnDb );
- zDb = db->aDb[iDb].zName;
+ assert( pTab->iDbnDb );
+ 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.
@@ -181,18 +171,18 @@
v = sqlite3GetVdbe(pParse);
if( v==0 ){
goto delete_from_cleanup;
}
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
- sqlite3BeginWriteOperation(pParse, triggers_exist, iDb);
+ sqlite3BeginWriteOperation(pParse, triggers_exist, pTab->iDb);
- /* If we are trying to delete from a view, realize that view into
- ** a ephemeral table.
+ /* 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_VirtualTab, iCur, 0, 0, 0, 0);
+ 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.
@@ -210,43 +200,46 @@
/* If counting rows deleted, just count the total number of
** entries in the table. */
int endOfLoop = sqlite3VdbeMakeLabel(v);
int addr;
if( !isView ){
- sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
+ 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, iDb);
- if( !pParse->nested ){
- sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
- }
+ sqlite3VdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb);
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- assert( pIdx->pSchema==pTab->pSchema );
- sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, iDb);
+ 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);
+ 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_Rowid, iCur, 0);
- sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
+ 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.
@@ -262,47 +255,48 @@
/* 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_FifoRead, 0, end);
+ addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
+ sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
if( !isView ){
- sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
- sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
+ sqlite3OpenTableForReading(v, iCur, pTab);
}
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
- sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
+ sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
- sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 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);
+ 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_FifoRead loop because the cursor have to all be closed
+ ** 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_FifoRead, 0, end);
+ addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
}
/* Delete the row */
sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0);
}
@@ -317,16 +311,17 @@
}
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);
+ 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);
@@ -382,14 +377,11 @@
){
int addr;
addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0);
sqlite3GenerateRowIndexDelete(db, v, pTab, iCur, 0);
sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
- if( count ){
- sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
- }
- sqlite3VdbeJumpHere(v, addr);
+ 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.
@@ -435,18 +427,17 @@
int iCur /* Cursor number for the pIdx->pTable table */
){
int j;
Table *pTab = pIdx->pTable;
- sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
+ sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
for(j=0; jnColumn; j++){
int idx = pIdx->aiColumn[j];
if( idx==pTab->iPKey ){
sqlite3VdbeAddOp(v, OP_Dup, j, 0);
}else{
sqlite3VdbeAddOp(v, OP_Column, iCur, idx);
- sqlite3ColumnDefault(v, pTab, idx);
}
}
- sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0);
+ sqlite3VdbeAddOp(v, OP_MakeRecord, pIdx->nColumn, (1<<24));
sqlite3IndexAffinityStr(v, pIdx);
}
DELETED SQLite.Interop/src/experimental.c
Index: SQLite.Interop/src/experimental.c
==================================================================
--- SQLite.Interop/src/experimental.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-** 2005 January 20
-**
-** 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 C code routines that are not a part of the official
-** SQLite API. These routines are unsupported.
-**
-** $Id: experimental.c,v 1.5 2006/01/16 15:51:47 rmsimpson Exp $
-*/
-#include "sqliteInt.h"
-
-/*
-** Set all the parameters in the compiled SQL statement to NULL.
-*/
-int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
- int i;
- int rc = SQLITE_OK;
- for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){
- rc = sqlite3_bind_null(pStmt, i);
- }
- return rc;
-}
-
-/*
-** Sleep for a little while. Return the amount of time slept.
-*/
-int sqlite3_sleep(int ms){
- return sqlite3OsSleep(ms);
-}
Index: SQLite.Interop/src/expr.c
==================================================================
--- SQLite.Interop/src/expr.c
+++ SQLite.Interop/src/expr.c
@@ -10,11 +10,11 @@
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.22 2006/01/16 15:51:47 rmsimpson Exp $
+** $Id: expr.c,v 1.1 2005/03/01 16:04:29 rmsimpson Exp $
*/
#include "sqliteInt.h"
#include
/*
@@ -32,22 +32,16 @@
** 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){
- int op = pExpr->op;
- if( op==TK_AS ){
+ if( pExpr->op==TK_AS ){
return sqlite3ExprAffinity(pExpr->pLeft);
}
- if( op==TK_SELECT ){
+ if( pExpr->op==TK_SELECT ){
return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].pExpr);
}
-#ifndef SQLITE_OMIT_CAST
- if( op==TK_CAST ){
- return sqlite3AffinityType(&pExpr->token);
- }
-#endif
return pExpr->affinity;
}
/*
** Return the default collation sequence for the expression pExpr. If
@@ -55,11 +49,11 @@
*/
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
CollSeq *pColl = 0;
if( pExpr ){
pColl = pExpr->pColl;
- if( (pExpr->op==TK_AS || pExpr->op==TK_CAST) && !pColl ){
+ if( pExpr->op==TK_AS && !pColl ){
return sqlite3ExprCollSeq(pParse, pExpr->pLeft);
}
}
if( sqlite3CheckCollSeq(pParse, pColl) ){
pColl = 0;
@@ -73,26 +67,28 @@
** 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
- ** affinity, use that. Otherwise use no affinity.
+ /* Both sides of the comparison are columns. If one has numeric or
+ ** integer affinity, use that. Otherwise use no affinity.
*/
- if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){
+ 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. */
- assert( aff1==0 || aff2==0 );
return (aff1 + aff2);
}
}
/*
@@ -124,18 +120,15 @@
** 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);
- switch( aff ){
- case SQLITE_AFF_NONE:
- return 1;
- case SQLITE_AFF_TEXT:
- return idx_affinity==SQLITE_AFF_TEXT;
- default:
- return sqlite3IsNumericAffinity(idx_affinity);
- }
+ 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.
@@ -143,11 +136,11 @@
** 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))+(jumpIfNull?0x100:0);
+ 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.
@@ -188,16 +181,11 @@
*/
Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){
Expr *pNew;
pNew = sqliteMalloc( sizeof(Expr) );
if( pNew==0 ){
- /* When malloc fails, delete pLeft and pRight. Expressions passed to
- ** this function must always be allocated with sqlite3Expr() for this
- ** reason.
- */
- sqlite3ExprDelete(pLeft);
- sqlite3ExprDelete(pRight);
+ /* When malloc fails, we leak memory from pLeft and pRight */
return 0;
}
pNew->op = op;
pNew->pLeft = pLeft;
pNew->pRight = pRight;
@@ -212,12 +200,13 @@
}
/*
** 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" means the top of the stack.
-** "#1" means the next down on the stack. And so forth.
+** 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.
@@ -224,23 +213,27 @@
*/
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;
}
- if( v==0 ) return 0;
p = sqlite3Expr(TK_REGISTER, 0, 0, pToken);
if( p==0 ){
return 0; /* Malloc failed */
}
- depth = atoi((char*)&pToken->z[1]);
- p->iTable = pParse->nMem++;
- sqlite3VdbeAddOp(v, OP_Dup, depth, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1);
+ 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
@@ -261,15 +254,15 @@
** text between the two given tokens.
*/
void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){
assert( pRight!=0 );
assert( pLeft!=0 );
- if( !sqlite3ThreadDataReadOnly()->mallocFailed && pRight->z && pLeft->z ){
+ 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 + (pRight->z - pLeft->z);
+ pExpr->span.n = pRight->n + Addr(pRight->z) - Addr(pLeft->z);
}else{
pExpr->span.z = 0;
}
}
}
@@ -280,11 +273,11 @@
*/
Expr *sqlite3ExprFunction(ExprList *pList, Token *pToken){
Expr *pNew;
pNew = sqliteMalloc( sizeof(Expr) );
if( pNew==0 ){
- sqlite3ExprListDelete(pList); /* Avoid leaking memory when malloc fails */
+ /* sqlite3ExprListDelete(pList); // Leak pList when malloc fails */
return 0;
}
pNew->op = TK_FUNCTION;
pNew->pList = pList;
if( pToken ){
@@ -325,11 +318,11 @@
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((char*)&pToken->z[1]);
+ 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 ){
@@ -353,14 +346,14 @@
}
if( i>=pParse->nVarExpr ){
pExpr->iTable = ++pParse->nVar;
if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){
pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10;
- sqliteReallocOrFree((void**)&pParse->apVarExpr,
+ pParse->apVarExpr = sqliteRealloc(pParse->apVarExpr,
pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) );
}
- if( !sqlite3ThreadDataReadOnly()->mallocFailed ){
+ if( !sqlite3_malloc_failed ){
assert( pParse->apVarExpr!=0 );
pParse->apVarExpr[pParse->nVarExpr++] = pExpr;
}
}
}
@@ -378,25 +371,10 @@
sqlite3ExprListDelete(p->pList);
sqlite3SelectDelete(p->pSelect);
sqliteFree(p);
}
-/*
-** The Expr.token field might be a string literal that is quoted.
-** If so, remove the quotation marks.
-*/
-void sqlite3DequoteExpr(Expr *p){
- if( ExprHasAnyProperty(p, EP_Dequoted) ){
- return;
- }
- ExprSetProperty(p, EP_Dequoted);
- if( p->token.dyn==0 ){
- sqlite3TokenCopy(&p->token, &p->token);
- }
- sqlite3Dequote((char*)p->token.z);
-}
-
/*
** 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)
@@ -413,28 +391,27 @@
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 = (u8*)sqliteStrNDup((char*)p->token.z, p->token.n);
+ 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);
- pNew->pTab = p->pTab;
return pNew;
}
void sqlite3TokenCopy(Token *pTo, Token *pFrom){
if( pTo->dyn ) sqliteFree((char*)pTo->z);
if( pFrom->z ){
pTo->n = pFrom->n;
- pTo->z = (u8*)sqliteStrNDup((char*)pFrom->z, pFrom->n);
+ pTo->z = sqliteStrNDup(pFrom->z, pFrom->n);
pTo->dyn = 1;
}else{
pTo->z = 0;
}
}
@@ -460,12 +437,11 @@
** 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
- || sqlite3ThreadDataReadOnly()->mallocFailed );
+ || pOldExpr->span.z==0 || sqlite3_malloc_failed );
pItem->zName = sqliteStrDup(pOldItem->zName);
pItem->sortOrder = pOldItem->sortOrder;
pItem->isAgg = pOldItem->isAgg;
pItem->done = 0;
}
@@ -490,19 +466,18 @@
if( pNew==0 ) return 0;
pNew->nSrc = pNew->nAlloc = p->nSrc;
for(i=0; inSrc; i++){
struct SrcList_item *pNewItem = &pNew->a[i];
struct SrcList_item *pOldItem = &p->a[i];
- Table *pTab;
pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase);
pNewItem->zName = sqliteStrDup(pOldItem->zName);
pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias);
pNewItem->jointype = pOldItem->jointype;
pNewItem->iCursor = pOldItem->iCursor;
- pTab = pNewItem->pTab = pOldItem->pTab;
- if( pTab ){
- pTab->nRef++;
+ 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;
@@ -515,14 +490,11 @@
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 ){
- sqliteFree(pNew);
- return 0;
- }
+ if( pNew->a==0 ) return 0;
for(i=0; inId; i++){
struct IdList_item *pNewItem = &pNew->a[i];
struct IdList_item *pOldItem = &p->a[i];
pNewItem->zName = sqliteStrDup(pOldItem->zName);
pNewItem->idx = pOldItem->idx;
@@ -545,18 +517,14 @@
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;
- pNew->usesVirt = 0;
- pNew->disallowOrderBy = 0;
- pNew->pRightmost = 0;
- pNew->addrOpenVirt[0] = -1;
- pNew->addrOpenVirt[1] = -1;
- pNew->addrOpenVirt[2] = -1;
return pNew;
}
#else
Select *sqlite3SelectDup(Select *p){
assert( p==0 );
@@ -571,38 +539,32 @@
*/
ExprList *sqlite3ExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
if( pList==0 ){
pList = sqliteMalloc( sizeof(ExprList) );
if( pList==0 ){
- goto no_mem;
+ /* sqlite3ExprDelete(pExpr); // Leak memory if malloc fails */
+ return 0;
}
assert( pList->nAlloc==0 );
}
if( pList->nAlloc<=pList->nExpr ){
- struct ExprList_item *a;
- int n = pList->nAlloc*2 + 4;
- a = sqliteRealloc(pList->a, n*sizeof(pList->a[0]));
- if( a==0 ){
- goto no_mem;
- }
- pList->a = a;
- pList->nAlloc = n;
+ 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->zName = sqlite3NameFromToken(pName);
pItem->pExpr = pExpr;
+ pItem->zName = sqlite3NameFromToken(pName);
}
return pList;
-
-no_mem:
- /* Avoid leaking memory if malloc has failed. */
- sqlite3ExprDelete(pExpr);
- sqlite3ExprListDelete(pList);
- return 0;
}
/*
** Delete an entire expression list.
*/
@@ -628,12 +590,10 @@
** 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.
-**
-** NOTICE: This routine does *not* descend into subqueries.
*/
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;
@@ -687,39 +647,29 @@
** 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 ){
- /* Consider functions to be constant if all their arguments are constant
- ** and *pArg==2 */
- case TK_FUNCTION:
- if( *((int*)pArg)==2 ) return 0;
- /* Fall through */
case TK_ID:
case TK_COLUMN:
case TK_DOT:
case TK_AGG_FUNCTION:
- case TK_AGG_COLUMN:
+ case TK_FUNCTION:
#ifndef SQLITE_OMIT_SUBQUERY
case TK_SELECT:
case TK_EXISTS:
#endif
*((int*)pArg) = 0;
return 2;
- case TK_IN:
- if( pExpr->pSelect ){
- *((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 or function calls.
+** 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.
*/
@@ -727,35 +677,20 @@
int isConst = 1;
walkExprTree(p, exprNodeIsConstant, &isConst);
return isConst;
}
-/*
-** Walk an expression tree. Return 1 if the expression is constant
-** or a function call with constant arguments. Return and 0 if there
-** are any 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 sqlite3ExprIsConstantOrFunction(Expr *p){
- int isConst = 2;
- walkExprTree(p, exprNodeIsConstant, &isConst);
- return isConst!=0;
-}
-
/*
** 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((char*)p->token.z, pValue) ){
+ if( sqlite3GetInt32(p->token.z, pValue) ){
return 1;
}
break;
}
case TK_UPLUS: {
@@ -808,11 +743,11 @@
**
** 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 */
+ 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 */
@@ -830,23 +765,24 @@
assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
zDb = sqlite3NameFromToken(pDbToken);
zTab = sqlite3NameFromToken(pTableToken);
zCol = sqlite3NameFromToken(pColumnToken);
- if( sqlite3ThreadDataReadOnly()->mallocFailed ){
- goto lookupname_end;
+ if( sqlite3_malloc_failed ){
+ return 1; /* Leak memory (zDb and zTab) if malloc fails */
}
pExpr->iTable = -1;
while( pNC && cnt==0 ){
- ExprList *pEList;
SrcList *pSrcList = pNC->pSrcList;
+ ExprList *pEList = pNC->pEList;
+ pNC->nRef++;
+ /* assert( zTab==0 || pEList==0 ); */
if( pSrcList ){
for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){
Table *pTab = pItem->pTab;
- int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
Column *pCol;
if( pTab==0 ) continue;
assert( pTab->nCol>0 );
if( zTab ){
@@ -854,51 +790,30 @@
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[iDb].zName, zDb)!=0 ){
+ if( zDb!=0 && sqlite3StrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
continue;
}
}
}
if( 0==(cntTab++) ){
pExpr->iTable = pItem->iCursor;
- pExpr->pSchema = pTab->pSchema;
+ pExpr->iDb = pTab->iDb;
pMatch = pItem;
}
for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- const char *zColl = pTab->aCol[j].zColl;
- IdList *pUsing;
cnt++;
pExpr->iTable = pItem->iCursor;
pMatch = pItem;
- pExpr->pSchema = pTab->pSchema;
+ 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 = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
- if( pItem->jointype & JT_NATURAL ){
- /* If this match occurred in the left table of a natural join,
- ** then skip the right table to avoid a duplicate match */
- pItem++;
- i++;
- }
- if( (pUsing = pItem->pUsing)!=0 ){
- /* If this match occurs on a column that is in the USING clause
- ** of a join, skip the search of the right table of the join
- ** to avoid a duplicate match there. */
- int k;
- for(k=0; knId; k++){
- if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
- pItem++;
- i++;
- break;
- }
- }
- }
+ pExpr->pColl = pTab->aCol[j].pColl;
break;
}
}
}
}
@@ -922,20 +837,18 @@
if( pTab ){
int j;
Column *pCol = pTab->aCol;
- pExpr->pSchema = pTab->pSchema;
+ pExpr->iDb = pTab->iDb;
cntTab++;
for(j=0; j < pTab->nCol; j++, pCol++) {
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- const char *zColl = pTab->aCol[j].zColl;
cnt++;
pExpr->iColumn = j==pTab->iPKey ? -1 : j;
pExpr->affinity = pTab->aCol[j].affinity;
- pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
- pExpr->pTab = pTab;
+ pExpr->pColl = pTab->aCol[j].pColl;
break;
}
}
}
}
@@ -960,21 +873,21 @@
** 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 = pNC->pEList)!=0 && zTab==0 ){
+ if( cnt==0 && pEList!=0 && zTab==0 ){
for(j=0; jnExpr; 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);
- cnt = 1;
+ sqliteFree(zCol);
assert( zTab==0 && zDb==0 );
- goto lookupname_end_2;
+ return 0;
}
}
}
/* Advance to the next name context. The loop will exit when either
@@ -989,13 +902,10 @@
** 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.
- **
- ** Because no reference was made to outer contexts, the pNC->nRef
- ** fields are not changed in any context.
*/
if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
sqliteFree(zCol);
return 0;
}
@@ -1007,13 +917,13 @@
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, (char*)0);
+ sqlite3SetString(&z, zDb, ".", zTab, ".", zCol, 0);
}else if( zTab ){
- sqlite3SetString(&z, zTab, ".", zCol, (char*)0);
+ sqlite3SetString(&z, zTab, ".", zCol, 0);
}else{
z = sqliteStrDup(zCol);
}
sqlite3ErrorMsg(pParse, zErr, z);
sqliteFree(z);
@@ -1033,39 +943,67 @@
}
assert( pMatch->iCursor==pExpr->iTable );
pMatch->colUsed |= 1<pLeft);
pExpr->pLeft = 0;
sqlite3ExprDelete(pExpr->pRight);
pExpr->pRight = 0;
pExpr->op = TK_COLUMN;
-lookupname_end_2:
- sqliteFree(zCol);
if( cnt==1 ){
assert( pNC!=0 );
sqlite3AuthRead(pParse, pExpr, pNC->pSrcList);
- if( pMatch && !pMatch->pSelect ){
- pExpr->pTab = pMatch->pTab;
- }
- /* Increment the nRef value on all name contexts from TopNC up to
- ** the point where the name matched. */
- for(;;){
- assert( pTopNC!=0 );
- pTopNC->nRef++;
- if( pTopNC==pNC ) break;
- pTopNC = pTopNC->pNext;
- }
- return 0;
- } else {
- return 1;
+ }
+ 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().
@@ -1089,11 +1027,11 @@
pParse = pNC->pParse;
if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1;
ExprSetProperty(pExpr, EP_Resolved);
#ifndef NDEBUG
- if( pSrcList && pSrcList->nAlloc>0 ){
+ if( pSrcList ){
int i;
for(i=0; inSrc; i++){
assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursornTab);
}
}
@@ -1139,11 +1077,15 @@
return 1;
}
/* Resolve function names
*/
- case TK_CONST_FUNC:
+ 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 */
@@ -1150,14 +1092,13 @@
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 = ENC(pParse->db); /* The database encoding */
+ int enc = pParse->db->enc; /* The database encoding */
- zId = (char*)pExpr->token.z;
- nId = pExpr->token.n;
+ 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;
@@ -1198,31 +1139,17 @@
case TK_EXISTS:
#endif
case TK_IN: {
if( pExpr->pSelect ){
int nRef = pNC->nRef;
-#ifndef SQLITE_OMIT_CHECK
- if( pNC->isCheck ){
- sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
- }
-#endif
sqlite3SelectResolve(pParse, pExpr->pSelect, pNC);
assert( pNC->nRef>=nRef );
if( nRef!=pNC->nRef ){
ExprSetProperty(pExpr, EP_VarSelect);
}
}
- break;
- }
-#ifndef SQLITE_OMIT_CHECK
- case TK_VARIABLE: {
- if( pNC->isCheck ){
- sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
- }
- break;
- }
-#endif
+ }
}
return 0;
}
/*
@@ -1248,23 +1175,15 @@
*/
int sqlite3ExprResolveNames(
NameContext *pNC, /* Namespace to resolve expressions in. */
Expr *pExpr /* The expression to be analyzed. */
){
- int savedHasAgg;
if( pExpr==0 ) return 0;
- savedHasAgg = pNC->hasAgg;
- pNC->hasAgg = 0;
walkExprTree(pExpr, nameResolverStep, pNC);
if( pNC->nErr>0 ){
ExprSetProperty(pExpr, EP_Error);
}
- if( pNC->hasAgg ){
- ExprSetProperty(pExpr, EP_Agg);
- }else if( savedHasAgg ){
- pNC->hasAgg = 1;
- }
return ExprHasProperty(pExpr, EP_Error);
}
/*
** A pointer instance of this structure is used to pass information
@@ -1276,55 +1195,55 @@
NameContext *pNC; /* Namespace of first enclosing query */
};
/*
-** Generate code for scalar subqueries used as an expression
-** and IN operators. Examples:
-**
-** (SELECT a FROM b) -- subquery
-** EXISTS (SELECT a FROM b) -- EXISTS subquery
-** x IN (4,5,11) -- IN operator with list on right-hand side
-** x IN (SELECT a FROM b) -- IN operator with subquery on the right
-**
-** The pExpr parameter describes the expression that contains the IN
-** operator or subquery.
+** 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 testAddr = 0; /* One-time test address */
+ int label = 0; /* Address after sub-select code */
Vdbe *v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
- /* This code must be run in its entirety every time it is encountered
- ** if any of the following is true:
- **
- ** * The right-hand side is a correlated subquery
- ** * The right-hand side is an expression list containing variables
- ** * We are inside a trigger
- **
- ** If all of the above are false, then we can run this code just once
- ** save the results, and reuse the same result on subsequent invocations.
+ /* 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);
- testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0);
- assert( testAddr>0 || sqlite3ThreadDataReadOnly()->mallocFailed );
- sqlite3VdbeAddOp(v, OP_MemInt, 1, mem);
+ 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_OpenVirtual instruction */
+ int addr; /* Address of OP_OpenTemp instruction */
affinity = sqlite3ExprAffinity(pExpr->pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN()'
- ** expression it is handled the same way. A virtual table is
+ ** 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 .
**
** If the 'x' expression is a column value, or the SELECT...
** statement returns a column value, then the affinity of that
@@ -1333,11 +1252,11 @@
** 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_OpenVirtual, pExpr->iTable, 0);
+ 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 ){
@@ -1362,40 +1281,31 @@
** store it in the temporary table. If is a column, then use
** that columns affinity when building index keys. If is not
** a column, use numeric affinity.
*/
int i;
- ExprList *pList = pExpr->pList;
- struct ExprList_item *pItem;
-
if( !affinity ){
affinity = SQLITE_AFF_NUMERIC;
}
keyInfo.aColl[0] = pExpr->pLeft->pColl;
/* Loop through each expression in . */
- for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
- Expr *pE2 = pItem->pExpr;
-
- /* If the expression is not constant then we will need to
- ** disable the test that was generated above that makes sure
- ** this code only executes once. Because for a non-constant
- ** expression we need to rerun this code each time.
- */
- if( testAddr>0 && !sqlite3ExprIsConstant(pE2) ){
- VdbeOp *aOp = sqlite3VdbeGetOp(v, testAddr-1);
- int i;
- for(i=0; i<3; i++){
- aOp[i].opcode = OP_Noop;
- }
- testAddr = 0;
+ for(i=0; ipList->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_IdxInsert, pExpr->iTable, 0);
+ sqlite3VdbeAddOp(v, OP_String8, 0, 0);
+ sqlite3VdbeAddOp(v, OP_PutStrKey, pExpr->iTable, 0);
}
}
sqlite3VdbeChangeP3(v, addr, (void *)&keyInfo, P3_KEYINFO);
break;
}
@@ -1404,35 +1314,34 @@
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.
*/
- static const Token one = { (u8*)"1", 0, 1 };
+ int sop;
Select *pSel;
- int iMem;
- int sop;
- pExpr->iColumn = iMem = pParse->nMem++;
+ pExpr->iColumn = pParse->nMem++;
pSel = pExpr->pSelect;
if( pExpr->op==TK_SELECT ){
sop = SRT_Mem;
- sqlite3VdbeAddOp(v, OP_MemNull, iMem, 0);
- VdbeComment((v, "# Init subquery result"));
}else{
+ static const Token one = { "1", 0, 1 };
sop = SRT_Exists;
- sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem);
- VdbeComment((v, "# Init EXISTS result"));
- }
- sqlite3ExprDelete(pSel->pLimit);
- pSel->pLimit = sqlite3Expr(TK_INTEGER, 0, 0, &one);
- sqlite3Select(pParse, pSel, sop, iMem, 0, 0, 0, 0);
- break;
- }
- }
-
- if( testAddr ){
- sqlite3VdbeJumpHere(v, testAddr);
+ 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 */
@@ -1443,11 +1352,11 @@
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_Int64, 0, 0, z, n);
+ sqlite3VdbeOp3(v, OP_Integer, 0, 0, z, n);
}else{
sqlite3VdbeOp3(v, OP_Real, 0, 0, z, n);
}
}
@@ -1462,111 +1371,67 @@
** below verify that the numbers are aligned correctly.
*/
void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
Vdbe *v = pParse->pVdbe;
int op;
- int stackChng = 1; /* Amount of change to stack depth */
-
if( v==0 ) return;
if( pExpr==0 ){
- sqlite3VdbeAddOp(v, OP_Null, 0, 0);
+ sqlite3VdbeAddOp(v, OP_String8, 0, 0); /* Empty expression evals to NULL */
return;
}
op = pExpr->op;
switch( op ){
- case TK_AGG_COLUMN: {
- AggInfo *pAggInfo = pExpr->pAggInfo;
- struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
- if( !pAggInfo->directMode ){
- sqlite3VdbeAddOp(v, OP_MemLoad, pCol->iMem, 0);
- break;
- }else if( pAggInfo->useSortingIdx ){
- sqlite3VdbeAddOp(v, OP_Column, pAggInfo->sortingIdx,
- pCol->iSorterColumn);
- break;
- }
- /* Otherwise, fall thru into the TK_COLUMN case */
- }
case TK_COLUMN: {
- if( pExpr->iTable<0 ){
- /* This only happens when coding check constraints */
- assert( pParse->ckOffset>0 );
- sqlite3VdbeAddOp(v, OP_Dup, pParse->ckOffset-pExpr->iColumn-1, 1);
+ if( !pParse->fillAgg && pExpr->iAgg>=0 ){
+ sqlite3VdbeAddOp(v, OP_AggGet, pExpr->iAggCtx, pExpr->iAgg);
}else if( pExpr->iColumn>=0 ){
- Table *pTab = pExpr->pTab;
- int iCol = pExpr->iColumn;
- sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, iCol);
- sqlite3ColumnDefault(v, pTab, iCol);
-#ifndef SQLITE_OMIT_FLOATING_POINT
- if( pTab && pTab->aCol[iCol].affinity==SQLITE_AFF_REAL ){
- sqlite3VdbeAddOp(v, OP_RealAffinity, 0, 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_Rowid, pExpr->iTable, 0);
+ sqlite3VdbeAddOp(v, OP_Recno, pExpr->iTable, 0);
}
break;
}
case TK_INTEGER: {
- codeInteger(v, (char*)pExpr->token.z, pExpr->token.n);
+ 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 );
- sqlite3DequoteExpr(pExpr);
- sqlite3VdbeOp3(v, op, 0, 0, (char*)pExpr->token.z, pExpr->token.n);
- break;
- }
- case TK_NULL: {
- sqlite3VdbeAddOp(v, OP_Null, 0, 0);
+ sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z, pExpr->token.n);
+ sqlite3VdbeDequoteP3(v, -1);
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
- int n;
- const char *z;
assert( TK_BLOB==OP_HexBlob );
- n = pExpr->token.n - 3;
- z = (char*)pExpr->token.z + 2;
- assert( n>=0 );
- if( n==0 ){
- z = "";
- }
- sqlite3VdbeOp3(v, op, 0, 0, z, n);
+ 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, (char*)pExpr->token.z, pExpr->token.n);
+ sqlite3VdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n);
}
break;
}
case TK_REGISTER: {
sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iTable, 0);
break;
}
-#ifndef SQLITE_OMIT_CAST
- case TK_CAST: {
- /* Expressions of the form: CAST(pLeft AS token) */
- int aff, op;
- sqlite3ExprCode(pParse, pExpr->pLeft);
- aff = sqlite3AffinityType(&pExpr->token);
- op = aff - SQLITE_AFF_TEXT + OP_ToText;
- assert( op==OP_ToText || aff!=SQLITE_AFF_TEXT );
- assert( op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
- assert( op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC );
- assert( op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
- assert( op==OP_ToReal || aff!=SQLITE_AFF_REAL );
- sqlite3VdbeAddOp(v, op, 0, 0);
- stackChng = 0;
- break;
- }
-#endif /* SQLITE_OMIT_CAST */
case TK_LT:
case TK_LE:
case TK_GT:
case TK_GE:
case TK_NE:
@@ -1578,11 +1443,10 @@
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);
- stackChng = -1;
break;
}
case TK_AND:
case TK_OR:
case TK_PLUS:
@@ -1607,19 +1471,19 @@
assert( TK_RSHIFT==OP_ShiftRight );
assert( TK_CONCAT==OP_Concat );
sqlite3ExprCode(pParse, pExpr->pLeft);
sqlite3ExprCode(pParse, pExpr->pRight);
sqlite3VdbeAddOp(v, op, 0, 0);
- stackChng = -1;
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 = sqlite3MPrintf("-%.*s", p->n, p->z);
+ 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);
}
@@ -1632,11 +1496,10 @@
case TK_NOT: {
assert( TK_BITNOT==OP_BitNot );
assert( TK_NOT==OP_Not );
sqlite3ExprCode(pParse, pExpr->pLeft);
sqlite3VdbeAddOp(v, op, 0, 0);
- stackChng = 0;
break;
}
case TK_ISNULL:
case TK_NOTNULL: {
int dest;
@@ -1645,53 +1508,48 @@
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);
- stackChng = 0;
break;
}
case TK_AGG_FUNCTION: {
- AggInfo *pInfo = pExpr->pAggInfo;
- if( pInfo==0 ){
- sqlite3ErrorMsg(pParse, "misuse of aggregate: %T",
- &pExpr->span);
- }else{
- sqlite3VdbeAddOp(v, OP_MemLoad, pInfo->aFunc[pExpr->iAgg].iMem, 0);
- }
+ sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
break;
}
- case TK_CONST_FUNC:
+ 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 constMask = 0;
+ int p2 = 0;
int i;
- u8 enc = ENC(pParse->db);
+ u8 enc = pParse->db->enc;
CollSeq *pColl = 0;
- zId = (char*)pExpr->token.z;
- nId = pExpr->token.n;
+ getFunctionName(pExpr, &zId, &nId);
pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
assert( pDef!=0 );
nExpr = sqlite3ExprCodeExprList(pParse, pList);
for(i=0; ia[i].pExpr) ){
- constMask |= (1<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, constMask, nExpr, (char*)pDef, P3_FUNCDEF);
- stackChng = 1-nExpr;
+ sqlite3VdbeOp3(v, OP_Function, nExpr, p2, (char*)pDef, P3_FUNCDEF);
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS:
case TK_SELECT: {
@@ -1718,11 +1576,11 @@
*/
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_Null, 0, 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 */
@@ -1746,16 +1604,16 @@
break;
}
case TK_UPLUS:
case TK_AS: {
sqlite3ExprCode(pParse, pExpr->pLeft);
- stackChng = 0;
break;
}
case TK_CASE: {
int expr_end_label;
int jumpInst;
+ int addr;
int nExpr;
int i;
ExprList *pEList;
struct ExprList_item *aListelem;
@@ -1779,19 +1637,20 @@
}else{
jumpInst = sqlite3VdbeAddOp(v, OP_IfNot, 1, 0);
}
sqlite3ExprCode(pParse, aListelem[i+1].pExpr);
sqlite3VdbeAddOp(v, OP_Goto, 0, expr_end_label);
- sqlite3VdbeJumpHere(v, jumpInst);
+ 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_Null, 0, 0);
+ sqlite3VdbeAddOp(v, OP_String8, 0, 0);
}
sqlite3VdbeResolveLabel(v, expr_end_label);
break;
}
#ifndef SQLITE_OMIT_TRIGGER
@@ -1803,28 +1662,22 @@
}
if( pExpr->iColumn!=OE_Ignore ){
assert( pExpr->iColumn==OE_Rollback ||
pExpr->iColumn == OE_Abort ||
pExpr->iColumn == OE_Fail );
- sqlite3DequoteExpr(pExpr);
sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn,
- (char*)pExpr->token.z, pExpr->token.n);
+ 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)"));
}
- stackChng = 0;
- break;
}
#endif
- }
-
- if( pParse->ckOffset ){
- pParse->ckOffset += stackChng;
- assert( pParse->ckOffset );
+ break;
}
}
#ifndef SQLITE_OMIT_TRIGGER
/*
@@ -1863,13 +1716,15 @@
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=n; i>0; i--, pItem++){
+ for(pItem=pList->a, i=0; ipExpr);
}
return n;
}
@@ -1888,11 +1743,10 @@
** 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;
- int ckOffset = pParse->ckOffset;
if( v==0 || pExpr==0 ) return;
op = pExpr->op;
switch( op ){
case TK_AND: {
int d2 = sqlite3VdbeMakeLabel(v);
@@ -1953,21 +1807,20 @@
pRight = pExpr->pList->a[1].pExpr;
sqlite3ExprCode(pParse, pRight);
codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull);
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
- sqlite3VdbeJumpHere(v, addr);
+ sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
break;
}
default: {
sqlite3ExprCode(pParse, pExpr);
sqlite3VdbeAddOp(v, OP_If, jumpIfNull, dest);
break;
}
}
- pParse->ckOffset = ckOffset;
}
/*
** Generate code for a boolean expression such that a jump is made
** to the label "dest" if the expression is false but execution
@@ -1977,11 +1830,10 @@
** 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;
- int ckOffset = pParse->ckOffset;
if( v==0 || pExpr==0 ) return;
/* The value of pExpr->op and op are related as follows:
**
** pExpr->op op
@@ -2074,11 +1926,10 @@
sqlite3ExprCode(pParse, pExpr);
sqlite3VdbeAddOp(v, OP_IfNot, jumpIfNull, dest);
break;
}
}
- pParse->ckOffset = ckOffset;
}
/*
** 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.
@@ -2089,11 +1940,10 @@
return pB==0;
}else if( pB==0 ){
return 0;
}
if( pA->op!=pB->op ) return 0;
- if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) 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;
@@ -2108,43 +1958,32 @@
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((char*)pA->token.z,(char*)pB->token.z,pB->token.n)!=0 ){
- return 0;
- }
+ if( sqlite3StrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0;
}
return 1;
}
-
-/*
-** Add a new element to the pAggInfo->aCol[] array. Return the index of
-** the new element. Return a negative number if malloc fails.
-*/
-static int addAggInfoColumn(AggInfo *pInfo){
- int i;
- i = sqlite3ArrayAllocate((void**)&pInfo->aCol, sizeof(pInfo->aCol[0]), 3);
- if( i<0 ){
- return -1;
- }
- return i;
-}
-
-/*
-** Add a new element to the pAggInfo->aFunc[] array. Return the index of
-** the new element. Return a negative number if malloc fails.
-*/
-static int addAggInfoFunc(AggInfo *pInfo){
- int i;
- i = sqlite3ArrayAllocate((void**)&pInfo->aFunc, sizeof(pInfo->aFunc[0]), 2);
- if( i<0 ){
- return -1;
- }
- return i;
-}
+/*
+** 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.
@@ -2151,122 +1990,64 @@
**
** 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;
- AggInfo *pAggInfo = pNC->pAggInfo;
-
switch( pExpr->op ){
case TK_COLUMN: {
- /* Check to see if the column is in one of the tables in the FROM
- ** clause of the aggregate query */
- if( pSrcList ){
- struct SrcList_item *pItem = pSrcList->a;
- for(i=0; inSrc; i++, pItem++){
- struct AggInfo_col *pCol;
- if( pExpr->iTable==pItem->iCursor ){
- /* If we reach this point, it means that pExpr refers to a table
- ** that is in the FROM clause of the aggregate query.
- **
- ** Make an entry for the column in pAggInfo->aCol[] if there
- ** is not an entry there already.
- */
- pCol = pAggInfo->aCol;
- for(i=0; inColumn; i++, pCol++){
- if( pCol->iTable==pExpr->iTable &&
- pCol->iColumn==pExpr->iColumn ){
- break;
- }
- }
- if( i>=pAggInfo->nColumn && (i = addAggInfoColumn(pAggInfo))>=0 ){
- pCol = &pAggInfo->aCol[i];
- pCol->iTable = pExpr->iTable;
- pCol->iColumn = pExpr->iColumn;
- pCol->iMem = pParse->nMem++;
- pCol->iSorterColumn = -1;
- pCol->pExpr = pExpr;
- if( pAggInfo->pGroupBy ){
- int j, n;
- ExprList *pGB = pAggInfo->pGroupBy;
- struct ExprList_item *pTerm = pGB->a;
- n = pGB->nExpr;
- for(j=0; jpExpr;
- if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable &&
- pE->iColumn==pExpr->iColumn ){
- pCol->iSorterColumn = j;
- break;
- }
- }
- }
- if( pCol->iSorterColumn<0 ){
- pCol->iSorterColumn = pAggInfo->nSortingColumn++;
- }
- }
- /* There is now an entry for pExpr in pAggInfo->aCol[] (either
- ** because it was there before or because we just created it).
- ** Convert the pExpr to be a TK_AGG_COLUMN referring to that
- ** pAggInfo->aCol[] entry.
- */
- pExpr->pAggInfo = pAggInfo;
- pExpr->op = TK_AGG_COLUMN;
- pExpr->iAgg = i;
- break;
- } /* endif pExpr->iTable==pItem->iCursor */
- } /* end loop over pSrcList */
+ for(i=0; pSrcList && inSrc; i++){
+ if( pExpr->iTable==pSrcList->a[i].iCursor ){
+ aAgg = pParse->aAgg;
+ for(i=0; inAgg; 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: {
- /* The pNC->nDepth==0 test causes aggregate functions in subqueries
- ** to be ignored */
if( pNC->nDepth==0 ){
- /* Check to see if pExpr is a duplicate of another aggregate
- ** function that is already in the pAggInfo structure
- */
- struct AggInfo_func *pItem = pAggInfo->aFunc;
- for(i=0; inFunc; i++, pItem++){
- if( sqlite3ExprCompare(pItem->pExpr, pExpr) ){
+ aAgg = pParse->aAgg;
+ for(i=0; inAgg; i++){
+ if( !aAgg[i].isAgg ) continue;
+ if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){
break;
}
}
- if( i>=pAggInfo->nFunc ){
- /* pExpr is original. Make a new entry in pAggInfo->aFunc[]
- */
- u8 enc = ENC(pParse->db);
- i = addAggInfoFunc(pAggInfo);
- if( i>=0 ){
- pItem = &pAggInfo->aFunc[i];
- pItem->pExpr = pExpr;
- pItem->iMem = pParse->nMem++;
- pItem->pFunc = sqlite3FindFunction(pParse->db,
- (char*)pExpr->token.z, pExpr->token.n,
- pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0);
- if( pExpr->flags & EP_Distinct ){
- pItem->iDistinct = pParse->nTab++;
- }else{
- pItem->iDistinct = -1;
- }
- }
- }
- /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
- */
- pExpr->iAgg = i;
- pExpr->pAggInfo = pAggInfo;
+ 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;
}
}
}
-
- /* Recursively walk subqueries looking for TK_COLUMN nodes that need
- ** to be changed to TK_AGG_COLUMN. But increment nDepth so that
- ** TK_AGG_FUNCTION nodes in subqueries will be unchanged.
- */
if( pExpr->pSelect ){
pNC->nDepth++;
walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC);
pNC->nDepth--;
}
@@ -2289,21 +2070,104 @@
walkExprTree(pExpr, analyzeAggregate, pNC);
return pNC->pParse->nErr - nErr;
}
/*
-** Call sqlite3ExprAnalyzeAggregates() for every expression in an
-** expression list. Return the number of errors.
-**
-** If an error is found, the analysis is cut short.
-*/
-int sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){
- struct ExprList_item *pItem;
- int i;
- int nErr = 0;
- if( pList ){
- for(pItem=pList->a, i=0; nErr==0 && inExpr; i++, pItem++){
- nErr += sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr);
- }
- }
- return 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;
}
Index: SQLite.Interop/src/func.c
==================================================================
--- SQLite.Interop/src/func.c
+++ SQLite.Interop/src/func.c
@@ -14,23 +14,20 @@
**
** 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.17 2006/01/16 15:51:47 rmsimpson Exp $
+** $Id: func.c,v 1.1 2005/03/01 16:04:29 rmsimpson Exp $
*/
#include "sqliteInt.h"
#include
-/* #include */
+#include
#include
#include
#include "vdbeInt.h"
#include "os.h"
-/*
-** Return the collating function associated with a function.
-*/
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
return context->pColl;
}
/*
@@ -79,11 +76,10 @@
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,
@@ -99,11 +95,11 @@
case SQLITE_FLOAT: {
sqlite3_result_int(context, sqlite3_value_bytes(argv[0]));
break;
}
case SQLITE_TEXT: {
- const unsigned char *z = sqlite3_value_text(argv[0]);
+ 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: {
@@ -144,12 +140,12 @@
static void substrFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
- const unsigned char *z;
- const unsigned char *z2;
+ const char *z;
+ const char *z2;
int i;
int p1, p2, len;
assert( argc==3 );
z = sqlite3_value_text(argv[0]);
@@ -176,30 +172,30 @@
for(; i30 ) n = 30;
if( n<0 ) n = 0;
}
if( SQLITE_NULL==sqlite3_value_type(argv[0]) ) return;
r = sqlite3_value_double(argv[0]);
- sqlite3_snprintf(sizeof(zBuf),zBuf,"%.*f",n,r);
+ sprintf(zBuf,"%.*f",n,r);
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
/*
** Implementation of the upper() and lower() SQL functions.
@@ -208,28 +204,28 @@
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((char*)z, (char*)sqlite3_value_text(argv[0]));
+ strcpy(z, sqlite3_value_text(argv[0]));
for(i=0; z[i]; i++){
z[i] = toupper(z[i]);
}
- sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT);
+ 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((char*)z, (char*)sqlite3_value_text(argv[0]));
+ strcpy(z, sqlite3_value_text(argv[0]));
for(i=0; z[i]; i++){
z[i] = tolower(z[i]);
}
- sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
sqliteFree(z);
}
/*
** Implementation of the IFNULL(), NVL(), and COALESCE() functions.
@@ -309,18 +305,12 @@
u8 matchAll;
u8 matchOne;
u8 matchSet;
u8 noCase;
};
-
static const struct compareInfo globInfo = { '*', '?', '[', 0 };
-/* The correct SQL-92 behavior is for the LIKE operator to ignore
-** case. Thus 'a' LIKE 'A' would be true. */
-static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 };
-/* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator
-** is case sensitive causing 'a' LIKE 'A' to be false */
-static const struct compareInfo likeInfoAlt = { '%', '_', 0, 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.
@@ -458,19 +448,10 @@
}
}
return *zString==0;
}
-/*
-** Count the number of times that the LIKE operator (or GLOB which is
-** just a variation of LIKE) gets called. This is used for testing
-** only.
-*/
-#ifdef SQLITE_TEST
-int sqlite3_like_count = 0;
-#endif
-
/*
** 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:
@@ -477,12 +458,12 @@
**
** A LIKE B
**
** is implemented as like(B,A).
**
-** This same function (with a different compareInfo structure) computes
-** the GLOB operator.
+** 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
@@ -493,23 +474,36 @@
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((char*)zEsc, -1)!=1 ){
+ if( sqlite3utf8CharLen(zEsc, -1)!=1 ){
sqlite3_result_error(context,
"ESCAPE expression must be a single character", -1);
return;
}
escape = sqlite3ReadUtf8(zEsc);
}
if( zA && zB ){
- struct compareInfo *pInfo = sqlite3_user_data(context);
-#ifdef SQLITE_TEST
- sqlite3_like_count++;
-#endif
- sqlite3_result_int(context, patternCompare(zA, zB, pInfo, escape));
+ 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
@@ -590,11 +584,11 @@
}
break;
}
case SQLITE_TEXT: {
int i,j,n;
- const unsigned char *zArg = sqlite3_value_text(argv[0]);
+ 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;
@@ -690,11 +684,11 @@
sqlite3Randomness(n, zBuf);
for(i=0; ienc);
zVal = sqliteMalloc(len+3);
zVal[len] = 0;
zVal[len-1] = 0;
assert( zVal );
zVal++;
- memcpy(zVal, sqlite3ValueText(argv[0], ENC(db)), len);
- if( ENC(db)==SQLITE_UTF8 ){
+ 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( ENC(db)==SQLITE_UTF16LE ){
+ }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 */
}
@@ -774,11 +768,11 @@
){
int i;
char *zRet = sqliteMalloc(nArg*2);
if( !zRet ) return;
for(i=0; isum += sqlite3_value_double(argv[0]);
p->cnt++;
- if( type==SQLITE_FLOAT ){
- p->seenFloat = 1;
- }
}
}
static void sumFinalize(sqlite3_context *context){
SumCtx *p;
- p = sqlite3_aggregate_context(context, 0);
- if( p && p->cnt>0 ){
- if( p->seenFloat ){
- sqlite3_result_double(context, p->sum);
- }else{
- sqlite3_result_int64(context, (i64)p->sum);
- }
- }
+ 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, 0);
+ p = sqlite3_aggregate_context(context, sizeof(*p));
if( p && p->cnt>0 ){
sqlite3_result_double(context, p->sum/(double)p->cnt);
}
}
-static void totalFinalize(sqlite3_context *context){
- SumCtx *p;
- p = sqlite3_aggregate_context(context, 0);
- sqlite3_result_double(context, p ? p->sum : 0.0);
-}
/*
** An instance of the following structure holds the context of a
** variance or standard deviation computation.
*/
@@ -899,13 +870,23 @@
p->n++;
}
}
static void countFinalize(sqlite3_context *context){
CountCtx *p;
- p = sqlite3_aggregate_context(context, 0);
+ 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){
@@ -937,17 +918,15 @@
sqlite3VdbeMemCopy(pBest, pArg);
}
}
static void minMaxFinalize(sqlite3_context *context){
sqlite3_value *pRes;
- pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0);
- if( pRes ){
- if( pRes->flags ){
- sqlite3_result_value(context, pRes);
- }
- sqlite3VdbeMemRelease(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
@@ -981,10 +960,13 @@
{ "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 },
@@ -1009,11 +991,10 @@
void (*xFinalize)(sqlite3_context*);
} aAggs[] = {
{ "min", 1, 0, 1, minmaxStep, minMaxFinalize },
{ "max", 1, 2, 1, minmaxStep, minMaxFinalize },
{ "sum", 1, 0, 0, sumStep, sumFinalize },
- { "total", 1, 0, 0, sumStep, totalFinalize },
{ "avg", 1, 0, 0, sumStep, avgFinalize },
{ "count", 0, 0, 0, countStep, countFinalize },
{ "count", 1, 0, 0, countStep, countFinalize },
};
int i;
@@ -1035,13 +1016,10 @@
}
}
#ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions(db);
#endif
-#ifndef SQLITE_OMIT_PARSER
- sqlite3AttachFunctions(db);
-#endif
for(i=0; ineedCollSeq = 1;
}
}
}
sqlite3RegisterDateTimeFunctions(db);
-#ifdef SQLITE_SSE
- sqlite3SseFunctions(db);
-#endif
-#ifdef SQLITE_CASE_SENSITIVE_LIKE
- sqlite3RegisterLikeFunctions(db, 1);
-#else
- sqlite3RegisterLikeFunctions(db, 0);
-#endif
-}
-
-/*
-** Set the LIKEOPT flag on the 2-argument function with the given name.
-*/
-static void setLikeOptFlag(sqlite3 *db, const char *zName, int flagVal){
- FuncDef *pDef;
- pDef = sqlite3FindFunction(db, zName, strlen(zName), 2, SQLITE_UTF8, 0);
- if( pDef ){
- pDef->flags = flagVal;
- }
-}
-
-/*
-** Register the built-in LIKE and GLOB functions. The caseSensitive
-** parameter determines whether or not the LIKE operator is case
-** sensitive. GLOB is always case sensitive.
-*/
-void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
- struct compareInfo *pInfo;
- if( caseSensitive ){
- pInfo = (struct compareInfo*)&likeInfoAlt;
- }else{
- pInfo = (struct compareInfo*)&likeInfoNorm;
- }
- sqlite3_create_function(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0);
- sqlite3_create_function(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0);
- sqlite3_create_function(db, "glob", 2, SQLITE_UTF8,
- (struct compareInfo*)&globInfo, likeFunc, 0,0);
- setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
- setLikeOptFlag(db, "like",
- caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE);
-}
-
-/*
-** pExpr points to an expression which implements a function. If
-** it is appropriate to apply the LIKE optimization to that function
-** then set aWc[0] through aWc[2] to the wildcard characters and
-** return TRUE. If the function is not a LIKE-style function then
-** return FALSE.
-*/
-int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
- FuncDef *pDef;
- if( pExpr->op!=TK_FUNCTION ){
- return 0;
- }
- if( pExpr->pList->nExpr!=2 ){
- return 0;
- }
- pDef = sqlite3FindFunction(db, (char*)pExpr->token.z, pExpr->token.n, 2,
- SQLITE_UTF8, 0);
- if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
- return 0;
- }
-
- /* The memcpy() statement assumes that the wildcard characters are
- ** the first three statements in the compareInfo structure. The
- ** asserts() that follow verify that assumption
- */
- memcpy(aWc, pDef->pUserData, 3);
- assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
- assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
- assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
- *pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0;
- return 1;
}
Index: SQLite.Interop/src/hash.c
==================================================================
--- SQLite.Interop/src/hash.c
+++ SQLite.Interop/src/hash.c
@@ -10,11 +10,11 @@
**
*************************************************************************
** This is the implementation of generic hash-tables
** used in SQLite.
**
-** $Id: hash.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $
+** $Id: hash.c,v 1.1 2005/03/01 16:04:29 rmsimpson Exp $
*/
#include "sqliteInt.h"
#include
/* Turn bulk memory into a hash table object by initializing the
@@ -292,15 +292,10 @@
if( pH->copyKey && elem->pKey ){
sqliteFree(elem->pKey);
}
sqliteFree( elem );
pH->count--;
- if( pH->count<=0 ){
- assert( pH->first==0 );
- assert( pH->count==0 );
- sqlite3HashClear(pH);
- }
}
/* 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.
Index: SQLite.Interop/src/hash.h
==================================================================
--- SQLite.Interop/src/hash.h
+++ SQLite.Interop/src/hash.h
@@ -10,11 +10,11 @@
**
*************************************************************************
** This is the header file for the generic hash-table implemenation
** used in SQLite.
**
-** $Id: hash.h,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $
+** $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. */
Index: SQLite.Interop/src/insert.c
==================================================================
--- SQLite.Interop/src/insert.c
+++ SQLite.Interop/src/insert.c
@@ -10,11 +10,11 @@
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $
+** $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
@@ -21,15 +21,14 @@
** 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
** ------------------------------
-** 'a' TEXT
-** 'b' NONE
-** 'c' NUMERIC
-** 'd' INTEGER
-** 'e' REAL
+** '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
@@ -60,15 +59,14 @@
** for each column indexed by the index, according to the affinity of the
** column:
**
** Character Column affinity
** ------------------------------
-** 'a' TEXT
-** 'b' NONE
-** 'c' NUMERIC
-** 'd' INTEGER
-** 'e' REAL
+** '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.
@@ -102,19 +100,19 @@
** "INSERT INTO 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, Schema *pSchema, int iTab){
+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; ipSrc->nSrc; i++, pItem++){
if( pItem->pSelect ){
- if( selectReadsTable(pItem->pSelect, pSchema, iTab) ) return 1;
+ if( selectReadsTable(p, iDb, iTab) ) return 1;
}else{
- if( pItem->pTab->pSchema==pSchema && pItem->pTab->tnum==iTab ) return 1;
+ if( pItem->pTab->iDb==iDb && pItem->pTab->tnum==iTab ) return 1;
}
}
return 0;
}
@@ -212,11 +210,10 @@
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 */
- int iDb;
#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
@@ -223,13 +220,11 @@
#ifndef SQLITE_OMIT_AUTOINCREMENT
int counterRowid; /* Memory cell holding rowid of autoinc counter */
#endif
- if( pParse->nErr || sqlite3ThreadDataReadOnly()->mallocFailed ){
- goto insert_cleanup;
- }
+ 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 );
@@ -237,13 +232,12 @@
if( zTab==0 ) goto insert_cleanup;
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ){
goto insert_cleanup;
}
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- assert( iDbnDb );
- pDb = &db->aDb[iDb];
+ assert( pTab->iDbnDb );
+ pDb = &db->aDb[pTab->iDb];
zDb = pDb->zName;
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
goto insert_cleanup;
}
@@ -274,17 +268,24 @@
/* 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, iDb);
+ 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++;
}
@@ -298,16 +299,18 @@
if( pTab->autoInc ){
int iCur = pParse->nTab;
int base = sqlite3VdbeCurrentAddr(v);
counterRowid = pParse->nMem++;
counterMem = pParse->nMem++;
- sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
+ 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, 0x100, base+12);
- sqlite3VdbeAddOp(v, OP_Rowid, iCur, 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);
@@ -331,13 +334,11 @@
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 || sqlite3ThreadDataReadOnly()->mallocFailed ){
- goto insert_cleanup;
- }
+ 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;
@@ -348,11 +349,11 @@
**
** 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->pSchema,pTab->tnum) ){
+ if( triggers_exist || selectReadsTable(pSelect, pTab->iDb, pTab->tnum) ){
useTempTable = 1;
}
if( useTempTable ){
/* Generate the subroutine that SELECT calls to process each row of
@@ -359,26 +360,27 @@
** the result. Store the result in a temporary table
*/
srcTab = pParse->nTab++;
sqlite3VdbeResolveLabel(v, iInsertBlock);
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
- sqlite3VdbeAddOp(v, OP_NewRowid, srcTab, 0);
+ sqlite3TableAffinityStr(v, pTab);
+ sqlite3VdbeAddOp(v, OP_NewRecno, srcTab, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
- sqlite3VdbeAddOp(v, OP_Insert, srcTab, 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.
*/
- sqlite3VdbeJumpHere(v, iInitCode);
- sqlite3VdbeAddOp(v, OP_OpenVirtual, srcTab, 0);
+ 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{
- sqlite3VdbeJumpHere(v, iInitCode);
+ sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v));
}
}else{
/* This is the case if the data for the INSERT is coming from a VALUES
** clause
*/
@@ -466,11 +468,12 @@
/* Initialize the count of rows to be inserted
*/
if( db->flags & SQLITE_CountRows ){
iCntMem = pParse->nMem++;
- sqlite3VdbeAddOp(v, OP_MemInt, 0, iCntMem);
+ 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;
@@ -542,11 +545,11 @@
** table column affinities.
*/
if( !isView ){
sqlite3TableAffinityStr(v, pTab);
}
- sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
+ 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;
@@ -560,11 +563,11 @@
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 NewRowid
+ ** 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 ){
@@ -573,19 +576,19 @@
}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_NewRowid
+ /* 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_NewRowid, base, counterMem);
+ sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem);
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
}else{
- sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
+ sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem);
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
if( pTab->autoInc ){
sqlite3VdbeAddOp(v, OP_MemMax, counterMem, 0);
}
@@ -598,11 +601,11 @@
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_Null, 0, 0);
+ sqlite3VdbeAddOp(v, OP_String8, 0, 0);
continue;
}
if( pColumn==0 ){
j = i;
}else{
@@ -631,11 +634,11 @@
}
/* Update the count of rows that are inserted
*/
if( (db->flags & SQLITE_CountRows)!=0 ){
- sqlite3VdbeAddOp(v, OP_MemIncr, 1, iCntMem);
+ sqlite3VdbeAddOp(v, OP_MemIncr, iCntMem, 0);
}
if( triggers_exist ){
/* Close all tables opened */
if( !isView ){
@@ -679,19 +682,21 @@
** table.
*/
if( pTab->autoInc ){
int iCur = pParse->nTab;
int base = sqlite3VdbeCurrentAddr(v);
- sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
+ 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_NewRowid, iCur, 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_Insert, iCur, 0);
+ sqlite3VdbeAddOp(v, OP_PutIntKey, iCur, 0);
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
#endif
/*
@@ -706,36 +711,36 @@
sqlite3VdbeSetColName(v, 0, "rows inserted", P3_STATIC);
}
insert_cleanup:
sqlite3SrcListDelete(pTabList);
- sqlite3ExprListDelete(pList);
- sqlite3SelectDelete(pSelect);
+ 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 rowid of the row to be updated before the update. This
+** 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 rowid of the row after the update.
+** 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 rowid shown as entry (1) above is omitted unless both isUpdate
-** and rowidChng are 1. isUpdate is true for UPDATEs and false for
-** INSERTs and rowidChng is true if the record number is being changed.
+** 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
@@ -795,11 +800,11 @@
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 rowidChng, /* True if the record number will change */
+ 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;
@@ -810,11 +815,12 @@
int extra;
int iCur;
Index *pIdx;
int seenReplace = 0;
int jumpInst1=0, jumpInst2;
- int hasTwoRowids = (isUpdate && rowidChng);
+ 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;
@@ -849,43 +855,32 @@
" may not be NULL", (char*)0);
sqlite3VdbeChangeP3(v, -1, zMsg, P3_DYNAMIC);
break;
}
case OE_Ignore: {
- sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0);
+ 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;
}
}
- sqlite3VdbeJumpHere(v, addr);
+ sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
}
/* Test all CHECK constraints
*/
-#ifndef SQLITE_OMIT_CHECK
- if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){
- int allOk = sqlite3VdbeMakeLabel(v);
- assert( pParse->ckOffset==0 );
- pParse->ckOffset = nCol;
- sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, 1);
- assert( pParse->ckOffset==nCol );
- pParse->ckOffset = 0;
- sqlite3VdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort);
- sqlite3VdbeResolveLabel(v, allOk);
- }
-#endif /* !defined(SQLITE_OMIT_CHECK) */
+ /**** 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( rowidChng ){
+ if( recnoChng ){
onError = pTab->keyConf;
if( overrideError!=OE_Default ){
onError = overrideError;
}else if( onError==OE_Default ){
onError = OE_Abort;
@@ -911,26 +906,27 @@
break;
}
case OE_Replace: {
sqlite3GenerateRowIndexDelete(pParse->db, v, pTab, base, 0);
if( isUpdate ){
- sqlite3VdbeAddOp(v, OP_Dup, nCol+hasTwoRowids, 1);
+ 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+hasTwoRowids, 0);
+ sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
break;
}
}
- sqlite3VdbeJumpHere(v, jumpInst2);
+ contAddr = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeChangeP2(v, jumpInst2, contAddr);
if( isUpdate ){
- sqlite3VdbeJumpHere(v, jumpInst1);
+ sqlite3VdbeChangeP2(v, jumpInst1, contAddr);
sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1);
sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
}
}
@@ -951,11 +947,11 @@
sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1);
}else{
sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1);
}
}
- jumpInst1 = sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0);
+ 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 */
@@ -969,11 +965,11 @@
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+hasTwoRowids, 1);
+ 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 );
@@ -1006,36 +1002,38 @@
sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, zErrMsg, 0);
break;
}
case OE_Ignore: {
assert( seenReplace==0 );
- sqlite3VdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRowids, 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+hasTwoRowids, 1);
+ 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
- sqlite3VdbeJumpHere(v, jumpInst1);
+ sqlite3VdbeChangeP2(v, jumpInst1, contAddr | (1<<24));
#endif
- sqlite3VdbeJumpHere(v, jumpInst2);
+ 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 rowid for the new entry. This routine creates the new
+** 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.
*/
@@ -1042,11 +1040,11 @@
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 rowidChng, /* True if the record number will change */
+ 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;
@@ -1058,33 +1056,29 @@
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_IdxInsert, base+i+1, 0);
+ 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_Insert, newIdx, 0);
+ sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
}
#endif
if( pParse->nested ){
pik_flags = 0;
}else{
- pik_flags = OPFLAG_NCHANGE;
- pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID);
- }
- sqlite3VdbeAddOp(v, OP_Insert, base, pik_flags);
- if( !pParse->nested ){
- sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
- }
-
- if( isUpdate && rowidChng ){
+ pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID));
+ }
+ sqlite3VdbeAddOp(v, OP_PutIntKey, base, pik_flags);
+
+ if( isUpdate && recnoChng ){
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
}
}
/*
@@ -1097,21 +1091,21 @@
Table *pTab, /* Table to be opened */
int base, /* Cursor number assigned to the table */
int op /* OP_OpenRead or OP_OpenWrite */
){
int i;
- int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
Index *pIdx;
Vdbe *v = sqlite3GetVdbe(pParse);
assert( v!=0 );
- sqlite3OpenTable(pParse, base, iDb, pTab, op);
+ 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++){
- KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
- assert( pIdx->pSchema==pTab->pSchema );
- sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
- VdbeComment((v, "# %s", pIdx->zName));
- sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF);
+ 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;
}
}
Index: SQLite.Interop/src/keywordhash.h
==================================================================
--- SQLite.Interop/src/keywordhash.h
+++ SQLite.Interop/src/keywordhash.h
@@ -1,87 +1,84 @@
-/* Hash score: 159 */
-static int keywordCode(const char *z, int n){
- static const char zText[537] =
- "ABORTABLEFTEMPORARYADDATABASELECTHENDEFAULTRANSACTIONATURALTER"
- "AISEACHECKEYAFTEREFERENCESCAPELSEXCEPTRIGGEREGEXPLAINITIALLYANALYZE"
- "XCLUSIVEXISTSTATEMENTANDEFERRABLEATTACHAVINGLOBEFOREIGNOREINDEX"
- "AUTOINCREMENTBEGINNERENAMEBETWEENOTNULLIKEBYCASCADEFERREDELETE"
- "CASECASTCOLLATECOLUMNCOMMITCONFLICTCONSTRAINTERSECTCREATECROSS"
- "CURRENT_DATECURRENT_TIMESTAMPLANDESCDETACHDISTINCTDROPRAGMATCH"
- "FAILIMITFROMFULLGROUPDATEIFIMMEDIATEINSERTINSTEADINTOFFSETISNULL"
- "JOINORDEREPLACEOUTERESTRICTPRIMARYQUERYRIGHTROLLBACKROWHENUNION"
- "UNIQUEUSINGVACUUMVALUESVIEWHERE";
- static const unsigned char aHash[127] = {
- 92, 80, 107, 91, 0, 4, 0, 0, 114, 0, 83, 0, 0,
- 96, 44, 76, 93, 0, 106, 109, 97, 90, 0, 10, 0, 0,
- 113, 0, 110, 103, 0, 28, 48, 0, 41, 0, 0, 65, 71,
- 0, 63, 19, 0, 105, 36, 104, 0, 108, 75, 0, 0, 33,
- 0, 61, 37, 0, 8, 0, 115, 38, 12, 0, 77, 40, 25,
- 66, 0, 0, 31, 81, 53, 30, 50, 20, 88, 0, 34, 0,
- 74, 26, 0, 72, 0, 0, 0, 64, 47, 67, 22, 87, 29,
- 69, 86, 0, 1, 0, 9, 101, 58, 18, 0, 112, 82, 99,
- 55, 6, 85, 0, 0, 49, 94, 0, 102, 0, 70, 0, 0,
- 15, 0, 116, 51, 56, 0, 2, 54, 0, 111,
- };
- static const unsigned char aNext[116] = {
- 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0,
- 0, 11, 0, 0, 0, 0, 5, 13, 0, 7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0,
- 0, 16, 0, 0, 23, 52, 0, 0, 0, 0, 45, 0, 59,
- 0, 0, 0, 0, 0, 0, 0, 0, 43, 73, 0, 24, 60,
- 21, 0, 79, 0, 0, 68, 0, 0, 84, 46, 0, 0, 0,
- 0, 0, 0, 0, 0, 39, 95, 98, 0, 0, 100, 0, 32,
- 0, 14, 27, 78, 0, 57, 89, 0, 35, 0, 62, 0,
- };
- static const unsigned char aLen[116] = {
- 5, 5, 4, 4, 9, 2, 3, 8, 2, 6, 4, 3, 7,
- 11, 2, 7, 5, 5, 4, 5, 3, 5, 10, 6, 4, 6,
- 7, 6, 7, 9, 3, 7, 9, 6, 9, 3, 10, 6, 6,
- 4, 6, 7, 3, 6, 7, 5, 13, 2, 2, 5, 5, 6,
- 7, 7, 3, 4, 4, 2, 7, 3, 8, 6, 4, 4, 7,
- 6, 6, 8, 10, 9, 6, 5, 12, 17, 12, 4, 4, 6,
- 8, 2, 4, 6, 5, 4, 5, 4, 4, 5, 6, 2, 9,
- 6, 7, 4, 6, 2, 3, 6, 4, 5, 7, 5, 8, 7,
- 5, 5, 8, 3, 4, 5, 6, 5, 6, 6, 4, 5,
- };
- static const unsigned short int aOffset[116] = {
- 0, 4, 7, 10, 10, 14, 19, 21, 26, 27, 32, 34, 36,
- 42, 51, 52, 57, 61, 65, 67, 71, 74, 78, 86, 91, 94,
- 99, 105, 108, 113, 118, 122, 128, 136, 141, 150, 152, 162, 167,
- 172, 175, 177, 177, 181, 185, 187, 192, 194, 196, 205, 208, 212,
- 218, 224, 224, 227, 230, 234, 236, 237, 241, 248, 254, 258, 262,
- 269, 275, 281, 289, 296, 305, 311, 316, 328, 328, 344, 348, 352,
- 358, 359, 366, 369, 373, 378, 381, 386, 390, 394, 397, 403, 405,
- 414, 420, 427, 430, 430, 433, 436, 442, 446, 450, 457, 461, 469,
- 476, 481, 486, 494, 496, 500, 505, 511, 516, 522, 528, 531,
- };
- static const unsigned char aCode[116] = {
- TK_ABORT, TK_TABLE, TK_JOIN_KW, TK_TEMP, TK_TEMP,
- TK_OR, TK_ADD, TK_DATABASE, TK_AS, TK_SELECT,
- TK_THEN, TK_END, TK_DEFAULT, TK_TRANSACTION,TK_ON,
- TK_JOIN_KW, TK_ALTER, TK_RAISE, TK_EACH, TK_CHECK,
- TK_KEY, TK_AFTER, TK_REFERENCES, TK_ESCAPE, TK_ELSE,
- TK_EXCEPT, TK_TRIGGER, TK_LIKE_KW, TK_EXPLAIN, TK_INITIALLY,
- TK_ALL, TK_ANALYZE, TK_EXCLUSIVE, TK_EXISTS, TK_STATEMENT,
- TK_AND, TK_DEFERRABLE, TK_ATTACH, TK_HAVING, TK_LIKE_KW,
- TK_BEFORE, TK_FOREIGN, TK_FOR, TK_IGNORE, TK_REINDEX,
- TK_INDEX, TK_AUTOINCR, TK_TO, TK_IN, TK_BEGIN,
- TK_JOIN_KW, TK_RENAME, TK_BETWEEN, TK_NOTNULL, TK_NOT,
- TK_NULL, TK_LIKE_KW, TK_BY, TK_CASCADE, TK_ASC,
- TK_DEFERRED, TK_DELETE, TK_CASE, TK_CAST, TK_COLLATE,
- TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_CONSTRAINT, TK_INTERSECT,
- TK_CREATE, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_CTIME_KW,
- TK_PLAN, TK_DESC, TK_DETACH, TK_DISTINCT, TK_IS,
- TK_DROP, TK_PRAGMA, TK_MATCH, TK_FAIL, TK_LIMIT,
- TK_FROM, TK_JOIN_KW, TK_GROUP, TK_UPDATE, TK_IF,
- TK_IMMEDIATE, TK_INSERT, TK_INSTEAD, TK_INTO, TK_OFFSET,
- TK_OF, TK_SET, TK_ISNULL, TK_JOIN, TK_ORDER,
- TK_REPLACE, TK_JOIN_KW, TK_RESTRICT, TK_PRIMARY, TK_QUERY,
- TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_WHEN, TK_UNION,
- TK_UNIQUE, TK_USING, TK_VACUUM, TK_VALUES, TK_VIEW,
- TK_WHERE,
+/* 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) ^
@@ -91,8 +88,8 @@
return aCode[i];
}
}
return TK_ID;
}
-int sqlite3KeywordCode(const unsigned char *z, int n){
- return keywordCode((char*)z, n);
+int sqlite3KeywordCode(const char *z, int n){
+ return keywordCode(z, n);
}
Index: SQLite.Interop/src/legacy.c
==================================================================
--- SQLite.Interop/src/legacy.c
+++ SQLite.Interop/src/legacy.c
@@ -12,11 +12,11 @@
** 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.15 2006/01/16 15:51:47 rmsimpson Exp $
+** $Id: legacy.c,v 1.1 2005/03/01 16:04:30 rmsimpson Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include
@@ -68,10 +68,11 @@
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;
@@ -119,15 +120,13 @@
exec_out:
if( pStmt ) sqlite3_finalize(pStmt);
if( azCols ) sqliteFree(azCols);
- if( sqlite3ThreadDataReadOnly()->mallocFailed ){
+ if( sqlite3_malloc_failed ){
rc = SQLITE_NOMEM;
- sqlite3MallocClearFailed();
}
-
if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){
*pzErrMsg = malloc(1+strlen(sqlite3_errmsg(db)));
if( *pzErrMsg ){
strcpy(*pzErrMsg, sqlite3_errmsg(db));
}
Index: SQLite.Interop/src/main.c
==================================================================
--- SQLite.Interop/src/main.c
+++ SQLite.Interop/src/main.c
@@ -12,11 +12,11 @@
** 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.15 2006/01/16 15:51:47 rmsimpson Exp $
+** $Id: main.c,v 1.1 2005/03/01 16:04:30 rmsimpson Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include
@@ -23,10 +23,362 @@
/*
** 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 && iDbnDb );
+ 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 && iDbnDb );
+
+ /* 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 && iaDb[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 && inDb; 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 " $";
@@ -107,14 +459,10 @@
}
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
-#ifdef SQLITE_SSE
- sqlite3_finalize(db->pFetch);
-#endif
-
/* 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;
@@ -129,21 +477,15 @@
if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){
/* printf("DID NOT CLOSE\n"); fflush(stdout); */
return SQLITE_ERROR;
}
- /* sqlite3_close() may not invoke sqliteMalloc(). */
- sqlite3MallocDisallow();
-
for(j=0; jnDb; j++){
struct Db *pDb = &db->aDb[j];
if( pDb->pBt ){
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
- if( j!=1 ){
- pDb->pSchema = 0;
- }
}
}
sqlite3ResetInternalSchema(db, 0);
assert( db->nDb<=2 );
assert( db->aDb==db->aDbStatic );
@@ -161,52 +503,34 @@
}
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;
-
- /* The temp-database schema is allocated differently from the other schema
- ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
- ** So it needs to be freed here. Todo: Why not roll the temp schema into
- ** the same sqliteMalloc() as the one that allocates the database
- ** structure?
- */
- sqliteFree(db->aDb[1].pSchema);
sqliteFree(db);
- sqlite3MallocAllow();
- sqlite3ReleaseThreadData();
return SQLITE_OK;
}
/*
** Rollback all database files.
*/
void sqlite3RollbackAll(sqlite3 *db){
int i;
- int inTrans = 0;
for(i=0; inDb; i++){
if( db->aDb[i].pBt ){
- if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){
- inTrans = 1;
- }
sqlite3BtreeRollback(db->aDb[i].pBt);
db->aDb[i].inTrans = 0;
}
}
- if( db->flags&SQLITE_InternChanges ){
- sqlite3ResetInternalSchema(db, 0);
- }
-
- /* If one has been configured, invoke the rollback-hook callback */
- if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
- db->xRollbackCallback(db->pRollbackArg);
- }
+ sqlite3ResetInternalSchema(db, 0);
}
/*
** Return a static string that describes the kind of error specified in the
** argument.
@@ -216,24 +540,27 @@
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_FULL: z = "database or disk is full"; 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;
@@ -250,65 +577,45 @@
** 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 *ptr, /* Database connection */
+ 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 u8 delays[] =
- { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 };
- static const u8 totals[] =
- { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 };
+ 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]))
- int timeout = ((sqlite3 *)ptr)->busyTimeout;
- int delay, prior;
+ ptr timeout = (ptr)Timeout;
+ ptr delay, prior;
- assert( count>=0 );
- if( count < NDELAY ){
- delay = delays[count];
- prior = totals[count];
+ if( count <= NDELAY ){
+ delay = delays[count-1];
+ prior = totals[count-1];
}else{
delay = delays[NDELAY-1];
- prior = totals[NDELAY-1] + delay*(count-(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 = ((sqlite3 *)ptr)->busyTimeout;
+ int timeout = (int)Timeout;
if( (count+1)*1000 > timeout ){
return 0;
}
sqlite3OsSleep(1000);
return 1;
#endif
}
-/*
-** Invoke the given busy handler.
-**
-** This routine is called when an operation failed with a lock.
-** If this routine returns non-zero, the lock is retried. If it
-** returns 0, the operation aborts with an SQLITE_BUSY error.
-*/
-int sqlite3InvokeBusyHandler(BusyHandler *p){
- int rc;
- if( p==0 || p->xFunc==0 || p->nBusy<0 ) return 0;
- rc = p->xFunc(p->pArg, p->nBusy);
- if( rc==0 ){
- p->nBusy = -1;
- }else{
- p->nBusy++;
- }
- return rc;
-}
-
/*
** This routine sets the busy callback for an Sqlite database to the
** given callback function with the given argument.
*/
int sqlite3_busy_handler(
@@ -319,11 +626,10 @@
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
db->busyHandler.xFunc = xBusy;
db->busyHandler.pArg = pArg;
- db->busyHandler.nBusy = 0;
return SQLITE_OK;
}
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/*
@@ -356,12 +662,11 @@
** 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 ){
- db->busyTimeout = ms;
- sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
+ sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)(ptr)ms);
}else{
sqlite3_busy_handler(db, 0, 0);
}
return SQLITE_OK;
}
@@ -453,11 +758,10 @@
}
}
p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1);
if( p==0 ) return SQLITE_NOMEM;
- p->flags = 0;
p->xFunc = xFunc;
p->xStep = xStep;
p->xFinalize = xFinal;
p->pUserData = pUserData;
return SQLITE_OK;
@@ -472,65 +776,48 @@
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*)
){
int rc;
- char *zFunc8;
+ char const *zFunc8;
+ sqlite3_value *pTmp;
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
- zFunc8 = sqlite3utf16to8(zFunctionName, -1);
+ 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);
- sqliteFree(zFunc8);
return rc;
}
#endif
-#ifndef SQLITE_OMIT_TRACE
/*
** 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
-** SQL statement.
+** 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;
}
-/*
-** Register a profile function. The pArg from the previously registered
-** profile function is returned.
-**
-** A NULL profile function means that no profiling is executes. A non-NULL
-** profile is a pointer to a function that is invoked at the conclusion of
-** each SQL statement that is run.
-*/
-void *sqlite3_profile(
- sqlite3 *db,
- void (*xProfile)(void*,const char*,sqlite_uint64),
- void *pArg
-){
- void *pOld = db->pProfileArg;
- db->xProfile = xProfile;
- db->pProfileArg = pArg;
- return pOld;
-}
-#endif /* SQLITE_OMIT_TRACE */
/*** EXPERIMENTAL ***
**
** Register a function to be invoked when a transaction comments.
-** If the invoked function returns non-zero, then the commit becomes a
+** 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 */
@@ -540,51 +827,22 @@
db->xCommitCallback = xCallback;
db->pCommitArg = pArg;
return pOld;
}
-/*
-** Register a callback to be invoked each time a row is updated,
-** inserted or deleted using this database connection.
-*/
-void *sqlite3_update_hook(
- sqlite3 *db, /* Attach the hook to this database */
- void (*xCallback)(void*,int,char const *,char const *,sqlite_int64),
- void *pArg /* Argument to the function */
-){
- void *pRet = db->pUpdateArg;
- db->xUpdateCallback = xCallback;
- db->pUpdateArg = pArg;
- return pRet;
-}
-
-/*
-** Register a callback to be invoked each time a transaction is rolled
-** back by this database connection.
-*/
-void *sqlite3_rollback_hook(
- sqlite3 *db, /* Attach the hook to this database */
- void (*xCallback)(void*), /* Callback function */
- void *pArg /* Argument to the function */
-){
- void *pRet = db->pRollbackArg;
- db->xRollbackCallback = xCallback;
- db->pRollbackArg = pArg;
- return pRet;
-}
/*
** 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 a "virtual" database for transient use only and is deleted as
-** soon as the connection is closed.
+** is for temporary use only and is deleted as soon as the connection
+** is closed.
**
-** A virtual database can be either a disk file (that is automatically
-** deleted when the file is closed) or it an be held entirely in memory,
+** 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
** ---------- -------------- ------------------------------
@@ -629,11 +887,11 @@
zFilename = ":memory:";
#endif
#endif /* SQLITE_OMIT_MEMORYDB */
}
- rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btree_flags);
+ rc = sqlite3BtreeOpen(zFilename, ppBtree, btree_flags);
if( rc==SQLITE_OK ){
sqlite3BtreeSetBusyHandler(*ppBtree, (void*)&db->busyHandler);
sqlite3BtreeSetCacheSize(*ppBtree, nCache);
}
return rc;
@@ -643,17 +901,17 @@
** Return UTF-8 encoded English language explanation of the most recent
** error.
*/
const char *sqlite3_errmsg(sqlite3 *db){
const char *z;
- if( sqlite3ThreadDataReadOnly()->mallocFailed ){
+ if( sqlite3_malloc_failed ){
return sqlite3ErrStr(SQLITE_NOMEM);
}
if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){
return sqlite3ErrStr(SQLITE_MISUSE);
}
- z = (char*)sqlite3_value_text(db->pErr);
+ z = sqlite3_value_text(db->pErr);
if( z==0 ){
z = sqlite3ErrStr(db->errCode);
}
return z;
}
@@ -682,11 +940,11 @@
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( sqlite3ThreadDataReadOnly()->mallocFailed ){
+ 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]);
}
@@ -699,110 +957,234 @@
return z;
}
#endif /* SQLITE_OMIT_UTF16 */
/*
-** Return the most recent error code generated by an SQLite routine. If NULL is
-** passed to this function, we assume a malloc() failed during sqlite3_open().
+** Return the most recent error code generated by an SQLite routine.
*/
int sqlite3_errcode(sqlite3 *db){
- if( !db || sqlite3ThreadDataReadOnly()->mallocFailed ){
+ 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 && iDbnDb; 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.
+** 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;
- CollSeq *pColl;
-
- assert( !sqlite3ThreadDataReadOnly()->mallocFailed );
+ 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);
-
-#if 0
for(i=0; inDb; 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);
}
-#endif
-
+
/* 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, SQLITE_UTF8, "BINARY", 6, 0))==0
- ){
- /* sqlite3_create_collation() is an external API. So the mallocFailed flag
- ** will have been cleared before returning. So set it explicitly here.
- */
- sqlite3ThreadData()->mallocFailed = 1;
+ !(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);
- /* Set flags on the built-in collating sequences */
- db->pDfltColl->type = SQLITE_COLL_BINARY;
- pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "NOCASE", 6, 0);
- if( pColl ){
- pColl->type = SQLITE_COLL_NOCASE;
- }
-
/* 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;
}
-#ifndef SQLITE_OMIT_PARSER
- db->aDb[0].pSchema = sqlite3SchemaGet(db->aDb[0].pBt);
- db->aDb[1].pSchema = sqlite3SchemaGet(0);
-#endif
-
- if( db->aDb[0].pSchema ){
- ENC(db) = SQLITE_UTF8;
- }
-
- /* 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].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;
-#ifndef SQLITE_OMIT_TEMPDB
- db->aDb[1].zName = "temp";
db->aDb[1].safety_level = 1;
-#endif
/* 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.
*/
@@ -809,17 +1191,15 @@
sqlite3RegisterBuiltinFunctions(db);
sqlite3Error(db, SQLITE_OK, 0);
db->magic = SQLITE_MAGIC_OPEN;
opendb_out:
- if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){
- sqlite3_close(db);
- db = 0;
+ if( sqlite3_errcode(db)==SQLITE_OK && sqlite3_malloc_failed ){
+ sqlite3Error(db, SQLITE_NOMEM, 0);
}
*ppDb = db;
- sqlite3MallocClearFailed();
- return rc;
+ return sqlite3_errcode(db);
}
/*
** Open a new database handle.
*/
@@ -840,26 +1220,24 @@
){
char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */
int rc = SQLITE_NOMEM;
sqlite3_value *pVal;
- assert( zFilename );
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 ){
- rc = sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0);
+ sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0);
}
- }else{
- assert( sqlite3ThreadDataReadOnly()->mallocFailed );
- sqlite3MallocClearFailed();
}
- sqlite3ValueFree(pVal);
+ if( pVal ){
+ sqlite3ValueFree(pVal);
+ }
return rc;
}
#endif /* SQLITE_OMIT_UTF16 */
@@ -894,11 +1272,11 @@
int rc;
if( pStmt==0 ){
rc = SQLITE_OK;
}else{
rc = sqlite3VdbeReset((Vdbe*)pStmt);
- sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0);
+ sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0, 0);
}
return rc;
}
/*
@@ -948,11 +1326,11 @@
sqlite3ExpirePreparedStatements(db);
}
pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1);
if( 0==pColl ){
- rc = SQLITE_NOMEM;
+ rc = SQLITE_NOMEM;
}else{
pColl->xCmp = xCompare;
pColl->pUser = pCtx;
pColl->enc = enc;
}
@@ -969,19 +1347,19 @@
const char *zName,
int enc,
void* pCtx,
int(*xCompare)(void*,int,const void*,int,const void*)
){
- char *zName8;
- int rc;
+ char const *zName8;
+ sqlite3_value *pTmp;
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
- zName8 = sqlite3utf16to8(zName, -1);
- rc = sqlite3_create_collation(db, zName8, enc, pCtx, xCompare);
- sqliteFree(zName8);
- return rc;
+ 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
@@ -1018,76 +1396,5 @@
db->xCollNeeded16 = xCollNeeded16;
db->pCollNeededArg = pCollNeededArg;
return SQLITE_OK;
}
#endif /* SQLITE_OMIT_UTF16 */
-
-#ifndef SQLITE_OMIT_GLOBALRECOVER
-/*
-** This function is now an anachronism. It used to be used to recover from a
-** malloc() failure, but SQLite now does this automatically.
-*/
-int sqlite3_global_recover(){
- return SQLITE_OK;
-}
-#endif
-
-/*
-** Test to see whether or not the database connection is in autocommit
-** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on
-** by default. Autocommit is disabled by a BEGIN statement and reenabled
-** by the next COMMIT or ROLLBACK.
-**
-******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
-*/
-int sqlite3_get_autocommit(sqlite3 *db){
- return db->autoCommit;
-}
-
-#ifdef SQLITE_DEBUG
-/*
-** The following routine is subtituted for constant SQLITE_CORRUPT in
-** debugging builds. This provides a way to set a breakpoint for when
-** corruption is first detected.
-*/
-int sqlite3Corrupt(void){
- return SQLITE_CORRUPT;
-}
-#endif
-
-
-#ifndef SQLITE_OMIT_SHARED_CACHE
-/*
-** Enable or disable the shared pager and schema features for the
-** current thread.
-**
-** This routine should only be called when there are no open
-** database connections.
-*/
-int sqlite3_enable_shared_cache(int enable){
- ThreadData *pTd = sqlite3ThreadData();
-
- /* It is only legal to call sqlite3_enable_shared_cache() when there
- ** are no currently open b-trees that were opened by the calling thread.
- ** This condition is only easy to detect if the shared-cache were
- ** previously enabled (and is being disabled).
- */
- if( pTd->pBtree && !enable ){
- assert( pTd->useSharedData );
- return SQLITE_MISUSE;
- }
-
- pTd->useSharedData = enable;
- sqlite3ReleaseThreadData();
- return SQLITE_OK;
-}
-#endif
-
-/*
-** This is a convenience routine that makes sure that all thread-specific
-** data for this thread has been deallocated.
-*/
-void sqlite3_thread_cleanup(void){
- ThreadData *pTd = sqlite3ThreadData();
- memset(pTd, 0, sizeof(*pTd));
- sqlite3ReleaseThreadData();
-}
DELETED SQLite.Interop/src/md5.c
Index: SQLite.Interop/src/md5.c
==================================================================
--- SQLite.Interop/src/md5.c
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
-** SQLite uses this code for testing only. It is not a part of
-** the SQLite library. This file implements two new TCL commands
-** "md5" and "md5file" that compute md5 checksums on arbitrary text
-** and on complete files. These commands are used by the "testfixture"
-** program to help verify the correct operation of the SQLite library.
-**
-** The original use of these TCL commands was to test the ROLLBACK
-** feature of SQLite. First compute the MD5-checksum of the database.
-** Then make some changes but rollback the changes rather than commit
-** them. Compute a second MD5-checksum of the file and verify that the
-** two checksums are the same. Such is the original use of this code.
-** New uses may have been added since this comment was written.
-*/
-/*
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest. This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
- * will fill a supplied 16-byte array with the digest.
- */
-#include
-#include
-#include "sqlite3.h"
-
-/*
- * If compiled on a machine that doesn't have a 32-bit integer,
- * you just set "uint32" to the appropriate datatype for an
- * unsigned 32-bit integer. For example:
- *
- * cc -Duint32='unsigned long' md5.c
- *
- */
-#ifndef uint32
-# define uint32 unsigned int
-#endif
-
-struct Context {
- uint32 buf[4];
- uint32 bits[2];
- unsigned char in[64];
-};
-typedef char MD5Context[88];
-
-/*
- * Note: this code is harmless on little-endian machines.
- */
-static void byteReverse (unsigned char *buf, unsigned longs){
- uint32 t;
- do {
- t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 |
- ((unsigned)buf[1]<<8 | buf[0]);
- *(uint32 *)buf = t;
- buf += 4;
- } while (--longs);
-}
-/* The four core functions - F1 is optimized somewhat */
-
-/* #define F1(x, y, z) (x & y | ~x & z) */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define MD5STEP(f, w, x, y, z, data, s) \
- ( w += f(x, y, z) + data, w = w<>(32-s), w += x )
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data. MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-static void MD5Transform(uint32 buf[4], const uint32 in[16]){
- register uint32 a, b, c, d;
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-
-/*
- * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
- * initialization constants.
- */
-static void MD5Init(MD5Context *pCtx){
- struct Context *ctx = (struct Context *)pCtx;
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
-}
-
-/*
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
-static
-void MD5Update(MD5Context *pCtx, const unsigned char *buf, unsigned int len){
- struct Context *ctx = (struct Context *)pCtx;
- uint32 t;
-
- /* Update bitcount */
-
- t = ctx->bits[0];
- if ((ctx->bits[0] = t + ((uint32)len << 3)) < t)
- ctx->bits[1]++; /* Carry from low to high */
- ctx->bits[1] += len >> 29;
-
- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
-
- /* Handle any leading odd-sized chunks */
-
- if ( t ) {
- unsigned char *p = (unsigned char *)ctx->in + t;
-
- t = 64-t;
- if (len < t) {
- memcpy(p, buf, len);
- return;
- }
- memcpy(p, buf, t);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
- buf += t;
- len -= t;
- }
-
- /* Process data in 64-byte chunks */
-
- while (len >= 64) {
- memcpy(ctx->in, buf, 64);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
- buf += 64;
- len -= 64;
- }
-
- /* Handle any remaining bytes of data. */
-
- memcpy(ctx->in, buf, len);
-}
-
-/*
- * Final wrapup - pad to 64-byte boundary with the bit pattern
- * 1 0* (64-bit count of bits processed, MSB-first)
- */
-static void MD5Final(unsigned char digest[16], MD5Context *pCtx){
- struct Context *ctx = (struct Context *)pCtx;
- unsigned count;
- unsigned char *p;
-
- /* Compute number of bytes mod 64 */
- count = (ctx->bits[0] >> 3) & 0x3F;
-
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- p = ctx->in + count;
- *p++ = 0x80;
-
- /* Bytes of padding needed to make 64 bytes */
- count = 64 - 1 - count;
-
- /* Pad out to 56 mod 64 */
- if (count < 8) {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset(p, 0, count);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
-
- /* Now fill the next block with 56 bytes */
- memset(ctx->in, 0, 56);
- } else {
- /* Pad block to 56 bytes */
- memset(p, 0, count-8);
- }
- byteReverse(ctx->in, 14);
-
- /* Append length in bits and transform */
- ((uint32 *)ctx->in)[ 14 ] = ctx->bits[0];
- ((uint32 *)ctx->in)[ 15 ] = ctx->bits[1];
-
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
- byteReverse((unsigned char *)ctx->buf, 4);
- memcpy(digest, ctx->buf, 16);
- memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
-}
-
-/*
-** Convert a digest into base-16. digest should be declared as
-** "unsigned char digest[16]" in the calling function. The MD5
-** digest is stored in the first 16 bytes. zBuf should
-** be "char zBuf[33]".
-*/
-static void DigestToBase16(unsigned char *digest, char *zBuf){
- static char const zEncode[] = "0123456789abcdef";
- int i, j;
-
- for(j=i=0; i<16; i++){
- int a = digest[i];
- zBuf[j++] = zEncode[(a>>4)&0xf];
- zBuf[j++] = zEncode[a & 0xf];
- }
- zBuf[j] = 0;
-}
-
-/*
-** A TCL command for md5. The argument is the text to be hashed. The
-** Result is the hash in base64.
-*/
-static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv){
- MD5Context ctx;
- unsigned char digest[16];
-
- if( argc!=2 ){
- Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
- " TEXT\"", 0);
- return TCL_ERROR;
- }
- MD5Init(&ctx);
- MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1]));
- MD5Final(digest, &ctx);
- DigestToBase16(digest, interp->result);
- return TCL_OK;
-}
-
-/*
-** A TCL command to take the md5 hash of a file. The argument is the
-** name of the file.
-*/
-static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv){
- FILE *in;
- MD5Context ctx;
- unsigned char digest[16];
- char zBuf[10240];
-
- if( argc!=2 ){
- Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
- " FILENAME\"", 0);
- return TCL_ERROR;
- }
- in = fopen(argv[1],"rb");
- if( in==0 ){
- Tcl_AppendResult(interp,"unable to open file \"", argv[1],
- "\" for reading", 0);
- return TCL_ERROR;
- }
- MD5Init(&ctx);
- for(;;){
- int n;
- n = fread(zBuf, 1, sizeof(zBuf), in);
- if( n<=0 ) break;
- MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
- }
- fclose(in);
- MD5Final(digest, &ctx);
- DigestToBase16(digest, interp->result);
- return TCL_OK;
-}
-
-/*
-** Register the two TCL commands above with the TCL interpreter.
-*/
-int Md5_Init(Tcl_Interp *interp){
- Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd, 0, 0);
- Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd, 0, 0);
- return TCL_OK;
-}
-
-/*
-** During testing, the special md5sum() aggregate function is available.
-** inside SQLite. The following routines implement that function.
-*/
-static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){
- MD5Context *p;
- int i;
- if( argc<1 ) return;
- p = sqlite3_aggregate_context(context, sizeof(*p));
- if( p==0 ) return;
- if( sqlite3_aggregate_count(context)==1 ){
- MD5Init(p);
- }
- for(i=0; ipMethod->xClose(pId);
- }else{
- return SQLITE_OK;
- }
-}
-int sqlite3OsOpenDirectory(OsFile *id, const char *zName){
- return id->pMethod->xOpenDirectory(id, zName);
-}
-int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
- return id->pMethod->xRead(id, pBuf, amt);
-}
-int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
- return id->pMethod->xWrite(id, pBuf, amt);
-}
-int sqlite3OsSeek(OsFile *id, i64 offset){
- return id->pMethod->xSeek(id, offset);
-}
-int sqlite3OsTruncate(OsFile *id, i64 size){
- return id->pMethod->xTruncate(id, size);
-}
-int sqlite3OsSync(OsFile *id, int fullsync){
- return id->pMethod->xSync(id, fullsync);
-}
-void sqlite3OsSetFullSync(OsFile *id, int value){
- id->pMethod->xSetFullSync(id, value);
-}
-int sqlite3OsFileHandle(OsFile *id){
- return id->pMethod->xFileHandle(id);
-}
-int sqlite3OsFileSize(OsFile *id, i64 *pSize){
- return id->pMethod->xFileSize(id, pSize);
-}
-int sqlite3OsLock(OsFile *id, int lockType){
- return id->pMethod->xLock(id, lockType);
-}
-int sqlite3OsUnlock(OsFile *id, int lockType){
- return id->pMethod->xUnlock(id, lockType);
-}
-int sqlite3OsLockState(OsFile *id){
- return id->pMethod->xLockState(id);
-}
-int sqlite3OsCheckReservedLock(OsFile *id){
- return id->pMethod->xCheckReservedLock(id);
-}
-
-#ifdef SQLITE_ENABLE_REDEF_IO
-/*
-** A function to return a pointer to the virtual function table.
-** This routine really does not accomplish very much since the
-** virtual function table is a global variable and anybody who
-** can call this function can just as easily access the variable
-** for themselves. Nevertheless, we include this routine for
-** backwards compatibility with an earlier redefinable I/O
-** interface design.
-*/
-struct sqlite3OsVtbl *sqlite3_os_switch(void){
- return &sqlite3Os;
-}
-#endif
Index: SQLite.Interop/src/os.h
==================================================================
--- SQLite.Interop/src/os.h
+++ SQLite.Interop/src/os.h
@@ -16,15 +16,16 @@
*/
#ifndef _SQLITE_OS_H_
#define _SQLITE_OS_H_
/*
-** Figure out if we are dealing with Unix, Windows, or some other
-** operating system.
+** 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_OTHER)
-# define OS_OTHER 0
+#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
@@ -38,26 +39,21 @@
# ifndef OS_WIN
# define OS_WIN 0
# endif
#endif
-
/*
-** Define the maximum size of a temporary filename
+** Invoke the appropriate operating-system specific header file.
*/
-#if OS_WIN
-# include
-# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
-#else
-# define SQLITE_TEMPNAME_SIZE 200
+#if OS_TEST
+# include "os_test.h"
+#endif
+#if OS_UNIX
+# include "os_unix.h"
#endif
-
-/* If the SET_FULLSYNC macro is not defined above, then make it
-** a no-op
-*/
-#ifndef SET_FULLSYNC
-# define SET_FULLSYNC(x,y)
+#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
@@ -69,108 +65,10 @@
*/
#ifndef TEMP_FILE_PREFIX
# define TEMP_FILE_PREFIX "sqlite_"
#endif
-/*
-** Define the interfaces for Unix and for Windows.
-*/
-#if OS_UNIX
-#define sqlite3OsOpenReadWrite sqlite3UnixOpenReadWrite
-#define sqlite3OsOpenExclusive sqlite3UnixOpenExclusive
-#define sqlite3OsOpenReadOnly sqlite3UnixOpenReadOnly
-#define sqlite3OsDelete sqlite3UnixDelete
-#define sqlite3OsFileExists sqlite3UnixFileExists
-#define sqlite3OsFullPathname sqlite3UnixFullPathname
-#define sqlite3OsIsDirWritable sqlite3UnixIsDirWritable
-#define sqlite3OsSyncDirectory sqlite3UnixSyncDirectory
-#define sqlite3OsTempFileName sqlite3UnixTempFileName
-#define sqlite3OsRandomSeed sqlite3UnixRandomSeed
-#define sqlite3OsSleep sqlite3UnixSleep
-#define sqlite3OsCurrentTime sqlite3UnixCurrentTime
-#define sqlite3OsEnterMutex sqlite3UnixEnterMutex
-#define sqlite3OsLeaveMutex sqlite3UnixLeaveMutex
-#define sqlite3OsInMutex sqlite3UnixInMutex
-#define sqlite3OsThreadSpecificData sqlite3UnixThreadSpecificData
-#define sqlite3OsMalloc sqlite3GenericMalloc
-#define sqlite3OsRealloc sqlite3GenericRealloc
-#define sqlite3OsFree sqlite3GenericFree
-#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
-#endif
-#if OS_WIN
-#define sqlite3OsOpenReadWrite sqlite3WinOpenReadWrite
-#define sqlite3OsOpenExclusive sqlite3WinOpenExclusive
-#define sqlite3OsOpenReadOnly sqlite3WinOpenReadOnly
-#define sqlite3OsDelete sqlite3WinDelete
-#define sqlite3OsFileExists sqlite3WinFileExists
-#define sqlite3OsFullPathname sqlite3WinFullPathname
-#define sqlite3OsIsDirWritable sqlite3WinIsDirWritable
-#define sqlite3OsSyncDirectory sqlite3WinSyncDirectory
-#define sqlite3OsTempFileName sqlite3WinTempFileName
-#define sqlite3OsRandomSeed sqlite3WinRandomSeed
-#define sqlite3OsSleep sqlite3WinSleep
-#define sqlite3OsCurrentTime sqlite3WinCurrentTime
-#define sqlite3OsEnterMutex sqlite3WinEnterMutex
-#define sqlite3OsLeaveMutex sqlite3WinLeaveMutex
-#define sqlite3OsInMutex sqlite3WinInMutex
-#define sqlite3OsThreadSpecificData sqlite3WinThreadSpecificData
-#define sqlite3OsMalloc sqlite3GenericMalloc
-#define sqlite3OsRealloc sqlite3GenericRealloc
-#define sqlite3OsFree sqlite3GenericFree
-#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
-#endif
-
-/*
-** If using an alternative OS interface, then we must have an "os_other.h"
-** header file available for that interface. Presumably the "os_other.h"
-** header file contains #defines similar to those above.
-*/
-#if OS_OTHER
-# include "os_other.h"
-#endif
-
-
-
-/*
-** Forward declarations
-*/
-typedef struct OsFile OsFile;
-typedef struct IoMethod IoMethod;
-
-/*
-** An instance of the following structure contains pointers to all
-** methods on an OsFile object.
-*/
-struct IoMethod {
- int (*xClose)(OsFile**);
- int (*xOpenDirectory)(OsFile*, const char*);
- int (*xRead)(OsFile*, void*, int amt);
- int (*xWrite)(OsFile*, const void*, int amt);
- int (*xSeek)(OsFile*, i64 offset);
- int (*xTruncate)(OsFile*, i64 size);
- int (*xSync)(OsFile*, int);
- void (*xSetFullSync)(OsFile *id, int setting);
- int (*xFileHandle)(OsFile *id);
- int (*xFileSize)(OsFile*, i64 *pSize);
- int (*xLock)(OsFile*, int);
- int (*xUnlock)(OsFile*, int);
- int (*xLockState)(OsFile *id);
- int (*xCheckReservedLock)(OsFile *id);
-};
-
-/*
-** The OsFile object describes an open disk file in an OS-dependent way.
-** The version of OsFile defined here is a generic version. Each OS
-** implementation defines its own subclass of this structure that contains
-** additional information needed to handle file I/O. But the pMethod
-** entry (pointing to the virtual function table) always occurs first
-** so that we can always find the appropriate methods.
-*/
-struct OsFile {
- IoMethod const *pMethod;
-};
-
/*
** 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.
@@ -221,14 +119,12 @@
** 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 sqlite_aux.h so that adaptors for
-** connecting SQLite to other operating systems can use the same byte
-** ranges for locking. In particular, the same locking strategy and
-** byte ranges are used for Unix. This leaves open the possiblity of having
+** 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.
@@ -247,194 +143,40 @@
** the incompatibility right away, even running a full regression test.
** The default location of PENDING_BYTE is the first byte past the
** 1GB boundary.
**
*/
-#ifndef SQLITE_TEST
#define PENDING_BYTE 0x40000000 /* First byte past the 1GB boundary */
-#else
-extern unsigned int sqlite3_pending_byte;
-#define PENDING_BYTE sqlite3_pending_byte
-#endif
-
+/* #define PENDING_BYTE 0x5400 // Page 22 - for testing */
#define RESERVED_BYTE (PENDING_BYTE+1)
#define SHARED_FIRST (PENDING_BYTE+2)
#define SHARED_SIZE 510
-/*
-** Prototypes for operating system interface routines.
-*/
-int sqlite3OsClose(OsFile**);
-int sqlite3OsOpenDirectory(OsFile*, const char*);
+
+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 sqlite3OsSync(OsFile*, int);
-void sqlite3OsSetFullSync(OsFile *id, int setting);
-int sqlite3OsFileHandle(OsFile *id);
int sqlite3OsFileSize(OsFile*, i64 *pSize);
-int sqlite3OsLock(OsFile*, int);
-int sqlite3OsUnlock(OsFile*, int);
-int sqlite3OsLockState(OsFile *id);
-int sqlite3OsCheckReservedLock(OsFile *id);
-int sqlite3OsOpenReadWrite(const char*, OsFile**, int*);
-int sqlite3OsOpenExclusive(const char*, OsFile**, int);
-int sqlite3OsOpenReadOnly(const char*, OsFile**);
-int sqlite3OsDelete(const char*);
-int sqlite3OsFileExists(const char*);
-char *sqlite3OsFullPathname(const char*);
-int sqlite3OsIsDirWritable(char*);
-int sqlite3OsSyncDirectory(const char*);
-int sqlite3OsTempFileName(char*);
int sqlite3OsRandomSeed(char*);
int sqlite3OsSleep(int ms);
int sqlite3OsCurrentTime(double*);
+int sqlite3OsFileModTime(OsFile*, double*);
void sqlite3OsEnterMutex(void);
void sqlite3OsLeaveMutex(void);
-int sqlite3OsInMutex(void);
-ThreadData *sqlite3OsThreadSpecificData(int);
-void *sqlite3OsMalloc(int);
-void *sqlite3OsRealloc(void *, int);
-void sqlite3OsFree(void *);
-int sqlite3OsAllocationSize(void *);
-
-/*
-** If the SQLITE_ENABLE_REDEF_IO macro is defined, then the OS-layer
-** interface routines are not called directly but are invoked using
-** pointers to functions. This allows the implementation of various
-** OS-layer interface routines to be modified at run-time. There are
-** obscure but legitimate reasons for wanting to do this. But for
-** most users, a direct call to the underlying interface is preferable
-** so the the redefinable I/O interface is turned off by default.
-*/
-#ifdef SQLITE_ENABLE_REDEF_IO
-
-/*
-** When redefinable I/O is enabled, a single global instance of the
-** following structure holds pointers to the routines that SQLite
-** uses to talk with the underlying operating system. Modify this
-** structure (before using any SQLite API!) to accomodate perculiar
-** operating system interfaces or behaviors.
-*/
-struct sqlite3OsVtbl {
- int (*xOpenReadWrite)(const char*, OsFile**, int*);
- int (*xOpenExclusive)(const char*, OsFile**, int);
- int (*xOpenReadOnly)(const char*, OsFile**);
-
- int (*xDelete)(const char*);
- int (*xFileExists)(const char*);
- char *(*xFullPathname)(const char*);
- int (*xIsDirWritable)(char*);
- int (*xSyncDirectory)(const char*);
- int (*xTempFileName)(char*);
-
- int (*xRandomSeed)(char*);
- int (*xSleep)(int ms);
- int (*xCurrentTime)(double*);
-
- void (*xEnterMutex)(void);
- void (*xLeaveMutex)(void);
- int (*xInMutex)(void);
- ThreadData *(*xThreadSpecificData)(int);
-
- void *(*xMalloc)(int);
- void *(*xRealloc)(void *, int);
- void (*xFree)(void *);
- int (*xAllocationSize)(void *);
-};
-
-/* Macro used to comment out routines that do not exists when there is
-** no disk I/O
-*/
-#ifdef SQLITE_OMIT_DISKIO
-# define IF_DISKIO(X) 0
-#else
-# define IF_DISKIO(X) X
-#endif
-
-#ifdef _SQLITE_OS_C_
- /*
- ** The os.c file implements the global virtual function table.
- */
- struct sqlite3OsVtbl sqlite3Os = {
- IF_DISKIO( sqlite3OsOpenReadWrite ),
- IF_DISKIO( sqlite3OsOpenExclusive ),
- IF_DISKIO( sqlite3OsOpenReadOnly ),
- IF_DISKIO( sqlite3OsDelete ),
- IF_DISKIO( sqlite3OsFileExists ),
- IF_DISKIO( sqlite3OsFullPathname ),
- IF_DISKIO( sqlite3OsIsDirWritable ),
- IF_DISKIO( sqlite3OsSyncDirectory ),
- IF_DISKIO( sqlite3OsTempFileName ),
- sqlite3OsRandomSeed,
- sqlite3OsSleep,
- sqlite3OsCurrentTime,
- sqlite3OsEnterMutex,
- sqlite3OsLeaveMutex,
- sqlite3OsInMutex,
- sqlite3OsThreadSpecificData,
- sqlite3OsMalloc,
- sqlite3OsRealloc,
- sqlite3OsFree,
- sqlite3OsAllocationSize
- };
-#else
- /*
- ** Files other than os.c just reference the global virtual function table.
- */
- extern struct sqlite3OsVtbl sqlite3Os;
-#endif /* _SQLITE_OS_C_ */
-
-
-/* This additional API routine is available with redefinable I/O */
-struct sqlite3OsVtbl *sqlite3_os_switch(void);
-
-
-/*
-** Redefine the OS interface to go through the virtual function table
-** rather than calling routines directly.
-*/
-#undef sqlite3OsOpenReadWrite
-#undef sqlite3OsOpenExclusive
-#undef sqlite3OsOpenReadOnly
-#undef sqlite3OsDelete
-#undef sqlite3OsFileExists
-#undef sqlite3OsFullPathname
-#undef sqlite3OsIsDirWritable
-#undef sqlite3OsSyncDirectory
-#undef sqlite3OsTempFileName
-#undef sqlite3OsRandomSeed
-#undef sqlite3OsSleep
-#undef sqlite3OsCurrentTime
-#undef sqlite3OsEnterMutex
-#undef sqlite3OsLeaveMutex
-#undef sqlite3OsInMutex
-#undef sqlite3OsThreadSpecificData
-#undef sqlite3OsMalloc
-#undef sqlite3OsRealloc
-#undef sqlite3OsFree
-#undef sqlite3OsAllocationSize
-#define sqlite3OsOpenReadWrite sqlite3Os.xOpenReadWrite
-#define sqlite3OsOpenExclusive sqlite3Os.xOpenExclusive
-#define sqlite3OsOpenReadOnly sqlite3Os.xOpenReadOnly
-#define sqlite3OsDelete sqlite3Os.xDelete
-#define sqlite3OsFileExists sqlite3Os.xFileExists
-#define sqlite3OsFullPathname sqlite3Os.xFullPathname
-#define sqlite3OsIsDirWritable sqlite3Os.xIsDirWritable
-#define sqlite3OsSyncDirectory sqlite3Os.xSyncDirectory
-#define sqlite3OsTempFileName sqlite3Os.xTempFileName
-#define sqlite3OsRandomSeed sqlite3Os.xRandomSeed
-#define sqlite3OsSleep sqlite3Os.xSleep
-#define sqlite3OsCurrentTime sqlite3Os.xCurrentTime
-#define sqlite3OsEnterMutex sqlite3Os.xEnterMutex
-#define sqlite3OsLeaveMutex sqlite3Os.xLeaveMutex
-#define sqlite3OsInMutex sqlite3Os.xInMutex
-#define sqlite3OsThreadSpecificData sqlite3Os.xThreadSpecificData
-#define sqlite3OsMalloc sqlite3Os.xMalloc
-#define sqlite3OsRealloc sqlite3Os.xRealloc
-#define sqlite3OsFree sqlite3Os.xFree
-#define sqlite3OsAllocationSize sqlite3Os.xAllocationSize
-
-#endif /* SQLITE_ENABLE_REDEF_IO */
+char *sqlite3OsFullPathname(const char*);
+int sqlite3OsLock(OsFile*, int);
+int sqlite3OsUnlock(OsFile*, int);
+int sqlite3OsCheckReservedLock(OsFile *id);
#endif /* _SQLITE_OS_H_ */
Index: SQLite.Interop/src/os_common.h
==================================================================
--- SQLite.Interop/src/os_common.h
+++ SQLite.Interop/src/os_common.h
@@ -26,18 +26,10 @@
#ifdef MEMORY_DEBUG
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
#endif
-/*
- * When testing, this global variable stores the location of the
- * pending-byte in the database file.
- */
-#ifdef SQLITE_TEST
-unsigned int sqlite3_pending_byte = 0x40000000;
-#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)
@@ -86,30 +78,21 @@
** 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_hit = 0;
int sqlite3_io_error_pending = 0;
int sqlite3_diskfull_pending = 0;
-int sqlite3_diskfull = 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_hit = 1; /* Really just a place to set a breakpoint */
+ 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(); \
- sqlite3_diskfull = 1; \
- return SQLITE_FULL; \
- }else{ \
- sqlite3_diskfull_pending--; \
- } \
- }
+ if( sqlite3_diskfull_pending ) \
+ if( sqlite3_diskfull_pending-- == 1 ){ local_ioerr(); return SQLITE_FULL; }
#else
#define SimulateIOError(A)
#define SimulateDiskfullError
#endif
@@ -119,73 +102,6 @@
#ifdef SQLITE_TEST
int sqlite3_open_file_count = 0;
#define OpenCounter(X) sqlite3_open_file_count+=(X)
#else
#define OpenCounter(X)
-#endif
-
-/*
-** sqlite3GenericMalloc
-** sqlite3GenericRealloc
-** sqlite3GenericOsFree
-** sqlite3GenericAllocationSize
-**
-** Implementation of the os level dynamic memory allocation interface in terms
-** of the standard malloc(), realloc() and free() found in many operating
-** systems. No rocket science here.
-**
-** There are two versions of these four functions here. The version
-** implemented here is only used if memory-management or memory-debugging is
-** enabled. This version allocates an extra 8-bytes at the beginning of each
-** block and stores the size of the allocation there.
-**
-** If neither memory-management or debugging is enabled, the second
-** set of implementations is used instead.
-*/
-#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || defined (SQLITE_MEMDEBUG)
-void *sqlite3GenericMalloc(int n){
- char *p = (char *)malloc(n+8);
- assert(n>0);
- assert(sizeof(int)<=8);
- if( p ){
- *(int *)p = n;
- p += 8;
- }
- return (void *)p;
-}
-void *sqlite3GenericRealloc(void *p, int n){
- char *p2 = ((char *)p - 8);
- assert(n>0);
- p2 = realloc(p2, n+8);
- if( p2 ){
- *(int *)p2 = n;
- p2 += 8;
- }
- return (void *)p2;
-}
-void sqlite3GenericFree(void *p){
- assert(p);
- free((void *)((char *)p - 8));
-}
-int sqlite3GenericAllocationSize(void *p){
- return p ? *(int *)((char *)p - 8) : 0;
-}
-#else
-void *sqlite3GenericMalloc(int n){
- char *p = (char *)malloc(n);
- return (void *)p;
-}
-void *sqlite3GenericRealloc(void *p, int n){
- assert(n>0);
- p = realloc(p, n);
- return p;
-}
-void sqlite3GenericFree(void *p){
- assert(p);
- free(p);
-}
-#if 0 /* Never actually invoked */
-int sqlite3GenericAllocationSize(void *p){
- assert(0);
-}
-#endif
#endif
Index: SQLite.Interop/src/os_unix.c
==================================================================
--- SQLite.Interop/src/os_unix.c
+++ SQLite.Interop/src/os_unix.c
@@ -14,112 +14,14 @@
*/
#include "sqliteInt.h"
#include "os.h"
#if OS_UNIX /* This file is used on unix only */
-/*
-** These #defines should enable >2GB file support on Posix if the
-** underlying operating system supports it. If the OS lacks
-** large file support, 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.
-*/
-#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
-#include
-#include
-#include
-#include
-#include
+
+#include
#include
-
-/*
-** If we are to be thread-safe, include the pthreads header and define
-** the SQLITE_UNIX_THREADS macro.
-*/
-#if defined(THREADSAFE) && THREADSAFE
-# include
-# define SQLITE_UNIX_THREADS 1
-#endif
-
-/*
-** Default permissions when creating a new file
-*/
-#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
-# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644
-#endif
-
-
-
-/*
-** The unixFile structure is subclass of OsFile specific for the unix
-** protability layer.
-*/
-typedef struct unixFile unixFile;
-struct unixFile {
- IoMethod const *pMethod; /* Always the first entry */
- 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 */
- unsigned char fullSync; /* Use F_FULLSYNC if available */
- int dirfd; /* File descriptor for the directory */
-#ifdef SQLITE_UNIX_THREADS
- pthread_t tid; /* The thread that "owns" this OsFile */
-#endif
-};
-
-/*
-** Provide the ability to override some OS-layer functions during
-** testing. This is used to simulate OS crashes to verify that
-** commits are atomic even in the event of an OS crash.
-*/
-#ifdef SQLITE_CRASH_TEST
- extern int sqlite3CrashTestEnable;
- extern int sqlite3CrashOpenReadWrite(const char*, OsFile**, int*);
- extern int sqlite3CrashOpenExclusive(const char*, OsFile**, int);
- extern int sqlite3CrashOpenReadOnly(const char*, OsFile**, int);
-# define CRASH_TEST_OVERRIDE(X,A,B,C) \
- if(sqlite3CrashTestEnable){ return X(A,B,C); }
-#else
-# define CRASH_TEST_OVERRIDE(X,A,B,C) /* no-op */
-#endif
-
-
-/*
-** Include code that is common to all os_*.c files
-*/
-#include "os_common.h"
-
-/*
-** Do not include any of the File I/O interface procedures if the
-** SQLITE_OMIT_DISKIO macro is defined (indicating that the database
-** will be in-memory only)
-*/
-#ifndef SQLITE_OMIT_DISKIO
-
-
-/*
-** Define various macros that are missing from some systems.
-*/
+#include
#ifndef O_LARGEFILE
# define O_LARGEFILE 0
#endif
#ifdef SQLITE_DISABLE_LFS
# undef O_LARGEFILE
@@ -129,54 +31,41 @@
# 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 it's DOS - what did you expect?
+** DJGPP. But its DOS - what did you expect?
*/
#ifdef __DJGPP__
# define fcntl(A,B,C) 0
#endif
/*
-** The threadid macro resolves to the thread-id or to 0. Used for
-** testing and debugging only.
+** 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.
*/
-#ifdef SQLITE_UNIX_THREADS
-#define threadid pthread_self()
-#else
-#define threadid 0
+#if defined(THREADSAFE) && THREADSAFE
+# include
+# define SQLITE_UNIX_THREADS 1
#endif
+
/*
-** Set or check the OsFile.tid field. This field is set when an OsFile
-** is first opened. All subsequent uses of the OsFile verify that the
-** same thread is operating on the OsFile. Some operating systems do
-** not allow locks to be overridden by other threads and that restriction
-** means that sqlite3* database handles cannot be moved from one thread
-** to another. This logic makes sure a user does not try to do that
-** by mistake.
-**
-** Version 3.3.1 (2006-01-15): OsFiles can be moved from one thread to
-** another as long as we are running on a system that supports threads
-** overriding each others locks (which now the most common behavior)
-** or if no locks are held. But the OsFile.pLock field needs to be
-** recomputed because its key includes the thread-id. See the
-** transferOwnership() function below for additional information
+** Include code that is common to all os_*.c files
*/
-#if defined(SQLITE_UNIX_THREADS)
-# define SET_THREADID(X) (X)->tid = pthread_self()
-# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \
- !pthread_equal((X)->tid, pthread_self()))
-#else
-# define SET_THREADID(X)
-# define CHECK_THREADID(X) 0
+#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
@@ -281,18 +170,18 @@
** 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 omitted
-** if we compile without threading support.
+** 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 can override each other */
+ 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
@@ -334,13 +223,12 @@
int nPending; /* Number of pending close() operations */
int *aPending; /* Malloced space holding fd's awaiting a close() */
};
/*
-** These hash tables map inodes and file descriptors (really, lockKey and
-** openKey structures) into lockInfo and openCnt structures. Access to
-** these hash tables must be protected by a mutex.
+** 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 };
@@ -350,20 +238,12 @@
** locks.
**
** 0: No. Threads cannot override each others locks.
** 1: Yes. Threads can override each others locks.
** -1: We don't know yet.
-**
-** This variable normally has file scope only. But during testing, we make
-** it a global so that the test code can change its value in order to verify
-** that the right stuff happens in either case.
*/
-#ifdef SQLITE_TEST
-int threadsOverrideEachOthersLocks = -1;
-#else
static int threadsOverrideEachOthersLocks = -1;
-#endif
/*
** This structure holds information passed into individual test
** threads by the testThreadLockingBehavior() routine.
*/
@@ -371,69 +251,10 @@
int fd; /* File to be locked */
struct flock lock; /* The locking operation */
int result; /* Result of the locking operation */
};
-#ifdef SQLITE_LOCK_TRACE
-/*
-** Print out information about all locking operations.
-**
-** This routine is used for troubleshooting locks on multithreaded
-** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE
-** command-line option on the compiler. This code is normally
-** turned off.
-*/
-static int lockTrace(int fd, int op, struct flock *p){
- char *zOpName, *zType;
- int s;
- int savedErrno;
- if( op==F_GETLK ){
- zOpName = "GETLK";
- }else if( op==F_SETLK ){
- zOpName = "SETLK";
- }else{
- s = fcntl(fd, op, p);
- sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
- return s;
- }
- if( p->l_type==F_RDLCK ){
- zType = "RDLCK";
- }else if( p->l_type==F_WRLCK ){
- zType = "WRLCK";
- }else if( p->l_type==F_UNLCK ){
- zType = "UNLCK";
- }else{
- assert( 0 );
- }
- assert( p->l_whence==SEEK_SET );
- s = fcntl(fd, op, p);
- savedErrno = errno;
- sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
- threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
- (int)p->l_pid, s);
- if( s && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
- struct flock l2;
- l2 = *p;
- fcntl(fd, F_GETLK, &l2);
- if( l2.l_type==F_RDLCK ){
- zType = "RDLCK";
- }else if( l2.l_type==F_WRLCK ){
- zType = "WRLCK";
- }else if( l2.l_type==F_UNLCK ){
- zType = "UNLCK";
- }else{
- assert( 0 );
- }
- sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
- zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
- }
- errno = savedErrno;
- return s;
-}
-#define fcntl lockTrace
-#endif /* SQLITE_LOCK_TRACE */
-
/*
** 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
@@ -476,11 +297,10 @@
/*
** Release a lockInfo structure previously allocated by findLockInfo().
*/
static void releaseLockInfo(struct lockInfo *pLock){
- assert( sqlite3OsInMutex() );
pLock->nRef--;
if( pLock->nRef==0 ){
sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0);
sqliteFree(pLock);
}
@@ -488,23 +308,22 @@
/*
** Release a openCnt structure previously allocated by findLockInfo().
*/
static void releaseOpenCnt(struct openCnt *pOpen){
- assert( sqlite3OsInMutex() );
pOpen->nRef--;
if( pOpen->nRef==0 ){
sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0);
- free(pOpen->aPending);
+ sqliteFree(pOpen->aPending);
sqliteFree(pOpen);
}
}
/*
** Given a file descriptor, locate lockInfo and openCnt structures that
-** describes that file descriptor. Create new ones if necessary. The
-** return values might be uninitialized if an error occurs.
+** 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 */
@@ -517,12 +336,10 @@
struct stat statbuf;
struct lockInfo *pLock;
struct openCnt *pOpen;
rc = fstat(fd, &statbuf);
if( rc!=0 ) return 1;
-
- assert( sqlite3OsInMutex() );
memset(&key1, 0, sizeof(key1));
key1.dev = statbuf.st_dev;
key1.ino = statbuf.st_ino;
#ifdef SQLITE_UNIX_THREADS
if( threadsOverrideEachOthersLocks<0 ){
@@ -535,143 +352,67 @@
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 ){
- rc = 1;
- goto exit_findlockinfo;
- }
+ 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);
- rc = 1;
- goto exit_findlockinfo;
+ return 1;
}
}else{
pLock->nRef++;
}
*ppLock = pLock;
- if( ppOpen!=0 ){
- pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2));
- if( pOpen==0 ){
- struct openCnt *pOld;
- pOpen = sqliteMallocRaw( sizeof(*pOpen) );
- if( pOpen==0 ){
- releaseLockInfo(pLock);
- rc = 1;
- goto exit_findlockinfo;
- }
- 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);
- rc = 1;
- goto exit_findlockinfo;
- }
- }else{
- pOpen->nRef++;
- }
- *ppOpen = pOpen;
- }
-
-exit_findlockinfo:
- return rc;
-}
-
-#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
-
-/*
-** If we are currently in a different thread than the thread that the
-** unixFile argument belongs to, then transfer ownership of the unixFile
-** over to the current thread.
-**
-** A unixFile is only owned by a thread on systems where one thread is
-** unable to override locks created by a different thread. RedHat9 is
-** an example of such a system.
-**
-** Ownership transfer is only allowed if the unixFile is currently unlocked.
-** If the unixFile is locked and an ownership is wrong, then return
-** SQLITE_MISUSE. SQLITE_OK is returned if everything works.
-*/
-#ifdef SQLITE_UNIX_THREADS
-static int transferOwnership(unixFile *pFile){
- int rc;
- pthread_t hSelf;
- if( threadsOverrideEachOthersLocks ){
- /* Ownership transfers not needed on this system */
- return SQLITE_OK;
- }
- hSelf = pthread_self();
- if( pthread_equal(pFile->tid, hSelf) ){
- /* We are still in the same thread */
- TRACE1("No-transfer, same thread\n");
- return SQLITE_OK;
- }
- if( pFile->locktype!=NO_LOCK ){
- /* We cannot change ownership while we are holding a lock! */
- return SQLITE_MISUSE;
- }
- TRACE4("Transfer ownership of %d from %d to %d\n", pFile->h,pFile->tid,hSelf);
- pFile->tid = hSelf;
- releaseLockInfo(pFile->pLock);
- rc = findLockInfo(pFile->h, &pFile->pLock, 0);
- TRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h,
- locktypeName(pFile->locktype),
- locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
- return rc;
-}
-#else
- /* On single-threaded builds, ownership transfer is a no-op */
-# define transferOwnership(X) SQLITE_OK
-#endif
+ 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 sqlite3UnixDelete(const char *zFilename){
+int sqlite3OsDelete(const char *zFilename){
unlink(zFilename);
return SQLITE_OK;
}
/*
** Return TRUE if the named file exists.
*/
-int sqlite3UnixFileExists(const char *zFilename){
+int sqlite3OsFileExists(const char *zFilename){
return access(zFilename, 0)==0;
}
-/* Forward declaration */
-static int allocateUnixFile(unixFile *pInit, OsFile **pId);
-
/*
** 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.
**
@@ -681,48 +422,45 @@
** SQLITE_OK.
**
** On failure, the function returns SQLITE_CANTOPEN and leaves
** *id and *pReadonly unchanged.
*/
-int sqlite3UnixOpenReadWrite(
+int sqlite3OsOpenReadWrite(
const char *zFilename,
- OsFile **pId,
+ OsFile *id,
int *pReadonly
){
int rc;
- unixFile f;
-
- CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadWrite, zFilename, pId, pReadonly);
- assert( 0==*pId );
- f.dirfd = -1;
- SET_THREADID(&f);
- f.h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY,
- SQLITE_DEFAULT_FILE_PERMISSIONS);
- if( f.h<0 ){
+ 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
- f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
- if( f.h<0 ){
+ 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(f.h, &f.pLock, &f.pOpen);
+ rc = findLockInfo(id->h, &id->pLock, &id->pOpen);
sqlite3OsLeaveMutex();
if( rc ){
- close(f.h);
+ close(id->h);
return SQLITE_NOMEM;
}
- f.locktype = 0;
- TRACE3("OPEN %-3d %s\n", f.h, zFilename);
- return allocateUnixFile(&f, pId);
+ 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.
@@ -736,73 +474,67 @@
**
** On success, write the file handle into *id and return SQLITE_OK.
**
** On failure, return SQLITE_CANTOPEN.
*/
-int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
+int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
int rc;
- unixFile f;
-
- CRASH_TEST_OVERRIDE(sqlite3CrashOpenExclusive, zFilename, pId, delFlag);
- assert( 0==*pId );
+ assert( !id->isOpen );
if( access(zFilename, 0)==0 ){
return SQLITE_CANTOPEN;
}
- SET_THREADID(&f);
- f.dirfd = -1;
- f.h = open(zFilename,
- O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY,
- SQLITE_DEFAULT_FILE_PERMISSIONS);
- if( f.h<0 ){
+ 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(f.h, &f.pLock, &f.pOpen);
+ rc = findLockInfo(id->h, &id->pLock, &id->pOpen);
sqlite3OsLeaveMutex();
if( rc ){
- close(f.h);
+ close(id->h);
unlink(zFilename);
return SQLITE_NOMEM;
}
- f.locktype = 0;
+ id->locktype = 0;
+ id->isOpen = 1;
if( delFlag ){
unlink(zFilename);
}
- TRACE3("OPEN-EX %-3d %s\n", f.h, zFilename);
- return allocateUnixFile(&f, pId);
+ 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 sqlite3UnixOpenReadOnly(const char *zFilename, OsFile **pId){
+int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){
int rc;
- unixFile f;
-
- CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadOnly, zFilename, pId, 0);
- assert( 0==*pId );
- SET_THREADID(&f);
- f.dirfd = -1;
- f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
- if( f.h<0 ){
+ 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(f.h, &f.pLock, &f.pOpen);
+ rc = findLockInfo(id->h, &id->pLock, &id->pOpen);
sqlite3OsLeaveMutex();
if( rc ){
- close(f.h);
+ close(id->h);
return SQLITE_NOMEM;
}
- f.locktype = 0;
- TRACE3("OPEN-RO %-3d %s\n", f.h, zFilename);
-
- return allocateUnixFile(&f, pId);
+ 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
@@ -810,51 +542,47 @@
** 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 at *id is
+** 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.
*/
-static int unixOpenDirectory(
- OsFile *id,
- const char *zDirname
+int sqlite3OsOpenDirectory(
+ const char *zDirname,
+ OsFile *id
){
- unixFile *pFile = (unixFile*)id;
- if( pFile==0 ){
+ if( !id->isOpen ){
/* Do not open the directory if the corresponding file is not already
** open. */
return SQLITE_CANTOPEN;
}
- SET_THREADID(pFile);
- assert( pFile->dirfd<0 );
- pFile->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0);
- if( pFile->dirfd<0 ){
+ 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", pFile->dirfd, zDirname);
+ 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.
-**
-** See also the "PRAGMA temp_store_directory" SQL command.
*/
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 sqlite3UnixTempFileName(char *zBuf){
+int sqlite3OsTempFileName(char *zBuf){
static const char *azDirs[] = {
0,
"/var/tmp",
"/usr/tmp",
"/tmp",
@@ -886,40 +614,39 @@
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 sqlite3UnixIsDirWritable(char *zBuf){
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+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;
-#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
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.
*/
-static int unixRead(OsFile *id, void *pBuf, int amt){
+int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
int got;
- assert( id );
+ assert( id->isOpen );
SimulateIOError(SQLITE_IOERR);
TIMER_START;
- got = read(((unixFile*)id)->h, pBuf, amt);
+ got = read(id->h, pBuf, amt);
TIMER_END;
- TRACE5("READ %-3d %5d %7d %d\n", ((unixFile*)id)->h, got,
- last_page, TIMER_ELAPSED);
+ 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{
@@ -929,24 +656,23 @@
/*
** Write data from a buffer into a file. Return SQLITE_OK on success
** or some other error code on failure.
*/
-static int unixWrite(OsFile *id, const void *pBuf, int amt){
+int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
int wrote = 0;
- assert( id );
+ assert( id->isOpen );
assert( amt>0 );
SimulateIOError(SQLITE_IOERR);
SimulateDiskfullError;
TIMER_START;
- while( amt>0 && (wrote = write(((unixFile*)id)->h, pBuf, amt))>0 ){
+ while( amt>0 && (wrote = write(id->h, pBuf, amt))>0 ){
amt -= wrote;
pBuf = &((char*)pBuf)[wrote];
}
TIMER_END;
- TRACE5("WRITE %-3d %5d %7d %d\n", ((unixFile*)id)->h, wrote,
- last_page, TIMER_ELAPSED);
+ TRACE4("WRITE %-3d %7d %d\n", id->h, last_page, TIMER_ELAPSED);
SEEK(0);
if( amt>0 ){
return SQLITE_FULL;
}
return SQLITE_OK;
@@ -953,37 +679,16 @@
}
/*
** Move the read/write pointer in a file.
*/
-static int unixSeek(OsFile *id, i64 offset){
- assert( id );
+int sqlite3OsSeek(OsFile *id, i64 offset){
+ assert( id->isOpen );
SEEK(offset/1024 + 1);
-#ifdef SQLITE_TEST
- if( offset ) SimulateDiskfullError
-#endif
- lseek(((unixFile*)id)->h, offset, SEEK_SET);
+ lseek(id->h, offset, SEEK_SET);
return SQLITE_OK;
}
-
-#ifdef SQLITE_TEST
-/*
-** Count the number of fullsyncs and normal syncs. This is used to test
-** that syncs and fullsyncs are occuring at the right times.
-*/
-int sqlite3_sync_count = 0;
-int sqlite3_fullsync_count = 0;
-#endif
-
-/*
-** Use the fdatasync() API only if the HAVE_FDATASYNC macro is defined.
-** Otherwise use fsync() in its place.
-*/
-#ifndef HAVE_FDATASYNC
-# define fdatasync fsync
-#endif
-
/*
** The fsync() system call does not work as advertised on many
** unix systems. The following procedure is an attempt to make
** it work better.
@@ -992,129 +697,87 @@
** 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, int fullSync, int dataOnly){
+static int full_fsync(int fd){
+#ifdef SQLITE_NO_SYNC
+ return SQLITE_OK;
+#else
int rc;
-
- /* Record the number of times that we do a normal fsync() and
- ** FULLSYNC. This is used during testing to verify that this procedure
- ** gets called with the correct arguments.
- */
-#ifdef SQLITE_TEST
- if( fullSync ) sqlite3_fullsync_count++;
- sqlite3_sync_count++;
-#endif
-
- /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
- ** no-op
- */
-#ifdef SQLITE_NO_SYNC
- rc = SQLITE_OK;
+#ifdef F_FULLFSYNC
+ rc = fcntl(fd, F_FULLFSYNC, 0);
+ if( rc ) rc = fsync(fd);
#else
-
-#ifdef F_FULLFSYNC
- if( fullSync ){
- rc = fcntl(fd, F_FULLFSYNC, 0);
- }else{
- rc = 1;
- }
- /* If the FULLSYNC failed, try to do a normal fsync() */
- if( rc ) rc = fsync(fd);
-
-#else /* if !defined(F_FULLSYNC) */
- if( dataOnly ){
- rc = fdatasync(fd);
- }else{
- rc = fsync(fd);
- }
-#endif /* defined(F_FULLFSYNC) */
-#endif /* defined(SQLITE_NO_SYNC) */
-
+ rc = fsync(fd);
+#endif
return rc;
+#endif
}
/*
** Make sure all writes to a particular file are committed to disk.
**
-** If dataOnly==0 then both the file itself and its metadata (file
-** size, access time, etc) are synced. If dataOnly!=0 then only the
-** file data is synced.
-**
** 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.
*/
-static int unixSync(OsFile *id, int dataOnly){
- unixFile *pFile = (unixFile*)id;
- assert( pFile );
- SimulateIOError(SQLITE_IOERR);
- TRACE2("SYNC %-3d\n", pFile->h);
- if( full_fsync(pFile->h, pFile->fullSync, dataOnly) ){
- return SQLITE_IOERR;
- }
- if( pFile->dirfd>=0 ){
- TRACE2("DIRSYNC %-3d\n", pFile->dirfd);
-#ifndef SQLITE_DISABLE_DIRSYNC
- if( full_fsync(pFile->dirfd, pFile->fullSync, 0) ){
- return SQLITE_IOERR;
- }
-#endif
- close(pFile->dirfd); /* Only need to sync once, so close the directory */
- pFile->dirfd = -1; /* when we are done. */
+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.
-**
-** This is used to make sure the master journal file has truely been deleted
-** before making changes to individual journals on a multi-database commit.
-** The F_FULLFSYNC option is not needed here.
*/
-int sqlite3UnixSyncDirectory(const char *zDirname){
-#ifdef SQLITE_DISABLE_DIRSYNC
- return SQLITE_OK;
-#else
+int sqlite3OsSyncDirectory(const char *zDirname){
int fd;
int r;
SimulateIOError(SQLITE_IOERR);
- fd = open(zDirname, O_RDONLY|O_BINARY, 0);
+ 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);
-#endif
}
/*
** Truncate an open file to a specified size
*/
-static int unixTruncate(OsFile *id, i64 nByte){
- assert( id );
+int sqlite3OsTruncate(OsFile *id, i64 nByte){
+ assert( id->isOpen );
SimulateIOError(SQLITE_IOERR);
- return ftruncate(((unixFile*)id)->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;
+ return ftruncate(id->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;
}
/*
** Determine the current size of a file in bytes
*/
-static int unixFileSize(OsFile *id, i64 *pSize){
+int sqlite3OsFileSize(OsFile *id, i64 *pSize){
struct stat buf;
- assert( id );
+ assert( id->isOpen );
SimulateIOError(SQLITE_IOERR);
- if( fstat(((unixFile*)id)->h, &buf)!=0 ){
+ if( fstat(id->h, &buf)!=0 ){
return SQLITE_IOERR;
}
*pSize = buf.st_size;
return SQLITE_OK;
}
@@ -1123,19 +786,18 @@
** 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.
*/
-static int unixCheckReservedLock(OsFile *id){
+int sqlite3OsCheckReservedLock(OsFile *id){
int r = 0;
- unixFile *pFile = (unixFile*)id;
- assert( pFile );
- sqlite3OsEnterMutex(); /* Because pFile->pLock is shared across threads */
+ assert( id->isOpen );
+ sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads */
/* Check if a thread in this process holds such a lock */
- if( pFile->pLock->locktype>SHARED_LOCK ){
+ if( id->pLock->locktype>SHARED_LOCK ){
r = 1;
}
/* Otherwise see if some other process holds it.
*/
@@ -1143,21 +805,39 @@
struct flock lock;
lock.l_whence = SEEK_SET;
lock.l_start = RESERVED_BYTE;
lock.l_len = 1;
lock.l_type = F_WRLCK;
- fcntl(pFile->h, F_GETLK, &lock);
+ fcntl(id->h, F_GETLK, &lock);
if( lock.l_type!=F_UNLCK ){
r = 1;
}
}
sqlite3OsLeaveMutex();
- TRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
+ 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:
**
@@ -1179,11 +859,11 @@
** PENDING -> EXCLUSIVE
**
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
-static int unixLock(OsFile *id, int locktype){
+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
@@ -1219,53 +899,42 @@
** 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;
- unixFile *pFile = (unixFile*)id;
- struct lockInfo *pLock = pFile->pLock;
+ struct lockInfo *pLock = id->pLock;
struct flock lock;
int s;
- assert( pFile );
- TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h,
- locktypeName(locktype), locktypeName(pFile->locktype),
- locktypeName(pLock->locktype), pLock->cnt , getpid());
+ 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( pFile->locktype>=locktype ){
- TRACE3("LOCK %d %s ok (already held)\n", pFile->h,
- locktypeName(locktype));
+ 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( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
+ assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK );
assert( locktype!=PENDING_LOCK );
- assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
+ assert( locktype!=RESERVED_LOCK || id->locktype==SHARED_LOCK );
- /* This mutex is needed because pFile->pLock is shared across threads
+ /* This mutex is needed because id->pLock is shared across threads
*/
sqlite3OsEnterMutex();
- /* Make sure the current thread owns the pFile.
- */
- rc = transferOwnership(pFile);
- if( rc!=SQLITE_OK ){
- sqlite3OsLeaveMutex();
- return rc;
- }
- pLock = pFile->pLock;
-
/* If some thread using this PID has a lock via a different OsFile*
** handle that precludes the requested lock, return BUSY.
*/
- if( (pFile->locktype!=pLock->locktype &&
+ if( (id->locktype!=pLock->locktype &&
(pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK))
){
rc = SQLITE_BUSY;
goto end_lock;
}
@@ -1275,32 +944,31 @@
** return SQLITE_OK.
*/
if( locktype==SHARED_LOCK &&
(pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){
assert( locktype==SHARED_LOCK );
- assert( pFile->locktype==0 );
+ assert( id->locktype==0 );
assert( pLock->cnt>0 );
- pFile->locktype = SHARED_LOCK;
+ id->locktype = SHARED_LOCK;
pLock->cnt++;
- pFile->pOpen->nLock++;
+ 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 && pFile->locktypelocktypeh, F_SETLK, &lock);
+ s = fcntl(id->h, F_SETLK, &lock);
if( s ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
goto end_lock;
}
}
@@ -1314,25 +982,22 @@
assert( pLock->locktype==0 );
/* Now get the read-lock */
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
- s = fcntl(pFile->h, F_SETLK, &lock);
+ 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;
- if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){
- rc = SQLITE_IOERR; /* This should never happen */
- goto end_lock;
- }
+ fcntl(id->h, F_SETLK, &lock);
if( s ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}else{
- pFile->locktype = SHARED_LOCK;
- pFile->pOpen->nLock++;
+ 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. */
@@ -1340,11 +1005,11 @@
}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!=pFile->locktype );
+ assert( 0!=id->locktype );
lock.l_type = F_WRLCK;
switch( locktype ){
case RESERVED_LOCK:
lock.l_start = RESERVED_BYTE;
break;
@@ -1353,79 +1018,76 @@
lock.l_len = SHARED_SIZE;
break;
default:
assert(0);
}
- s = fcntl(pFile->h, F_SETLK, &lock);
+ s = fcntl(id->h, F_SETLK, &lock);
if( s ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}
}
if( rc==SQLITE_OK ){
- pFile->locktype = locktype;
+ id->locktype = locktype;
pLock->locktype = locktype;
}else if( locktype==EXCLUSIVE_LOCK ){
- pFile->locktype = PENDING_LOCK;
+ id->locktype = PENDING_LOCK;
pLock->locktype = PENDING_LOCK;
}
end_lock:
sqlite3OsLeaveMutex();
- TRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
+ TRACE4("LOCK %d %s %s\n", id->h, locktypeName(locktype),
rc==SQLITE_OK ? "ok" : "failed");
return rc;
}
/*
-** Lower the locking level on file descriptor pFile to locktype. locktype
+** 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.
*/
-static int unixUnlock(OsFile *id, int locktype){
+int sqlite3OsUnlock(OsFile *id, int locktype){
struct lockInfo *pLock;
struct flock lock;
int rc = SQLITE_OK;
- unixFile *pFile = (unixFile*)id;
- assert( pFile );
- TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype,
- pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid());
+ 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( pFile->locktype<=locktype ){
+ if( id->locktype<=locktype ){
return SQLITE_OK;
}
- if( CHECK_THREADID(pFile) ){
- return SQLITE_MISUSE;
- }
sqlite3OsEnterMutex();
- pLock = pFile->pLock;
+ pLock = id->pLock;
assert( pLock->cnt!=0 );
- if( pFile->locktype>SHARED_LOCK ){
- assert( pLock->locktype==pFile->locktype );
+ 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(pFile->h, F_SETLK, &lock)!=0 ){
+ 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 );
- if( fcntl(pFile->h, F_SETLK, &lock)==0 ){
- pLock->locktype = SHARED_LOCK;
- }else{
- rc = SQLITE_IOERR; /* This should never happen */
- }
+ 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
@@ -1435,210 +1097,99 @@
pLock->cnt--;
if( pLock->cnt==0 ){
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
- if( fcntl(pFile->h, F_SETLK, &lock)==0 ){
- pLock->locktype = NO_LOCK;
- }else{
- rc = SQLITE_IOERR; /* This should never happen */
- }
+ 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 = pFile->pOpen;
+ pOpen = id->pOpen;
pOpen->nLock--;
assert( pOpen->nLock>=0 );
if( pOpen->nLock==0 && pOpen->nPending>0 ){
int i;
for(i=0; inPending; i++){
close(pOpen->aPending[i]);
}
- free(pOpen->aPending);
+ sqliteFree(pOpen->aPending);
pOpen->nPending = 0;
pOpen->aPending = 0;
}
}
sqlite3OsLeaveMutex();
- pFile->locktype = locktype;
+ id->locktype = locktype;
return rc;
}
/*
** Close a file.
*/
-static int unixClose(OsFile **pId){
- unixFile *id = (unixFile*)*pId;
- int rc;
-
- if( !id ) return SQLITE_OK;
- unixUnlock(*pId, NO_LOCK);
+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;
- aNew = realloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
+ 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] = id->h;
- pOpen->nPending++;
+ 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);
- sqliteFree(id);
- *pId = 0;
- return rc;
-}
-
-/*
-** 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 *sqlite3UnixFullPathname(const char *zRelative){
- char *zFull = 0;
- if( zRelative[0]=='/' ){
- sqlite3SetString(&zFull, zRelative, (char*)0);
- }else{
- char *zBuf = sqliteMalloc(5000);
- if( zBuf==0 ){
- return 0;
- }
- zBuf[0] = 0;
- sqlite3SetString(&zFull, getcwd(zBuf, 5000), "/", zRelative,
- (char*)0);
- sqliteFree(zBuf);
- }
- return zFull;
-}
-
-/*
-** Change the value of the fullsync flag in the given file descriptor.
-*/
-static void unixSetFullSync(OsFile *id, int v){
- ((unixFile*)id)->fullSync = v;
-}
-
-/*
-** Return the underlying file handle for an OsFile
-*/
-static int unixFileHandle(OsFile *id){
- return ((unixFile*)id)->h;
-}
-
-/*
-** Return an integer that indices the type of lock currently held
-** by this handle. (Used for testing and analysis only.)
-*/
-static int unixLockState(OsFile *id){
- return ((unixFile*)id)->locktype;
-}
-
-/*
-** This vector defines all the methods that can operate on an OsFile
-** for unix.
-*/
-static const IoMethod sqlite3UnixIoMethod = {
- unixClose,
- unixOpenDirectory,
- unixRead,
- unixWrite,
- unixSeek,
- unixTruncate,
- unixSync,
- unixSetFullSync,
- unixFileHandle,
- unixFileSize,
- unixLock,
- unixUnlock,
- unixLockState,
- unixCheckReservedLock,
-};
-
-/*
-** Allocate memory for a unixFile. Initialize the new unixFile
-** to the value given in pInit and return a pointer to the new
-** OsFile. If we run out of memory, close the file and return NULL.
-*/
-static int allocateUnixFile(unixFile *pInit, OsFile **pId){
- unixFile *pNew;
- pNew = sqliteMalloc( sizeof(unixFile) );
- if( pNew==0 ){
- close(pInit->h);
- sqlite3OsEnterMutex();
- releaseLockInfo(pInit->pLock);
- releaseOpenCnt(pInit->pOpen);
- sqlite3OsLeaveMutex();
- *pId = 0;
- return SQLITE_NOMEM;
- }else{
- *pNew = *pInit;
- pNew->pMethod = &sqlite3UnixIoMethod;
- *pId = (OsFile*)pNew;
- OpenCounter(+1);
- return SQLITE_OK;
- }
-}
-
-
-#endif /* SQLITE_OMIT_DISKIO */
-/***************************************************************************
-** Everything above deals with file I/O. Everything that follows deals
-** with other miscellanous aspects of the operating system interface
-****************************************************************************/
-
+ 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 sqlite3UnixRandomSeed(char *zBuf){
+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
+ ** 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_t t;
- time(&t);
- memcpy(zBuf, &t, sizeof(t));
+ time((time_t*)zBuf);
pid = getpid();
memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid));
}else{
read(fd, zBuf, 256);
close(fd);
@@ -1648,13 +1199,12 @@
return SQLITE_OK;
}
/*
** Sleep for a little while. Return the amount of time slept.
-** The argument is the number of milliseconds we want to sleep.
*/
-int sqlite3UnixSleep(int ms){
+int sqlite3OsSleep(int ms){
#if defined(HAVE_USLEEP) && HAVE_USLEEP
usleep(ms*1000);
return ms;
#else
sleep((ms+999)/1000);
@@ -1675,127 +1225,42 @@
** 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.
-**
-** This mutex is not recursive.
*/
-void sqlite3UnixEnterMutex(){
+void sqlite3OsEnterMutex(){
#ifdef SQLITE_UNIX_THREADS
pthread_mutex_lock(&mutex);
#endif
assert( !inMutex );
inMutex = 1;
}
-void sqlite3UnixLeaveMutex(){
+void sqlite3OsLeaveMutex(){
assert( inMutex );
inMutex = 0;
#ifdef SQLITE_UNIX_THREADS
pthread_mutex_unlock(&mutex);
#endif
}
/*
-** Return TRUE if we are currently within the mutex and FALSE if not.
-*/
-int sqlite3UnixInMutex(){
- return inMutex;
-}
-
-/*
-** Remember the number of thread-specific-data blocks allocated.
-** Use this to verify that we are not leaking thread-specific-data.
-** Ticket #1601
-*/
-#ifdef SQLITE_TEST
-int sqlite3_tsd_count = 0;
-# ifdef SQLITE_UNIX_THREADS
- static pthread_mutex_t tsd_counter_mutex = PTHREAD_MUTEX_INITIALIZER;
-# define TSD_COUNTER(N) \
- pthread_mutex_lock(&tsd_counter_mutex); \
- sqlite3_tsd_count += N; \
- pthread_mutex_unlock(&tsd_counter_mutex);
-# else
-# define TSD_COUNTER(N) sqlite3_tsd_count += N
-# endif
-#else
-# define TSD_COUNTER(N) /* no-op */
-#endif
-
-
-/*
-** If called with allocateFlag>0, then return a pointer to thread
-** specific data for the current thread. Allocate and zero the
-** thread-specific data if it does not already exist.
-**
-** If called with allocateFlag==0, then check the current thread
-** specific data. Return it if it exists. If it does not exist,
-** then return NULL.
-**
-** If called with allocateFlag<0, check to see if the thread specific
-** data is allocated and is all zero. If it is then deallocate it.
-** Return a pointer to the thread specific data or NULL if it is
-** unallocated or gets deallocated.
-*/
-ThreadData *sqlite3UnixThreadSpecificData(int allocateFlag){
- static const ThreadData zeroData;
-#ifdef SQLITE_UNIX_THREADS
- static pthread_key_t key;
- static int keyInit = 0;
- ThreadData *pTsd;
-
- if( !keyInit ){
- sqlite3OsEnterMutex();
- if( !keyInit ){
- int rc;
- rc = pthread_key_create(&key, 0);
- if( rc ){
- sqlite3OsLeaveMutex();
- return 0;
- }
- keyInit = 1;
- }
- sqlite3OsLeaveMutex();
- }
-
- pTsd = pthread_getspecific(key);
- if( allocateFlag>0 ){
- if( pTsd==0 ){
- pTsd = sqlite3OsMalloc(sizeof(zeroData));
- if( pTsd ){
- *pTsd = zeroData;
- pthread_setspecific(key, pTsd);
- TSD_COUNTER(+1);
- }
- }
- }else if( pTsd!=0 && allocateFlag<0
- && memcmp(pTsd, &zeroData, sizeof(zeroData))==0 ){
- sqlite3OsFree(pTsd);
- pthread_setspecific(key, 0);
- TSD_COUNTER(-1);
- pTsd = 0;
- }
- return pTsd;
-#else
- static ThreadData *pTsd = 0;
- if( allocateFlag>0 ){
- if( pTsd==0 ){
- pTsd = sqlite3OsMalloc( sizeof(zeroData) );
- if( pTsd ){
- *pTsd = zeroData;
- TSD_COUNTER(+1);
- }
- }
- }else if( pTsd!=0 && allocateFlag<0
- && memcmp(pTsd, &zeroData, sizeof(zeroData))==0 ){
- sqlite3OsFree(pTsd);
- TSD_COUNTER(-1);
- pTsd = 0;
- }
- return pTsd;
-#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.
@@ -1807,25 +1272,38 @@
/*
** 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 sqlite3UnixCurrentTime(double *prNow){
-#ifdef NO_GETTOD
+int sqlite3OsCurrentTime(double *prNow){
time_t t;
time(&t);
*prNow = t/86400.0 + 2440587.5;
-#else
- struct timeval sNow;
- struct timezone sTz; /* Not used */
- gettimeofday(&sNow, &sTz);
- *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_usec/86400000000.0;
-#endif
#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
Index: SQLite.Interop/src/os_unix.h
==================================================================
--- /dev/null
+++ SQLite.Interop/src/os_unix.h
@@ -0,0 +1,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
+#include
+#include
+#include
+
+/*
+** 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_ */
Index: SQLite.Interop/src/os_win.c
==================================================================
--- SQLite.Interop/src/os_win.c
+++ SQLite.Interop/src/os_win.c
@@ -16,14 +16,10 @@
#include "os.h"
#if OS_WIN /* This file is used for windows only */
#include
-#ifdef __CYGWIN__
-# include
-#endif
-
/*
** Macros used to determine whether or not to use threads.
*/
#if defined(THREADSAFE) && THREADSAFE
# define SQLITE_W32_THREADS 1
@@ -32,491 +28,25 @@
/*
** Include code that is common to all os_*.c files
*/
#include "os_common.h"
-/*
-** Determine if we are dealing with WindowsCE - which has a much
-** reduced API.
-*/
-#if defined(_WIN32_WCE)
-# define OS_WINCE 1
-#else
-# define OS_WINCE 0
-#endif
-
-/*
-** WinCE lacks native support for file locking so we have to fake it
-** with some code of our own.
-*/
-#if OS_WINCE
-typedef struct winceLock {
- int nReaders; /* Number of reader locks obtained */
- BOOL bPending; /* Indicates a pending lock has been obtained */
- BOOL bReserved; /* Indicates a reserved lock has been obtained */
- BOOL bExclusive; /* Indicates an exclusive lock has been obtained */
-} winceLock;
-#endif
-
-/*
-** The winFile structure is a subclass of OsFile specific to the win32
-** portability layer.
-*/
-typedef struct winFile winFile;
-struct winFile {
- IoMethod const *pMethod;/* Must be first */
- HANDLE h; /* Handle for accessing the file */
- unsigned char locktype; /* Type of lock currently held on this file */
- short sharedLockByte; /* Randomly chosen byte used as a shared lock */
-#if OS_WINCE
- WCHAR *zDeleteOnClose; /* Name of file to delete when closing */
- HANDLE hMutex; /* Mutex used to control access to shared lock */
- HANDLE hShared; /* Shared memory segment used for locking */
- winceLock local; /* Locks obtained by this instance of winFile */
- winceLock *shared; /* Global shared lock memory for the file */
-#endif
-};
-
-
-/*
-** Do not include any of the File I/O interface procedures if the
-** SQLITE_OMIT_DISKIO macro is defined (indicating that there database
-** will be in-memory only)
-*/
-#ifndef SQLITE_OMIT_DISKIO
-
-/*
-** The following variable is (normally) set once and never changes
-** thereafter. It records whether the operating system is Win95
-** or WinNT.
-**
-** 0: Operating system unknown.
-** 1: Operating system is Win95.
-** 2: Operating system is WinNT.
-**
-** In order to facilitate testing on a WinNT system, the test fixture
-** can manually set this value to 1 to emulate Win98 behavior.
-*/
-int sqlite3_os_type = 0;
-
-/*
-** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
-** or WinCE. 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.
-*/
-#if OS_WINCE
-# define isNT() (1)
-#else
- static int isNT(void){
- if( sqlite3_os_type==0 ){
- OSVERSIONINFO sInfo;
- sInfo.dwOSVersionInfoSize = sizeof(sInfo);
- GetVersionEx(&sInfo);
- sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
- }
- return sqlite3_os_type==2;
- }
-#endif /* OS_WINCE */
-
-/*
-** Convert a UTF-8 string to UTF-32. Space to hold the returned string
-** is obtained from sqliteMalloc.
-*/
-static WCHAR *utf8ToUnicode(const char *zFilename){
- int nByte;
- WCHAR *zWideFilename;
-
- if( !isNT() ){
- return 0;
- }
- nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0)*sizeof(WCHAR);
- zWideFilename = sqliteMalloc( nByte*sizeof(zWideFilename[0]) );
- if( zWideFilename==0 ){
- return 0;
- }
- nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nByte);
- if( nByte==0 ){
- sqliteFree(zWideFilename);
- zWideFilename = 0;
- }
- return zWideFilename;
-}
-
-/*
-** Convert UTF-32 to UTF-8. Space to hold the returned string is
-** obtained from sqliteMalloc().
-*/
-static char *unicodeToUtf8(const WCHAR *zWideFilename){
- int nByte;
- char *zFilename;
-
- nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
- zFilename = sqliteMalloc( nByte );
- if( zFilename==0 ){
- return 0;
- }
- nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
- 0, 0);
- if( nByte == 0 ){
- sqliteFree(zFilename);
- zFilename = 0;
- }
- return zFilename;
-}
-
-#if OS_WINCE
-/*************************************************************************
-** This section contains code for WinCE only.
-*/
-/*
-** WindowsCE does not have a localtime() function. So create a
-** substitute.
-*/
-#include
-struct tm *__cdecl localtime(const time_t *t)
-{
- static struct tm y;
- FILETIME uTm, lTm;
- SYSTEMTIME pTm;
- i64 t64;
- t64 = *t;
- t64 = (t64 + 11644473600)*10000000;
- uTm.dwLowDateTime = t64 & 0xFFFFFFFF;
- uTm.dwHighDateTime= t64 >> 32;
- FileTimeToLocalFileTime(&uTm,&lTm);
- FileTimeToSystemTime(&lTm,&pTm);
- y.tm_year = pTm.wYear - 1900;
- y.tm_mon = pTm.wMonth - 1;
- y.tm_wday = pTm.wDayOfWeek;
- y.tm_mday = pTm.wDay;
- y.tm_hour = pTm.wHour;
- y.tm_min = pTm.wMinute;
- y.tm_sec = pTm.wSecond;
- return &y;
-}
-
-/* This will never be called, but defined to make the code compile */
-#define GetTempPathA(a,b)
-
-#define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e)
-#define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e)
-#define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f)
-
-#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-offsetof(winFile,h)]
-
-/*
-** Acquire a lock on the handle h
-*/
-static void winceMutexAcquire(HANDLE h){
- DWORD dwErr;
- do {
- dwErr = WaitForSingleObject(h, INFINITE);
- } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
-}
-/*
-** Release a lock acquired by winceMutexAcquire()
-*/
-#define winceMutexRelease(h) ReleaseMutex(h)
-
-/*
-** Create the mutex and shared memory used for locking in the file
-** descriptor pFile
-*/
-static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
- WCHAR *zTok;
- WCHAR *zName = utf8ToUnicode(zFilename);
- BOOL bInit = TRUE;
-
- /* Initialize the local lockdata */
- ZeroMemory(&pFile->local, sizeof(pFile->local));
-
- /* Replace the backslashes from the filename and lowercase it
- ** to derive a mutex name. */
- zTok = CharLowerW(zName);
- for (;*zTok;zTok++){
- if (*zTok == '\\') *zTok = '_';
- }
-
- /* Create/open the named mutex */
- pFile->hMutex = CreateMutexW(NULL, FALSE, zName);
- if (!pFile->hMutex){
- sqliteFree(zName);
- return FALSE;
- }
-
- /* Acquire the mutex before continuing */
- winceMutexAcquire(pFile->hMutex);
-
- /* Since the names of named mutexes, semaphores, file mappings etc are
- ** case-sensitive, take advantage of that by uppercasing the mutex name
- ** and using that as the shared filemapping name.
- */
- CharUpperW(zName);
- pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
- PAGE_READWRITE, 0, sizeof(winceLock),
- zName);
-
- /* Set a flag that indicates we're the first to create the memory so it
- ** must be zero-initialized */
- if (GetLastError() == ERROR_ALREADY_EXISTS){
- bInit = FALSE;
- }
-
- sqliteFree(zName);
-
- /* If we succeeded in making the shared memory handle, map it. */
- if (pFile->hShared){
- pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared,
- FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
- /* If mapping failed, close the shared memory handle and erase it */
- if (!pFile->shared){
- CloseHandle(pFile->hShared);
- pFile->hShared = NULL;
- }
- }
-
- /* If shared memory could not be created, then close the mutex and fail */
- if (pFile->hShared == NULL){
- winceMutexRelease(pFile->hMutex);
- CloseHandle(pFile->hMutex);
- pFile->hMutex = NULL;
- return FALSE;
- }
-
- /* Initialize the shared memory if we're supposed to */
- if (bInit) {
- ZeroMemory(pFile->shared, sizeof(winceLock));
- }
-
- winceMutexRelease(pFile->hMutex);
- return TRUE;
-}
-
-/*
-** Destroy the part of winFile that deals with wince locks
-*/
-static void winceDestroyLock(winFile *pFile){
- if (pFile->hMutex){
- /* Acquire the mutex */
- winceMutexAcquire(pFile->hMutex);
-
- /* The following blocks should probably assert in debug mode, but they
- are to cleanup in case any locks remained open */
- if (pFile->local.nReaders){
- pFile->shared->nReaders --;
- }
- if (pFile->local.bReserved){
- pFile->shared->bReserved = FALSE;
- }
- if (pFile->local.bPending){
- pFile->shared->bPending = FALSE;
- }
- if (pFile->local.bExclusive){
- pFile->shared->bExclusive = FALSE;
- }
-
- /* De-reference and close our copy of the shared memory handle */
- UnmapViewOfFile(pFile->shared);
- CloseHandle(pFile->hShared);
-
- /* Done with the mutex */
- winceMutexRelease(pFile->hMutex);
- CloseHandle(pFile->hMutex);
- pFile->hMutex = NULL;
- }
-}
-
-/*
-** An implementation of the LockFile() API of windows for wince
-*/
-static BOOL winceLockFile(
- HANDLE *phFile,
- DWORD dwFileOffsetLow,
- DWORD dwFileOffsetHigh,
- DWORD nNumberOfBytesToLockLow,
- DWORD nNumberOfBytesToLockHigh
-){
- winFile *pFile = HANDLE_TO_WINFILE(phFile);
- BOOL bReturn = FALSE;
-
- if (!pFile->hMutex) return TRUE;
- winceMutexAcquire(pFile->hMutex);
-
- /* Wanting an exclusive lock? */
- if (dwFileOffsetLow == SHARED_FIRST
- && nNumberOfBytesToLockLow == SHARED_SIZE){
- if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
- pFile->shared->bExclusive = TRUE;
- pFile->local.bExclusive = TRUE;
- bReturn = TRUE;
- }
- }
-
- /* Want a read-only lock? */
- else if ((dwFileOffsetLow >= SHARED_FIRST &&
- dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE) &&
- nNumberOfBytesToLockLow == 1){
- if (pFile->shared->bExclusive == 0){
- pFile->local.nReaders ++;
- if (pFile->local.nReaders == 1){
- pFile->shared->nReaders ++;
- }
- bReturn = TRUE;
- }
- }
-
- /* Want a pending lock? */
- else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToLockLow == 1){
- /* If no pending lock has been acquired, then acquire it */
- if (pFile->shared->bPending == 0) {
- pFile->shared->bPending = TRUE;
- pFile->local.bPending = TRUE;
- bReturn = TRUE;
- }
- }
- /* Want a reserved lock? */
- else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToLockLow == 1){
- if (pFile->shared->bReserved == 0) {
- pFile->shared->bReserved = TRUE;
- pFile->local.bReserved = TRUE;
- bReturn = TRUE;
- }
- }
-
- winceMutexRelease(pFile->hMutex);
- return bReturn;
-}
-
-/*
-** An implementation of the UnlockFile API of windows for wince
-*/
-static BOOL winceUnlockFile(
- HANDLE *phFile,
- DWORD dwFileOffsetLow,
- DWORD dwFileOffsetHigh,
- DWORD nNumberOfBytesToUnlockLow,
- DWORD nNumberOfBytesToUnlockHigh
-){
- winFile *pFile = HANDLE_TO_WINFILE(phFile);
- BOOL bReturn = FALSE;
-
- if (!pFile->hMutex) return TRUE;
- winceMutexAcquire(pFile->hMutex);
-
- /* Releasing a reader lock or an exclusive lock */
- if (dwFileOffsetLow >= SHARED_FIRST &&
- dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE){
- /* Did we have an exclusive lock? */
- if (pFile->local.bExclusive){
- pFile->local.bExclusive = FALSE;
- pFile->shared->bExclusive = FALSE;
- bReturn = TRUE;
- }
-
- /* Did we just have a reader lock? */
- else if (pFile->local.nReaders){
- pFile->local.nReaders --;
- if (pFile->local.nReaders == 0)
- {
- pFile->shared->nReaders --;
- }
- bReturn = TRUE;
- }
- }
-
- /* Releasing a pending lock */
- else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){
- if (pFile->local.bPending){
- pFile->local.bPending = FALSE;
- pFile->shared->bPending = FALSE;
- bReturn = TRUE;
- }
- }
- /* Releasing a reserved lock */
- else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){
- if (pFile->local.bReserved) {
- pFile->local.bReserved = FALSE;
- pFile->shared->bReserved = FALSE;
- bReturn = TRUE;
- }
- }
-
- winceMutexRelease(pFile->hMutex);
- return bReturn;
-}
-
-/*
-** An implementation of the LockFileEx() API of windows for wince
-*/
-static BOOL winceLockFileEx(
- HANDLE *phFile,
- DWORD dwFlags,
- DWORD dwReserved,
- DWORD nNumberOfBytesToLockLow,
- DWORD nNumberOfBytesToLockHigh,
- LPOVERLAPPED lpOverlapped
-){
- /* If the caller wants a shared read lock, forward this call
- ** to winceLockFile */
- if (lpOverlapped->Offset == SHARED_FIRST &&
- dwFlags == 1 &&
- nNumberOfBytesToLockLow == SHARED_SIZE){
- return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0);
- }
- return FALSE;
-}
-/*
-** End of the special code for wince
-*****************************************************************************/
-#endif /* OS_WINCE */
-
/*
** Delete the named file
*/
-int sqlite3WinDelete(const char *zFilename){
- WCHAR *zWide = utf8ToUnicode(zFilename);
- if( zWide ){
- DeleteFileW(zWide);
- sqliteFree(zWide);
- }else{
-#if OS_WINCE
- return SQLITE_NOMEM;
-#else
- DeleteFileA(zFilename);
-#endif
- }
+int sqlite3OsDelete(const char *zFilename){
+ DeleteFileA(zFilename);
TRACE2("DELETE \"%s\"\n", zFilename);
return SQLITE_OK;
}
/*
** Return TRUE if the named file exists.
*/
-int sqlite3WinFileExists(const char *zFilename){
- int exists = 0;
- WCHAR *zWide = utf8ToUnicode(zFilename);
- if( zWide ){
- exists = GetFileAttributesW(zWide) != 0xffffffff;
- sqliteFree(zWide);
- }else{
-#if OS_WINCE
- return SQLITE_NOMEM;
-#else
- exists = GetFileAttributesA(zFilename) != 0xffffffff;
-#endif
- }
- return exists;
-}
-
-/* Forward declaration */
-int allocateWinFile(winFile *pInit, OsFile **pId);
+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.
@@ -527,91 +57,48 @@
** SQLITE_OK.
**
** On failure, the function returns SQLITE_CANTOPEN and leaves
** *id and *pReadonly unchanged.
*/
-int sqlite3WinOpenReadWrite(
+int sqlite3OsOpenReadWrite(
const char *zFilename,
- OsFile **pId,
+ OsFile *id,
int *pReadonly
){
- winFile f;
HANDLE h;
- WCHAR *zWide = utf8ToUnicode(zFilename);
- assert( *pId==0 );
- if( zWide ){
- h = CreateFileW(zWide,
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
+ 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 ){
- h = CreateFileW(zWide,
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
- NULL
- );
- if( h==INVALID_HANDLE_VALUE ){
- sqliteFree(zWide);
- return SQLITE_CANTOPEN;
- }
- *pReadonly = 1;
- }else{
- *pReadonly = 0;
- }
-#if OS_WINCE
- if (!winceCreateLock(zFilename, &f)){
- CloseHandle(h);
- sqliteFree(zWide);
- return SQLITE_CANTOPEN;
- }
-#endif
- sqliteFree(zWide);
- }else{
-#if OS_WINCE
- return SQLITE_NOMEM;
-#else
- 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;
- }
-#endif /* OS_WINCE */
- }
- f.h = h;
- f.locktype = NO_LOCK;
- f.sharedLockByte = 0;
-#if OS_WINCE
- f.zDeleteOnClose = 0;
-#endif
- TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename);
- return allocateWinFile(&f, pId);
+ 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.
@@ -625,108 +112,68 @@
**
** On success, write the file handle into *id and return SQLITE_OK.
**
** On failure, return SQLITE_CANTOPEN.
*/
-int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
- winFile f;
+int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
HANDLE h;
int fileflags;
- WCHAR *zWide = utf8ToUnicode(zFilename);
- assert( *pId == 0 );
- fileflags = FILE_FLAG_RANDOM_ACCESS;
-#if !OS_WINCE
+ assert( !id->isOpen );
if( delFlag ){
- fileflags |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE;
- }
-#endif
- if( zWide ){
- h = CreateFileW(zWide,
- GENERIC_READ | GENERIC_WRITE,
- 0,
- NULL,
- CREATE_ALWAYS,
- fileflags,
- NULL
- );
- sqliteFree(zWide);
+ fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS
+ | FILE_FLAG_DELETE_ON_CLOSE;
}else{
-#if OS_WINCE
- return SQLITE_NOMEM;
-#else
- h = CreateFileA(zFilename,
- GENERIC_READ | GENERIC_WRITE,
- 0,
- NULL,
- CREATE_ALWAYS,
- fileflags,
- NULL
- );
-#endif /* OS_WINCE */
- }
+ 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;
}
- f.h = h;
- f.locktype = NO_LOCK;
- f.sharedLockByte = 0;
-#if OS_WINCE
- f.zDeleteOnClose = delFlag ? utf8ToUnicode(zFilename) : 0;
- f.hMutex = NULL;
-#endif
+ id->h = h;
+ id->locktype = NO_LOCK;
+ id->sharedLockByte = 0;
+ id->isOpen = 1;
+ OpenCounter(+1);
TRACE3("OPEN EX %d \"%s\"\n", h, zFilename);
- return allocateWinFile(&f, pId);
+ 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 sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){
- winFile f;
+int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){
HANDLE h;
- WCHAR *zWide = utf8ToUnicode(zFilename);
- assert( *pId==0 );
- if( zWide ){
- h = CreateFileW(zWide,
- GENERIC_READ,
- 0,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
- NULL
- );
- sqliteFree(zWide);
- }else{
-#if OS_WINCE
- return SQLITE_NOMEM;
-#else
- h = CreateFileA(zFilename,
- GENERIC_READ,
- 0,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
- NULL
- );
-#endif
- }
+ 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;
}
- f.h = h;
- f.locktype = NO_LOCK;
- f.sharedLockByte = 0;
-#if OS_WINCE
- f.zDeleteOnClose = 0;
- f.hMutex = NULL;
-#endif
+ id->h = h;
+ id->locktype = NO_LOCK;
+ id->sharedLockByte = 0;
+ id->isOpen = 1;
+ OpenCounter(+1);
TRACE3("OPEN RO %d \"%s\"\n", h, zFilename);
- return allocateWinFile(&f, pId);
+ 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
@@ -741,13 +188,13 @@
** returned.
**
** On failure, the function returns SQLITE_CANTOPEN and leaves
** *id unchanged.
*/
-static int winOpenDirectory(
- OsFile *id,
- const char *zDirname
+int sqlite3OsOpenDirectory(
+ const char *zDirname,
+ OsFile *id
){
return SQLITE_OK;
}
/*
@@ -759,30 +206,20 @@
/*
** Create a temporary file name in zBuf. zBuf must be big enough to
** hold at least SQLITE_TEMPNAME_SIZE characters.
*/
-int sqlite3WinTempFileName(char *zBuf){
+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 if( isNT() ){
- char *zMulti;
- WCHAR zWidePath[SQLITE_TEMPNAME_SIZE];
- GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath);
- zMulti = unicodeToUtf8(zWidePath);
- if( zMulti ){
- strncpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30);
- zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
- sqliteFree(zMulti);
- }
}else{
GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath);
}
for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
zTempPath[i] = 0;
@@ -801,40 +238,31 @@
}
/*
** Close a file.
*/
-static int winClose(OsFile **pId){
- winFile *pFile;
- if( pId && (pFile = (winFile*)*pId)!=0 ){
- TRACE2("CLOSE %d\n", pFile->h);
- CloseHandle(pFile->h);
-#if OS_WINCE
- winceDestroyLock(pFile);
- if( pFile->zDeleteOnClose ){
- DeleteFileW(pFile->zDeleteOnClose);
- sqliteFree(pFile->zDeleteOnClose);
- }
-#endif
+int sqlite3OsClose(OsFile *id){
+ if( id->isOpen ){
+ TRACE2("CLOSE %d\n", id->h);
+ CloseHandle(id->h);
OpenCounter(-1);
- sqliteFree(pFile);
- *pId = 0;
+ 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.
*/
-static int winRead(OsFile *id, void *pBuf, int amt){
+int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
DWORD got;
- assert( id!=0 );
+ assert( id->isOpen );
SimulateIOError(SQLITE_IOERR);
- TRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
- if( !ReadFile(((winFile*)id)->h, pBuf, amt, &got, 0) ){
+ 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{
@@ -844,63 +272,49 @@
/*
** Write data from a buffer into a file. Return SQLITE_OK on success
** or some other error code on failure.
*/
-static int winWrite(OsFile *id, const void *pBuf, int amt){
+int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
int rc = 0;
DWORD wrote;
- assert( id!=0 );
+ assert( id->isOpen );
SimulateIOError(SQLITE_IOERR);
SimulateDiskfullError;
- TRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
+ TRACE3("WRITE %d lock=%d\n", id->h, id->locktype);
assert( amt>0 );
- while( amt>0 && (rc = WriteFile(((winFile*)id)->h, pBuf, amt, &wrote, 0))!=0
- && wrote>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;
}
-/*
-** Some microsoft compilers lack this definition.
-*/
-#ifndef INVALID_SET_FILE_POINTER
-# define INVALID_SET_FILE_POINTER ((DWORD)-1)
-#endif
-
/*
** Move the read/write pointer in a file.
*/
-static int winSeek(OsFile *id, i64 offset){
+int sqlite3OsSeek(OsFile *id, i64 offset){
LONG upperBits = offset>>32;
LONG lowerBits = offset & 0xffffffff;
DWORD rc;
- assert( id!=0 );
-#ifdef SQLITE_TEST
- if( offset ) SimulateDiskfullError
-#endif
+ assert( id->isOpen );
SEEK(offset/1024 + 1);
- rc = SetFilePointer(((winFile*)id)->h, lowerBits, &upperBits, FILE_BEGIN);
- TRACE3("SEEK %d %lld\n", ((winFile*)id)->h, offset);
- if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){
- return SQLITE_FULL;
- }
+ 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.
*/
-static int winSync(OsFile *id, int dataOnly){
- assert( id!=0 );
- TRACE3("SYNC %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
- if( FlushFileBuffers(((winFile*)id)->h) ){
+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;
}
}
@@ -907,53 +321,68 @@
/*
** Sync the directory zDirname. This is a no-op on operating systems other
** than UNIX.
*/
-int sqlite3WinSyncDirectory(const char *zDirname){
+int sqlite3OsSyncDirectory(const char *zDirname){
SimulateIOError(SQLITE_IOERR);
return SQLITE_OK;
}
/*
** Truncate an open file to a specified size
*/
-static int winTruncate(OsFile *id, i64 nByte){
+int sqlite3OsTruncate(OsFile *id, i64 nByte){
LONG upperBits = nByte>>32;
- assert( id!=0 );
- TRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte);
+ assert( id->isOpen );
+ TRACE3("TRUNCATE %d %lld\n", id->h, nByte);
SimulateIOError(SQLITE_IOERR);
- SetFilePointer(((winFile*)id)->h, nByte, &upperBits, FILE_BEGIN);
- SetEndOfFile(((winFile*)id)->h);
+ SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN);
+ SetEndOfFile(id->h);
return SQLITE_OK;
}
/*
** Determine the current size of a file in bytes
*/
-static int winFileSize(OsFile *id, i64 *pSize){
+int sqlite3OsFileSize(OsFile *id, i64 *pSize){
DWORD upperBits, lowerBits;
- assert( id!=0 );
+ assert( id->isOpen );
SimulateIOError(SQLITE_IOERR);
- lowerBits = GetFileSize(((winFile*)id)->h, &upperBits);
+ lowerBits = GetFileSize(id->h, &upperBits);
*pSize = (((i64)upperBits)<<32) + lowerBits;
return SQLITE_OK;
}
/*
-** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
+** 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.
*/
-#ifndef LOCKFILE_FAIL_IMMEDIATELY
-# define LOCKFILE_FAIL_IMMEDIATELY 1
-#endif
+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(winFile *id){
+static int getReadLock(OsFile *id){
int res;
if( isNT() ){
OVERLAPPED ovlp;
ovlp.Offset = SHARED_FIRST;
ovlp.OffsetHigh = 0;
@@ -969,41 +398,30 @@
}
/*
** Undo a readlock
*/
-static int unlockReadLock(winFile *pFile){
+static int unlockReadLock(OsFile *id){
int res;
if( isNT() ){
- res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
+ res = UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
}else{
- res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
+ 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 sqlite3WinIsDirWritable(char *zDirname){
+int sqlite3OsIsDirWritable(char *zBuf){
int fileAttr;
- WCHAR *zWide;
- if( zDirname==0 ) return 0;
- if( !isNT() && strlen(zDirname)>MAX_PATH ) return 0;
- zWide = utf8ToUnicode(zDirname);
- if( zWide ){
- fileAttr = GetFileAttributesW(zWide);
- sqliteFree(zWide);
- }else{
-#if OS_WINCE
- return 0;
-#else
- fileAttr = GetFileAttributesA(zDirname);
-#endif
- }
+ 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;
@@ -1029,50 +447,49 @@
** SHARED -> RESERVED
** SHARED -> (PENDING) -> EXCLUSIVE
** RESERVED -> (PENDING) -> EXCLUSIVE
** PENDING -> EXCLUSIVE
**
-** This routine will only increase a lock. The winUnlock() routine
+** 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.
*/
-static int winLock(OsFile *id, int locktype){
+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 */
- winFile *pFile = (winFile*)id;
- assert( pFile!=0 );
+ assert( id->isOpen );
TRACE5("LOCK %d %d was %d(%d)\n",
- pFile->h, locktype, pFile->locktype, pFile->sharedLockByte);
+ 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( pFile->locktype>=locktype ){
+ if( id->locktype>=locktype ){
return SQLITE_OK;
}
/* Make sure the locking sequence is correct
*/
- assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
+ assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK );
assert( locktype!=PENDING_LOCK );
- assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_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 = pFile->locktype;
- if( pFile->locktype==NO_LOCK
- || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
+ newLocktype = id->locktype;
+ if( id->locktype==NO_LOCK
+ || (locktype==EXCLUSIVE_LOCK && id->locktype==RESERVED_LOCK)
){
int cnt = 3;
- while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){
+ 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);
@@ -1081,22 +498,22 @@
}
/* Acquire a shared lock
*/
if( locktype==SHARED_LOCK && res ){
- assert( pFile->locktype==NO_LOCK );
- res = getReadLock(pFile);
+ assert( id->locktype==NO_LOCK );
+ res = getReadLock(id);
if( res ){
newLocktype = SHARED_LOCK;
}
}
/* Acquire a RESERVED lock
*/
if( locktype==RESERVED_LOCK && res ){
- assert( pFile->locktype==SHARED_LOCK );
- res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
+ assert( id->locktype==SHARED_LOCK );
+ res = LockFile(id->h, RESERVED_BYTE, 0, 1, 0);
if( res ){
newLocktype = RESERVED_LOCK;
}
}
@@ -1108,14 +525,14 @@
}
/* Acquire an EXCLUSIVE lock
*/
if( locktype==EXCLUSIVE_LOCK && res ){
- assert( pFile->locktype>=SHARED_LOCK );
- res = unlockReadLock(pFile);
+ assert( id->locktype>=SHARED_LOCK );
+ res = unlockReadLock(id);
TRACE2("unreadlock = %d\n", res);
- res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
+ res = LockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
if( res ){
newLocktype = EXCLUSIVE_LOCK;
}else{
TRACE2("error-code = %d\n", GetLastError());
}
@@ -1123,46 +540,45 @@
/* If we are holding a PENDING lock that ought to be released, then
** release it now.
*/
if( gotPendingLock && locktype==SHARED_LOCK ){
- UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
+ 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", pFile->h,
+ TRACE4("LOCK FAILED %d trying for %d but got %d\n", id->h,
locktype, newLocktype);
rc = SQLITE_BUSY;
}
- pFile->locktype = newLocktype;
+ 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.
*/
-static int winCheckReservedLock(OsFile *id){
+int sqlite3OsCheckReservedLock(OsFile *id){
int rc;
- winFile *pFile = (winFile*)id;
- assert( pFile!=0 );
- if( pFile->locktype>=RESERVED_LOCK ){
+ assert( id->isOpen );
+ if( id->locktype>=RESERVED_LOCK ){
rc = 1;
- TRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc);
+ TRACE3("TEST WR-LOCK %d %d (local)\n", id->h, rc);
}else{
- rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
+ rc = LockFile(id->h, RESERVED_BYTE, 0, 1, 0);
if( rc ){
- UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
+ UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0);
}
rc = !rc;
- TRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc);
+ TRACE3("TEST WR-LOCK %d %d (remote)\n", id->h, rc);
}
return rc;
}
/*
@@ -1174,160 +590,45 @@
**
** 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;
*/
-static int winUnlock(OsFile *id, int locktype){
+int sqlite3OsUnlock(OsFile *id, int locktype){
int type;
int rc = SQLITE_OK;
- winFile *pFile = (winFile*)id;
- assert( pFile!=0 );
+ assert( id->isOpen );
assert( locktype<=SHARED_LOCK );
- TRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
- pFile->locktype, pFile->sharedLockByte);
- type = pFile->locktype;
+ TRACE5("UNLOCK %d to %d was %d(%d)\n", id->h, locktype,
+ id->locktype, id->sharedLockByte);
+ type = id->locktype;
if( type>=EXCLUSIVE_LOCK ){
- UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
- if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
+ 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(pFile->h, RESERVED_BYTE, 0, 1, 0);
+ UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0);
}
if( locktype==NO_LOCK && type>=SHARED_LOCK ){
- unlockReadLock(pFile);
+ unlockReadLock(id);
}
if( type>=PENDING_LOCK ){
- UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
+ UnlockFile(id->h, PENDING_BYTE, 0, 1, 0);
}
- pFile->locktype = locktype;
+ id->locktype = locktype;
return rc;
}
-/*
-** 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 *sqlite3WinFullPathname(const char *zRelative){
- char *zFull;
-#if defined(__CYGWIN__)
- int nByte;
- nByte = strlen(zRelative) + MAX_PATH + 1001;
- zFull = sqliteMalloc( nByte );
- if( zFull==0 ) return 0;
- if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0;
-#elif OS_WINCE
- /* WinCE has no concept of a relative pathname, or so I am told. */
- zFull = sqliteStrDup(zRelative);
-#else
- char *zNotUsed;
- WCHAR *zWide;
- int nByte;
- zWide = utf8ToUnicode(zRelative);
- if( zWide ){
- WCHAR *zTemp, *zNotUsedW;
- nByte = GetFullPathNameW(zWide, 0, 0, &zNotUsedW) + 1;
- zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) );
- if( zTemp==0 ) return 0;
- GetFullPathNameW(zWide, nByte, zTemp, &zNotUsedW);
- sqliteFree(zWide);
- zFull = unicodeToUtf8(zTemp);
- sqliteFree(zTemp);
- }else{
- nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1;
- zFull = sqliteMalloc( nByte*sizeof(zFull[0]) );
- if( zFull==0 ) return 0;
- GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed);
- }
-#endif
- return zFull;
-}
-
-/*
-** The fullSync option is meaningless on windows. This is a no-op.
-*/
-static void winSetFullSync(OsFile *id, int v){
- return;
-}
-
-/*
-** Return the underlying file handle for an OsFile
-*/
-static int winFileHandle(OsFile *id){
- return (int)((winFile*)id)->h;
-}
-
-/*
-** Return an integer that indices the type of lock currently held
-** by this handle. (Used for testing and analysis only.)
-*/
-static int winLockState(OsFile *id){
- return ((winFile*)id)->locktype;
-}
-
-/*
-** This vector defines all the methods that can operate on an OsFile
-** for win32.
-*/
-static const IoMethod sqlite3WinIoMethod = {
- winClose,
- winOpenDirectory,
- winRead,
- winWrite,
- winSeek,
- winTruncate,
- winSync,
- winSetFullSync,
- winFileHandle,
- winFileSize,
- winLock,
- winUnlock,
- winLockState,
- winCheckReservedLock,
-};
-
-/*
-** Allocate memory for an OsFile. Initialize the new OsFile
-** to the value given in pInit and return a pointer to the new
-** OsFile. If we run out of memory, close the file and return NULL.
-*/
-int allocateWinFile(winFile *pInit, OsFile **pId){
- winFile *pNew;
- pNew = sqliteMalloc( sizeof(*pNew) );
- if( pNew==0 ){
- CloseHandle(pInit->h);
-#if OS_WINCE
- sqliteFree(pInit->zDeleteOnClose);
-#endif
- *pId = 0;
- return SQLITE_NOMEM;
- }else{
- *pNew = *pInit;
- pNew->pMethod = &sqlite3WinIoMethod;
- *pId = (OsFile*)pNew;
- return SQLITE_OK;
- }
-}
-
-
-#endif /* SQLITE_OMIT_DISKIO */
-/***************************************************************************
-** Everything above deals with file I/O. Everything that follows deals
-** with other miscellanous aspects of the operating system interface
-****************************************************************************/
-
/*
** 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 sqlite3WinRandomSeed(char *zBuf){
+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
@@ -1344,11 +645,11 @@
}
/*
** Sleep for a little while. Return the amount of time slept.
*/
-int sqlite3WinSleep(int ms){
+int sqlite3OsSleep(int ms){
Sleep(ms);
return ms;
}
/*
@@ -1365,11 +666,11 @@
** 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 sqlite3WinEnterMutex(){
+void sqlite3OsEnterMutex(){
#ifdef SQLITE_W32_THREADS
static int isInit = 0;
while( !isInit ){
static long lock = 0;
if( InterlockedIncrement(&lock)==1 ){
@@ -1382,25 +683,34 @@
EnterCriticalSection(&cs);
#endif
assert( !inMutex );
inMutex = 1;
}
-void sqlite3WinLeaveMutex(){
+void sqlite3OsLeaveMutex(){
assert( inMutex );
inMutex = 0;
#ifdef SQLITE_W32_THREADS
LeaveCriticalSection(&cs);
#endif
}
/*
-** Return TRUE if we are currently within the mutex and FALSE if not.
+** 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.
*/
-int sqlite3WinInMutex(){
- return inMutex;
+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.
*/
@@ -1411,23 +721,17 @@
/*
** 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 sqlite3WinCurrentTime(double *prNow){
+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;
-#if OS_WINCE
- SYSTEMTIME time;
- GetSystemTime(&time);
- SystemTimeToFileTime(&time,&ft);
-#else
GetSystemTimeAsFileTime( &ft );
-#endif
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;
@@ -1435,72 +739,28 @@
#endif
return 0;
}
/*
-** Remember the number of thread-specific-data blocks allocated.
-** Use this to verify that we are not leaking thread-specific-data.
-** Ticket #1601
-*/
-#ifdef SQLITE_TEST
-int sqlite3_tsd_count = 0;
-# define TSD_COUNTER_INCR InterlockedIncrement(&sqlite3_tsd_count)
-# define TSD_COUNTER_DECR InterlockedDecrement(&sqlite3_tsd_count)
-#else
-# define TSD_COUNTER_INCR /* no-op */
-# define TSD_COUNTER_DECR /* no-op */
-#endif
-
-
-
-/*
-** If called with allocateFlag>1, then return a pointer to thread
-** specific data for the current thread. Allocate and zero the
-** thread-specific data if it does not already exist necessary.
-**
-** If called with allocateFlag==0, then check the current thread
-** specific data. Return it if it exists. If it does not exist,
-** then return NULL.
-**
-** If called with allocateFlag<0, check to see if the thread specific
-** data is allocated and is all zero. If it is then deallocate it.
-** Return a pointer to the thread specific data or NULL if it is
-** unallocated or gets deallocated.
-*/
-ThreadData *sqlite3WinThreadSpecificData(int allocateFlag){
- static int key;
- static int keyInit = 0;
- static const ThreadData zeroData;
- ThreadData *pTsd;
-
- if( !keyInit ){
- sqlite3OsEnterMutex();
- if( !keyInit ){
- key = TlsAlloc();
- if( key==0xffffffff ){
- sqlite3OsLeaveMutex();
- return 0;
- }
- keyInit = 1;
- }
- sqlite3OsLeaveMutex();
- }
- pTsd = TlsGetValue(key);
- if( allocateFlag>0 ){
- if( !pTsd ){
- pTsd = sqlite3OsMalloc( sizeof(zeroData) );
- if( pTsd ){
- *pTsd = zeroData;
- TlsSetValue(key, pTsd);
- TSD_COUNTER_INCR;
- }
- }
- }else if( pTsd!=0 && allocateFlag<0
- && memcmp(pTsd, &zeroData, sizeof(zeroData))==0 ){
- sqlite3OsFree(pTsd);
- TlsSetValue(key, 0);
- TSD_COUNTER_DECR;
- pTsd = 0;
- }
- return pTsd;
-}
+** 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
Index: SQLite.Interop/src/os_win.h
==================================================================
--- /dev/null
+++ SQLite.Interop/src/os_win.h
@@ -0,0 +1,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
+#include
+
+/*
+** 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_ */
Index: SQLite.Interop/src/pager.c
==================================================================
--- SQLite.Interop/src/pager.c
+++ SQLite.Interop/src/pager.c
@@ -16,13 +16,12 @@
** 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.17 2006/01/16 15:51:47 rmsimpson Exp $
+** @(#) $Id: pager.c,v 1.1 2005/03/01 16:04:31 rmsimpson Exp $
*/
-#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include
#include
@@ -44,18 +43,25 @@
#define TRACE5(X,Y,Z,W,V)
#endif
/*
** The following two macros are used within the TRACEX() macros above
-** to print out file-descriptors.
+** 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.
*/
-#define PAGERID(p) FILEHANDLEID(&(p)->fd)
-#define FILEHANDLEID(fd) (sqlite3OsFileHandle(&fd))
+#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:
**
@@ -163,11 +169,11 @@
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->pageSize bytes of page data follow this header */
+ /* 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
@@ -199,44 +205,53 @@
** 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)->pageSize])
+#define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->psAligned])
#define PGHDR_TO_HIST(P,PGR) \
- ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra])
+ ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->psAligned+(PGR)->nExtra])
/*
** How big to make the hash table used for locating in-memory pages
-** by page number. This macro looks a little silly, but is evaluated
-** at compile-time, not run-time (at least for gcc this is true).
+** by page number.
*/
-#define N_PG_HASH (\
- (MAX_PAGES>1024)?2048: \
- (MAX_PAGES>512)?1024: \
- (MAX_PAGES>256)?512: \
- (MAX_PAGES>128)?256: \
- (MAX_PAGES>64)?128:64 \
-)
+#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.
-**
-** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, SQLITE_PROTOCOL
-** or SQLITE_FULL. Once one of the first three errors occurs, it persists
-** and is returned as the result of every major pager API call. The
-** SQLITE_FULL return code is slightly different. It persists only until the
-** next successful rollback is performed on the pager cache. Also,
-** SQLITE_FULL does not affect the sqlite3pager_get() and sqlite3pager_lookup()
-** APIs, they may still be used successfully.
*/
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 */
@@ -243,71 +258,41 @@
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 errCode; /* One of several kinds of errors */
+ 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 setMaster; /* True if a m-j name has been written to jrnl */
- 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() */
- 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 */
- int pageSize; /* Number of bytes in a page */
- int nPage; /* Total number of in-memory pages */
- int nMaxPage; /* High water mark of nPage */
- int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */
- int mxPage; /* Maximum number of pages to hold in cache */
u8 *aInJournal; /* One bit for each page in the database file */
u8 *aInStmt; /* One bit for each page in the database */
- 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*/
+ 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 */
- i64 stmtJSize; /* Size of journal at stmt_begin() */
int sectorSize; /* Assumed sector size during rollback */
-#ifdef SQLITE_TEST
- int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */
- int nRead,nWrite; /* Database pages read/written */
-#endif
- void (*xDestructor)(void*,int); /* Call this routine when freeing pages */
- void (*xReiniter)(void*,int); /* Call this routine when reloading pages */
- void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
- void *pCodecArg; /* First argument to xCodec() */
PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number to PgHdr */
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- Pager *pNext; /* Linked list of pagers in this thread */
-#endif
};
/*
-** If SQLITE_TEST is defined then increment the variable given in
-** the argument
+** These are bits that can be set in Pager.errMask.
*/
-#ifdef SQLITE_TEST
-# define TEST_INCR(x) x++
-#else
-# define TEST_INCR(x)
-#endif
+#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.
**
@@ -404,35 +389,32 @@
** error code is something goes wrong.
**
** All values are stored on disk as big-endian.
*/
static int read32bits(OsFile *fd, u32 *pRes){
- unsigned char ac[4];
- int rc = sqlite3OsRead(fd, ac, sizeof(ac));
+ u32 res;
+ int rc;
+ rc = sqlite3OsRead(fd, &res, sizeof(res));
if( rc==SQLITE_OK ){
- *pRes = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3];
- }
- return rc;
-}
-
-/*
-** Write a 32-bit integer into a string buffer in big-endian byte order.
-*/
-static void put32bits(char *ac, u32 val){
- ac[0] = (val>>24) & 0xff;
- ac[1] = (val>>16) & 0xff;
- ac[2] = (val>>8) & 0xff;
- ac[3] = val & 0xff;
+ 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];
- put32bits(ac, val);
+ 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
@@ -439,11 +421,14 @@
** 'p' at offset 'offset'.
*/
static void store32bits(u32 val, PgHdr *p, int offset){
unsigned char *ac;
ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset];
- put32bits(ac, val);
+ 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'.
@@ -454,29 +439,20 @@
return (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3];
}
/*
-** This function should be called when an error occurs within the pager
-** code. The first argument is a pointer to the pager structure, the
-** second the error-code about to be returned by a pager API function.
-** The value returned is a copy of the second argument to this function.
-**
-** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT or SQLITE_PROTOCOL,
-** the error becomes persistent. All subsequent API calls on this Pager
-** will immediately return the same error code.
+** Convert the bits in the pPager->errMask into an approprate
+** return code.
*/
-static int pager_error(Pager *pPager, int rc){
- assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK );
- if(
- rc==SQLITE_FULL ||
- rc==SQLITE_IOERR ||
- rc==SQLITE_CORRUPT ||
- rc==SQLITE_PROTOCOL
- ){
- pPager->errCode = rc;
- }
+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
/*
@@ -498,11 +474,11 @@
** 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->errCode || MEMDB || pPg->dirty ||
+ assert( !pPg->pageHash || pPager->errMask || MEMDB || pPg->dirty ||
pPg->pageHash==pager_pagehash(pPg) );
}
#else
#define CHECK_PAGE(x)
@@ -599,11 +575,11 @@
}
assert( offset%JOURNAL_HDR_SZ(pPager)==0 );
assert( offset>=c );
assert( (offset-c)journalOff = offset;
- return sqlite3OsSeek(pPager->jfd, pPager->journalOff);
+ 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
@@ -617,11 +593,10 @@
** - 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){
- char zHeader[sizeof(aJournalMagic)+16];
int rc = seekJournalHdr(pPager);
if( rc ) return rc;
pPager->journalHdr = pPager->journalOff;
@@ -636,30 +611,36 @@
** 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.
*/
- memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
- /* The nRec Field. 0xFFFFFFFF for no-sync journals. */
- put32bits(&zHeader[sizeof(aJournalMagic)], pPager->noSync ? 0xffffffff : 0);
- /* The random check-hash initialiser */
- sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
- put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
- /* The initial database size */
- put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize);
- /* The assumed sector size for this process */
- put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
- rc = sqlite3OsWrite(pPager->jfd, zHeader, sizeof(zHeader));
+ 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 ){
- rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff-1);
- if( rc==SQLITE_OK ){
- rc = sqlite3OsWrite(pPager->jfd, "\000", 1);
- }
+ sqlite3OsSeek(&pPager->jfd, pPager->journalOff-1);
+ rc = sqlite3OsWrite(&pPager->jfd, "\000", 1);
}
return rc;
}
/*
@@ -692,37 +673,37 @@
if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
return SQLITE_DONE;
}
- rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic));
+ 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);
+ rc = read32bits(&pPager->jfd, pNRec);
if( rc ) return rc;
- rc = read32bits(pPager->jfd, &pPager->cksumInit);
+ rc = read32bits(&pPager->jfd, &pPager->cksumInit);
if( rc ) return rc;
- rc = read32bits(pPager->jfd, pDbSize);
+ 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);
+ rc = read32bits(&pPager->jfd, (u32 *)&pPager->sectorSize);
if( rc ) return rc;
pPager->journalOff += JOURNAL_HDR_SZ(pPager);
- rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff);
+ rc = sqlite3OsSeek(&pPager->jfd, pPager->journalOff);
return rc;
}
/*
@@ -738,20 +719,16 @@
** + 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.
-**
-** If zMaster is a NULL pointer (occurs for a single database transaction),
-** this call is a no-op.
*/
static int writeMasterJournal(Pager *pPager, const char *zMaster){
int rc;
int len;
int i;
- u32 cksum = 0;
- char zBuf[sizeof(aJournalMagic)+2*4];
+ u32 cksum = 0;
if( !zMaster || pPager->setMaster) return SQLITE_OK;
pPager->setMaster = 1;
len = strlen(zMaster);
@@ -767,21 +744,24 @@
rc = seekJournalHdr(pPager);
if( rc!=SQLITE_OK ) return rc;
}
pPager->journalOff += (len+20);
- rc = write32bits(pPager->jfd, PAGER_MJ_PGNO(pPager));
+ 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 = sqlite3OsWrite(pPager->jfd, zMaster, len);
+ rc = write32bits(&pPager->jfd, cksum);
if( rc!=SQLITE_OK ) return rc;
- put32bits(zBuf, len);
- put32bits(&zBuf[4], cksum);
- memcpy(&zBuf[8], aJournalMagic, sizeof(aJournalMagic));
- rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic));
- pPager->needSync = !pPager->noSync;
+ 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
@@ -840,11 +820,10 @@
** 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;
- if( pPager->errCode ) return;
for(pPg=pPager->pAll; pPg; pPg=pNext){
pNext = pPg->pNextAll;
sqliteFree(pPg);
}
pPager->pFirst = 0;
@@ -854,11 +833,11 @@
memset(pPager->aHash, 0, sizeof(pPager->aHash));
pPager->nPage = 0;
if( pPager->state>=PAGER_RESERVED ){
sqlite3pager_rollback(pPager);
}
- sqlite3OsUnlock(pPager->fd, NO_LOCK);
+ sqlite3OsUnlock(&pPager->fd, NO_LOCK);
pPager->state = PAGER_UNLOCK;
pPager->dbSize = -1;
pPager->nRef = 0;
assert( pPager->journalOpen==0 );
}
@@ -900,14 +879,13 @@
#endif
}
pPager->dirtyCache = 0;
pPager->nRec = 0;
}else{
- assert( pPager->aInJournal==0 );
assert( pPager->dirtyCache==0 || pPager->useJournal==0 );
}
- rc = sqlite3OsUnlock(pPager->fd, SHARED_LOCK);
+ rc = sqlite3OsUnlock(&pPager->fd, SHARED_LOCK);
pPager->state = PAGER_SHARED;
pPager->origDbSize = 0;
pPager->setMaster = 0;
return rc;
}
@@ -930,11 +908,11 @@
** 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 u8 *aData){
+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;
@@ -954,16 +932,10 @@
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 */
-
- /* useCksum should be true for the main journal and false for
- ** statement journals. Verify that this is always the case
- */
- assert( jfd == (useCksum ? pPager->jfd : pPager->stfd) );
-
rc = read32bits(jfd, &pgno);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3OsRead(jfd, &aData, pPager->pageSize);
if( rc!=SQLITE_OK ) return rc;
@@ -995,33 +967,17 @@
** 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.
- **
- ** Ticket #1171: The statement journal might contain page content that is
- ** different from the page content at the start of the transaction.
- ** This occurs when a page is changed prior to the start of a statement
- ** then changed again within the statement. When rolling back such a
- ** statement we must not write to the original database unless we know
- ** for certain that original page contents are in the main rollback
- ** journal. Otherwise, if a full ROLLBACK occurs after the statement
- ** rollback the full ROLLBACK will not restore the page to its original
- ** content. Two conditions must be met before writing to the database
- ** files. (1) the database must be locked. (2) we know that the original
- ** page content is in the main journal either because the page is not in
- ** cache or else it is marked as needSync==0.
*/
pPg = pager_lookup(pPager, pgno);
- assert( pPager->state>=PAGER_EXCLUSIVE || pPg!=0 );
+ assert( pPager->state>=PAGER_EXCLUSIVE || pPg );
TRACE3("PLAYBACK %d page %d\n", PAGERID(pPager), pgno);
- if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) ){
- rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize);
- if( rc==SQLITE_OK ){
- rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize);
- }
- if( pPg ) pPg->dirty = 0;
+ 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
@@ -1033,13 +989,17 @@
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);
+ pPg->pageHash = pager_pagehash(pPg);
#endif
+ }
CODEC(pPager, pData, pPg->pgno, 3);
}
return rc;
}
@@ -1055,21 +1015,22 @@
** 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 = 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);
+ rc = sqlite3OsFileSize(&master, &nMasterJournal);
if( rc!=SQLITE_OK ) goto delmaster_out;
if( nMasterJournal>0 ){
char *zJournal;
char *zMasterPtr = 0;
@@ -1080,29 +1041,30 @@
zMasterJournal = (char *)sqliteMalloc(nMasterJournal);
if( !zMasterJournal ){
rc = SQLITE_NOMEM;
goto delmaster_out;
}
- rc = sqlite3OsRead(master, zMasterJournal, nMasterJournal);
+ rc = sqlite3OsRead(&master, zMasterJournal, nMasterJournal);
if( rc!=SQLITE_OK ) goto delmaster_out;
zJournal = zMasterJournal;
while( (zJournal-zMasterJournal)pAll; pPg; pPg=pPg->pNextAll){
char zBuf[SQLITE_MAX_PAGE_SIZE];
if( !pPg->dirty ) continue;
if( (int)pPg->pgno <= pPager->origDbSize ){
- rc = sqlite3OsSeek(pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1));
- if( rc==SQLITE_OK ){
- rc = sqlite3OsRead(pPager->fd, zBuf, pPager->pageSize);
- }
+ 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);
@@ -1176,11 +1136,11 @@
** 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);
+ 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.
@@ -1244,29 +1204,29 @@
/* Figure out how many records are in the journal. Abort early if
** the journal is empty.
*/
assert( pPager->journalOpen );
- rc = sqlite3OsFileSize(pPager->jfd, &szJ);
+ 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);
+ 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);
+ 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 ){
@@ -1305,17 +1265,17 @@
goto end_playback;
}
pPager->dbSize = mxPg;
}
- /* rc = sqlite3OsSeek(pPager->jfd, JOURNAL_HDR_SZ(pPager)); */
+ /* 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; ijfd, 1);
+ rc = pager_playback_one_page(pPager, &pPager->jfd, 1);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
pPager->journalOff = szJ;
break;
@@ -1378,11 +1338,11 @@
szJ = pPager->journalOff;
#ifndef NDEBUG
{
i64 os_szJ;
- rc = sqlite3OsFileSize(pPager->jfd, &os_szJ);
+ rc = sqlite3OsFileSize(&pPager->jfd, &os_szJ);
if( rc!=SQLITE_OK ) return rc;
assert( szJ==os_szJ );
}
#endif
@@ -1404,20 +1364,20 @@
pPager->dbSize = pPager->stmtSize;
/* Figure out how many records are in the statement journal.
*/
assert( pPager->stmtInUse && pPager->journalOpen );
- sqlite3OsSeek(pPager->stfd, 0);
+ 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);
+ 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
@@ -1426,19 +1386,19 @@
** 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);
+ 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);
+ 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 ){
@@ -1451,32 +1411,47 @@
}
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);
+ 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 ){
- rc = pager_error(pPager, SQLITE_CORRUPT);
+ 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;
}
@@ -1515,33 +1490,25 @@
if( pPager->noSync ) pPager->needSync = 0;
}
#endif
/*
-** The following global variable is incremented whenever the library
-** attempts to open a temporary file. This information is used for
-** testing and analysis only.
-*/
-int sqlite3_opentemp_count = 0;
-
-/*
-** Open a temporary file. Write the name of the file into zFile
-** (zFile must be at least SQLITE_TEMPNAME_SIZE bytes long.) Write
+** 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 **pFd){
+static int sqlite3pager_opentemp(char *zFile, OsFile *fd){
int cnt = 8;
int rc;
- sqlite3_opentemp_count++; /* Used for testing and analysis only */
do{
cnt--;
sqlite3OsTempFileName(zFile);
- rc = sqlite3OsOpenExclusive(zFile, pFd, 1);
+ rc = sqlite3OsOpenExclusive(zFile, fd, 1);
}while( cnt>0 && rc!=SQLITE_OK && rc!=SQLITE_NOMEM );
return rc;
}
/*
@@ -1562,44 +1529,34 @@
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 = 0;
+ Pager *pPager;
char *zFullPathname = 0;
int nameLen;
- OsFile *fd;
+ 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];
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- const ThreadData *pTsdro = sqlite3ThreadDataReadOnly();
-#endif
-
- /* If malloc() has already failed return SQLITE_NOMEM. Before even
- ** testing for this, set *ppPager to NULL so the caller knows the pager
- ** structure was never allocated.
- */
+
*ppPager = 0;
- if( sqlite3ThreadDataReadOnly()->mallocFailed ){
+ memset(&fd, 0, sizeof(fd));
+ if( sqlite3_malloc_failed ){
return SQLITE_NOMEM;
}
- memset(&fd, 0, sizeof(fd));
-
- /* Open the pager file and set zFullPathname to point at malloc()ed
- ** memory containing the complete filename (i.e. including the directory).
- */
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 ){
@@ -1612,82 +1569,70 @@
zFullPathname = sqlite3OsFullPathname(zFilename);
if( rc==SQLITE_OK ){
tempFile = 1;
}
}
-
- /* Allocate the Pager structure. As part of the same allocation, allocate
- ** space for the full paths of the file, directory and journal
- ** (Pager.zFilename, Pager.zDirectory and Pager.zJournal).
- */
- if( zFullPathname ){
- nameLen = strlen(zFullPathname);
- pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 );
- }
-
- /* If an error occured in either of the blocks above, free the memory
- ** pointed to by zFullPathname, free the Pager structure and close the
- ** file. Since the pager is not allocated there is no need to set
- ** any Pager.errMask variables.
- */
- if( !pPager || !zFullPathname || rc!=SQLITE_OK ){
+ 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);
- sqliteFree(pPager);
- return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc);
+ 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;
- /* pPager->journalOpen = 0; */
+#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->stmtOpen = 0;
+ pPager->stmtInUse = 0;
+ pPager->nRef = 0;
pPager->dbSize = memDb-1;
pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE;
- /* pPager->stmtSize = 0; */
- /* pPager->stmtJSize = 0; */
- /* pPager->nPage = 0; */
- /* pPager->nMaxPage = 0; */
+ pPager->psAligned = FORCE_ALIGNMENT(pPager->pageSize);
+ pPager->stmtSize = 0;
+ pPager->stmtJSize = 0;
+ pPager->nPage = 0;
pPager->mxPage = 100;
- assert( PAGER_UNLOCK==0 );
- /* pPager->state = PAGER_UNLOCK; */
- /* pPager->errMask = 0; */
+ pPager->state = PAGER_UNLOCK;
+ pPager->errMask = 0;
pPager->tempFile = tempFile;
pPager->memDb = memDb;
pPager->readOnly = readOnly;
- /* pPager->needSync = 0; */
+ pPager->needSync = 0;
pPager->noSync = pPager->tempFile || !useJournal;
pPager->fullSync = (pPager->noSync?0:1);
- /* pPager->pFirst = 0; */
- /* pPager->pFirstSynced = 0; */
- /* pPager->pLast = 0; */
+ 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)); */
+ pPager->pBusyHandler = 0;
+ memset(pPager->aHash, 0, sizeof(pPager->aHash));
*ppPager = pPager;
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- if( pTsdro->useMemoryManagement ){
- ThreadData *pTsd = sqlite3ThreadData();
- pPager->pNext = pTsd->pPager;
- pTsd->pPager = pPager;
- }
-#endif
return SQLITE_OK;
}
/*
** Set the busy handler function.
@@ -1718,99 +1663,52 @@
void sqlite3pager_set_reiniter(Pager *pPager, void (*xReinit)(void*,int)){
pPager->xReiniter = xReinit;
}
/*
-** Set the page size. Return the new size. If the suggest new page
-** size is inappropriate, then an alternative page size is selected
-** and returned.
+** Set the page size.
+**
+** The page size must only be changed when the cache is empty.
*/
-int sqlite3pager_set_pagesize(Pager *pPager, int pageSize){
+void sqlite3pager_set_pagesize(Pager *pPager, int pageSize){
assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE );
- if( !pPager->memDb ){
- pPager->pageSize = pageSize;
- }
- return pPager->pageSize;
-}
-
-/*
-** The following set of routines are used to disable the simulated
-** I/O error mechanism. These routines are used to avoid simulated
-** errors in places where we do not care about errors.
-**
-** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops
-** and generate no code.
-*/
-#ifdef SQLITE_TEST
-extern int sqlite3_io_error_pending;
-extern int sqlite3_io_error_hit;
-static int saved_cnt;
-void clear_simulated_io_error(){
- sqlite3_io_error_hit = 0;
-}
-void disable_simulated_io_errors(void){
- saved_cnt = sqlite3_io_error_pending;
- sqlite3_io_error_pending = -1;
-}
-void enable_simulated_io_errors(void){
- sqlite3_io_error_pending = saved_cnt;
-}
-#else
-# define clear_simulated_io_error()
-# define disable_simulated_io_errors()
-# define enable_simulated_io_errors()
-#endif
+ 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. The rational for this is that this function
-** may be called even if the file does not exist or contain a header. In
-** these cases sqlite3OsRead() will return an error, to which the correct
-** response is to zero the memory at pDest and continue. A real IO error
-** will presumably recur and be picked up later (Todo: Think about this).
+** 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);
- clear_simulated_io_error();
+ sqlite3OsSeek(&pPager->fd, 0);
+ sqlite3OsRead(&pPager->fd, pDest, N);
}
}
/*
** Return the total number of pages in the disk file associated with
-** pPager.
-**
-** If the PENDING_BYTE lies on the page directly after the end of the
-** file, then consider this page part of the file too. For example, if
-** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the
-** file is 4096 bytes, 5 is returned instead of 4.
+** pPager.
*/
int sqlite3pager_pagecount(Pager *pPager){
i64 n;
assert( pPager!=0 );
if( pPager->dbSize>=0 ){
- n = pPager->dbSize;
- } else {
- if( sqlite3OsFileSize(pPager->fd, &n)!=SQLITE_OK ){
- pager_error(pPager, SQLITE_IOERR);
- return 0;
- }
- if( n>0 && npageSize ){
- n = 1;
- }else{
- n /= pPager->pageSize;
- }
- if( pPager->state!=PAGER_UNLOCK ){
- pPager->dbSize = n;
- }
- }
- if( n==(PENDING_BYTE/pPager->pageSize) ){
+ 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;
}
/*
@@ -1909,11 +1807,11 @@
#define memoryTruncate(p)
#endif
/*
** Try to obtain a lock on a file. Invoke the busy callback if the lock
-** is currently not available. Repeat until the busy callback returns
+** 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.
*/
@@ -1923,13 +1821,18 @@
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 && sqlite3InvokeBusyHandler(pPager->pBusyHandler) );
+ 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;
@@ -1939,12 +1842,12 @@
** Truncate the file to the number of pages specified.
*/
int sqlite3pager_truncate(Pager *pPager, Pgno nPage){
int rc;
sqlite3pager_pagecount(pPager);
- if( pPager->errCode ){
- rc = pPager->errCode;
+ if( pPager->errMask!=0 ){
+ rc = pager_errcode(pPager);
return rc;
}
if( nPage>=(unsigned)pPager->dbSize ){
return SQLITE_OK;
}
@@ -1977,42 +1880,39 @@
** 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.
-**
-** This function always succeeds. If a transaction is active an attempt
-** is made to roll it back. If an error occurs during the rollback
-** a hot journal may be left in the filesystem but no error is returned
-** to the caller.
*/
int sqlite3pager_close(Pager *pPager){
PgHdr *pPg, *pNext;
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- const ThreadData *pTsd = sqlite3ThreadDataReadOnly();
-#endif
-
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.
*/
- disable_simulated_io_errors();
+#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);
- enable_simulated_io_errors();
+#if defined(SQLITE_TEST) && (defined(OS_UNIX) || defined(OS_WIN))
+ sqlite3_io_error_pending = ioerr_cnt;
+#endif
if( !MEMDB ){
- sqlite3OsUnlock(pPager->fd, NO_LOCK);
+ sqlite3OsUnlock(&pPager->fd, NO_LOCK);
}
- assert( pPager->errCode || pPager->journalOpen==0 );
+ assert( pPager->journalOpen==0 );
break;
}
case PAGER_SHARED: {
if( !MEMDB ){
- sqlite3OsUnlock(pPager->fd, NO_LOCK);
+ sqlite3OsUnlock(&pPager->fd, NO_LOCK);
}
break;
}
default: {
/* Do nothing */
@@ -2030,43 +1930,18 @@
#endif
pNext = pPg->pNextAll;
sqliteFree(pPg);
}
TRACE2("CLOSE %d\n", PAGERID(pPager));
- assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) );
- if( pPager->journalOpen ){
- sqlite3OsClose(&pPager->jfd);
- }
- sqliteFree(pPager->aInJournal);
- if( pPager->stmtOpen ){
- sqlite3OsClose(&pPager->stfd);
- }
sqlite3OsClose(&pPager->fd);
+ assert( pPager->journalOpen==0 );
/* Temp files are automatically deleted by the OS
** if( pPager->tempFile ){
** sqlite3OsDelete(pPager->zFilename);
** }
*/
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- /* Remove the pager from the linked list of pagers starting at
- ** ThreadData.pPager if memory-management is enabled.
- */
- if( pTsd->useMemoryManagement ){
- if( pPager==pTsd->pPager ){
- pTsd->pPager = pPager->pNext;
- }else{
- Pager *pTmp;
- for(pTmp = pTsd->pPager; pTmp->pNext!=pPager; pTmp=pTmp->pNext);
- pTmp->pNext = pPager->pNext;
- }
- }
-#endif
-
-#ifdef SQLITE_HAS_CODEC
- sqlite3pager_free_codecarg(pPager->pCodecArg);
-#endif
sqliteFree(pPager);
return SQLITE_OK;
}
/*
@@ -2168,11 +2043,11 @@
{
/* 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);
+ rc = sqlite3OsFileSize(&pPager->jfd, &jSz);
if( rc!=0 ) return rc;
assert( pPager->journalOff==jSz );
}
#endif
{
@@ -2181,24 +2056,21 @@
** 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, 0);
+ rc = sqlite3OsSync(&pPager->jfd);
if( rc!=0 ) return rc;
}
- rc = sqlite3OsSeek(pPager->jfd,
- pPager->journalHdr + sizeof(aJournalMagic));
- if( rc ) return rc;
- rc = write32bits(pPager->jfd, pPager->nRec);
+ sqlite3OsSeek(&pPager->jfd, pPager->journalHdr + sizeof(aJournalMagic));
+ rc = write32bits(&pPager->jfd, pPager->nRec);
if( rc ) return rc;
- rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff);
- if( rc ) return rc;
+ sqlite3OsSeek(&pPager->jfd, pPager->journalOff);
}
TRACE2("SYNC journal of %d\n", PAGERID(pPager));
- rc = sqlite3OsSync(pPager->jfd, pPager->fullSync);
+ rc = sqlite3OsSync(&pPager->jfd);
if( rc!=0 ) return rc;
pPager->journalStarted = 1;
}
pPager->needSync = 0;
@@ -2259,24 +2131,22 @@
return rc;
}
while( pList ){
assert( pList->dirty );
- rc = sqlite3OsSeek(pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize);
- if( rc ) return rc;
+ 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);
+ rc = sqlite3OsWrite(&pPager->fd, PGHDR_TO_DATA(pList), pPager->pageSize);
CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0);
- TEST_INCR(pPager->nWrite);
+ pPager->nWrite++;
}
#ifndef NDEBUG
else{
TRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno);
}
@@ -2306,194 +2176,10 @@
}
}
return pList;
}
-/*
-** Return TRUE if there is a hot journal on the given pager.
-** A hot journal is one that needs to be played back.
-**
-** If the current size of the database file is 0 but a journal file
-** exists, that is probably an old journal left over from a prior
-** database with the same name. Just delete the journal.
-*/
-static int hasHotJournal(Pager *pPager){
- if( !pPager->useJournal ) return 0;
- if( !sqlite3OsFileExists(pPager->zJournal) ) return 0;
- if( sqlite3OsCheckReservedLock(pPager->fd) ) return 0;
- if( sqlite3pager_pagecount(pPager)==0 ){
- sqlite3OsDelete(pPager->zJournal);
- return 0;
- }else{
- return 1;
- }
-}
-
-/*
-** Try to find a page in the cache that can be recycled.
-**
-** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It
-** does not set the pPager->errCode variable.
-*/
-static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){
- PgHdr *pPg;
- *ppPg = 0;
-
- /* 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 && pPager->pFirst && syncOk && !MEMDB){
- int rc = syncJournal(pPager);
- if( rc!=0 ){
- return rc;
- }
- 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 ){
- return rc;
- }
- }
- pPg = pPager->pFirst;
- }
- if( pPg==0 ){
- return SQLITE_OK;
- }
-
- assert( pPg->nRef==0 );
-
- /* Write the page to the database file if it is dirty.
- */
- if( pPg->dirty ){
- int rc;
- assert( pPg->needSync==0 );
- pPg->pDirty = 0;
- rc = pager_write_pagelist( pPg );
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
- 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);
- TEST_INCR(pPager->nOvfl);
-
- *ppPg = pPg;
- return SQLITE_OK;
-}
-
-/*
-** This function is called to free superfluous dynamically allocated memory
-** held by the pager system. Memory in use by any SQLite pager allocated
-** by the current thread may be sqliteFree()ed.
-**
-** nReq is the number of bytes of memory required. Once this much has
-** been released, the function returns. A negative value for nReq means
-** free as much memory as possible. The return value is the total number
-** of bytes of memory released.
-*/
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-int sqlite3pager_release_memory(int nReq){
- const ThreadData *pTsdro = sqlite3ThreadDataReadOnly();
- Pager *p;
- int nReleased = 0;
- int i;
-
- /* If the the global mutex is held, this subroutine becomes a
- ** o-op; zero bytes of memory are freed. This is because
- ** some of the code invoked by this function may also
- ** try to obtain the mutex, resulting in a deadlock.
- */
- if( sqlite3OsInMutex() ){
- return 0;
- }
-
- /* Outermost loop runs for at most two iterations. First iteration we
- ** try to find memory that can be released without calling fsync(). Second
- ** iteration (which only runs if the first failed to free nReq bytes of
- ** memory) is permitted to call fsync(). This is of course much more
- ** expensive.
- */
- for(i=0; i<=1; i++){
-
- /* Loop through all the SQLite pagers opened by the current thread. */
- for(p=pTsdro->pPager; p && (nReq<0 || nReleasedpNext){
- PgHdr *pPg;
- int rc;
-
- /* For each pager, try to free as many pages as possible (without
- ** calling fsync() if this is the first iteration of the outermost
- ** loop).
- */
- while( SQLITE_OK==(rc = pager_recycle(p, i, &pPg)) && pPg) {
- /* We've found a page to free. At this point the page has been
- ** removed from the page hash-table, free-list and synced-list
- ** (pFirstSynced). It is still in the all pages (pAll) list.
- ** Remove it from this list before freeing.
- **
- ** Todo: Check the Pager.pStmt list to make sure this is Ok. It
- ** probably is though.
- */
- PgHdr *pTmp;
- assert( pPg );
- page_remove_from_stmt_list(pPg);
- if( pPg==p->pAll ){
- p->pAll = pPg->pNextAll;
- }else{
- for( pTmp=p->pAll; pTmp->pNextAll!=pPg; pTmp=pTmp->pNextAll );
- pTmp->pNextAll = pPg->pNextAll;
- }
- nReleased += sqliteAllocSize(pPg);
- sqliteFree(pPg);
- }
-
- if( rc!=SQLITE_OK ){
- /* An error occured whilst writing to the database file or
- ** journal in pager_recycle(). The error is not returned to the
- ** caller of this function. Instead, set the Pager.errCode variable.
- ** The error will be returned to the user (or users, in the case
- ** of a shared pager cache) of the pager for which the error occured.
- */
- assert( rc==SQLITE_IOERR || rc==SQLITE_FULL );
- assert( p->state>=PAGER_RESERVED );
- pager_error(p, rc);
- }
- }
- }
-
- return nReleased;
-}
-#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
-
/*
** 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.
@@ -2515,42 +2201,45 @@
** 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;
+ 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 || pgno==PAGER_MJ_PGNO(pPager) ){
- return SQLITE_CORRUPT_BKPT;
+ 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->errCode && pPager->errCode!=SQLITE_FULL ){
- return pPager->errCode;
+ 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 pager_error(pPager, rc);
+ 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( hasHotJournal(pPager) ){
+ 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
@@ -2560,15 +2249,15 @@
**
** 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);
+ rc = sqlite3OsLock(&pPager->fd, EXCLUSIVE_LOCK);
if( rc!=SQLITE_OK ){
- sqlite3OsUnlock(pPager->fd, NO_LOCK);
+ sqlite3OsUnlock(&pPager->fd, NO_LOCK);
pPager->state = PAGER_UNLOCK;
- return pager_error(pPager, rc);
+ return rc;
}
pPager->state = PAGER_EXCLUSIVE;
/* Open the journal for reading only. Return SQLITE_BUSY if
** we are unable to open the journal file.
@@ -2578,11 +2267,11 @@
** 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);
+ sqlite3OsUnlock(&pPager->fd, NO_LOCK);
pPager->state = PAGER_UNLOCK;
return SQLITE_BUSY;
}
pPager->journalOpen = 1;
pPager->journalStarted = 0;
@@ -2593,11 +2282,11 @@
/* Playback and delete the journal. Drop the database write
** lock and reacquire the read lock.
*/
rc = pager_playback(pPager);
if( rc!=SQLITE_OK ){
- return pager_error(pPager, rc);
+ return rc;
}
}
pPg = 0;
}else{
/* Search for page in cache */
@@ -2607,17 +2296,21 @@
}
}
if( pPg==0 ){
/* The requested page is not in the page cache. */
int h;
- TEST_INCR(pPager->nMiss);
+ pPager->nMiss++;
if( pPager->nPagemxPage || pPager->pFirst==0 || MEMDB ){
/* Create a new page */
- pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize
+ 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));
@@ -2624,20 +2317,75 @@
}
pPg->pPager = pPager;
pPg->pNextAll = pPager->pAll;
pPager->pAll = pPg;
pPager->nPage++;
- if( pPager->nPage>pPager->nMaxPage ){
- assert( pPager->nMaxPage==(pPager->nPage-1) );
- pPager->nMaxPage++;
- }
}else{
- rc = pager_recycle(pPager, 1, &pPg);
- if( rc!=SQLITE_OK ){
- return pager_error(pPager, rc);
+ /* 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;
}
- assert(pPg) ;
+
+ /* 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 );
@@ -2665,47 +2413,44 @@
pPg->pNextHash->pPrevHash = pPg;
}
if( pPager->nExtra>0 ){
memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);
}
- if( pPager->errCode ){
+ n = sqlite3pager_pagecount(pPager);
+ if( pPager->errMask!=0 ){
sqlite3pager_unref(PGHDR_TO_DATA(pPg));
- rc = pPager->errCode;
+ rc = pager_errcode(pPager);
return rc;
}
- if( sqlite3pager_pagecount(pPager)<(int)pgno ){
+ if( n<(int)pgno ){
memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
}else{
int rc;
assert( MEMDB==0 );
- rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize);
- if( rc==SQLITE_OK ){
- rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg),
- pPager->pageSize);
- }
+ 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
+ if( sqlite3OsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK
|| fileSize>=pgno*pPager->pageSize ){
sqlite3pager_unref(PGHDR_TO_DATA(pPg));
- return pager_error(pPager, rc);
+ return rc;
}else{
- clear_simulated_io_error();
memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
}
}else{
- TEST_INCR(pPager->nRead);
+ pPager->nRead++;
}
}
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
}else{
/* The requested page is in the page cache. */
- TEST_INCR(pPager->nHit);
+ pPager->nHit++;
page_ref(pPg);
}
*ppPage = PGHDR_TO_DATA(pPg);
return SQLITE_OK;
}
@@ -2724,11 +2469,11 @@
void *sqlite3pager_lookup(Pager *pPager, Pgno pgno){
PgHdr *pPg;
assert( pPager!=0 );
assert( pgno!=0 );
- if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
+ if( pPager->errMask & ~(PAGER_ERR_FULL) ){
return 0;
}
pPg = pager_lookup(pPager, pgno);
if( pPg==0 ) return 0;
page_ref(pPg);
@@ -2799,45 +2544,41 @@
int rc;
assert( !MEMDB );
assert( pPager->state>=PAGER_RESERVED );
assert( pPager->journalOpen==0 );
assert( pPager->useJournal );
- assert( pPager->aInJournal==0 );
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);
+ 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;
}
- sqlite3OsSetFullSync(pPager->jfd, pPager->fullSync);
- sqlite3OsSetFullSync(pPager->fd, pPager->fullSync);
- sqlite3OsOpenDirectory(pPager->jfd, pPager->zDirectory);
+ sqlite3OsOpenDirectory(pPager->zDirectory, &pPager->jfd);
pPager->journalOpen = 1;
pPager->journalStarted = 0;
pPager->needSync = 0;
pPager->alwaysRollback = 0;
pPager->nRec = 0;
- if( pPager->errCode ){
- rc = pPager->errCode;
- goto failed_to_open_journal;
+ 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!=SQLITE_NOMEM ){
+ if( rc!=SQLITE_OK ){
rc = pager_unwritelock(pPager);
if( rc==SQLITE_OK ){
rc = SQLITE_FULL;
}
}
@@ -2844,21 +2585,12 @@
return rc;
failed_to_open_journal:
sqliteFree(pPager->aInJournal);
pPager->aInJournal = 0;
- if( rc==SQLITE_NOMEM ){
- /* If this was a malloc() failure, then we will not be closing the pager
- ** file. So delete any journal file we may have just created. Otherwise,
- ** the system will get confused, we have a read-lock on the file and a
- ** mysterious journal has appeared in the filesystem.
- */
- sqlite3OsDelete(pPager->zJournal);
- }else{
- sqlite3OsUnlock(pPager->fd, NO_LOCK);
- pPager->state = PAGER_UNLOCK;
- }
+ sqlite3OsUnlock(&pPager->fd, NO_LOCK);
+ pPager->state = PAGER_UNLOCK;
return rc;
}
/*
** Acquire a write-lock on the database. The lock is removed when
@@ -2897,11 +2629,15 @@
assert( pPager->aInJournal==0 );
if( MEMDB ){
pPager->state = PAGER_EXCLUSIVE;
pPager->origDbSize = pPager->dbSize;
}else{
- rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK);
+ 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);
}
@@ -2941,12 +2677,12 @@
Pager *pPager = pPg->pPager;
int rc = SQLITE_OK;
/* Check for errors
*/
- if( pPager->errCode ){
- return pPager->errCode;
+ if( pPager->errMask ){
+ return pager_errcode(pPager);
}
if( pPager->readOnly ){
return SQLITE_PERM;
}
@@ -2998,31 +2734,25 @@
if( pHist->pOrig ){
memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize);
}
}else{
u32 cksum;
- /* We should never write to the journal file the page that
- ** contains the database locks. The following assert verifies
- ** that we do not. */
- assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
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);
+ 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);
- if( !pPager->errCode ){
- pager_error(pPager, SQLITE_FULL);
- }
+ pPager->errMask |= PAGER_ERR_FULL;
return rc;
}
pPager->nRec++;
assert( pPager->aInJournal!=0 );
pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
@@ -3059,19 +2789,16 @@
}
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);
+ 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);
- if( !pPager->errCode ){
- pager_error(pPager, SQLITE_FULL);
- }
+ pPager->errMask |= PAGER_ERR_FULL;
return rc;
}
pPager->stmtNRec++;
assert( pPager->aInStmt!=0 );
pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
@@ -3151,11 +2878,11 @@
if( MEMDB ) return;
pPg = pager_lookup(pPager, pgno);
pPg->alwaysRollback = 1;
- if( pPg && pPg->dirty && !pPager->stmtInUse ){
+ if( pPg && pPg->dirty ){
if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSizedbSize ){
/* 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
@@ -3227,19 +2954,19 @@
*/
int sqlite3pager_commit(Pager *pPager){
int rc;
PgHdr *pPg;
- if( pPager->errCode==SQLITE_FULL ){
+ if( pPager->errMask==PAGER_ERR_FULL ){
rc = sqlite3pager_rollback(pPager);
if( rc==SQLITE_OK ){
rc = SQLITE_FULL;
}
return rc;
}
- if( pPager->errCode ){
- rc = pPager->errCode;
+ if( pPager->errMask!=0 ){
+ rc = pager_errcode(pPager);
return rc;
}
if( pPager->statedbSize = -1;
return rc;
}
- if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
+ if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){
if( pPager->state>=PAGER_EXCLUSIVE ){
pager_playback(pPager);
}
- return pPager->errCode;
+ return pager_errcode(pPager);
}
if( pPager->state==PAGER_RESERVED ){
int rc2;
rc = pager_reload_cache(pPager);
rc2 = pager_unwritelock(pPager);
@@ -3363,12 +3090,12 @@
}
}else{
rc = pager_playback(pPager);
}
if( rc!=SQLITE_OK ){
- rc = SQLITE_CORRUPT_BKPT;
- pager_error(pPager, SQLITE_CORRUPT);
+ rc = SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ pPager->errMask |= PAGER_ERR_CORRUPT;
}
pPager->dbSize = -1;
return rc;
}
@@ -3388,18 +3115,16 @@
a[0] = pPager->nRef;
a[1] = pPager->nPage;
a[2] = pPager->mxPage;
a[3] = pPager->dbSize;
a[4] = pPager->state;
- a[5] = pPager->errCode;
-#ifdef SQLITE_TEST
+ a[5] = pPager->errMask;
a[6] = pPager->nHit;
a[7] = pPager->nMiss;
a[8] = pPager->nOvfl;
a[9] = pPager->nRead;
a[10] = pPager->nWrite;
-#endif
return a;
}
/*
** Set the statement rollback point.
@@ -3424,15 +3149,15 @@
return SQLITE_OK;
}
assert( pPager->journalOpen );
pPager->aInStmt = sqliteMalloc( pPager->dbSize/8 + 1 );
if( pPager->aInStmt==0 ){
- /* sqlite3OsLock(pPager->fd, SHARED_LOCK); */
+ sqlite3OsLock(&pPager->fd, SHARED_LOCK);
return SQLITE_NOMEM;
}
#ifndef NDEBUG
- rc = sqlite3OsFileSize(pPager->jfd, &pPager->stmtJSize);
+ 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;
@@ -3461,12 +3186,12 @@
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); */
+ sqlite3OsSeek(&pPager->stfd, 0);
+ /* sqlite3OsTruncate(&pPager->stfd, 0); */
sqliteFree( pPager->aInStmt );
pPager->aInStmt = 0;
}
for(pPg=pPager->pStmt; pPg; pPg=pNext){
pNext = pPg->pNextStmt;
@@ -3537,18 +3262,10 @@
*/
const char *sqlite3pager_journalname(Pager *pPager){
return pPager->zJournal;
}
-/*
-** Return true if fsync() calls are disabled for this pager. Return FALSE
-** if fsync()s are executed normally.
-*/
-int sqlite3pager_nosync(Pager *pPager){
- return pPager->noSync;
-}
-
/*
** Set the codec for this pager
*/
void sqlite3pager_set_codec(
Pager *pPager,
@@ -3633,13 +3350,12 @@
** being discarded by the truncation must be written to the journal
** file.
*/
Pgno i;
void *pPage;
- int iSkip = PAGER_MJ_PGNO(pPager);
for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){
- if( !(pPager->aInJournal[i/8] & (1<<(i&7))) && i!=iSkip ){
+ 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;
@@ -3665,11 +3381,11 @@
rc = pager_write_pagelist(pPg);
if( rc!=SQLITE_OK ) goto sync_exit;
/* Sync the database file. */
if( !pPager->noSync ){
- rc = sqlite3OsSync(pPager->fd, 0);
+ rc = sqlite3OsSync(&pPager->fd);
}
pPager->state = PAGER_SYNCED;
}
@@ -3688,21 +3404,20 @@
**
** 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. It used to be
-** required that a statement transaction was not active, but this restriction
-** has been removed (CREATE INDEX needs to move a page when a statement
-** transaction is active).
+** 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);
@@ -3779,11 +3494,15 @@
** 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){
- return sqlite3OsLockState(pPager->fd);
+#ifdef OS_TEST
+ return pPager->fd->fd.locktype;
+#else
+ return pPager->fd.locktype;
+#endif
}
#endif
#ifdef SQLITE_DEBUG
/*
@@ -3796,7 +3515,5 @@
sqlite3DebugPrintf("PAGE %3d addr=%p nRef=%d\n",
pPg->pgno, PGHDR_TO_DATA(pPg), pPg->nRef);
}
}
#endif
-
-#endif /* SQLITE_OMIT_DISKIO */
Index: SQLite.Interop/src/pager.h
==================================================================
--- SQLite.Interop/src/pager.h
+++ SQLite.Interop/src/pager.h
@@ -11,35 +11,29 @@
*************************************************************************
** 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.16 2006/01/16 15:51:47 rmsimpson Exp $
+** @(#) $Id: pager.h,v 1.1 2005/03/01 16:04:31 rmsimpson Exp $
*/
-#ifndef _PAGER_H_
-#define _PAGER_H_
-
/*
** 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 32768. This a limit
-** imposed by necessity of storing the value in a 2-byte unsigned integer
-** and the fact that the page size must be a power of 2.
-**
-** This value is used to initialize certain arrays on the stack at
-** various places in the code. On embedded machines where stack space
-** is limited and the flexibility of having large pages is not needed,
-** it makes good sense to reduce the maximum page size to something more
-** reasonable, like 1024.
+/* 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 32768
+# define SQLITE_MAX_PAGE_SIZE 8192
#endif
/*
** Maximum number of pages in one database.
*/
@@ -72,11 +66,11 @@
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));
-int sqlite3pager_set_pagesize(Pager*, 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);
@@ -101,22 +95,17 @@
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_nosync(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);
-int sqlite3pager_reset(Pager*);
-int sqlite3pager_release_memory(int);
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
int sqlite3pager_lockstate(Pager*);
#endif
#ifdef SQLITE_TEST
void sqlite3pager_refdump(Pager*);
int pager3_refinfo_enable;
#endif
-
-#endif /* _PAGER_H_ */
Index: SQLite.Interop/src/parse.c
==================================================================
--- SQLite.Interop/src/parse.c
+++ SQLite.Interop/src/parse.c
@@ -2,11 +2,11 @@
** The author disclaims copyright to this source code.
*/
/* First off, code is include which follows the "include" declaration
** in the input file. */
#include
-#line 51 "parse.y"
+#line 33 "parse.y"
#include "sqliteInt.h"
#include "parse.h"
/*
@@ -21,12 +21,12 @@
/*
** An instance of this structure is used to store the LIKE,
** GLOB, NOT LIKE, and NOT GLOB operators.
*/
struct LikeOp {
- Token operator; /* "like" or "glob" or "regexp" */
- int not; /* True if the NOT keyword is present */
+ 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,
@@ -91,39 +91,39 @@
** 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 240
+#define YYNOCODE 239
#define YYACTIONTYPE unsigned short int
#define sqlite3ParserTOKENTYPE Token
typedef union {
sqlite3ParserTOKENTYPE yy0;
- struct {int value; int mask;} yy13;
- struct TrigEvent yy132;
- IdList* yy160;
- Expr* yy178;
- int yy230;
- Select* yy239;
- TriggerStep* yy247;
- struct LimitVal yy270;
- SrcList* yy285;
- Expr * yy292;
- Token yy384;
- struct LikeOp yy440;
- ExprList* yy462;
- int yy479;
+ 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 561
-#define YYNRULE 295
-#define YYERRORSYMBOL 137
-#define YYERRSYMDT yy479
+#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)
@@ -173,401 +173,485 @@
** 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 */ 281, 67, 344, 80, 150, 157, 225, 517, 92, 92,
- /* 10 */ 92, 92, 288, 59, 59, 59, 59, 58, 58, 57,
- /* 20 */ 57, 57, 65, 346, 478, 48, 544, 86, 59, 59,
- /* 30 */ 59, 59, 58, 58, 57, 57, 57, 65, 67, 481,
- /* 40 */ 80, 150, 231, 64, 88, 295, 525, 518, 530, 530,
- /* 50 */ 72, 72, 92, 92, 92, 92, 219, 59, 59, 59,
- /* 60 */ 59, 58, 58, 57, 57, 57, 65, 281, 252, 189,
- /* 70 */ 517, 296, 344, 81, 59, 59, 59, 59, 58, 58,
- /* 80 */ 57, 57, 57, 65, 166, 115, 246, 303, 264, 323,
- /* 90 */ 196, 236, 158, 544, 478, 49, 387, 69, 228, 857,
- /* 100 */ 128, 560, 247, 56, 2, 381, 22, 476, 456, 363,
- /* 110 */ 64, 88, 295, 525, 518, 530, 530, 72, 72, 92,
- /* 120 */ 92, 92, 92, 283, 59, 59, 59, 59, 58, 58,
- /* 130 */ 57, 57, 57, 65, 281, 344, 279, 386, 395, 553,
- /* 140 */ 388, 165, 386, 276, 361, 288, 223, 439, 520, 451,
- /* 150 */ 344, 58, 58, 57, 57, 57, 65, 478, 38, 365,
- /* 160 */ 544, 145, 143, 282, 67, 393, 80, 150, 451, 500,
- /* 170 */ 393, 189, 478, 36, 500, 424, 425, 64, 88, 295,
- /* 180 */ 525, 518, 530, 530, 72, 72, 92, 92, 92, 92,
- /* 190 */ 71, 59, 59, 59, 59, 58, 58, 57, 57, 57,
- /* 200 */ 65, 281, 508, 508, 508, 429, 146, 508, 508, 508,
- /* 210 */ 294, 512, 507, 198, 344, 520, 350, 357, 362, 246,
- /* 220 */ 303, 264, 323, 196, 236, 283, 221, 544, 367, 310,
- /* 230 */ 228, 228, 57, 57, 57, 65, 478, 48, 308, 299,
- /* 240 */ 534, 537, 306, 417, 64, 88, 295, 525, 518, 530,
- /* 250 */ 530, 72, 72, 92, 92, 92, 92, 551, 59, 59,
- /* 260 */ 59, 59, 58, 58, 57, 57, 57, 65, 281, 550,
- /* 270 */ 202, 416, 198, 375, 520, 350, 357, 362, 512, 507,
- /* 280 */ 413, 414, 344, 293, 344, 372, 21, 367, 198, 522,
- /* 290 */ 517, 350, 357, 362, 544, 359, 539, 371, 374, 126,
- /* 300 */ 403, 209, 200, 367, 478, 18, 478, 43, 194, 169,
- /* 310 */ 384, 64, 88, 295, 525, 518, 530, 530, 72, 72,
- /* 320 */ 92, 92, 92, 92, 232, 59, 59, 59, 59, 58,
- /* 330 */ 58, 57, 57, 57, 65, 511, 344, 512, 507, 427,
- /* 340 */ 281, 420, 479, 479, 148, 419, 331, 233, 344, 67,
- /* 350 */ 344, 80, 150, 517, 344, 176, 155, 309, 478, 32,
- /* 360 */ 315, 436, 149, 184, 464, 195, 544, 348, 78, 533,
- /* 370 */ 478, 51, 478, 51, 378, 428, 478, 51, 479, 443,
- /* 380 */ 158, 377, 85, 64, 88, 295, 525, 518, 530, 530,
- /* 390 */ 72, 72, 92, 92, 92, 92, 479, 59, 59, 59,
- /* 400 */ 59, 58, 58, 57, 57, 57, 65, 281, 387, 467,
- /* 410 */ 504, 162, 77, 324, 344, 290, 521, 457, 22, 300,
- /* 420 */ 353, 520, 513, 513, 432, 487, 14, 487, 329, 271,
- /* 430 */ 257, 487, 426, 544, 523, 524, 478, 51, 217, 208,
- /* 440 */ 206, 144, 380, 355, 534, 537, 353, 55, 513, 513,
- /* 450 */ 64, 88, 295, 525, 518, 530, 530, 72, 72, 92,
- /* 460 */ 92, 92, 92, 375, 59, 59, 59, 59, 58, 58,
- /* 470 */ 57, 57, 57, 65, 281, 372, 11, 127, 71, 218,
- /* 480 */ 520, 241, 182, 126, 512, 507, 164, 155, 374, 520,
- /* 490 */ 338, 488, 452, 398, 543, 353, 200, 513, 513, 1,
- /* 500 */ 544, 401, 353, 520, 513, 513, 200, 553, 366, 165,
- /* 510 */ 157, 463, 517, 358, 540, 538, 479, 64, 88, 295,
- /* 520 */ 525, 518, 530, 530, 72, 72, 92, 92, 92, 92,
- /* 530 */ 468, 59, 59, 59, 59, 58, 58, 57, 57, 57,
- /* 540 */ 65, 370, 541, 512, 507, 437, 281, 344, 172, 506,
- /* 550 */ 239, 344, 512, 507, 344, 387, 224, 448, 93, 344,
- /* 560 */ 89, 344, 313, 344, 555, 22, 512, 507, 182, 478,
- /* 570 */ 27, 520, 544, 478, 43, 517, 478, 50, 561, 547,
- /* 580 */ 369, 478, 47, 478, 114, 478, 95, 528, 91, 64,
- /* 590 */ 88, 295, 525, 518, 530, 530, 72, 72, 92, 92,
- /* 600 */ 92, 92, 479, 59, 59, 59, 59, 58, 58, 57,
- /* 610 */ 57, 57, 65, 281, 226, 344, 251, 174, 110, 344,
- /* 620 */ 141, 147, 344, 465, 344, 449, 325, 370, 270, 344,
- /* 630 */ 421, 344, 450, 554, 512, 507, 2, 478, 52, 544,
- /* 640 */ 595, 478, 44, 311, 478, 30, 478, 45, 313, 173,
- /* 650 */ 418, 478, 53, 478, 25, 479, 64, 88, 295, 525,
- /* 660 */ 518, 530, 530, 72, 72, 92, 92, 92, 92, 344,
- /* 670 */ 59, 59, 59, 59, 58, 58, 57, 57, 57, 65,
- /* 680 */ 281, 344, 404, 479, 433, 344, 470, 344, 152, 344,
- /* 690 */ 469, 478, 112, 344, 415, 314, 415, 344, 411, 344,
- /* 700 */ 126, 287, 161, 478, 94, 440, 544, 478, 113, 478,
- /* 710 */ 12, 478, 99, 401, 465, 478, 41, 292, 456, 478,
- /* 720 */ 100, 478, 46, 64, 88, 295, 525, 518, 530, 530,
- /* 730 */ 72, 72, 92, 92, 92, 92, 344, 59, 59, 59,
- /* 740 */ 59, 58, 58, 57, 57, 57, 65, 281, 344, 485,
- /* 750 */ 19, 404, 344, 514, 344, 79, 307, 260, 478, 111,
- /* 760 */ 344, 242, 344, 548, 548, 344, 503, 501, 497, 466,
- /* 770 */ 478, 42, 404, 544, 478, 26, 478, 39, 478, 3,
- /* 780 */ 304, 423, 478, 31, 478, 40, 291, 478, 37, 305,
- /* 790 */ 64, 88, 295, 525, 518, 530, 530, 72, 72, 92,
- /* 800 */ 92, 92, 92, 344, 59, 59, 59, 59, 58, 58,
- /* 810 */ 57, 57, 57, 65, 281, 344, 470, 404, 126, 344,
- /* 820 */ 469, 344, 20, 344, 139, 478, 97, 344, 320, 7,
- /* 830 */ 242, 344, 190, 181, 180, 208, 451, 478, 28, 258,
- /* 840 */ 544, 478, 54, 478, 35, 478, 33, 222, 327, 478,
- /* 850 */ 34, 262, 204, 478, 29, 435, 191, 64, 76, 295,
- /* 860 */ 525, 518, 530, 530, 72, 72, 92, 92, 92, 92,
- /* 870 */ 404, 59, 59, 59, 59, 58, 58, 57, 57, 57,
- /* 880 */ 65, 281, 404, 454, 177, 162, 344, 208, 344, 175,
- /* 890 */ 479, 320, 447, 235, 211, 794, 242, 286, 456, 516,
- /* 900 */ 352, 441, 409, 410, 409, 298, 385, 544, 478, 24,
- /* 910 */ 478, 98, 252, 252, 252, 252, 275, 284, 479, 252,
- /* 920 */ 334, 252, 252, 479, 281, 88, 295, 525, 518, 530,
- /* 930 */ 530, 72, 72, 92, 92, 92, 92, 274, 59, 59,
- /* 940 */ 59, 59, 58, 58, 57, 57, 57, 65, 517, 242,
- /* 950 */ 544, 244, 252, 237, 340, 215, 494, 214, 390, 546,
- /* 960 */ 492, 242, 256, 489, 475, 406, 79, 397, 273, 295,
- /* 970 */ 525, 518, 530, 530, 72, 72, 92, 92, 92, 92,
- /* 980 */ 116, 59, 59, 59, 59, 58, 58, 57, 57, 57,
- /* 990 */ 65, 62, 345, 484, 4, 407, 412, 269, 289, 126,
- /* 1000 */ 519, 259, 23, 550, 202, 552, 349, 62, 345, 549,
- /* 1010 */ 4, 517, 354, 493, 289, 14, 547, 369, 402, 316,
- /* 1020 */ 240, 453, 349, 339, 472, 356, 142, 266, 471, 477,
- /* 1030 */ 249, 319, 505, 386, 459, 343, 529, 428, 255, 339,
- /* 1040 */ 71, 458, 499, 118, 333, 130, 121, 192, 389, 386,
- /* 1050 */ 123, 156, 60, 61, 483, 103, 87, 125, 212, 480,
- /* 1060 */ 62, 328, 330, 178, 277, 500, 229, 210, 60, 61,
- /* 1070 */ 438, 297, 399, 491, 476, 473, 62, 328, 330, 62,
- /* 1080 */ 345, 500, 4, 474, 208, 302, 289, 342, 207, 186,
- /* 1090 */ 498, 68, 278, 120, 349, 136, 400, 556, 508, 508,
- /* 1100 */ 508, 509, 510, 17, 312, 106, 243, 326, 205, 245,
- /* 1110 */ 373, 339, 434, 285, 508, 508, 508, 509, 510, 17,
- /* 1120 */ 74, 386, 160, 431, 248, 8, 321, 227, 220, 230,
- /* 1130 */ 102, 332, 137, 382, 383, 536, 405, 234, 75, 183,
- /* 1140 */ 60, 61, 317, 170, 265, 254, 135, 336, 62, 328,
- /* 1150 */ 330, 442, 267, 500, 263, 66, 318, 261, 201, 455,
- /* 1160 */ 447, 73, 461, 408, 168, 531, 443, 83, 482, 446,
- /* 1170 */ 376, 171, 396, 167, 444, 542, 545, 208, 238, 272,
- /* 1180 */ 213, 163, 188, 101, 364, 96, 508, 508, 508, 509,
- /* 1190 */ 510, 17, 490, 63, 270, 322, 153, 105, 335, 535,
- /* 1200 */ 526, 108, 558, 394, 527, 532, 250, 515, 379, 391,
- /* 1210 */ 13, 368, 557, 107, 351, 337, 216, 257, 82, 132,
- /* 1220 */ 559, 280, 109, 179, 347, 140, 208, 159, 65, 185,
- /* 1230 */ 502, 341, 268, 193, 392, 131, 129, 203, 496, 151,
- /* 1240 */ 10, 104, 154, 430, 486, 138, 253, 199, 495, 422,
- /* 1250 */ 360, 162, 445, 5, 15, 597, 9, 187, 117, 122,
- /* 1260 */ 596, 119, 133, 16, 6, 124, 301, 134, 14, 90,
- /* 1270 */ 70, 462, 84, 460, 197,
+ /* 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 */ 16, 216, 146, 218, 219, 21, 146, 23, 68, 69,
- /* 10 */ 70, 71, 16, 73, 74, 75, 76, 77, 78, 79,
- /* 20 */ 80, 81, 82, 146, 168, 169, 42, 72, 73, 74,
- /* 30 */ 75, 76, 77, 78, 79, 80, 81, 82, 216, 217,
- /* 40 */ 218, 219, 146, 59, 60, 61, 62, 63, 64, 65,
- /* 50 */ 66, 67, 68, 69, 70, 71, 146, 73, 74, 75,
- /* 60 */ 76, 77, 78, 79, 80, 81, 82, 16, 146, 43,
- /* 70 */ 86, 215, 146, 22, 73, 74, 75, 76, 77, 78,
- /* 80 */ 79, 80, 81, 82, 88, 89, 90, 91, 92, 93,
- /* 90 */ 94, 95, 22, 42, 168, 169, 146, 46, 102, 138,
- /* 100 */ 139, 140, 152, 19, 143, 155, 156, 23, 160, 187,
- /* 110 */ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 120 */ 69, 70, 71, 97, 73, 74, 75, 76, 77, 78,
- /* 130 */ 79, 80, 81, 82, 16, 146, 157, 58, 20, 160,
- /* 140 */ 161, 162, 58, 189, 16, 16, 220, 199, 23, 146,
- /* 150 */ 146, 77, 78, 79, 80, 81, 82, 168, 169, 237,
- /* 160 */ 42, 77, 78, 149, 216, 86, 218, 219, 146, 90,
- /* 170 */ 86, 43, 168, 169, 90, 89, 90, 59, 60, 61,
- /* 180 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 190 */ 120, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 200 */ 82, 16, 123, 124, 125, 20, 22, 123, 124, 125,
- /* 210 */ 207, 86, 87, 88, 146, 23, 91, 92, 93, 90,
- /* 220 */ 91, 92, 93, 94, 95, 97, 146, 42, 103, 207,
- /* 230 */ 102, 102, 79, 80, 81, 82, 168, 169, 224, 163,
- /* 240 */ 164, 165, 228, 177, 59, 60, 61, 62, 63, 64,
- /* 250 */ 65, 66, 67, 68, 69, 70, 71, 146, 73, 74,
- /* 260 */ 75, 76, 77, 78, 79, 80, 81, 82, 16, 77,
- /* 270 */ 78, 177, 88, 12, 23, 91, 92, 93, 86, 87,
- /* 280 */ 51, 52, 146, 215, 146, 24, 19, 103, 88, 97,
- /* 290 */ 23, 91, 92, 93, 42, 141, 142, 20, 37, 22,
- /* 300 */ 39, 147, 226, 103, 168, 169, 168, 169, 154, 154,
- /* 310 */ 49, 59, 60, 61, 62, 63, 64, 65, 66, 67,
- /* 320 */ 68, 69, 70, 71, 14, 73, 74, 75, 76, 77,
- /* 330 */ 78, 79, 80, 81, 82, 20, 146, 86, 87, 146,
- /* 340 */ 16, 25, 188, 188, 154, 29, 208, 209, 146, 216,
- /* 350 */ 146, 218, 219, 86, 146, 200, 201, 41, 168, 169,
- /* 360 */ 205, 20, 154, 53, 113, 55, 42, 213, 44, 236,
- /* 370 */ 168, 169, 168, 169, 175, 176, 168, 169, 188, 49,
- /* 380 */ 22, 182, 130, 59, 60, 61, 62, 63, 64, 65,
- /* 390 */ 66, 67, 68, 69, 70, 71, 188, 73, 74, 75,
- /* 400 */ 76, 77, 78, 79, 80, 81, 82, 16, 146, 20,
- /* 410 */ 20, 22, 21, 211, 146, 211, 146, 155, 156, 211,
- /* 420 */ 105, 23, 107, 108, 20, 223, 22, 223, 98, 99,
- /* 430 */ 100, 223, 177, 42, 164, 165, 168, 169, 14, 109,
- /* 440 */ 191, 179, 180, 163, 164, 165, 105, 198, 107, 108,
- /* 450 */ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 460 */ 69, 70, 71, 12, 73, 74, 75, 76, 77, 78,
- /* 470 */ 79, 80, 81, 82, 16, 24, 19, 53, 120, 55,
- /* 480 */ 23, 20, 154, 22, 86, 87, 200, 201, 37, 23,
- /* 490 */ 39, 223, 166, 167, 42, 105, 226, 107, 108, 19,
- /* 500 */ 42, 175, 105, 23, 107, 108, 226, 160, 161, 162,
- /* 510 */ 21, 113, 23, 16, 62, 63, 188, 59, 60, 61,
- /* 520 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 530 */ 22, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 540 */ 82, 213, 90, 86, 87, 79, 16, 146, 19, 146,
- /* 550 */ 20, 146, 86, 87, 146, 146, 132, 229, 129, 146,
- /* 560 */ 131, 146, 234, 146, 155, 156, 86, 87, 154, 168,
- /* 570 */ 169, 23, 42, 168, 169, 86, 168, 169, 0, 1,
- /* 580 */ 2, 168, 169, 168, 169, 168, 169, 90, 130, 59,
- /* 590 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
- /* 600 */ 70, 71, 188, 73, 74, 75, 76, 77, 78, 79,
- /* 610 */ 80, 81, 82, 16, 209, 146, 90, 230, 21, 146,
- /* 620 */ 112, 154, 146, 22, 146, 27, 231, 213, 102, 146,
- /* 630 */ 30, 146, 34, 140, 86, 87, 143, 168, 169, 42,
- /* 640 */ 111, 168, 169, 229, 168, 169, 168, 169, 234, 154,
- /* 650 */ 50, 168, 169, 168, 169, 188, 59, 60, 61, 62,
- /* 660 */ 63, 64, 65, 66, 67, 68, 69, 70, 71, 146,
- /* 670 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
- /* 680 */ 16, 146, 146, 188, 20, 146, 106, 146, 87, 146,
- /* 690 */ 110, 168, 169, 146, 98, 99, 100, 146, 20, 146,
- /* 700 */ 22, 101, 19, 168, 169, 167, 42, 168, 169, 168,
- /* 710 */ 169, 168, 169, 175, 113, 168, 169, 181, 160, 168,
- /* 720 */ 169, 168, 169, 59, 60, 61, 62, 63, 64, 65,
- /* 730 */ 66, 67, 68, 69, 70, 71, 146, 73, 74, 75,
- /* 740 */ 76, 77, 78, 79, 80, 81, 82, 16, 146, 146,
- /* 750 */ 67, 146, 146, 20, 146, 22, 146, 199, 168, 169,
- /* 760 */ 146, 225, 146, 123, 124, 146, 7, 8, 9, 202,
- /* 770 */ 168, 169, 146, 42, 168, 169, 168, 169, 168, 169,
- /* 780 */ 146, 18, 168, 169, 168, 169, 181, 168, 169, 79,
- /* 790 */ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 800 */ 69, 70, 71, 146, 73, 74, 75, 76, 77, 78,
- /* 810 */ 79, 80, 81, 82, 16, 146, 106, 146, 22, 146,
- /* 820 */ 110, 146, 19, 146, 21, 168, 169, 146, 146, 190,
- /* 830 */ 225, 146, 98, 99, 100, 109, 146, 168, 169, 146,
- /* 840 */ 42, 168, 169, 168, 169, 168, 169, 146, 122, 168,
- /* 850 */ 169, 225, 181, 168, 169, 92, 154, 59, 60, 61,
- /* 860 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 870 */ 146, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 880 */ 82, 16, 146, 20, 154, 22, 146, 109, 146, 154,
- /* 890 */ 188, 146, 96, 146, 212, 132, 225, 207, 160, 146,
- /* 900 */ 122, 184, 185, 184, 185, 181, 146, 42, 168, 169,
- /* 910 */ 168, 169, 146, 146, 146, 146, 146, 181, 188, 146,
- /* 920 */ 146, 146, 146, 188, 16, 60, 61, 62, 63, 64,
- /* 930 */ 65, 66, 67, 68, 69, 70, 71, 199, 73, 74,
- /* 940 */ 75, 76, 77, 78, 79, 80, 81, 82, 23, 225,
- /* 950 */ 42, 146, 146, 187, 187, 187, 187, 212, 159, 227,
- /* 960 */ 187, 225, 187, 187, 20, 171, 22, 168, 146, 61,
- /* 970 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 980 */ 146, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 990 */ 82, 16, 17, 187, 19, 7, 8, 20, 23, 22,
- /* 1000 */ 20, 171, 22, 77, 78, 160, 31, 16, 17, 227,
- /* 1010 */ 19, 86, 172, 20, 23, 22, 1, 2, 171, 146,
- /* 1020 */ 192, 146, 31, 48, 171, 146, 190, 144, 148, 171,
- /* 1030 */ 146, 146, 193, 58, 146, 222, 146, 176, 146, 48,
- /* 1040 */ 120, 193, 193, 59, 15, 183, 186, 111, 151, 58,
- /* 1050 */ 186, 6, 77, 78, 145, 19, 129, 186, 221, 193,
- /* 1060 */ 85, 86, 87, 151, 173, 90, 95, 210, 77, 78,
- /* 1070 */ 79, 40, 178, 145, 23, 159, 85, 86, 87, 16,
- /* 1080 */ 17, 90, 19, 145, 109, 151, 23, 15, 210, 150,
- /* 1090 */ 197, 119, 173, 19, 31, 214, 159, 136, 123, 124,
- /* 1100 */ 125, 126, 127, 128, 97, 238, 193, 117, 210, 194,
- /* 1110 */ 170, 48, 170, 151, 123, 124, 125, 126, 127, 128,
- /* 1120 */ 118, 58, 5, 170, 195, 22, 153, 10, 11, 12,
- /* 1130 */ 13, 115, 214, 170, 170, 33, 151, 196, 235, 150,
- /* 1140 */ 77, 78, 38, 26, 170, 28, 151, 151, 85, 86,
- /* 1150 */ 87, 183, 35, 90, 232, 97, 114, 203, 210, 204,
- /* 1160 */ 96, 129, 170, 233, 47, 145, 49, 235, 151, 172,
- /* 1170 */ 170, 54, 178, 56, 204, 151, 151, 109, 135, 203,
- /* 1180 */ 174, 183, 134, 174, 57, 158, 123, 124, 125, 126,
- /* 1190 */ 127, 128, 188, 19, 102, 146, 146, 14, 185, 1,
- /* 1200 */ 90, 19, 180, 168, 20, 20, 20, 106, 180, 168,
- /* 1210 */ 19, 44, 20, 19, 44, 98, 99, 100, 19, 121,
- /* 1220 */ 4, 104, 19, 111, 3, 19, 109, 121, 82, 111,
- /* 1230 */ 11, 16, 146, 97, 17, 101, 112, 44, 20, 19,
- /* 1240 */ 5, 19, 111, 20, 17, 21, 132, 22, 20, 45,
- /* 1250 */ 133, 22, 11, 116, 22, 111, 1, 112, 32, 45,
- /* 1260 */ 111, 101, 20, 19, 116, 97, 36, 19, 22, 67,
- /* 1270 */ 19, 113, 67, 20, 94,
+ /* 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 (-61)
-#define YY_SHIFT_MAX 371
+#define YY_SHIFT_USE_DFLT (-76)
static const short yy_shift_ofst[] = {
- /* 0 */ 1015, 975, 1117, -16, 975, 1063, 1063, 1063, 125, 330,
- /* 10 */ 330, 1068, 324, 1063, 1063, 1063, 1063, 1063, -45, 192,
- /* 20 */ 548, 926, 925, 926, 51, 391, 118, 185, 252, 458,
- /* 30 */ 530, 597, 664, 731, 731, 731, 731, 731, 731, 731,
- /* 40 */ 731, 731, 798, 731, 731, 731, 731, 731, 731, 731,
- /* 50 */ 731, 731, 865, 908, 908, 991, 1063, 1063, 1063, 1063,
- /* 60 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063,
- /* 70 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063,
- /* 80 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063,
- /* 90 */ 1063, 1063, 1063, 1063, -60, -60, -4, 1, 1, 74,
- /* 100 */ 153, 128, 763, 548, 548, 548, 548, 548, 548, 548,
- /* 110 */ 925, 1146, -61, -61, -61, 84, 129, 261, 261, 548,
- /* 120 */ 548, 548, 548, 548, 548, 548, 548, 548, 578, 548,
- /* 130 */ 548, 548, 548, 489, 548, 489, 778, 726, 1068, 1068,
- /* 140 */ 1068, -61, -61, 79, 184, 79, 200, 390, 341, 315,
- /* 150 */ 480, 451, 251, 398, 466, 457, 548, 548, 548, 548,
- /* 160 */ 759, 548, 548, 548, 601, 267, 548, 548, 548, 397,
- /* 170 */ 548, 548, 710, 397, 596, 397, 601, 397, 316, 548,
- /* 180 */ 600, 600, 397, 548, 548, 548, 548, 548, 548, 548,
- /* 190 */ 600, 397, 548, 548, 397, 548, 548, 548, 548, 548,
- /* 200 */ 640, 598, 640, 598, 796, 598, 508, 598, 580, 803,
- /* 210 */ 598, 70, 429, 26, 358, 920, 984, 1029, 1029, 936,
- /* 220 */ 1045, 920, 1036, 927, 1029, 936, 971, 1045, 1031, 1051,
- /* 230 */ 1045, 936, 1072, 971, 972, 1036, 1051, 1074, 961, 1007,
- /* 240 */ 920, 1007, 971, 990, 936, 1002, 1007, 1103, 1016, 1074,
- /* 250 */ 1007, 1007, 936, 1072, 1102, 936, 1104, 984, 936, 1007,
- /* 260 */ 1058, 1042, 971, 1032, 1007, 1064, 1045, 1102, 936, 1007,
- /* 270 */ 1031, 984, 1042, 936, 1058, 936, 1068, -61, -61, -61,
- /* 280 */ 424, 452, 310, 734, 277, 683, 389, 86, 526, 529,
- /* 290 */ 404, 461, 678, 733, 863, 497, 944, 988, 977, 980,
- /* 300 */ 993, 229, 1136, 1193, 1222, 1223, 1235, 1131, 1114, 1204,
- /* 310 */ 1229, 1241, 1226, 1255, 1214, 1242, 1160, 1230, 1248, 1202,
- /* 320 */ 1205, 1253, 1158, 1251, 1246, 1168, 1148, 1244, 1149, 1145,
- /* 330 */ 1144, 1232, 1137, 1227, 1228, 1225, 1224, 1124, 1218, 1220,
- /* 340 */ 1134, 1217, 1215, 1219, 1118, 1206, 1112, 1216, 1098, 1199,
- /* 350 */ 1170, 1194, 1191, 1101, 1186, 1185, 1184, 1182, 1110, 1198,
- /* 360 */ 1183, 1092, 1174, 1127, 1048, 1043, 1192, 1167, 1203, 1221,
- /* 370 */ 1106, 1180,
+ /* 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 (-216)
-#define YY_REDUCE_MAX 279
+#define YY_REDUCE_USE_DFLT (-95)
static const short yy_reduce_ofst[] = {
- /* 0 */ -39, 208, 154, -52, 190, 138, 202, 204, 262, 328,
- /* 10 */ 414, 155, 133, 68, 268, 405, -144, -74, -178, 270,
- /* 20 */ -50, 76, -21, 280, -215, -215, -215, -215, -215, -215,
- /* 30 */ -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
- /* 40 */ -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
- /* 50 */ -215, -215, -215, -215, -215, 610, 606, 590, 551, 543,
- /* 60 */ 539, 523, 483, 476, 469, 415, 408, 136, 740, -11,
- /* 70 */ 401, 413, 417, 473, 478, 485, 535, 541, 547, 553,
- /* 80 */ 602, 608, 614, 4, 616, 619, 657, 669, 673, 675,
- /* 90 */ 677, 681, 742, 685, -215, -215, 326, -215, -215, -215,
- /* 100 */ -215, 199, 14, 536, 605, -78, 409, 671, 724, 736,
- /* 110 */ 347, -215, -215, -215, -215, 799, 538, 719, 717, 745,
- /* 120 */ 690, 806, 22, 776, 775, 773, 626, 769, 493, 768,
- /* 130 */ 767, 682, 766, 738, 3, 558, 735, 730, 702, 495,
- /* 140 */ 467, 286, 249, 1041, 1028, 1035, 1022, -46, -46, -46,
- /* 150 */ 1086, 1013, 1050, 1049, -123, 892, 890, 888, 885, 884,
- /* 160 */ 883, 879, 875, 873, 567, 845, 834, 822, 805, -46,
- /* 170 */ 770, 753, 639, -46, 395, -46, 567, -46, 387, 403,
- /* 180 */ 94, 66, -46, -104, -140, -123, -90, 80, 111, 193,
- /* 190 */ 255, -46, 603, 634, -46, 693, 701, 747, 760, 774,
- /* 200 */ 732, 794, 782, 830, 840, 847, 828, 853, 836, 880,
- /* 210 */ 858, 839, 813, 861, 848, 849, 862, 860, 864, 897,
- /* 220 */ 909, 866, 891, 837, 871, 912, 857, 928, 894, 916,
- /* 230 */ 938, 934, 939, 878, 893, 919, 937, 881, 867, 940,
- /* 240 */ 913, 942, 898, 915, 962, 929, 953, 973, 941, 918,
- /* 250 */ 963, 964, 985, 989, 903, 995, 922, 968, 996, 974,
- /* 260 */ 954, 955, 948, 930, 992, 997, 1020, 932, 1017, 1000,
- /* 270 */ 994, 998, 970, 1024, 976, 1025, 1004, 1006, 1009, 1027,
+ /* 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 */ 567, 791, 856, 682, 856, 856, 791, 791, 856, 829,
- /* 10 */ 829, 686, 842, 856, 791, 856, 856, 787, 762, 813,
- /* 20 */ 856, 813, 598, 813, 717, 856, 856, 856, 856, 856,
- /* 30 */ 856, 856, 856, 724, 782, 784, 846, 783, 718, 719,
- /* 40 */ 725, 843, 856, 706, 827, 715, 730, 722, 731, 786,
- /* 50 */ 698, 790, 752, 768, 751, 856, 856, 856, 856, 856,
- /* 60 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 70 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 80 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 90 */ 856, 856, 856, 856, 773, 754, 591, 761, 753, 755,
- /* 100 */ 756, 651, 586, 856, 856, 856, 856, 856, 856, 856,
- /* 110 */ 856, 757, 769, 770, 758, 856, 856, 856, 856, 856,
- /* 120 */ 856, 856, 856, 856, 856, 856, 856, 856, 567, 856,
- /* 130 */ 856, 856, 856, 682, 856, 682, 856, 856, 856, 856,
- /* 140 */ 856, 686, 676, 856, 642, 856, 856, 856, 856, 856,
- /* 150 */ 856, 856, 856, 856, 856, 856, 572, 856, 856, 856,
- /* 160 */ 574, 856, 856, 856, 684, 600, 856, 847, 856, 689,
- /* 170 */ 849, 801, 674, 588, 856, 727, 690, 832, 819, 856,
- /* 180 */ 856, 856, 834, 856, 856, 856, 856, 856, 856, 856,
- /* 190 */ 856, 663, 856, 856, 665, 856, 856, 856, 856, 856,
- /* 200 */ 856, 709, 856, 709, 624, 709, 683, 709, 674, 856,
- /* 210 */ 709, 721, 785, 621, 721, 721, 655, 662, 662, 691,
- /* 220 */ 571, 721, 795, 856, 662, 691, 710, 571, 638, 856,
- /* 230 */ 571, 691, 583, 710, 716, 795, 856, 732, 854, 653,
- /* 240 */ 721, 653, 710, 712, 691, 714, 653, 641, 702, 732,
- /* 250 */ 653, 653, 691, 583, 845, 691, 823, 655, 691, 653,
- /* 260 */ 699, 701, 710, 826, 653, 624, 571, 845, 691, 653,
- /* 270 */ 638, 655, 701, 691, 699, 691, 856, 626, 626, 608,
- /* 280 */ 856, 856, 856, 856, 856, 808, 856, 856, 856, 739,
- /* 290 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 300 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 310 */ 822, 856, 856, 856, 821, 856, 856, 856, 856, 856,
- /* 320 */ 856, 856, 856, 856, 713, 856, 856, 856, 744, 856,
- /* 330 */ 740, 703, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 340 */ 856, 856, 856, 856, 856, 856, 741, 856, 856, 856,
- /* 350 */ 856, 856, 856, 668, 856, 856, 856, 856, 856, 856,
- /* 360 */ 856, 856, 856, 853, 856, 856, 856, 856, 856, 568,
- /* 370 */ 856, 856, 838, 649, 839, 837, 648, 650, 652, 644,
- /* 380 */ 645, 590, 647, 617, 659, 646, 750, 592, 599, 582,
- /* 390 */ 615, 614, 584, 744, 613, 612, 636, 611, 610, 637,
- /* 400 */ 623, 622, 798, 658, 799, 693, 797, 639, 815, 657,
- /* 410 */ 654, 796, 640, 824, 825, 820, 631, 630, 635, 816,
- /* 420 */ 817, 634, 818, 585, 633, 632, 629, 628, 627, 620,
- /* 430 */ 749, 616, 748, 737, 792, 793, 777, 679, 678, 677,
- /* 440 */ 609, 656, 728, 729, 688, 814, 618, 625, 828, 707,
- /* 450 */ 708, 735, 607, 734, 700, 687, 681, 589, 830, 680,
- /* 460 */ 587, 619, 697, 696, 695, 694, 685, 733, 675, 672,
- /* 470 */ 673, 581, 705, 711, 580, 831, 593, 704, 736, 666,
- /* 480 */ 833, 763, 779, 579, 660, 692, 661, 789, 788, 664,
- /* 490 */ 667, 578, 800, 776, 840, 836, 835, 577, 671, 720,
- /* 500 */ 738, 576, 781, 575, 780, 723, 742, 597, 743, 745,
- /* 510 */ 746, 778, 596, 670, 726, 669, 802, 594, 774, 601,
- /* 520 */ 595, 803, 804, 805, 806, 771, 767, 807, 765, 573,
- /* 530 */ 764, 570, 602, 841, 605, 566, 844, 606, 775, 564,
- /* 540 */ 772, 766, 848, 760, 759, 850, 809, 565, 811, 810,
- /* 550 */ 812, 851, 604, 603, 562, 852, 855, 747, 643, 569,
- /* 560 */ 563,
+ /* 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:
@@ -580,70 +664,76 @@
** 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 */
- 23, /* EXPLAIN => ID */
- 23, /* QUERY => ID */
- 23, /* PLAN => ID */
- 23, /* BEGIN => ID */
+ 26, /* EXPLAIN => ID */
+ 26, /* BEGIN => ID */
0, /* TRANSACTION => nothing */
- 23, /* DEFERRED => ID */
- 23, /* IMMEDIATE => ID */
- 23, /* EXCLUSIVE => ID */
+ 26, /* DEFERRED => ID */
+ 26, /* IMMEDIATE => ID */
+ 26, /* EXCLUSIVE => ID */
0, /* COMMIT => nothing */
- 23, /* END => ID */
+ 26, /* END => ID */
0, /* ROLLBACK => nothing */
0, /* CREATE => nothing */
0, /* TABLE => nothing */
- 23, /* IF => ID */
- 0, /* NOT => nothing */
- 0, /* EXISTS => nothing */
- 23, /* TEMP => ID */
+ 26, /* TEMP => ID */
0, /* LP => nothing */
0, /* RP => nothing */
0, /* AS => nothing */
0, /* COMMA => nothing */
0, /* ID => nothing */
- 23, /* ABORT => ID */
- 23, /* AFTER => ID */
- 23, /* ANALYZE => ID */
- 23, /* ASC => ID */
- 23, /* ATTACH => ID */
- 23, /* BEFORE => ID */
- 23, /* CASCADE => ID */
- 23, /* CAST => ID */
- 23, /* CONFLICT => ID */
- 23, /* DATABASE => ID */
- 23, /* DESC => ID */
- 23, /* DETACH => ID */
- 23, /* EACH => ID */
- 23, /* FAIL => ID */
- 23, /* FOR => ID */
- 23, /* IGNORE => ID */
- 23, /* INITIALLY => ID */
- 23, /* INSTEAD => ID */
- 23, /* LIKE_KW => ID */
- 23, /* MATCH => ID */
- 23, /* KEY => ID */
- 23, /* OF => ID */
- 23, /* OFFSET => ID */
- 23, /* PRAGMA => ID */
- 23, /* RAISE => ID */
- 23, /* REPLACE => ID */
- 23, /* RESTRICT => ID */
- 23, /* ROW => ID */
- 23, /* STATEMENT => ID */
- 23, /* TRIGGER => ID */
- 23, /* VACUUM => ID */
- 23, /* VIEW => ID */
- 23, /* REINDEX => ID */
- 23, /* RENAME => ID */
- 23, /* CTIME_KW => ID */
+ 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 */
@@ -686,12 +776,12 @@
0, /* DEFERRABLE => nothing */
0, /* FOREIGN => nothing */
0, /* DROP => nothing */
0, /* UNION => nothing */
0, /* ALL => nothing */
- 0, /* EXCEPT => nothing */
0, /* INTERSECT => nothing */
+ 0, /* EXCEPT => nothing */
0, /* SELECT => nothing */
0, /* DISTINCT => nothing */
0, /* DOT => nothing */
0, /* FROM => nothing */
0, /* JOIN => nothing */
@@ -707,19 +797,17 @@
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, /* ALTER => nothing */
0, /* TO => nothing */
- 0, /* ADD => nothing */
- 0, /* COLUMNKW => nothing */
};
#endif /* YYFALLBACK */
/* The following structure represents a single element of the
** parser's stack. Information stored includes:
@@ -786,70 +874,70 @@
#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[] = {
- "$", "SEMI", "EXPLAIN", "QUERY",
- "PLAN", "BEGIN", "TRANSACTION", "DEFERRED",
- "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END",
- "ROLLBACK", "CREATE", "TABLE", "IF",
- "NOT", "EXISTS", "TEMP", "LP",
- "RP", "AS", "COMMA", "ID",
- "ABORT", "AFTER", "ANALYZE", "ASC",
- "ATTACH", "BEFORE", "CASCADE", "CAST",
- "CONFLICT", "DATABASE", "DESC", "DETACH",
- "EACH", "FAIL", "FOR", "IGNORE",
- "INITIALLY", "INSTEAD", "LIKE_KW", "MATCH",
- "KEY", "OF", "OFFSET", "PRAGMA",
- "RAISE", "REPLACE", "RESTRICT", "ROW",
- "STATEMENT", "TRIGGER", "VACUUM", "VIEW",
- "REINDEX", "RENAME", "CTIME_KW", "OR",
- "AND", "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", "EXCEPT",
- "INTERSECT", "SELECT", "DISTINCT", "DOT",
- "FROM", "JOIN", "USING", "ORDER",
- "BY", "GROUP", "HAVING", "LIMIT",
- "WHERE", "INTO", "VALUES", "INTEGER",
- "FLOAT", "BLOB", "REGISTER", "VARIABLE",
- "CASE", "WHEN", "THEN", "ELSE",
- "INDEX", "ALTER", "TO", "ADD",
- "COLUMNKW", "error", "input", "cmdlist",
+ "$", "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", "ifnotexists", "dbnm",
- "columnlist", "conslist_opt", "select", "column",
- "columnid", "type", "carglist", "id",
- "ids", "typetoken", "typename", "signed",
- "plus_num", "minus_num", "carg", "ccons",
- "term", "expr", "onconf", "sortorder",
- "autoinc", "idxlist_opt", "refargs", "defer_subclause",
- "refarg", "refact", "init_deferred_pred_opt", "conslist",
- "tcons", "idxlist", "defer_subclause_opt", "orconf",
- "resolvetype", "raisetype", "ifexists", "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", "add_column_fullname", "kwcolumn_opt",
+ "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.
@@ -861,297 +949,307 @@
/* 3 */ "cmdx ::= cmd",
/* 4 */ "ecmd ::= SEMI",
/* 5 */ "ecmd ::= explain cmdx SEMI",
/* 6 */ "explain ::=",
/* 7 */ "explain ::= EXPLAIN",
- /* 8 */ "explain ::= EXPLAIN QUERY PLAN",
- /* 9 */ "cmd ::= BEGIN transtype trans_opt",
- /* 10 */ "trans_opt ::=",
- /* 11 */ "trans_opt ::= TRANSACTION",
- /* 12 */ "trans_opt ::= TRANSACTION nm",
- /* 13 */ "transtype ::=",
- /* 14 */ "transtype ::= DEFERRED",
- /* 15 */ "transtype ::= IMMEDIATE",
- /* 16 */ "transtype ::= EXCLUSIVE",
- /* 17 */ "cmd ::= COMMIT trans_opt",
- /* 18 */ "cmd ::= END trans_opt",
- /* 19 */ "cmd ::= ROLLBACK trans_opt",
- /* 20 */ "cmd ::= create_table create_table_args",
- /* 21 */ "create_table ::= CREATE temp TABLE ifnotexists nm dbnm",
- /* 22 */ "ifnotexists ::=",
- /* 23 */ "ifnotexists ::= IF NOT EXISTS",
- /* 24 */ "temp ::= TEMP",
- /* 25 */ "temp ::=",
- /* 26 */ "create_table_args ::= LP columnlist conslist_opt RP",
- /* 27 */ "create_table_args ::= AS select",
- /* 28 */ "columnlist ::= columnlist COMMA column",
- /* 29 */ "columnlist ::= column",
- /* 30 */ "column ::= columnid type carglist",
- /* 31 */ "columnid ::= nm",
- /* 32 */ "id ::= ID",
- /* 33 */ "ids ::= ID|STRING",
- /* 34 */ "nm ::= ID",
- /* 35 */ "nm ::= STRING",
- /* 36 */ "nm ::= JOIN_KW",
- /* 37 */ "type ::=",
- /* 38 */ "type ::= typetoken",
- /* 39 */ "typetoken ::= typename",
- /* 40 */ "typetoken ::= typename LP signed RP",
- /* 41 */ "typetoken ::= typename LP signed COMMA signed RP",
- /* 42 */ "typename ::= ids",
- /* 43 */ "typename ::= typename ids",
- /* 44 */ "signed ::= plus_num",
- /* 45 */ "signed ::= minus_num",
- /* 46 */ "carglist ::= carglist carg",
- /* 47 */ "carglist ::=",
- /* 48 */ "carg ::= CONSTRAINT nm ccons",
- /* 49 */ "carg ::= ccons",
- /* 50 */ "carg ::= DEFAULT term",
- /* 51 */ "carg ::= DEFAULT LP expr RP",
- /* 52 */ "carg ::= DEFAULT PLUS term",
- /* 53 */ "carg ::= DEFAULT MINUS term",
- /* 54 */ "carg ::= DEFAULT id",
- /* 55 */ "ccons ::= NULL onconf",
- /* 56 */ "ccons ::= NOT NULL onconf",
- /* 57 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
- /* 58 */ "ccons ::= UNIQUE onconf",
- /* 59 */ "ccons ::= CHECK LP expr RP",
- /* 60 */ "ccons ::= REFERENCES nm idxlist_opt refargs",
- /* 61 */ "ccons ::= defer_subclause",
- /* 62 */ "ccons ::= COLLATE id",
- /* 63 */ "autoinc ::=",
- /* 64 */ "autoinc ::= AUTOINCR",
- /* 65 */ "refargs ::=",
- /* 66 */ "refargs ::= refargs refarg",
- /* 67 */ "refarg ::= MATCH nm",
- /* 68 */ "refarg ::= ON DELETE refact",
- /* 69 */ "refarg ::= ON UPDATE refact",
- /* 70 */ "refarg ::= ON INSERT refact",
- /* 71 */ "refact ::= SET NULL",
- /* 72 */ "refact ::= SET DEFAULT",
- /* 73 */ "refact ::= CASCADE",
- /* 74 */ "refact ::= RESTRICT",
- /* 75 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
- /* 76 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
- /* 77 */ "init_deferred_pred_opt ::=",
- /* 78 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
- /* 79 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
- /* 80 */ "conslist_opt ::=",
- /* 81 */ "conslist_opt ::= COMMA conslist",
- /* 82 */ "conslist ::= conslist COMMA tcons",
- /* 83 */ "conslist ::= conslist tcons",
- /* 84 */ "conslist ::= tcons",
- /* 85 */ "tcons ::= CONSTRAINT nm",
- /* 86 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
- /* 87 */ "tcons ::= UNIQUE LP idxlist RP onconf",
- /* 88 */ "tcons ::= CHECK LP expr RP onconf",
- /* 89 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
- /* 90 */ "defer_subclause_opt ::=",
- /* 91 */ "defer_subclause_opt ::= defer_subclause",
- /* 92 */ "onconf ::=",
- /* 93 */ "onconf ::= ON CONFLICT resolvetype",
- /* 94 */ "orconf ::=",
- /* 95 */ "orconf ::= OR resolvetype",
- /* 96 */ "resolvetype ::= raisetype",
- /* 97 */ "resolvetype ::= IGNORE",
- /* 98 */ "resolvetype ::= REPLACE",
- /* 99 */ "cmd ::= DROP TABLE ifexists fullname",
- /* 100 */ "ifexists ::= IF EXISTS",
- /* 101 */ "ifexists ::=",
- /* 102 */ "cmd ::= CREATE temp VIEW nm dbnm AS select",
- /* 103 */ "cmd ::= DROP VIEW ifexists fullname",
- /* 104 */ "cmd ::= select",
- /* 105 */ "select ::= oneselect",
- /* 106 */ "select ::= select multiselect_op oneselect",
- /* 107 */ "multiselect_op ::= UNION",
- /* 108 */ "multiselect_op ::= UNION ALL",
- /* 109 */ "multiselect_op ::= EXCEPT|INTERSECT",
- /* 110 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
- /* 111 */ "distinct ::= DISTINCT",
- /* 112 */ "distinct ::= ALL",
- /* 113 */ "distinct ::=",
- /* 114 */ "sclp ::= selcollist COMMA",
- /* 115 */ "sclp ::=",
- /* 116 */ "selcollist ::= sclp expr as",
- /* 117 */ "selcollist ::= sclp STAR",
- /* 118 */ "selcollist ::= sclp nm DOT STAR",
- /* 119 */ "as ::= AS nm",
- /* 120 */ "as ::= ids",
- /* 121 */ "as ::=",
- /* 122 */ "from ::=",
- /* 123 */ "from ::= FROM seltablist",
- /* 124 */ "stl_prefix ::= seltablist joinop",
- /* 125 */ "stl_prefix ::=",
- /* 126 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt",
- /* 127 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt",
- /* 128 */ "seltablist_paren ::= select",
- /* 129 */ "seltablist_paren ::= seltablist",
- /* 130 */ "dbnm ::=",
- /* 131 */ "dbnm ::= DOT nm",
- /* 132 */ "fullname ::= nm dbnm",
- /* 133 */ "joinop ::= COMMA|JOIN",
- /* 134 */ "joinop ::= JOIN_KW JOIN",
- /* 135 */ "joinop ::= JOIN_KW nm JOIN",
- /* 136 */ "joinop ::= JOIN_KW nm nm JOIN",
- /* 137 */ "on_opt ::= ON expr",
- /* 138 */ "on_opt ::=",
- /* 139 */ "using_opt ::= USING LP inscollist RP",
- /* 140 */ "using_opt ::=",
- /* 141 */ "orderby_opt ::=",
- /* 142 */ "orderby_opt ::= ORDER BY sortlist",
- /* 143 */ "sortlist ::= sortlist COMMA sortitem collate sortorder",
- /* 144 */ "sortlist ::= sortitem collate sortorder",
- /* 145 */ "sortitem ::= expr",
- /* 146 */ "sortorder ::= ASC",
- /* 147 */ "sortorder ::= DESC",
- /* 148 */ "sortorder ::=",
- /* 149 */ "collate ::=",
- /* 150 */ "collate ::= COLLATE id",
- /* 151 */ "groupby_opt ::=",
- /* 152 */ "groupby_opt ::= GROUP BY exprlist",
- /* 153 */ "having_opt ::=",
- /* 154 */ "having_opt ::= HAVING expr",
- /* 155 */ "limit_opt ::=",
- /* 156 */ "limit_opt ::= LIMIT expr",
- /* 157 */ "limit_opt ::= LIMIT expr OFFSET expr",
- /* 158 */ "limit_opt ::= LIMIT expr COMMA expr",
- /* 159 */ "cmd ::= DELETE FROM fullname where_opt",
- /* 160 */ "where_opt ::=",
- /* 161 */ "where_opt ::= WHERE expr",
- /* 162 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt",
- /* 163 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 164 */ "setlist ::= nm EQ expr",
- /* 165 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP",
- /* 166 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
- /* 167 */ "insert_cmd ::= INSERT orconf",
- /* 168 */ "insert_cmd ::= REPLACE",
- /* 169 */ "itemlist ::= itemlist COMMA expr",
- /* 170 */ "itemlist ::= expr",
- /* 171 */ "inscollist_opt ::=",
- /* 172 */ "inscollist_opt ::= LP inscollist RP",
- /* 173 */ "inscollist ::= inscollist COMMA nm",
- /* 174 */ "inscollist ::= nm",
- /* 175 */ "expr ::= term",
- /* 176 */ "expr ::= LP expr RP",
- /* 177 */ "term ::= NULL",
- /* 178 */ "expr ::= ID",
- /* 179 */ "expr ::= JOIN_KW",
- /* 180 */ "expr ::= nm DOT nm",
- /* 181 */ "expr ::= nm DOT nm DOT nm",
- /* 182 */ "term ::= INTEGER|FLOAT|BLOB",
- /* 183 */ "term ::= STRING",
- /* 184 */ "expr ::= REGISTER",
- /* 185 */ "expr ::= VARIABLE",
- /* 186 */ "expr ::= CAST LP expr AS typetoken RP",
- /* 187 */ "expr ::= ID LP distinct exprlist RP",
- /* 188 */ "expr ::= ID LP STAR RP",
- /* 189 */ "term ::= CTIME_KW",
- /* 190 */ "expr ::= expr AND expr",
- /* 191 */ "expr ::= expr OR expr",
- /* 192 */ "expr ::= expr LT|GT|GE|LE expr",
- /* 193 */ "expr ::= expr EQ|NE expr",
- /* 194 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
- /* 195 */ "expr ::= expr PLUS|MINUS expr",
- /* 196 */ "expr ::= expr STAR|SLASH|REM expr",
- /* 197 */ "expr ::= expr CONCAT expr",
- /* 198 */ "likeop ::= LIKE_KW",
- /* 199 */ "likeop ::= NOT LIKE_KW",
- /* 200 */ "escape ::= ESCAPE expr",
- /* 201 */ "escape ::=",
- /* 202 */ "expr ::= expr likeop expr escape",
- /* 203 */ "expr ::= expr ISNULL|NOTNULL",
- /* 204 */ "expr ::= expr IS NULL",
- /* 205 */ "expr ::= expr NOT NULL",
- /* 206 */ "expr ::= expr IS NOT NULL",
- /* 207 */ "expr ::= NOT|BITNOT expr",
- /* 208 */ "expr ::= MINUS expr",
- /* 209 */ "expr ::= PLUS expr",
- /* 210 */ "between_op ::= BETWEEN",
- /* 211 */ "between_op ::= NOT BETWEEN",
- /* 212 */ "expr ::= expr between_op expr AND expr",
- /* 213 */ "in_op ::= IN",
- /* 214 */ "in_op ::= NOT IN",
- /* 215 */ "expr ::= expr in_op LP exprlist RP",
- /* 216 */ "expr ::= LP select RP",
- /* 217 */ "expr ::= expr in_op LP select RP",
- /* 218 */ "expr ::= expr in_op nm dbnm",
- /* 219 */ "expr ::= EXISTS LP select RP",
- /* 220 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 221 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 222 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 223 */ "case_else ::= ELSE expr",
- /* 224 */ "case_else ::=",
- /* 225 */ "case_operand ::= expr",
- /* 226 */ "case_operand ::=",
- /* 227 */ "exprlist ::= exprlist COMMA expritem",
- /* 228 */ "exprlist ::= expritem",
- /* 229 */ "expritem ::= expr",
- /* 230 */ "expritem ::=",
- /* 231 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP onconf",
- /* 232 */ "uniqueflag ::= UNIQUE",
- /* 233 */ "uniqueflag ::=",
- /* 234 */ "idxlist_opt ::=",
- /* 235 */ "idxlist_opt ::= LP idxlist RP",
- /* 236 */ "idxlist ::= idxlist COMMA idxitem collate sortorder",
- /* 237 */ "idxlist ::= idxitem collate sortorder",
- /* 238 */ "idxitem ::= nm",
- /* 239 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 240 */ "cmd ::= VACUUM",
- /* 241 */ "cmd ::= VACUUM nm",
- /* 242 */ "cmd ::= PRAGMA nm dbnm EQ nm",
- /* 243 */ "cmd ::= PRAGMA nm dbnm EQ ON",
- /* 244 */ "cmd ::= PRAGMA nm dbnm EQ plus_num",
- /* 245 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 246 */ "cmd ::= PRAGMA nm dbnm LP nm RP",
- /* 247 */ "cmd ::= PRAGMA nm dbnm",
- /* 248 */ "plus_num ::= plus_opt number",
- /* 249 */ "minus_num ::= MINUS number",
- /* 250 */ "number ::= INTEGER|FLOAT",
- /* 251 */ "plus_opt ::= PLUS",
- /* 252 */ "plus_opt ::=",
- /* 253 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
- /* 254 */ "trigger_decl ::= temp TRIGGER nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 255 */ "trigger_time ::= BEFORE",
- /* 256 */ "trigger_time ::= AFTER",
- /* 257 */ "trigger_time ::= INSTEAD OF",
- /* 258 */ "trigger_time ::=",
- /* 259 */ "trigger_event ::= DELETE|INSERT",
- /* 260 */ "trigger_event ::= UPDATE",
- /* 261 */ "trigger_event ::= UPDATE OF inscollist",
- /* 262 */ "foreach_clause ::=",
- /* 263 */ "foreach_clause ::= FOR EACH ROW",
- /* 264 */ "foreach_clause ::= FOR EACH STATEMENT",
- /* 265 */ "when_clause ::=",
- /* 266 */ "when_clause ::= WHEN expr",
- /* 267 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list",
- /* 268 */ "trigger_cmd_list ::=",
- /* 269 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
- /* 270 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
- /* 271 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
- /* 272 */ "trigger_cmd ::= DELETE FROM nm where_opt",
- /* 273 */ "trigger_cmd ::= select",
- /* 274 */ "expr ::= RAISE LP IGNORE RP",
- /* 275 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 276 */ "raisetype ::= ROLLBACK",
- /* 277 */ "raisetype ::= ABORT",
- /* 278 */ "raisetype ::= FAIL",
- /* 279 */ "cmd ::= DROP TRIGGER fullname",
- /* 280 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 281 */ "key_opt ::=",
- /* 282 */ "key_opt ::= KEY expr",
- /* 283 */ "database_kw_opt ::= DATABASE",
- /* 284 */ "database_kw_opt ::=",
- /* 285 */ "cmd ::= DETACH database_kw_opt expr",
- /* 286 */ "cmd ::= REINDEX",
- /* 287 */ "cmd ::= REINDEX nm dbnm",
- /* 288 */ "cmd ::= ANALYZE",
- /* 289 */ "cmd ::= ANALYZE nm dbnm",
- /* 290 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 291 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
- /* 292 */ "add_column_fullname ::= fullname",
- /* 293 */ "kwcolumn_opt ::=",
- /* 294 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 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
@@ -1205,85 +1303,76 @@
**
** 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 154:
- case 188:
- case 205:
-#line 368 "parse.y"
-{sqlite3SelectDelete((yypminor->yy239));}
-#line 1217 "parse.c"
- break;
- case 168:
- case 169:
- case 193:
- case 195:
- case 203:
- case 209:
- case 217:
- case 220:
- case 222:
- case 223:
- case 233:
-#line 625 "parse.y"
-{sqlite3ExprDelete((yypminor->yy178));}
-#line 1232 "parse.c"
- break;
- case 173:
- case 181:
- case 191:
+ 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 198:
- case 208:
- case 211:
- case 212:
- case 215:
- case 221:
-#line 857 "parse.y"
-{sqlite3ExprListDelete((yypminor->yy462));}
-#line 1247 "parse.c"
+ case 204:
+ case 210:
+ case 224:
+#line 584 "parse.y"
+{sqlite3ExprDelete((yypminor->yy454));}
+#line 1326 "parse.c"
break;
- case 187:
+ case 175:
+ case 183:
case 192:
- case 200:
- case 201:
-#line 496 "parse.y"
-{sqlite3SrcListDelete((yypminor->yy285));}
-#line 1255 "parse.c"
- break;
+ case 195:
case 197:
-#line 557 "parse.y"
-{
- sqlite3ExprDelete((yypminor->yy270).pLimit);
- sqlite3ExprDelete((yypminor->yy270).pOffset);
-}
-#line 1263 "parse.c"
- break;
- case 204:
- case 207:
- case 214:
-#line 513 "parse.y"
-{sqlite3IdListDelete((yypminor->yy160));}
-#line 1270 "parse.c"
- break;
- case 229:
- case 234:
-#line 951 "parse.y"
-{sqlite3DeleteTriggerStep((yypminor->yy247));}
-#line 1276 "parse.c"
- break;
- case 231:
-#line 935 "parse.y"
-{sqlite3IdListDelete((yypminor->yy132).b);}
-#line 1281 "parse.c"
- break;
- case 236:
-#line 1010 "parse.y"
-{sqlite3ExprDelete((yypminor->yy292));}
-#line 1286 "parse.c"
+ 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 */
}
}
@@ -1348,11 +1437,13 @@
int iLookAhead /* The look-ahead token */
){
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
- if( stateno>YY_SHIFT_MAX || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
+ /* 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;
}
@@ -1390,12 +1481,12 @@
int iLookAhead /* The look-ahead token */
){
int i;
/* int stateno = pParser->yystack[pParser->yyidx].stateno; */
- if( stateno>YY_REDUCE_MAX ||
- (i = yy_reduce_ofst[stateno])==YY_REDUCE_USE_DFLT ){
+ i = yy_reduce_ofst[stateno];
+ if( i==YY_REDUCE_USE_DFLT ){
return yy_default[stateno];
}
if( iLookAhead==YYNOCODE ){
return YY_NO_ACTION;
}
@@ -1453,305 +1544,315 @@
*/
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[] = {
- { 138, 1 },
- { 139, 2 },
- { 139, 1 },
- { 141, 1 },
- { 140, 1 },
- { 140, 3 },
- { 143, 0 },
- { 143, 1 },
- { 143, 3 },
- { 142, 3 },
- { 145, 0 },
- { 145, 1 },
- { 145, 2 },
- { 144, 0 },
- { 144, 1 },
- { 144, 1 },
- { 144, 1 },
- { 142, 2 },
- { 142, 2 },
- { 142, 2 },
- { 142, 2 },
- { 147, 6 },
- { 150, 0 },
- { 150, 3 },
- { 149, 1 },
- { 149, 0 },
- { 148, 4 },
- { 148, 2 },
- { 152, 3 },
- { 152, 1 },
+ { 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 },
- { 156, 1 },
+ { 155, 1 },
+ { 158, 3 },
{ 159, 1 },
- { 160, 1 },
- { 146, 1 },
- { 146, 1 },
- { 146, 1 },
- { 157, 0 },
- { 157, 1 },
- { 161, 1 },
- { 161, 4 },
- { 161, 6 },
{ 162, 1 },
- { 162, 2 },
{ 163, 1 },
{ 163, 1 },
- { 158, 2 },
- { 158, 0 },
- { 166, 3 },
- { 166, 1 },
- { 166, 2 },
- { 166, 4 },
- { 166, 3 },
- { 166, 3 },
- { 166, 2 },
- { 167, 2 },
- { 167, 3 },
- { 167, 5 },
- { 167, 2 },
- { 167, 4 },
- { 167, 4 },
- { 167, 1 },
- { 167, 2 },
- { 172, 0 },
- { 172, 1 },
- { 174, 0 },
- { 174, 2 },
+ { 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 },
- { 176, 3 },
- { 176, 3 },
- { 176, 3 },
- { 177, 2 },
- { 177, 2 },
- { 177, 1 },
- { 177, 1 },
- { 175, 3 },
- { 175, 2 },
- { 178, 0 },
- { 178, 2 },
- { 178, 2 },
- { 153, 0 },
- { 153, 2 },
- { 179, 3 },
+ { 178, 2 },
+ { 178, 3 },
+ { 178, 3 },
+ { 178, 3 },
+ { 179, 2 },
{ 179, 2 },
{ 179, 1 },
- { 180, 2 },
- { 180, 7 },
- { 180, 5 },
- { 180, 5 },
- { 180, 10 },
- { 182, 0 },
- { 182, 1 },
- { 170, 0 },
- { 170, 3 },
- { 183, 0 },
- { 183, 2 },
- { 184, 1 },
- { 184, 1 },
- { 184, 1 },
- { 142, 4 },
- { 186, 2 },
- { 186, 0 },
- { 142, 7 },
- { 142, 4 },
- { 142, 1 },
- { 154, 1 },
- { 154, 3 },
- { 189, 1 },
- { 189, 2 },
- { 189, 1 },
- { 188, 9 },
+ { 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 },
- { 190, 0 },
- { 198, 2 },
- { 198, 0 },
- { 191, 3 },
- { 191, 2 },
- { 191, 4 },
+ { 189, 9 },
+ { 191, 1 },
+ { 191, 1 },
+ { 191, 0 },
{ 199, 2 },
- { 199, 1 },
{ 199, 0 },
- { 192, 0 },
+ { 192, 3 },
{ 192, 2 },
- { 201, 2 },
- { 201, 0 },
- { 200, 6 },
- { 200, 7 },
- { 205, 1 },
- { 205, 1 },
- { 151, 0 },
- { 151, 2 },
- { 187, 2 },
- { 202, 1 },
- { 202, 2 },
- { 202, 3 },
- { 202, 4 },
- { 203, 2 },
- { 203, 0 },
- { 204, 4 },
- { 204, 0 },
- { 196, 0 },
- { 196, 3 },
- { 208, 5 },
- { 208, 3 },
- { 209, 1 },
- { 171, 1 },
- { 171, 1 },
- { 171, 0 },
- { 210, 0 },
- { 210, 2 },
- { 194, 0 },
- { 194, 3 },
- { 195, 0 },
- { 195, 2 },
- { 197, 0 },
- { 197, 2 },
- { 197, 4 },
- { 197, 4 },
- { 142, 4 },
+ { 192, 4 },
+ { 200, 2 },
+ { 200, 1 },
+ { 200, 0 },
{ 193, 0 },
{ 193, 2 },
- { 142, 6 },
- { 212, 5 },
- { 212, 3 },
- { 142, 8 },
- { 142, 5 },
- { 213, 2 },
- { 213, 1 },
- { 215, 3 },
- { 215, 1 },
- { 214, 0 },
- { 214, 3 },
- { 207, 3 },
- { 207, 1 },
- { 169, 1 },
- { 169, 3 },
- { 168, 1 },
- { 169, 1 },
- { 169, 1 },
- { 169, 3 },
- { 169, 5 },
- { 168, 1 },
- { 168, 1 },
- { 169, 1 },
- { 169, 1 },
- { 169, 6 },
- { 169, 5 },
- { 169, 4 },
- { 168, 1 },
- { 169, 3 },
- { 169, 3 },
- { 169, 3 },
- { 169, 3 },
- { 169, 3 },
- { 169, 3 },
- { 169, 3 },
- { 169, 3 },
+ { 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 },
- { 216, 2 },
+ { 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, 0 },
- { 169, 4 },
- { 169, 2 },
- { 169, 3 },
- { 169, 3 },
- { 169, 4 },
- { 169, 2 },
- { 169, 2 },
- { 169, 2 },
- { 218, 1 },
+ { 217, 2 },
{ 218, 2 },
- { 169, 5 },
+ { 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 },
- { 169, 5 },
- { 169, 3 },
- { 169, 5 },
- { 169, 4 },
- { 169, 4 },
- { 169, 5 },
- { 221, 5 },
- { 221, 4 },
- { 222, 2 },
- { 222, 0 },
+ { 174, 5 },
{ 220, 1 },
- { 220, 0 },
- { 211, 3 },
- { 211, 1 },
- { 223, 1 },
+ { 220, 2 },
+ { 174, 5 },
+ { 174, 3 },
+ { 174, 5 },
+ { 174, 4 },
+ { 174, 4 },
+ { 174, 5 },
+ { 222, 5 },
+ { 222, 4 },
+ { 223, 2 },
{ 223, 0 },
- { 142, 12 },
+ { 221, 1 },
+ { 221, 0 },
+ { 212, 3 },
+ { 212, 1 },
{ 224, 1 },
{ 224, 0 },
- { 173, 0 },
- { 173, 3 },
- { 181, 5 },
- { 181, 3 },
+ { 146, 11 },
{ 225, 1 },
- { 142, 4 },
- { 142, 1 },
- { 142, 2 },
- { 142, 5 },
- { 142, 5 },
- { 142, 5 },
- { 142, 5 },
- { 142, 6 },
- { 142, 3 },
- { 164, 2 },
- { 165, 2 },
+ { 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 },
- { 226, 1 },
- { 226, 0 },
- { 142, 5 },
- { 228, 10 },
- { 230, 1 },
- { 230, 1 },
- { 230, 2 },
- { 230, 0 },
+ { 227, 0 },
+ { 146, 5 },
+ { 229, 10 },
{ 231, 1 },
{ 231, 1 },
- { 231, 3 },
- { 232, 0 },
- { 232, 3 },
+ { 231, 2 },
+ { 231, 0 },
+ { 232, 1 },
+ { 232, 1 },
+ { 232, 1 },
{ 232, 3 },
{ 233, 0 },
- { 233, 2 },
- { 229, 3 },
- { 229, 0 },
- { 234, 6 },
- { 234, 8 },
- { 234, 5 },
- { 234, 4 },
- { 234, 1 },
- { 169, 4 },
- { 169, 6 },
- { 185, 1 },
- { 185, 1 },
- { 185, 1 },
- { 142, 3 },
- { 142, 6 },
+ { 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 },
- { 236, 2 },
- { 235, 1 },
- { 235, 0 },
- { 142, 3 },
- { 142, 1 },
- { 142, 3 },
- { 142, 1 },
- { 142, 3 },
- { 142, 6 },
- { 142, 6 },
- { 237, 1 },
- { 238, 0 },
- { 238, 1 },
+ { 146, 3 },
+ { 146, 1 },
+ { 146, 3 },
+ { 146, 6 },
};
static void yy_accept(yyParser*); /* Forward Declaration */
/*
@@ -1797,1279 +1898,1202 @@
** { ... } // User supplied code
** #line
** break;
*/
case 3:
-#line 95 "parse.y"
+#line 84 "parse.y"
{ sqlite3FinishCoding(pParse); }
-#line 1806 "parse.c"
+#line 1907 "parse.c"
break;
case 6:
-#line 98 "parse.y"
+#line 87 "parse.y"
{ sqlite3BeginParse(pParse, 0); }
-#line 1811 "parse.c"
+#line 1912 "parse.c"
break;
case 7:
-#line 100 "parse.y"
+#line 89 "parse.y"
{ sqlite3BeginParse(pParse, 1); }
-#line 1816 "parse.c"
+#line 1917 "parse.c"
break;
case 8:
-#line 101 "parse.y"
-{ sqlite3BeginParse(pParse, 2); }
-#line 1821 "parse.c"
+#line 95 "parse.y"
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy60);}
+#line 1922 "parse.c"
break;
- case 9:
-#line 107 "parse.y"
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy230);}
-#line 1826 "parse.c"
+ case 12:
+#line 100 "parse.y"
+{yygotominor.yy60 = TK_DEFERRED;}
+#line 1927 "parse.c"
break;
case 13:
-#line 112 "parse.y"
-{yygotominor.yy230 = TK_DEFERRED;}
-#line 1831 "parse.c"
- break;
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 107:
- case 109:
-#line 113 "parse.y"
-{yygotominor.yy230 = yymsp[0].major;}
-#line 1840 "parse.c"
- break;
case 17:
- case 18:
-#line 116 "parse.y"
+#line 104 "parse.y"
{sqlite3CommitTransaction(pParse);}
-#line 1846 "parse.c"
+#line 1943 "parse.c"
break;
- case 19:
-#line 118 "parse.y"
+ case 18:
+#line 106 "parse.y"
{sqlite3RollbackTransaction(pParse);}
-#line 1851 "parse.c"
+#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:
-#line 123 "parse.y"
-{
- sqlite3StartTable(pParse,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy384,&yymsp[0].minor.yy384,yymsp[-4].minor.yy230,0,yymsp[-2].minor.yy230);
-}
-#line 1858 "parse.c"
+ 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 25:
- case 63:
- case 77:
- case 79:
- case 90:
- case 101:
- case 112:
- case 113:
- case 210:
- case 213:
-#line 127 "parse.y"
-{yygotominor.yy230 = 0;}
-#line 1873 "parse.c"
+ 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:
- case 64:
- case 78:
- case 100:
- case 111:
- case 211:
- case 214:
-#line 128 "parse.y"
-{yygotominor.yy230 = 1;}
-#line 1885 "parse.c"
- break;
- case 26:
-#line 134 "parse.y"
-{
- sqlite3EndTable(pParse,&yymsp[-1].minor.yy384,&yymsp[0].minor.yy0,0);
-}
-#line 1892 "parse.c"
- break;
- case 27:
-#line 137 "parse.y"
-{
- sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy239);
- sqlite3SelectDelete(yymsp[0].minor.yy239);
-}
-#line 1900 "parse.c"
- break;
+#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:
-#line 149 "parse.y"
-{
- yygotominor.yy384.z = yymsp[-2].minor.yy384.z;
- yygotominor.yy384.n = (pParse->sLastToken.z-yymsp[-2].minor.yy384.z) + pParse->sLastToken.n;
-}
-#line 1908 "parse.c"
- break;
case 31:
-#line 153 "parse.y"
-{
- sqlite3AddColumn(pParse,&yymsp[0].minor.yy384);
- yygotominor.yy384 = yymsp[0].minor.yy384;
-}
-#line 1916 "parse.c"
- break;
case 32:
case 33:
case 34:
- case 35:
- case 36:
- case 250:
-#line 163 "parse.y"
-{yygotominor.yy384 = yymsp[0].minor.yy0;}
-#line 1926 "parse.c"
- break;
- case 38:
-#line 222 "parse.y"
-{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy384);}
-#line 1931 "parse.c"
- break;
- case 39:
- case 42:
- case 119:
- case 120:
- case 131:
- case 150:
- case 238:
- case 248:
- case 249:
-#line 223 "parse.y"
-{yygotominor.yy384 = yymsp[0].minor.yy384;}
-#line 1944 "parse.c"
- break;
- case 40:
-#line 224 "parse.y"
-{
- yygotominor.yy384.z = yymsp[-3].minor.yy384.z;
- yygotominor.yy384.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy384.z;
-}
-#line 1952 "parse.c"
- break;
- case 41:
-#line 228 "parse.y"
-{
- yygotominor.yy384.z = yymsp[-5].minor.yy384.z;
- yygotominor.yy384.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy384.z;
-}
-#line 1960 "parse.c"
- break;
- case 43:
-#line 234 "parse.y"
-{yygotominor.yy384.z=yymsp[-1].minor.yy384.z; yygotominor.yy384.n=yymsp[0].minor.yy384.n+(yymsp[0].minor.yy384.z-yymsp[-1].minor.yy384.z);}
-#line 1965 "parse.c"
- break;
- case 44:
-#line 236 "parse.y"
-{ yygotominor.yy230 = atoi((char*)yymsp[0].minor.yy384.z); }
-#line 1970 "parse.c"
- break;
- case 45:
-#line 237 "parse.y"
-{ yygotominor.yy230 = -atoi((char*)yymsp[0].minor.yy384.z); }
-#line 1975 "parse.c"
- break;
- case 50:
- case 52:
-#line 246 "parse.y"
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy178);}
-#line 1981 "parse.c"
- break;
- case 51:
-#line 247 "parse.y"
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy178);}
-#line 1986 "parse.c"
- break;
- case 53:
-#line 249 "parse.y"
-{
- Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy178, 0, 0);
- sqlite3AddDefaultValue(pParse,p);
-}
-#line 1994 "parse.c"
- break;
- case 54:
-#line 253 "parse.y"
-{
- Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy384);
- sqlite3AddDefaultValue(pParse,p);
-}
-#line 2002 "parse.c"
- break;
- case 56:
-#line 262 "parse.y"
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy230);}
-#line 2007 "parse.c"
- break;
- case 57:
-#line 264 "parse.y"
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy230,yymsp[0].minor.yy230,yymsp[-2].minor.yy230);}
-#line 2012 "parse.c"
- break;
- case 58:
-#line 265 "parse.y"
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy230,0,0,0,0);}
-#line 2017 "parse.c"
- break;
- case 59:
-#line 266 "parse.y"
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy178);}
-#line 2022 "parse.c"
- break;
- case 60:
-#line 268 "parse.y"
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy384,yymsp[-1].minor.yy462,yymsp[0].minor.yy230);}
-#line 2027 "parse.c"
- break;
- case 61:
-#line 269 "parse.y"
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy230);}
-#line 2032 "parse.c"
- break;
- case 62:
-#line 270 "parse.y"
-{sqlite3AddCollateType(pParse, (char*)yymsp[0].minor.yy384.z, yymsp[0].minor.yy384.n);}
-#line 2037 "parse.c"
- break;
- case 65:
-#line 283 "parse.y"
-{ yygotominor.yy230 = OE_Restrict * 0x010101; }
-#line 2042 "parse.c"
- break;
- case 66:
-#line 284 "parse.y"
-{ yygotominor.yy230 = (yymsp[-1].minor.yy230 & yymsp[0].minor.yy13.mask) | yymsp[0].minor.yy13.value; }
-#line 2047 "parse.c"
- break;
- case 67:
-#line 286 "parse.y"
-{ yygotominor.yy13.value = 0; yygotominor.yy13.mask = 0x000000; }
-#line 2052 "parse.c"
- break;
- case 68:
-#line 287 "parse.y"
-{ yygotominor.yy13.value = yymsp[0].minor.yy230; yygotominor.yy13.mask = 0x0000ff; }
-#line 2057 "parse.c"
- break;
- case 69:
-#line 288 "parse.y"
-{ yygotominor.yy13.value = yymsp[0].minor.yy230<<8; yygotominor.yy13.mask = 0x00ff00; }
-#line 2062 "parse.c"
- break;
- case 70:
-#line 289 "parse.y"
-{ yygotominor.yy13.value = yymsp[0].minor.yy230<<16; yygotominor.yy13.mask = 0xff0000; }
-#line 2067 "parse.c"
+ 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:
-#line 291 "parse.y"
-{ yygotominor.yy230 = OE_SetNull; }
-#line 2072 "parse.c"
- break;
case 72:
-#line 292 "parse.y"
-{ yygotominor.yy230 = OE_SetDflt; }
-#line 2077 "parse.c"
- break;
- case 73:
-#line 293 "parse.y"
-{ yygotominor.yy230 = OE_Cascade; }
-#line 2082 "parse.c"
- break;
- case 74:
-#line 294 "parse.y"
-{ yygotominor.yy230 = OE_Restrict; }
-#line 2087 "parse.c"
- break;
- case 75:
- case 76:
+ case 87:
+ case 89:
case 91:
- case 93:
- case 95:
- case 96:
- case 167:
-#line 296 "parse.y"
-{yygotominor.yy230 = yymsp[0].minor.yy230;}
-#line 2098 "parse.c"
- break;
- case 80:
-#line 306 "parse.y"
-{yygotominor.yy384.n = 0; yygotominor.yy384.z = 0;}
-#line 2103 "parse.c"
- break;
- case 81:
-#line 307 "parse.y"
-{yygotominor.yy384 = yymsp[-1].minor.yy0;}
-#line 2108 "parse.c"
- break;
- case 86:
-#line 313 "parse.y"
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy462,yymsp[0].minor.yy230,yymsp[-2].minor.yy230,0);}
-#line 2113 "parse.c"
- break;
- case 87:
-#line 315 "parse.y"
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy462,yymsp[0].minor.yy230,0,0,0,0);}
-#line 2118 "parse.c"
+ 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:
-#line 316 "parse.y"
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy178);}
-#line 2123 "parse.c"
- break;
- case 89:
-#line 318 "parse.y"
-{
- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy462, &yymsp[-3].minor.yy384, yymsp[-2].minor.yy462, yymsp[-1].minor.yy230);
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy230);
-}
-#line 2131 "parse.c"
- break;
- case 92:
+ 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:
-#line 332 "parse.y"
-{yygotominor.yy230 = OE_Default;}
-#line 2137 "parse.c"
+ 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 337 "parse.y"
-{yygotominor.yy230 = OE_Ignore;}
-#line 2142 "parse.c"
+#line 312 "parse.y"
+{
+ sqlite3DropTable(pParse, yymsp[0].minor.yy427, 1);
+}
+#line 2221 "parse.c"
break;
case 98:
- case 168:
-#line 338 "parse.y"
-{yygotominor.yy230 = OE_Replace;}
-#line 2148 "parse.c"
+#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:
-#line 342 "parse.y"
+ case 123:
+#line 329 "parse.y"
+{yygotominor.yy331 = yymsp[0].minor.yy331;}
+#line 2235 "parse.c"
+ break;
+ case 100:
+#line 331 "parse.y"
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy285, 0, yymsp[-1].minor.yy230);
+ 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 2155 "parse.c"
+#line 2246 "parse.c"
break;
case 102:
-#line 352 "parse.y"
-{
- sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy384, &yymsp[-2].minor.yy384, yymsp[0].minor.yy239, yymsp[-5].minor.yy230);
-}
-#line 2162 "parse.c"
- break;
- case 103:
-#line 355 "parse.y"
-{
- sqlite3DropTable(pParse, yymsp[0].minor.yy285, 1, yymsp[-1].minor.yy230);
-}
-#line 2169 "parse.c"
- break;
- case 104:
-#line 362 "parse.y"
-{
- sqlite3Select(pParse, yymsp[0].minor.yy239, SRT_Callback, 0, 0, 0, 0, 0);
- sqlite3SelectDelete(yymsp[0].minor.yy239);
-}
-#line 2177 "parse.c"
+#line 340 "parse.y"
+{yygotominor.yy60 = TK_ALL;}
+#line 2251 "parse.c"
break;
case 105:
- case 128:
-#line 372 "parse.y"
-{yygotominor.yy239 = yymsp[0].minor.yy239;}
-#line 2183 "parse.c"
+#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 106:
+ 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"
{
- if( yymsp[0].minor.yy239 ){
- yymsp[0].minor.yy239->op = yymsp[-1].minor.yy230;
- yymsp[0].minor.yy239->pPrior = yymsp[-2].minor.yy239;
- }
- yygotominor.yy239 = yymsp[0].minor.yy239;
-}
-#line 2194 "parse.c"
- break;
- case 108:
-#line 383 "parse.y"
-{yygotominor.yy230 = TK_ALL;}
-#line 2199 "parse.c"
- break;
- case 110:
-#line 387 "parse.y"
-{
- yygotominor.yy239 = sqlite3SelectNew(yymsp[-6].minor.yy462,yymsp[-5].minor.yy285,yymsp[-4].minor.yy178,yymsp[-3].minor.yy462,yymsp[-2].minor.yy178,yymsp[-1].minor.yy462,yymsp[-7].minor.yy230,yymsp[0].minor.yy270.pLimit,yymsp[0].minor.yy270.pOffset);
-}
-#line 2206 "parse.c"
- break;
- case 114:
- case 235:
-#line 408 "parse.y"
-{yygotominor.yy462 = yymsp[-1].minor.yy462;}
-#line 2212 "parse.c"
- break;
- case 115:
- case 141:
- case 151:
- case 234:
-#line 409 "parse.y"
-{yygotominor.yy462 = 0;}
-#line 2220 "parse.c"
+ 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 410 "parse.y"
-{
- yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-2].minor.yy462,yymsp[-1].minor.yy178,yymsp[0].minor.yy384.n?&yymsp[0].minor.yy384:0);
-}
-#line 2227 "parse.c"
+#line 386 "parse.y"
+{yygotominor.yy406.n = 0;}
+#line 2300 "parse.c"
break;
case 117:
-#line 413 "parse.y"
-{
- yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-1].minor.yy462, sqlite3Expr(TK_ALL, 0, 0, 0), 0);
-}
-#line 2234 "parse.c"
+#line 398 "parse.y"
+{yygotominor.yy427 = sqliteMalloc(sizeof(*yygotominor.yy427));}
+#line 2305 "parse.c"
break;
case 118:
-#line 416 "parse.y"
+#line 399 "parse.y"
+{yygotominor.yy427 = yymsp[0].minor.yy427;}
+#line 2310 "parse.c"
+ break;
+ case 119:
+#line 404 "parse.y"
{
- Expr *pRight = sqlite3Expr(TK_ALL, 0, 0, 0);
- Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy384);
- yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-3].minor.yy462, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0);
+ 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 2243 "parse.c"
+#line 2318 "parse.c"
+ break;
+ case 120:
+#line 408 "parse.y"
+{yygotominor.yy427 = 0;}
+#line 2323 "parse.c"
break;
case 121:
-#line 428 "parse.y"
-{yygotominor.yy384.n = 0;}
-#line 2248 "parse.c"
+#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 440 "parse.y"
-{yygotominor.yy285 = sqliteMalloc(sizeof(*yygotominor.yy285));}
-#line 2253 "parse.c"
- break;
- case 123:
-#line 441 "parse.y"
-{yygotominor.yy285 = yymsp[0].minor.yy285;}
-#line 2258 "parse.c"
+#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 446 "parse.y"
+#line 444 "parse.y"
{
- yygotominor.yy285 = yymsp[-1].minor.yy285;
- if( yygotominor.yy285 && yygotominor.yy285->nSrc>0 ) yygotominor.yy285->a[yygotominor.yy285->nSrc-1].jointype = yymsp[0].minor.yy230;
-}
-#line 2266 "parse.c"
+ 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.yy285 = 0;}
-#line 2271 "parse.c"
- break;
- case 126:
-#line 451 "parse.y"
-{
- yygotominor.yy285 = sqlite3SrcListAppend(yymsp[-5].minor.yy285,&yymsp[-4].minor.yy384,&yymsp[-3].minor.yy384);
- if( yymsp[-2].minor.yy384.n ) sqlite3SrcListAddAlias(yygotominor.yy285,&yymsp[-2].minor.yy384);
- if( yymsp[-1].minor.yy178 ){
- if( yygotominor.yy285 && yygotominor.yy285->nSrc>1 ){ yygotominor.yy285->a[yygotominor.yy285->nSrc-2].pOn = yymsp[-1].minor.yy178; }
- else { sqlite3ExprDelete(yymsp[-1].minor.yy178); }
- }
- if( yymsp[0].minor.yy160 ){
- if( yygotominor.yy285 && yygotominor.yy285->nSrc>1 ){ yygotominor.yy285->a[yygotominor.yy285->nSrc-2].pUsing = yymsp[0].minor.yy160; }
- else { sqlite3IdListDelete(yymsp[0].minor.yy160); }
- }
-}
-#line 2287 "parse.c"
+{yygotominor.yy406.z=0; yygotominor.yy406.n=0;}
+#line 2368 "parse.c"
break;
case 127:
-#line 465 "parse.y"
-{
- yygotominor.yy285 = sqlite3SrcListAppend(yymsp[-6].minor.yy285,0,0);
- yygotominor.yy285->a[yygotominor.yy285->nSrc-1].pSelect = yymsp[-4].minor.yy239;
- if( yymsp[-2].minor.yy384.n ) sqlite3SrcListAddAlias(yygotominor.yy285,&yymsp[-2].minor.yy384);
- if( yymsp[-1].minor.yy178 ){
- if( yygotominor.yy285 && yygotominor.yy285->nSrc>1 ){ yygotominor.yy285->a[yygotominor.yy285->nSrc-2].pOn = yymsp[-1].minor.yy178; }
- else { sqlite3ExprDelete(yymsp[-1].minor.yy178); }
- }
- if( yymsp[0].minor.yy160 ){
- if( yygotominor.yy285 && yygotominor.yy285->nSrc>1 ){ yygotominor.yy285->a[yygotominor.yy285->nSrc-2].pUsing = yymsp[0].minor.yy160; }
- else { sqlite3IdListDelete(yymsp[0].minor.yy160); }
- }
- }
-#line 2304 "parse.c"
+#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 486 "parse.y"
-{
- yygotominor.yy239 = sqlite3SelectNew(0,yymsp[0].minor.yy285,0,0,0,0,0,0,0);
- }
-#line 2311 "parse.c"
+#line 459 "parse.y"
+{ yygotominor.yy60 = JT_INNER; }
+#line 2379 "parse.c"
break;
case 130:
-#line 492 "parse.y"
-{yygotominor.yy384.z=0; yygotominor.yy384.n=0;}
-#line 2316 "parse.c"
+#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 497 "parse.y"
-{yygotominor.yy285 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy384,&yymsp[0].minor.yy384);}
-#line 2321 "parse.c"
+#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:
-#line 501 "parse.y"
-{ yygotominor.yy230 = JT_INNER; }
-#line 2326 "parse.c"
+ 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:
-#line 502 "parse.y"
-{ yygotominor.yy230 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
-#line 2331 "parse.c"
+ 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:
-#line 503 "parse.y"
-{ yygotominor.yy230 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy384,0); }
-#line 2336 "parse.c"
+ case 168:
+#line 473 "parse.y"
+{yygotominor.yy272 = yymsp[-1].minor.yy272;}
+#line 2424 "parse.c"
break;
case 136:
-#line 505 "parse.y"
-{ yygotominor.yy230 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy384,&yymsp[-1].minor.yy384); }
-#line 2341 "parse.c"
- break;
- case 137:
- case 145:
- case 154:
- case 161:
- case 175:
- case 200:
- case 223:
- case 225:
- case 229:
-#line 509 "parse.y"
-{yygotominor.yy178 = yymsp[0].minor.yy178;}
-#line 2354 "parse.c"
+ case 167:
+#line 474 "parse.y"
+{yygotominor.yy272 = 0;}
+#line 2430 "parse.c"
break;
case 138:
- case 153:
- case 160:
- case 201:
- case 224:
- case 226:
- case 230:
-#line 510 "parse.y"
-{yygotominor.yy178 = 0;}
-#line 2365 "parse.c"
+ case 148:
+#line 485 "parse.y"
+{yygotominor.yy266 = yymsp[0].minor.yy266;}
+#line 2436 "parse.c"
break;
case 139:
- case 172:
-#line 514 "parse.y"
-{yygotominor.yy160 = yymsp[-1].minor.yy160;}
-#line 2371 "parse.c"
+#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:
- case 171:
-#line 515 "parse.y"
-{yygotominor.yy160 = 0;}
-#line 2377 "parse.c"
+#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 152:
-#line 526 "parse.y"
-{yygotominor.yy462 = yymsp[0].minor.yy462;}
-#line 2383 "parse.c"
+ case 144:
+#line 499 "parse.y"
+{yygotominor.yy60 = SQLITE_SO_ASC;}
+#line 2458 "parse.c"
break;
case 143:
-#line 527 "parse.y"
-{
- yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-4].minor.yy462,yymsp[-2].minor.yy178,yymsp[-1].minor.yy384.n>0?&yymsp[-1].minor.yy384:0);
- if( yygotominor.yy462 ) yygotominor.yy462->a[yygotominor.yy462->nExpr-1].sortOrder = yymsp[0].minor.yy230;
-}
-#line 2391 "parse.c"
- break;
- case 144:
-#line 531 "parse.y"
-{
- yygotominor.yy462 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy178,yymsp[-1].minor.yy384.n>0?&yymsp[-1].minor.yy384:0);
- if( yygotominor.yy462 && yygotominor.yy462->a ) yygotominor.yy462->a[0].sortOrder = yymsp[0].minor.yy230;
-}
-#line 2399 "parse.c"
- break;
- case 146:
- case 148:
-#line 540 "parse.y"
-{yygotominor.yy230 = SQLITE_SO_ASC;}
-#line 2405 "parse.c"
- break;
- case 147:
-#line 541 "parse.y"
-{yygotominor.yy230 = SQLITE_SO_DESC;}
-#line 2410 "parse.c"
- break;
- case 149:
-#line 543 "parse.y"
-{yygotominor.yy384.z = 0; yygotominor.yy384.n = 0;}
-#line 2415 "parse.c"
+#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 561 "parse.y"
-{yygotominor.yy270.pLimit = 0; yygotominor.yy270.pOffset = 0;}
-#line 2420 "parse.c"
- break;
- case 156:
-#line 562 "parse.y"
-{yygotominor.yy270.pLimit = yymsp[0].minor.yy178; yygotominor.yy270.pOffset = 0;}
-#line 2425 "parse.c"
- break;
- case 157:
-#line 564 "parse.y"
-{yygotominor.yy270.pLimit = yymsp[-2].minor.yy178; yygotominor.yy270.pOffset = yymsp[0].minor.yy178;}
-#line 2430 "parse.c"
+#line 529 "parse.y"
+{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy427,yymsp[0].minor.yy454);}
+#line 2493 "parse.c"
break;
case 158:
-#line 566 "parse.y"
-{yygotominor.yy270.pOffset = yymsp[-2].minor.yy178; yygotominor.yy270.pLimit = yymsp[0].minor.yy178;}
-#line 2435 "parse.c"
+#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 570 "parse.y"
-{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy285,yymsp[0].minor.yy178);}
-#line 2440 "parse.c"
+#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 581 "parse.y"
-{sqlite3Update(pParse,yymsp[-3].minor.yy285,yymsp[-1].minor.yy462,yymsp[0].minor.yy178,yymsp[-4].minor.yy230);}
-#line 2445 "parse.c"
- break;
- case 163:
-#line 587 "parse.y"
-{yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-4].minor.yy462,yymsp[0].minor.yy178,&yymsp[-2].minor.yy384);}
-#line 2450 "parse.c"
- break;
- case 164:
-#line 588 "parse.y"
-{yygotominor.yy462 = sqlite3ExprListAppend(0,yymsp[0].minor.yy178,&yymsp[-2].minor.yy384);}
-#line 2455 "parse.c"
+#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:
-#line 594 "parse.y"
-{sqlite3Insert(pParse, yymsp[-5].minor.yy285, yymsp[-1].minor.yy462, 0, yymsp[-4].minor.yy160, yymsp[-7].minor.yy230);}
-#line 2460 "parse.c"
+ 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:
-#line 596 "parse.y"
-{sqlite3Insert(pParse, yymsp[-2].minor.yy285, 0, yymsp[0].minor.yy239, yymsp[-1].minor.yy160, yymsp[-4].minor.yy230);}
-#line 2465 "parse.c"
+ case 241:
+#line 566 "parse.y"
+{yygotominor.yy266 = sqlite3ExprListAppend(0,yymsp[0].minor.yy454,0);}
+#line 2530 "parse.c"
break;
case 169:
- case 227:
-#line 606 "parse.y"
-{yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-2].minor.yy462,yymsp[0].minor.yy178,0);}
-#line 2471 "parse.c"
+#line 575 "parse.y"
+{yygotominor.yy272 = sqlite3IdListAppend(yymsp[-2].minor.yy272,&yymsp[0].minor.yy406);}
+#line 2535 "parse.c"
break;
case 170:
- case 228:
-#line 607 "parse.y"
-{yygotominor.yy462 = sqlite3ExprListAppend(0,yymsp[0].minor.yy178,0);}
-#line 2477 "parse.c"
+#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:
-#line 616 "parse.y"
-{yygotominor.yy160 = sqlite3IdListAppend(yymsp[-2].minor.yy160,&yymsp[0].minor.yy384);}
-#line 2482 "parse.c"
+ 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:
-#line 617 "parse.y"
-{yygotominor.yy160 = sqlite3IdListAppend(0,&yymsp[0].minor.yy384);}
-#line 2487 "parse.c"
+ 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 628 "parse.y"
-{yygotominor.yy178 = yymsp[-1].minor.yy178; sqlite3ExprSpan(yygotominor.yy178,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
-#line 2492 "parse.c"
+#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 629 "parse.y"
-{yygotominor.yy178 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
-#line 2499 "parse.c"
- break;
- case 178:
- case 179:
-#line 630 "parse.y"
-{yygotominor.yy178 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
-#line 2505 "parse.c"
- break;
- case 180:
-#line 632 "parse.y"
-{
- Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy384);
- Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy384);
- yygotominor.yy178 = sqlite3Expr(TK_DOT, temp1, temp2, 0);
-}
-#line 2514 "parse.c"
- break;
- case 181:
-#line 637 "parse.y"
-{
- Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy384);
- Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy384);
- Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy384);
- Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0);
- yygotominor.yy178 = sqlite3Expr(TK_DOT, temp1, temp4, 0);
-}
-#line 2525 "parse.c"
+#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 646 "parse.y"
-{yygotominor.yy178 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
-#line 2530 "parse.c"
+#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 647 "parse.y"
+#line 617 "parse.y"
{
- Token *pToken = &yymsp[0].minor.yy0;
- Expr *pExpr = yygotominor.yy178 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
- sqlite3ExprAssignVarNumber(pParse, pExpr);
+ yygotominor.yy454 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
-#line 2539 "parse.c"
+#line 2610 "parse.c"
break;
case 186:
-#line 653 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_CAST, yymsp[-3].minor.yy178, 0, &yymsp[-1].minor.yy384);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
-}
-#line 2547 "parse.c"
- break;
case 187:
-#line 658 "parse.y"
-{
- yygotominor.yy178 = sqlite3ExprFunction(yymsp[-1].minor.yy462, &yymsp[-4].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
- if( yymsp[-2].minor.yy230 ){
- yygotominor.yy178->flags |= EP_Distinct;
- }
-}
-#line 2558 "parse.c"
- break;
case 188:
-#line 665 "parse.y"
-{
- yygotominor.yy178 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
-}
-#line 2566 "parse.c"
+#line 621 "parse.y"
+{yygotominor.yy454 = sqlite3Expr(yymsp[0].major,0,0,0);}
+#line 2617 "parse.c"
break;
case 189:
-#line 669 "parse.y"
-{
- /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
- ** treated as functions that return constants */
- yygotominor.yy178 = sqlite3ExprFunction(0,&yymsp[0].minor.yy0);
- if( yygotominor.yy178 ) yygotominor.yy178->op = TK_CONST_FUNC;
-}
-#line 2576 "parse.c"
- break;
case 190:
case 191:
case 192:
case 193:
case 194:
case 195:
case 196:
case 197:
-#line 675 "parse.y"
-{yygotominor.yy178 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy178, yymsp[0].minor.yy178, 0);}
-#line 2588 "parse.c"
- break;
- case 198:
-#line 685 "parse.y"
-{yygotominor.yy440.operator = yymsp[0].minor.yy0; yygotominor.yy440.not = 0;}
-#line 2593 "parse.c"
- break;
- case 199:
-#line 686 "parse.y"
-{yygotominor.yy440.operator = yymsp[0].minor.yy0; yygotominor.yy440.not = 1;}
-#line 2598 "parse.c"
- break;
- case 202:
-#line 691 "parse.y"
-{
- ExprList *pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy178, 0);
- pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy178, 0);
- if( yymsp[0].minor.yy178 ){
- pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy178, 0);
- }
- yygotominor.yy178 = sqlite3ExprFunction(pList, &yymsp[-2].minor.yy440.operator);
- if( yymsp[-2].minor.yy440.not ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178, &yymsp[-3].minor.yy178->span, &yymsp[-1].minor.yy178->span);
-}
-#line 2612 "parse.c"
- break;
- case 203:
-#line 702 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(yymsp[0].major, yymsp[-1].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-1].minor.yy178->span,&yymsp[0].minor.yy0);
-}
-#line 2620 "parse.c"
- break;
- case 204:
-#line 706 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-2].minor.yy178->span,&yymsp[0].minor.yy0);
-}
-#line 2628 "parse.c"
- break;
- case 205:
-#line 710 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-2].minor.yy178->span,&yymsp[0].minor.yy0);
-}
-#line 2636 "parse.c"
- break;
- case 206:
-#line 714 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-3].minor.yy178->span,&yymsp[0].minor.yy0);
-}
-#line 2644 "parse.c"
- break;
- case 207:
-#line 718 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy178->span);
-}
-#line 2652 "parse.c"
- break;
- case 208:
-#line 722 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy178->span);
-}
-#line 2660 "parse.c"
- break;
- case 209:
-#line 726 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy178->span);
-}
-#line 2668 "parse.c"
- break;
- case 212:
-#line 733 "parse.y"
-{
- ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy178, 0);
- pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy178, 0);
- yygotominor.yy178 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy178, 0, 0);
- if( yygotominor.yy178 ){
- yygotominor.yy178->pList = pList;
- }else{
- sqlite3ExprListDelete(pList);
- }
- if( yymsp[-3].minor.yy230 ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-4].minor.yy178->span,&yymsp[0].minor.yy178->span);
-}
-#line 2684 "parse.c"
- break;
- case 215:
-#line 749 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy178, 0, 0);
- if( yygotominor.yy178 ){
- yygotominor.yy178->pList = yymsp[-1].minor.yy462;
- }else{
- sqlite3ExprListDelete(yymsp[-1].minor.yy462);
- }
- if( yymsp[-3].minor.yy230 ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-4].minor.yy178->span,&yymsp[0].minor.yy0);
- }
-#line 2698 "parse.c"
- break;
- case 216:
-#line 759 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_SELECT, 0, 0, 0);
- if( yygotominor.yy178 ){
- yygotominor.yy178->pSelect = yymsp[-1].minor.yy239;
- }else{
- sqlite3SelectDelete(yymsp[-1].minor.yy239);
- }
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
- }
-#line 2711 "parse.c"
- break;
- case 217:
-#line 768 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy178, 0, 0);
- if( yygotominor.yy178 ){
- yygotominor.yy178->pSelect = yymsp[-1].minor.yy239;
- }else{
- sqlite3SelectDelete(yymsp[-1].minor.yy239);
- }
- if( yymsp[-3].minor.yy230 ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-4].minor.yy178->span,&yymsp[0].minor.yy0);
- }
-#line 2725 "parse.c"
- break;
- case 218:
-#line 778 "parse.y"
-{
- SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy384,&yymsp[0].minor.yy384);
- yygotominor.yy178 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy178, 0, 0);
- if( yygotominor.yy178 ){
- yygotominor.yy178->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0);
- }else{
- sqlite3SrcListDelete(pSrc);
- }
- if( yymsp[-2].minor.yy230 ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-3].minor.yy178->span,yymsp[0].minor.yy384.z?&yymsp[0].minor.yy384:&yymsp[-1].minor.yy384);
- }
-#line 2740 "parse.c"
- break;
- case 219:
-#line 789 "parse.y"
-{
- Expr *p = yygotominor.yy178 = sqlite3Expr(TK_EXISTS, 0, 0, 0);
- if( p ){
- p->pSelect = yymsp[-1].minor.yy239;
- sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
- }else{
- sqlite3SelectDelete(yymsp[-1].minor.yy239);
- }
- }
-#line 2753 "parse.c"
- break;
- case 220:
-#line 801 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy178, yymsp[-1].minor.yy178, 0);
- if( yygotominor.yy178 ){
- yygotominor.yy178->pList = yymsp[-2].minor.yy462;
- }else{
- sqlite3ExprListDelete(yymsp[-2].minor.yy462);
- }
- sqlite3ExprSpan(yygotominor.yy178, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
-}
-#line 2766 "parse.c"
- break;
- case 221:
-#line 812 "parse.y"
-{
- yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-4].minor.yy462, yymsp[-2].minor.yy178, 0);
- yygotominor.yy462 = sqlite3ExprListAppend(yygotominor.yy462, yymsp[0].minor.yy178, 0);
-}
-#line 2774 "parse.c"
- break;
- case 222:
-#line 816 "parse.y"
-{
- yygotominor.yy462 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy178, 0);
- yygotominor.yy462 = sqlite3ExprListAppend(yygotominor.yy462, yymsp[0].minor.yy178, 0);
-}
-#line 2782 "parse.c"
- break;
- case 231:
-#line 843 "parse.y"
-{
- if( yymsp[-10].minor.yy230!=OE_None ) yymsp[-10].minor.yy230 = yymsp[0].minor.yy230;
- if( yymsp[-10].minor.yy230==OE_Default) yymsp[-10].minor.yy230 = OE_Abort;
- sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy384, &yymsp[-6].minor.yy384, sqlite3SrcListAppend(0,&yymsp[-4].minor.yy384,0), yymsp[-2].minor.yy462, yymsp[-10].minor.yy230,
- &yymsp[-11].minor.yy0, &yymsp[-1].minor.yy0, SQLITE_SO_ASC, yymsp[-8].minor.yy230);
-}
-#line 2792 "parse.c"
- break;
- case 232:
- case 277:
-#line 851 "parse.y"
-{yygotominor.yy230 = OE_Abort;}
-#line 2798 "parse.c"
- break;
- case 233:
-#line 852 "parse.y"
-{yygotominor.yy230 = OE_None;}
-#line 2803 "parse.c"
- break;
- case 236:
-#line 862 "parse.y"
-{
- Expr *p = 0;
- if( yymsp[-1].minor.yy384.n>0 ){
- p = sqlite3Expr(TK_COLUMN, 0, 0, 0);
- if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy384.z, yymsp[-1].minor.yy384.n);
- }
- yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-4].minor.yy462, p, &yymsp[-2].minor.yy384);
- if( yygotominor.yy462 ) yygotominor.yy462->a[yygotominor.yy462->nExpr-1].sortOrder = yymsp[0].minor.yy230;
-}
-#line 2816 "parse.c"
- break;
- case 237:
-#line 871 "parse.y"
-{
- Expr *p = 0;
- if( yymsp[-1].minor.yy384.n>0 ){
- p = sqlite3Expr(TK_COLUMN, 0, 0, 0);
- if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy384.z, yymsp[-1].minor.yy384.n);
- }
- yygotominor.yy462 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy384);
- if( yygotominor.yy462 ) yygotominor.yy462->a[yygotominor.yy462->nExpr-1].sortOrder = yymsp[0].minor.yy230;
-}
-#line 2829 "parse.c"
- break;
- case 239:
-#line 885 "parse.y"
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy285, yymsp[-1].minor.yy230);}
-#line 2834 "parse.c"
- break;
- case 240:
- case 241:
-#line 889 "parse.y"
-{sqlite3Vacuum(pParse,0);}
-#line 2840 "parse.c"
- break;
- case 242:
- case 244:
-#line 895 "parse.y"
-{sqlite3Pragma(pParse,&yymsp[-3].minor.yy384,&yymsp[-2].minor.yy384,&yymsp[0].minor.yy384,0);}
-#line 2846 "parse.c"
- break;
- case 243:
-#line 896 "parse.y"
-{sqlite3Pragma(pParse,&yymsp[-3].minor.yy384,&yymsp[-2].minor.yy384,&yymsp[0].minor.yy0,0);}
-#line 2851 "parse.c"
- break;
- case 245:
-#line 898 "parse.y"
-{
- sqlite3Pragma(pParse,&yymsp[-3].minor.yy384,&yymsp[-2].minor.yy384,&yymsp[0].minor.yy384,1);
-}
-#line 2858 "parse.c"
- break;
- case 246:
-#line 901 "parse.y"
-{sqlite3Pragma(pParse,&yymsp[-4].minor.yy384,&yymsp[-3].minor.yy384,&yymsp[-1].minor.yy384,0);}
-#line 2863 "parse.c"
- break;
- case 247:
-#line 902 "parse.y"
-{sqlite3Pragma(pParse,&yymsp[-1].minor.yy384,&yymsp[0].minor.yy384,0,0);}
-#line 2868 "parse.c"
- break;
- case 253:
-#line 914 "parse.y"
-{
- Token all;
- all.z = yymsp[-3].minor.yy384.z;
- all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy384.z) + yymsp[0].minor.yy0.n;
- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy247, &all);
-}
-#line 2878 "parse.c"
- break;
- case 254:
-#line 923 "parse.y"
-{
- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy384, &yymsp[-6].minor.yy384, yymsp[-5].minor.yy230, yymsp[-4].minor.yy132.a, yymsp[-4].minor.yy132.b, yymsp[-2].minor.yy285, yymsp[-1].minor.yy230, yymsp[0].minor.yy178, yymsp[-9].minor.yy230);
- yygotominor.yy384 = (yymsp[-6].minor.yy384.n==0?yymsp[-7].minor.yy384:yymsp[-6].minor.yy384);
-}
-#line 2886 "parse.c"
- break;
- case 255:
- case 258:
-#line 929 "parse.y"
-{ yygotominor.yy230 = TK_BEFORE; }
-#line 2892 "parse.c"
- break;
- case 256:
-#line 930 "parse.y"
-{ yygotominor.yy230 = TK_AFTER; }
-#line 2897 "parse.c"
- break;
- case 257:
-#line 931 "parse.y"
-{ yygotominor.yy230 = TK_INSTEAD;}
-#line 2902 "parse.c"
- break;
- case 259:
- case 260:
-#line 936 "parse.y"
-{yygotominor.yy132.a = yymsp[0].major; yygotominor.yy132.b = 0;}
-#line 2908 "parse.c"
- break;
- case 261:
-#line 938 "parse.y"
-{yygotominor.yy132.a = TK_UPDATE; yygotominor.yy132.b = yymsp[0].minor.yy160;}
-#line 2913 "parse.c"
- break;
- case 262:
- case 263:
-#line 941 "parse.y"
-{ yygotominor.yy230 = TK_ROW; }
-#line 2919 "parse.c"
- break;
- case 264:
-#line 943 "parse.y"
-{ yygotominor.yy230 = TK_STATEMENT; }
-#line 2924 "parse.c"
- break;
- case 265:
-#line 947 "parse.y"
-{ yygotominor.yy178 = 0; }
-#line 2929 "parse.c"
- break;
- case 266:
-#line 948 "parse.y"
-{ yygotominor.yy178 = yymsp[0].minor.yy178; }
-#line 2934 "parse.c"
- break;
- case 267:
-#line 952 "parse.y"
-{
- yymsp[-2].minor.yy247->pNext = yymsp[0].minor.yy247;
- yygotominor.yy247 = yymsp[-2].minor.yy247;
-}
-#line 2942 "parse.c"
- break;
- case 268:
-#line 956 "parse.y"
-{ yygotominor.yy247 = 0; }
-#line 2947 "parse.c"
- break;
- case 269:
-#line 962 "parse.y"
-{ yygotominor.yy247 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy384, yymsp[-1].minor.yy462, yymsp[0].minor.yy178, yymsp[-4].minor.yy230); }
-#line 2952 "parse.c"
- break;
- case 270:
-#line 967 "parse.y"
-{yygotominor.yy247 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy384, yymsp[-4].minor.yy160, yymsp[-1].minor.yy462, 0, yymsp[-7].minor.yy230);}
-#line 2957 "parse.c"
- break;
- case 271:
-#line 970 "parse.y"
-{yygotominor.yy247 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy384, yymsp[-1].minor.yy160, 0, yymsp[0].minor.yy239, yymsp[-4].minor.yy230);}
-#line 2962 "parse.c"
- break;
- case 272:
-#line 974 "parse.y"
-{yygotominor.yy247 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy384, yymsp[0].minor.yy178);}
-#line 2967 "parse.c"
- break;
- case 273:
-#line 977 "parse.y"
-{yygotominor.yy247 = sqlite3TriggerSelectStep(yymsp[0].minor.yy239); }
-#line 2972 "parse.c"
- break;
- case 274:
-#line 980 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_RAISE, 0, 0, 0);
- yygotominor.yy178->iColumn = OE_Ignore;
- sqlite3ExprSpan(yygotominor.yy178, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
-}
-#line 2981 "parse.c"
- break;
- case 275:
-#line 985 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy384);
- yygotominor.yy178->iColumn = yymsp[-3].minor.yy230;
- sqlite3ExprSpan(yygotominor.yy178, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
-}
-#line 2990 "parse.c"
- break;
- case 276:
-#line 993 "parse.y"
-{yygotominor.yy230 = OE_Rollback;}
-#line 2995 "parse.c"
- break;
- case 278:
-#line 995 "parse.y"
-{yygotominor.yy230 = OE_Fail;}
-#line 3000 "parse.c"
- break;
- case 279:
-#line 1000 "parse.y"
-{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy285);
-}
-#line 3007 "parse.c"
- break;
- case 280:
-#line 1006 "parse.y"
-{
- sqlite3Attach(pParse, yymsp[-3].minor.yy178, yymsp[-1].minor.yy178, yymsp[0].minor.yy292);
-}
-#line 3014 "parse.c"
- break;
- case 281:
-#line 1011 "parse.y"
-{ yygotominor.yy292 = 0; }
-#line 3019 "parse.c"
- break;
- case 282:
-#line 1012 "parse.y"
-{ yygotominor.yy292 = yymsp[0].minor.yy178; }
-#line 3024 "parse.c"
- break;
- case 285:
-#line 1018 "parse.y"
-{
- sqlite3Detach(pParse, yymsp[0].minor.yy178);
-}
-#line 3031 "parse.c"
- break;
- case 286:
-#line 1024 "parse.y"
-{sqlite3Reindex(pParse, 0, 0);}
-#line 3036 "parse.c"
- break;
- case 287:
-#line 1025 "parse.y"
-{sqlite3Reindex(pParse, &yymsp[-1].minor.yy384, &yymsp[0].minor.yy384);}
-#line 3041 "parse.c"
- break;
- case 288:
-#line 1030 "parse.y"
-{sqlite3Analyze(pParse, 0, 0);}
-#line 3046 "parse.c"
- break;
- case 289:
-#line 1031 "parse.y"
-{sqlite3Analyze(pParse, &yymsp[-1].minor.yy384, &yymsp[0].minor.yy384);}
-#line 3051 "parse.c"
- break;
- case 290:
-#line 1036 "parse.y"
-{
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy285,&yymsp[0].minor.yy384);
-}
-#line 3058 "parse.c"
- break;
- case 291:
-#line 1039 "parse.y"
-{
- sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy384);
-}
-#line 3065 "parse.c"
- break;
- case 292:
-#line 1042 "parse.y"
-{
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy285);
-}
-#line 3072 "parse.c"
+ 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;
@@ -3122,20 +3146,20 @@
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 34 "parse.y"
+#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 3139 "parse.c"
+#line 3163 "parse.c"
sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
/*
** The following is executed when the parser accepts
@@ -3187,11 +3211,11 @@
yyParser *yypParser; /* The parser */
/* (re)initialize the parser, if necessary */
yypParser = (yyParser*)yyp;
if( yypParser->yyidx<0 ){
- /* if( yymajor==0 ) return; // not sure why this was here... */
+ if( yymajor==0 ) return;
yypParser->yyidx = 0;
yypParser->yyerrcnt = -1;
yypParser->yystack[0].stateno = 0;
yypParser->yystack[0].major = 0;
}
Index: SQLite.Interop/src/parse.h
==================================================================
--- SQLite.Interop/src/parse.h
+++ SQLite.Interop/src/parse.h
@@ -1,151 +1,140 @@
-#define TK_SEMI 1
-#define TK_EXPLAIN 2
-#define TK_QUERY 3
-#define TK_PLAN 4
-#define TK_BEGIN 5
-#define TK_TRANSACTION 6
-#define TK_DEFERRED 7
-#define TK_IMMEDIATE 8
-#define TK_EXCLUSIVE 9
-#define TK_COMMIT 10
-#define TK_END 11
-#define TK_ROLLBACK 12
-#define TK_CREATE 13
-#define TK_TABLE 14
-#define TK_IF 15
-#define TK_NOT 16
-#define TK_EXISTS 17
-#define TK_TEMP 18
-#define TK_LP 19
-#define TK_RP 20
-#define TK_AS 21
-#define TK_COMMA 22
-#define TK_ID 23
-#define TK_ABORT 24
-#define TK_AFTER 25
-#define TK_ANALYZE 26
-#define TK_ASC 27
-#define TK_ATTACH 28
-#define TK_BEFORE 29
-#define TK_CASCADE 30
-#define TK_CAST 31
-#define TK_CONFLICT 32
-#define TK_DATABASE 33
-#define TK_DESC 34
-#define TK_DETACH 35
-#define TK_EACH 36
-#define TK_FAIL 37
-#define TK_FOR 38
-#define TK_IGNORE 39
-#define TK_INITIALLY 40
-#define TK_INSTEAD 41
-#define TK_LIKE_KW 42
-#define TK_MATCH 43
-#define TK_KEY 44
-#define TK_OF 45
-#define TK_OFFSET 46
-#define TK_PRAGMA 47
-#define TK_RAISE 48
-#define TK_REPLACE 49
-#define TK_RESTRICT 50
-#define TK_ROW 51
-#define TK_STATEMENT 52
-#define TK_TRIGGER 53
-#define TK_VACUUM 54
-#define TK_VIEW 55
-#define TK_REINDEX 56
-#define TK_RENAME 57
-#define TK_CTIME_KW 58
-#define TK_OR 59
-#define TK_AND 60
-#define TK_IS 61
-#define TK_BETWEEN 62
-#define TK_IN 63
-#define TK_ISNULL 64
-#define TK_NOTNULL 65
-#define TK_NE 66
-#define TK_EQ 67
-#define TK_GT 68
-#define TK_LE 69
-#define TK_LT 70
-#define TK_GE 71
-#define TK_ESCAPE 72
-#define TK_BITAND 73
-#define TK_BITOR 74
-#define TK_LSHIFT 75
-#define TK_RSHIFT 76
-#define TK_PLUS 77
-#define TK_MINUS 78
-#define TK_STAR 79
-#define TK_SLASH 80
-#define TK_REM 81
-#define TK_CONCAT 82
-#define TK_UMINUS 83
-#define TK_UPLUS 84
-#define TK_BITNOT 85
-#define TK_STRING 86
-#define TK_JOIN_KW 87
-#define TK_CONSTRAINT 88
-#define TK_DEFAULT 89
-#define TK_NULL 90
-#define TK_PRIMARY 91
-#define TK_UNIQUE 92
-#define TK_CHECK 93
-#define TK_REFERENCES 94
-#define TK_COLLATE 95
-#define TK_AUTOINCR 96
-#define TK_ON 97
-#define TK_DELETE 98
-#define TK_UPDATE 99
-#define TK_INSERT 100
-#define TK_SET 101
-#define TK_DEFERRABLE 102
-#define TK_FOREIGN 103
-#define TK_DROP 104
-#define TK_UNION 105
-#define TK_ALL 106
-#define TK_EXCEPT 107
-#define TK_INTERSECT 108
-#define TK_SELECT 109
-#define TK_DISTINCT 110
-#define TK_DOT 111
-#define TK_FROM 112
-#define TK_JOIN 113
-#define TK_USING 114
-#define TK_ORDER 115
-#define TK_BY 116
-#define TK_GROUP 117
-#define TK_HAVING 118
-#define TK_LIMIT 119
-#define TK_WHERE 120
-#define TK_INTO 121
-#define TK_VALUES 122
-#define TK_INTEGER 123
-#define TK_FLOAT 124
-#define TK_BLOB 125
-#define TK_REGISTER 126
-#define TK_VARIABLE 127
-#define TK_CASE 128
-#define TK_WHEN 129
-#define TK_THEN 130
-#define TK_ELSE 131
-#define TK_INDEX 132
-#define TK_ALTER 133
-#define TK_TO 134
-#define TK_ADD 135
-#define TK_COLUMNKW 136
-#define TK_TO_TEXT 137
-#define TK_TO_BLOB 138
-#define TK_TO_NUMERIC 139
-#define TK_TO_INT 140
-#define TK_TO_REAL 141
-#define TK_END_OF_FILE 142
-#define TK_ILLEGAL 143
-#define TK_SPACE 144
-#define TK_UNCLOSED_STRING 145
-#define TK_COMMENT 146
-#define TK_FUNCTION 147
-#define TK_COLUMN 148
-#define TK_AGG_FUNCTION 149
-#define TK_AGG_COLUMN 150
-#define TK_CONST_FUNC 151
+#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
Index: SQLite.Interop/src/pragma.c
==================================================================
--- SQLite.Interop/src/pragma.c
+++ SQLite.Interop/src/pragma.c
@@ -9,19 +9,19 @@
** 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.15 2006/01/16 15:51:47 rmsimpson Exp $
+** $Id: pragma.c,v 1.1 2005/03/01 16:04:34 rmsimpson Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include
/* Ignore this whole file if pragmas are disabled
*/
-#if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER)
+#ifndef SQLITE_OMIT_PRAGMA
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
# include "pager.h"
# include "btree.h"
#endif
@@ -34,11 +34,11 @@
** 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 char *z){
+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};
@@ -56,11 +56,11 @@
}
/*
** Interpret the given string as a boolean value.
*/
-static int getBoolean(const char *z){
+static int getBoolean(const u8 *z){
return getSafetyLevel(z)&1;
}
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
/*
@@ -77,13 +77,11 @@
return 2;
}else{
return 0;
}
}
-#endif /* SQLITE_PAGER_PRAGMAS */
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
/*
** 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){
@@ -98,13 +96,11 @@
db->aDb[1].pBt = 0;
sqlite3ResetInternalSchema(db, 0);
}
return SQLITE_OK;
}
-#endif /* SQLITE_PAGER_PRAGMAS */
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
/*
** 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.
*/
@@ -116,11 +112,11 @@
return SQLITE_ERROR;
}
db->temp_store = ts;
return SQLITE_OK;
}
-#endif /* SQLITE_PAGER_PRAGMAS */
+#endif
/*
** Generate code to return a single integer value.
*/
static void returnSingleInt(Parse *pParse, const char *zLabel, int value){
@@ -131,11 +127,10 @@
sqlite3VdbeSetColName(v, 0, zLabel, P3_STATIC);
}
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
}
-#ifndef SQLITE_OMIT_FLAG_PRAGMAS
/*
** 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.
*/
@@ -149,21 +144,13 @@
{ "vdbe_listing", SQLITE_VdbeListing },
{ "full_column_names", SQLITE_FullColNames },
{ "short_column_names", SQLITE_ShortColNames },
{ "count_changes", SQLITE_CountRows },
{ "empty_result_callbacks", SQLITE_NullCallback },
- { "legacy_file_format", SQLITE_LegacyFileFmt },
-#ifndef SQLITE_OMIT_CHECK
- { "ignore_check_constraints", SQLITE_IgnoreChecks },
-#endif
/* The following is VERY experimental */
{ "writable_schema", SQLITE_WriteSchema },
{ "omit_readlock", SQLITE_NoReadlock },
-
- /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted
- ** flag if there are any active statements. */
- { "read_uncommitted", SQLITE_ReadUncommitted },
};
int i;
const struct sPragmaType *p;
for(i=0, p=aPragma; izName)==0 ){
@@ -188,11 +175,10 @@
return 1;
}
}
return 0;
}
-#endif /* SQLITE_OMIT_FLAG_PRAGMAS */
/*
** Process a pragma statement.
**
** Pragmas are of this form:
@@ -286,12 +272,12 @@
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->pSchema->cache_size = size;
- sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
+ pDb->cache_size = size;
+ sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size);
}
}else
/*
** PRAGMA [database.]page_size
@@ -348,16 +334,16 @@
** 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->pSchema->cache_size);
+ returnSingleInt(pParse, "cache_size", pDb->cache_size);
}else{
int size = atoi(zRight);
if( size<0 ) size = -size;
- pDb->pSchema->cache_size = size;
- sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
+ pDb->cache_size = size;
+ sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size);
}
}else
/*
** PRAGMA temp_store
@@ -440,16 +426,14 @@
}
}
}else
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
-#ifndef SQLITE_OMIT_FLAG_PRAGMAS
if( flagPragma(pParse, zLeft, zRight) ){
/* The flagPragma() subroutine also generates any necessary code
** there is nothing more to do here */
}else
-#endif /* SQLITE_OMIT_FLAG_PRAGMAS */
#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
/*
** PRAGMA table_info()
**
@@ -589,17 +573,16 @@
sqlite3VdbeSetColName(v, 3, "from", P3_STATIC);
sqlite3VdbeSetColName(v, 4, "to", P3_STATIC);
while(pFK){
int j;
for(j=0; jnCol; j++){
- char *zCol = pFK->aCol[j].zCol;
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, zCol ? OP_String8 : OP_Null, 0, 0, zCol, 0);
+ sqlite3VdbeOp3(v, OP_String8, 0, 0, pFK->aCol[j].zCol, 0);
sqlite3VdbeAddOp(v, OP_Callback, 5, 0);
}
++i;
pFK = pFK->pNextFrom;
}
@@ -609,32 +592,29 @@
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
#ifndef NDEBUG
if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
extern void sqlite3ParserTrace(FILE*, char *);
- if( zRight ){
- if( getBoolean(zRight) ){
- sqlite3ParserTrace(stderr, "parser: ");
- }else{
- sqlite3ParserTrace(0, 0);
- }
+ if( getBoolean(zRight) ){
+ sqlite3ParserTrace(stdout, "parser: ");
+ }else{
+ sqlite3ParserTrace(0, 0);
}
}else
#endif
- /* Reinstall the LIKE and GLOB functions. The variant of LIKE
- ** used will be case sensitive or not depending on the RHS.
- */
- if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
- if( zRight ){
- sqlite3RegisterLikeFunctions(db, getBoolean(zRight));
- }
- }else
-
#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
*/
@@ -648,108 +628,106 @@
/* Initialize the VDBE program */
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, "integrity_check", P3_STATIC);
- sqlite3VdbeAddOp(v, OP_MemInt, 0, 0); /* Initialize error count to 0 */
+ sqlite3VdbeAddOpList(v, ArraySize(initCode), initCode);
/* Do an integrity check on each database file */
for(i=0; inDb; i++){
HashElem *x;
- Hash *pTbls;
int cnt = 0;
- if( OMIT_TEMPDB && i==1 ) continue;
-
sqlite3CodeVerifySchema(pParse, i);
/* Do an integrity check of the B-Tree
*/
- pTbls = &db->aDb[i].pSchema->tblHash;
- for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
+ 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+7);
+ 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);
- sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0);
/* Make sure all the indices are constructed correctly.
*/
sqlite3CodeVerifySchema(pParse, i);
- for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
+ 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_MemInt, 0, 1);
+ sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
+ sqlite3VdbeAddOp(v, OP_MemStore, 1, 1);
loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0);
- sqlite3VdbeAddOp(v, OP_MemIncr, 1, 1);
+ 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, 1, 0, 0},
+ { OP_MemIncr, 0, 0, 0},
{ OP_String8, 0, 0, "rowid "},
- { OP_Rowid, 1, 0, 0},
+ { 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);
- sqlite3VdbeJumpHere(v, jmp2);
+ sqlite3VdbeChangeP2(v, jmp2, sqlite3VdbeCurrentAddr(v));
}
sqlite3VdbeAddOp(v, OP_Next, 1, loopTop+1);
- sqlite3VdbeJumpHere(v, loopTop);
+ sqlite3VdbeChangeP2(v, loopTop, sqlite3VdbeCurrentAddr(v));
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
static const VdbeOpList cntIdx[] = {
- { OP_MemInt, 0, 2, 0},
- { OP_Rewind, 0, 0, 0}, /* 1 */
- { OP_MemIncr, 1, 2, 0},
- { OP_Next, 0, 0, 0}, /* 3 */
+ { 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}, /* 6 */
- { OP_MemIncr, 1, 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}, /* 9 */
+ { 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+1, j+2);
- sqlite3VdbeChangeP2(v, addr+1, addr+4);
- sqlite3VdbeChangeP1(v, addr+3, j+2);
- sqlite3VdbeChangeP2(v, addr+3, addr+2);
- sqlite3VdbeJumpHere(v, addr+6);
- sqlite3VdbeChangeP3(v, addr+9, pIdx->zName, P3_STATIC);
+ 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);
- sqlite3VdbeJumpHere(v, addr+2);
+ sqlite3VdbeChangeP2(v, addr+2, addr+ArraySize(endCode));
}else
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
#ifndef SQLITE_OMIT_UTF16
/*
@@ -795,11 +773,11 @@
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==ENC(pParse->db) ){
+ if( pEnc->enc==pParse->db->enc ){
sqlite3VdbeChangeP3(v, -1, pEnc->zName, P3_STATIC);
break;
}
}
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
@@ -807,17 +785,14 @@
/* 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(
- !(DbHasProperty(db, 0, DB_SchemaLoaded)) ||
- DbHasProperty(db, 0, DB_Empty)
- ){
+ if( !(pParse->db->flags&SQLITE_Initialized) ){
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
- ENC(pParse->db) = pEnc->enc;
+ pParse->db->enc = pEnc->enc;
break;
}
}
if( !pEnc->zName ){
sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight);
@@ -904,41 +879,24 @@
sqlite3VdbeSetColName(v, 1, "status", P3_STATIC);
for(i=0; inDb; i++){
Btree *pBt;
Pager *pPager;
if( db->aDb[i].zName==0 ) continue;
- sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, P3_STATIC);
+ 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_String8, 0, 0, "closed", P3_STATIC);
+ sqlite3VdbeOp3(v, OP_String, 0, 0, "closed", P3_STATIC);
}else{
int j = sqlite3pager_lockstate(pPager);
- sqlite3VdbeOp3(v, OP_String8, 0, 0,
+ sqlite3VdbeOp3(v, OP_String, 0, 0,
(j>=0 && j<=4) ? azLockName[j] : "unknown", P3_STATIC);
}
sqlite3VdbeAddOp(v, OP_Callback, 2, 0);
}
}else
#endif
-#ifdef SQLITE_SSE
- /*
- ** Check to see if the sqlite_statements table exists. Create it
- ** if it does not.
- */
- if( sqlite3StrICmp(zLeft, "create_sqlite_statement_table")==0 ){
- extern int sqlite3CreateStatementsTable(Parse*);
- sqlite3CreateStatementsTable(pParse);
- }else
-#endif
-
-#if SQLITE_HAS_CODEC
- if( sqlite3StrICmp(zLeft, "key")==0 ){
- sqlite3_key(db, zRight, strlen(zRight));
- }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
@@ -949,6 +907,6 @@
pragma_out:
sqliteFree(zLeft);
sqliteFree(zRight);
}
-#endif /* SQLITE_OMIT_PRAGMA || SQLITE_OMIT_PARSER */
+#endif /* SQLITE_OMIT_PRAGMA */
DELETED SQLite.Interop/src/prepare.c
Index: SQLite.Interop/src/prepare.c
==================================================================
--- SQLite.Interop/src/prepare.c
+++ /dev/null
@@ -1,628 +0,0 @@
-/*
-** 2005 May 25
-**
-** 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 the implementation of the sqlite3_prepare()
-** interface, and routines that contribute to loading the database schema
-** from disk.
-**
-** $Id: prepare.c,v 1.11 2006/01/16 15:51:47 rmsimpson Exp $
-*/
-#include "sqliteInt.h"
-#include "os.h"
-#include
-
-/*
-** Fill the InitData structure with an error message that indicates
-** that the database is corrupt.
-*/
-static void corruptSchema(InitData *pData, const char *zExtra){
- if( !sqlite3ThreadDataReadOnly()->mallocFailed ){
- 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;
-
- if( sqlite3ThreadDataReadOnly()->mallocFailed ){
- return SQLITE_NOMEM;
- }
-
- 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 && iDbnDb );
- 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 ){
- if( rc==SQLITE_NOMEM ){
- sqlite3ThreadData()->mallocFailed = 1;
- }else{
- 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;
- Db *pDb;
- char const *azArg[5];
- char zDbNum[30];
- int meta[10];
- InitData initData;
- char const *zMasterSchema;
- char const *zMasterName = SCHEMA_TABLE(iDb);
-
- /*
- ** 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"
- ")"
- ;
-#ifndef SQLITE_OMIT_TEMPDB
- 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"
- ")"
- ;
-#else
- #define temp_master_schema 0
-#endif
-
- assert( iDb>=0 && iDbnDb );
- assert( db->aDb[iDb].pSchema );
-
- /* 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( !OMIT_TEMPDB && iDb==1 ){
- zMasterSchema = temp_master_schema;
- }else{
- zMasterSchema = master_schema;
- }
- zMasterName = SCHEMA_TABLE(iDb);
-
- /* 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
- */
- pDb = &db->aDb[iDb];
- if( pDb->pBt==0 ){
- if( !OMIT_TEMPDB && iDb==1 ){
- DbSetProperty(db, 1, DB_SchemaLoaded);
- }
- return SQLITE_OK;
- }
- rc = sqlite3BtreeCursor(pDb->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 && ipBt, i+1, (u32 *)&meta[i]);
- }
- if( rc ){
- sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
- sqlite3BtreeCloseCursor(curMain);
- return rc;
- }
- }else{
- memset(meta, 0, sizeof(meta));
- }
- pDb->pSchema->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 ENC(db). */
- ENC(db) = (u8)meta[4];
- db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0);
- }else{
- /* If opening an attached database, the encoding much match ENC(db) */
- if( meta[4]!=ENC(db) ){
- sqlite3BtreeCloseCursor(curMain);
- sqlite3SetString(pzErrMsg, "attached databases must use the same"
- " text encoding as main database", (char*)0);
- return SQLITE_ERROR;
- }
- }
- }else{
- DbSetProperty(db, iDb, DB_Empty);
- }
- pDb->pSchema->enc = ENC(db);
-
- size = meta[2];
- if( size==0 ){ size = MAX_PAGES; }
- pDb->pSchema->cache_size = size;
- sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
-
- /*
- ** file_format==1 Version 3.0.0.
- ** file_format==2 Version 3.1.3. // ALTER TABLE ADD COLUMN
- ** file_format==3 Version 3.1.4. // ditto but with non-NULL defaults
- ** file_format==4 Version 3.3.0. // DESC indices. Boolean constants
- */
- pDb->pSchema->file_format = meta[1];
- if( pDb->pSchema->file_format==0 ){
- pDb->pSchema->file_format = 1;
- }
- if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){
- sqlite3BtreeCloseCursor(curMain);
- sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
- return SQLITE_ERROR;
- }
-
-
- /* 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);
-#ifndef SQLITE_OMIT_ANALYZE
- if( rc==SQLITE_OK ){
- sqlite3AnalysisLoad(db, iDb);
- }
-#endif
- sqlite3BtreeCloseCursor(curMain);
- }
- if( sqlite3ThreadDataReadOnly()->mallocFailed ){
- 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 a database is initialized, the DB_SchemaLoaded bit is set
-** bit is set in the flags field of the Db structure. If the database
-** file was of zero-length, then the DB_Empty flag is also set.
-*/
-int sqlite3Init(sqlite3 *db, char **pzErrMsg){
- int i, rc;
- int called_initone = 0;
-
- if( db->init.busy ) return SQLITE_OK;
- rc = SQLITE_OK;
- db->init.busy = 1;
- for(i=0; rc==SQLITE_OK && inDb; i++){
- if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
- rc = sqlite3InitOne(db, i, pzErrMsg);
- if( rc ){
- sqlite3ResetInternalSchema(db, i);
- }
- called_initone = 1;
- }
-
- /* 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.
- */
-#ifndef SQLITE_OMIT_TEMPDB
- if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
- rc = sqlite3InitOne(db, 1, pzErrMsg);
- if( rc ){
- sqlite3ResetInternalSchema(db, 1);
- }
- called_initone = 1;
- }
-#endif
-
- db->init.busy = 0;
- if( rc==SQLITE_OK && called_initone ){
- sqlite3CommitInternalChanges(db);
- }
-
- 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 ){
- rc = sqlite3Init(db, &pParse->zErrMsg);
- }
- if( rc!=SQLITE_OK ){
- pParse->rc = rc;
- pParse->nErr++;
- }
- return rc;
-}
-
-
-/*
-** 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 && iDbnDb; 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].pSchema->schema_cookie ){
- allOk = 0;
- }
- sqlite3BtreeCloseCursor(curTemp);
- }
- }
- return allOk;
-}
-
-/*
-** Free all resources held by the schema structure. The void* argument points
-** at a Schema struct. This function does not call sqliteFree() on the
-** pointer itself, it just cleans up subsiduary resources (i.e. the contents
-** of the schema hash tables).
-*/
-void sqlite3SchemaFree(void *p){
- Hash temp1;
- Hash temp2;
- HashElem *pElem;
- Schema *pSchema = (Schema *)p;
-
- temp1 = pSchema->tblHash;
- temp2 = pSchema->trigHash;
- sqlite3HashInit(&pSchema->trigHash, SQLITE_HASH_STRING, 0);
- sqlite3HashClear(&pSchema->aFKey);
- sqlite3HashClear(&pSchema->idxHash);
- for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
- sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem));
- }
- sqlite3HashClear(&temp2);
- sqlite3HashInit(&pSchema->tblHash, SQLITE_HASH_STRING, 0);
- for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
- Table *pTab = sqliteHashData(pElem);
- sqlite3DeleteTable(0, pTab);
- }
- sqlite3HashClear(&temp1);
- pSchema->pSeqTab = 0;
- pSchema->flags &= ~DB_SchemaLoaded;
-}
-
-Schema *sqlite3SchemaGet(Btree *pBt){
- Schema * p;
- if( pBt ){
- p = (Schema *)sqlite3BtreeSchema(pBt,sizeof(Schema),sqlite3SchemaFree);
- }else{
- p = (Schema *)sqliteMalloc(sizeof(Schema));
- }
- if( p && 0==p->file_format ){
- sqlite3HashInit(&p->tblHash, SQLITE_HASH_STRING, 0);
- sqlite3HashInit(&p->idxHash, SQLITE_HASH_STRING, 0);
- sqlite3HashInit(&p->trigHash, SQLITE_HASH_STRING, 0);
- sqlite3HashInit(&p->aFKey, SQLITE_HASH_STRING, 1);
- }
- return p;
-}
-
-int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
- int i = -1000000;
-
- /* If pSchema is NULL, then return -1000000. This happens when code in
- ** expr.c is trying to resolve a reference to a transient table (i.e. one
- ** created by a sub-select). In this case the return value of this
- ** function should never be used.
- **
- ** We return -1000000 instead of the more usual -1 simply because using
- ** -1000000 as incorrectly using -1000000 index into db->aDb[] is much
- ** more likely to cause a segfault than -1 (of course there are assert()
- ** statements too, but it never hurts to play the odds).
- */
- if( pSchema ){
- for(i=0; inDb; i++){
- if( db->aDb[i].pSchema==pSchema ){
- break;
- }
- }
- assert( i>=0 &&i>=0 && inDb );
- }
- return i;
-}
-
-/*
-** 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;
- int i;
-
- /* Assert that malloc() has not failed */
- assert( !sqlite3ThreadDataReadOnly()->mallocFailed );
-
- assert( ppStmt );
- *ppStmt = 0;
- if( sqlite3SafetyOn(db) ){
- return SQLITE_MISUSE;
- }
-
- /* If any attached database schemas are locked, do not proceed with
- ** compilation. Instead return SQLITE_LOCKED immediately.
- */
- for(i=0; inDb; i++) {
- Btree *pBt = db->aDb[i].pBt;
- if( pBt && sqlite3BtreeSchemaLocked(pBt) ){
- const char *zDb = db->aDb[i].zName;
- sqlite3Error(db, SQLITE_LOCKED, "database schema is locked: %s", zDb);
- sqlite3SafetyOff(db);
- return SQLITE_LOCKED;
- }
- }
-
- memset(&sParse, 0, sizeof(sParse));
- sParse.db = db;
- sParse.pTsd = sqlite3ThreadData();
- sParse.pTsd->nRef++;
- sqlite3RunParser(&sParse, zSql, &zErrMsg);
-
- if( sParse.pTsd->mallocFailed ){
- sParse.rc = SQLITE_NOMEM;
- }
- if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
- if( 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 ){
- if( sParse.explain==2 ){
- sqlite3VdbeSetNumCols(sParse.pVdbe, 3);
- sqlite3VdbeSetColName(sParse.pVdbe, 0, "order", P3_STATIC);
- sqlite3VdbeSetColName(sParse.pVdbe, 1, "from", P3_STATIC);
- sqlite3VdbeSetColName(sParse.pVdbe, 2, "detail", P3_STATIC);
- }else{
- 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
-
- 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);
- }
-
- /* We must check for malloc failure last of all, in case malloc() failed
- ** inside of the sqlite3Error() call above or something.
- */
- if( sParse.pTsd->mallocFailed ){
- rc = SQLITE_NOMEM;
- sqlite3Error(db, rc, 0);
- }
-
- sParse.pTsd->nRef--;
- sqlite3MallocClearFailed();
- sqlite3ReleaseThreadData();
- 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 *zSql8 = 0;
- const char *zTail8 = 0;
- int rc;
-
- if( sqlite3SafetyCheck(db) ){
- return SQLITE_MISUSE;
- }
- zSql8 = sqlite3utf16to8(zSql, nBytes);
- 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);
- }
- sqliteFree(zSql8);
- return rc;
-}
-#endif /* SQLITE_OMIT_UTF16 */
Index: SQLite.Interop/src/printf.c
==================================================================
--- SQLite.Interop/src/printf.c
+++ SQLite.Interop/src/printf.c
@@ -109,25 +109,23 @@
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 },
- { 'g', 0, 1, etGENERIC, 30, 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 },
-#ifndef SQLITE_OMIT_FLOATING_POINT
{ '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 },
-#endif
{ '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 },
@@ -134,14 +132,14 @@
{ 'S', 0, 2, etSRCLIST, 0, 0 },
};
#define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
/*
-** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
+** If NOFLOATINGPOINT is defined, then none of the floating point
** conversions will work.
*/
-#ifndef SQLITE_OMIT_FLOATING_POINT
+#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.
**
@@ -161,21 +159,13 @@
d = digit;
digit += '0';
*val = (*val - d)*10.0;
return digit;
}
-#endif /* SQLITE_OMIT_FLOATING_POINT */
-
-/*
-** On machines with a small stack size, you can redefine the
-** SQLITE_PRINT_BUF_SIZE to be less than 350. But beware - for
-** smaller values some %f conversions may go into an infinite loop.
-*/
-#ifndef SQLITE_PRINT_BUF_SIZE
-# define SQLITE_PRINT_BUF_SIZE 350
#endif
-#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
+
+#define etBUFSIZE 1000 /* Size of the output buffer */
/*
** The root program. All variations call this core.
**
** INPUTS:
@@ -218,15 +208,13 @@
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_altform2; /* 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 */
- etByte done; /* Loop termination flag */
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'. */
@@ -234,12 +222,12 @@
etByte xtype; /* Conversion paradigm */
char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
static const char spaces[] =
" ";
#define etSPACESIZE (sizeof(spaces)-1)
-#ifndef SQLITE_OMIT_FLOATING_POINT
- int exp, e2; /* exponent of real numbers */
+#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 */
@@ -264,23 +252,21 @@
count++;
break;
}
/* Find out what flags are present */
flag_leftjustify = flag_plussign = flag_blanksign =
- flag_alternateform = flag_altform2 = flag_zeropad = 0;
- done = 0;
+ flag_alternateform = flag_zeropad = 0;
do{
switch( c ){
- case '-': flag_leftjustify = 1; break;
- case '+': flag_plussign = 1; break;
- case ' ': flag_blanksign = 1; break;
- case '#': flag_alternateform = 1; break;
- case '!': flag_altform2 = 1; break;
- case '0': flag_zeropad = 1; break;
- default: done = 1; break;
- }
- }while( !done && (c=(*++fmt))!=0 );
+ 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 ){
@@ -348,11 +334,10 @@
/*
** At this point, variables are initialized as follows:
**
** flag_alternateform TRUE if a '#' is present.
- ** flag_altform2 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
@@ -425,34 +410,34 @@
break;
case etFLOAT:
case etEXP:
case etGENERIC:
realvalue = va_arg(ap,double);
-#ifndef SQLITE_OMIT_FLOATING_POINT
+#ifndef etNOFLOATINGPOINT
if( precision<0 ) precision = 6; /* Set default precision */
- if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
+ 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( xtype==etGENERIC && precision>0 ) precision--;
+ 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( xtype==etFLOAT ) realvalue += rounder;
+ if( infop->type==etFLOAT ) realvalue += rounder;
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
if( realvalue>0.0 ){
- while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
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 ){
@@ -480,71 +465,55 @@
xtype = etFLOAT;
}
}else{
flag_rtz = 0;
}
- if( xtype==etEXP ){
- e2 = 0;
- }else{
- e2 = exp;
- }
- nsd = 0;
- flag_dp = (precision>0) | flag_alternateform | flag_altform2;
- /* The sign in front of the number */
- if( prefix ){
- *(bufpt++) = prefix;
- }
- /* Digits prior to the decimal point */
- if( e2<0 ){
- *(bufpt++) = '0';
- }else{
- for(; e2>=0; e2--){
- *(bufpt++) = et_getdigit(&realvalue,&nsd);
- }
- }
- /* The decimal point */
- if( flag_dp ){
- *(bufpt++) = '.';
- }
- /* "0" digits after the decimal point but before the first
- ** significant digit of the number */
- for(e2++; e2<0 && precision>0; precision--, e2++){
- *(bufpt++) = '0';
- }
- /* Significant digits after the decimal point */
- while( (precision--)>0 ){
- *(bufpt++) = et_getdigit(&realvalue,&nsd);
- }
- /* Remove trailing zeros and the "." if no digits follow the "." */
- if( flag_rtz && flag_dp ){
- while( bufpt[-1]=='0' ) *(--bufpt) = 0;
- assert( bufpt>buf );
- if( bufpt[-1]=='.' ){
- if( flag_altform2 ){
- *(bufpt++) = '0';
- }else{
- *(--bufpt) = 0;
- }
- }
- }
- /* Add the "eNNN" suffix */
- if( flag_exp || (xtype==etEXP && exp) ){
- *(bufpt++) = aDigits[infop->charset];
- if( exp<0 ){
- *(bufpt++) = '-'; exp = -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 */
- }
- *bufpt = 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+precision0 || 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;
@@ -593,43 +562,44 @@
}
length = strlen(bufpt);
if( precision>=0 && precisionetBUFSIZE ){
- 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 && precisionetBUFSIZE ){
+ 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 && precisionz ){
- (*func)(arg, (char*)pToken->z, pToken->n);
+ (*func)(arg, pToken->z, pToken->n);
}
length = width = 0;
break;
}
case etSRCLIST: {
@@ -726,15 +696,11 @@
pM->zText = pM->xRealloc(0, pM->nAlloc);
if( pM->zText && pM->nChar ){
memcpy(pM->zText, pM->zBase, pM->nChar);
}
}else{
- char *zNew;
- zNew = pM->xRealloc(pM->zText, pM->nAlloc);
- if( zNew ){
- pM->zText = zNew;
- }
+ pM->zText = pM->xRealloc(pM->zText, pM->nAlloc);
}
}
}
if( pM->zText ){
if( nNewChar>0 ){
@@ -768,14 +734,11 @@
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 ){
- char *zNew = xRealloc(sM.zText, sM.nChar+1);
- if( zNew ){
- sM.zText = zNew;
- }
+ sM.zText = xRealloc(sM.zText, sM.nChar+1);
}
}
return sM.zText;
}
@@ -789,11 +752,11 @@
/*
** Print into memory obtained from sqliteMalloc(). Use the internal
** %-conversion extensions.
*/
char *sqlite3VMPrintf(const char *zFormat, va_list ap){
- char zBase[SQLITE_PRINT_BUF_SIZE];
+ char zBase[1000];
return base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
}
/*
** Print into memory obtained from sqliteMalloc(). Use the internal
@@ -800,11 +763,11 @@
** %-conversion extensions.
*/
char *sqlite3MPrintf(const char *zFormat, ...){
va_list ap;
char *z;
- char zBase[SQLITE_PRINT_BUF_SIZE];
+ char zBase[1000];
va_start(ap, zFormat);
z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
va_end(ap);
return z;
}
Index: SQLite.Interop/src/random.c
==================================================================
--- SQLite.Interop/src/random.c
+++ SQLite.Interop/src/random.c
@@ -13,11 +13,11 @@
** 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.15 2006/01/16 15:51:47 rmsimpson Exp $
+** $Id: random.c,v 1.1 2005/03/01 16:04:34 rmsimpson Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -24,20 +24,17 @@
/*
** 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_NewRowid opcode in the VDBE depends on having a very
+** 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.
-**
-** (Later): Actually, OP_NewRowid does not depend on a good source of
-** randomness any more. But we will leave this code in all the same.
*/
static int randomByte(){
unsigned char t;
/* All threads share a single random number generator.
@@ -96,5 +93,8 @@
while( N-- ){
*(zBuf++) = randomByte();
}
sqlite3OsLeaveMutex();
}
+
+
+
Index: SQLite.Interop/src/select.c
==================================================================
--- SQLite.Interop/src/select.c
+++ SQLite.Interop/src/select.c
@@ -10,14 +10,14 @@
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $
+** $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.
*/
@@ -58,13 +58,10 @@
pNew->op = TK_SELECT;
pNew->pLimit = pLimit;
pNew->pOffset = pOffset;
pNew->iLimit = -1;
pNew->iOffset = -1;
- pNew->addrOpenVirt[0] = -1;
- pNew->addrOpenVirt[1] = -1;
- pNew->addrOpenVirt[2] = -1;
}
return pNew;
}
/*
@@ -71,11 +68,10 @@
** 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_CROSS
** JT_OUTER
** JT_NATURAL
** JT_LEFT
** JT_RIGHT
**
@@ -87,31 +83,31 @@
int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
int jointype = 0;
Token *apAll[3];
Token *p;
static const struct {
- const char zKeyword[8];
+ 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|JT_CROSS },
+ { "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; jn==keywords[j].nChar
- && sqlite3StrNICmp((char*)p->z, keywords[j].zKeyword, p->n)==0 ){
+ && sqlite3StrNICmp(p->z, keywords[j].zKeyword, p->n)==0 ){
jointype |= keywords[j].code;
break;
}
}
if( j>=sizeof(keywords)/sizeof(keywords[0]) ){
@@ -152,24 +148,15 @@
/*
** Set the value of a token to a '\000'-terminated string.
*/
static void setToken(Token *p, const char *z){
- p->z = (u8*)z;
- p->n = z ? strlen(z) : 0;
+ p->z = z;
+ p->n = strlen(z);
p->dyn = 0;
}
-/*
-** Create an expression node for an identifier with the name of zName
-*/
-static Expr *createIdExpr(const char *zName){
- Token dummy;
- setToken(&dummy, zName);
- return sqlite3Expr(TK_ID, 0, 0, &dummy);
-}
-
/*
** Add a term to the WHERE expression in *ppExpr that requires the
** zCol column to be equal in the two tables pTab1 and pTab2.
*/
@@ -177,66 +164,51 @@
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 */
- int iRightJoinTable, /* VDBE cursor for the right table */
Expr **ppExpr /* Add the equality term to this expression */
){
+ Token dummy;
Expr *pE1a, *pE1b, *pE1c;
Expr *pE2a, *pE2b, *pE2c;
Expr *pE;
- pE1a = createIdExpr(zCol);
- pE2a = createIdExpr(zCol);
+ setToken(&dummy, zCol);
+ pE1a = sqlite3Expr(TK_ID, 0, 0, &dummy);
+ pE2a = sqlite3Expr(TK_ID, 0, 0, &dummy);
if( zAlias1==0 ){
zAlias1 = pTab1->zName;
}
- pE1b = createIdExpr(zAlias1);
+ setToken(&dummy, zAlias1);
+ pE1b = sqlite3Expr(TK_ID, 0, 0, &dummy);
if( zAlias2==0 ){
zAlias2 = pTab2->zName;
}
- pE2b = createIdExpr(zAlias2);
+ 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);
- pE->iRightJoinTable = iRightJoinTable;
*ppExpr = sqlite3ExprAnd(*ppExpr, pE);
}
/*
** Set the EP_FromJoin property on all terms of the given expression.
-** And set the Expr.iRightJoinTable to iTable for every term in the
-** 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.
-**
-** The Expr.iRightJoinTable tells the WHERE clause processing that the
-** expression depends on table iRightJoinTable even if that table is not
-** explicitly mentioned in the expression. That information is needed
-** for cases like this:
-**
-** SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5
-**
-** The where clause needs to defer the handling of the t1.x=5
-** term until after the t2 loop of the join. In that way, a
-** NULL t2 row will be inserted whenever t1.x!=5. If we do not
-** defer the handling of t1.x=5, it will be processed immediately
-** after the t1 loop and rows with t1.x!=5 will never appear in
-** the output, which is incorrect.
*/
-static void setJoinExpr(Expr *p, int iTable){
+static void setJoinExpr(Expr *p){
while( p ){
ExprSetProperty(p, EP_FromJoin);
- p->iRightJoinTable = iTable;
- setJoinExpr(p->pLeft, iTable);
+ setJoinExpr(p->pLeft);
p = p->pRight;
}
}
/*
@@ -279,13 +251,11 @@
}
for(j=0; jnCol; j++){
char *zName = pLeftTab->aCol[j].zName;
if( columnIndex(pRightTab, zName)>=0 ){
addWhereTerm(zName, pLeftTab, pLeft->zAlias,
- pRightTab, pRight->zAlias,
- pRight->iCursor, &p->pWhere);
-
+ pRightTab, pRight->zAlias, &p->pWhere);
}
}
}
/* Disallow both ON and USING clauses in the same join
@@ -298,11 +268,11 @@
/* Add the ON clause to the end of the WHERE clause, connected by
** an AND operator.
*/
if( pLeft->pOn ){
- setJoinExpr(pLeft->pOn, pRight->iCursor);
+ setJoinExpr(pLeft->pOn);
p->pWhere = sqlite3ExprAnd(p->pWhere, pLeft->pOn);
pLeft->pOn = 0;
}
/* Create extra terms on the WHERE clause for each column named
@@ -320,12 +290,11 @@
sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
"not present in both tables", zName);
return 1;
}
addWhereTerm(zName, pLeftTab, pLeft->zAlias,
- pRightTab, pRight->zAlias,
- pRight->iCursor, &p->pWhere);
+ pRightTab, pRight->zAlias, &p->pWhere);
}
}
}
return 0;
}
@@ -349,83 +318,45 @@
/*
** Insert code into "v" that will push the record on the top of the
** stack into the sorter.
*/
-static void pushOntoSorter(
- Parse *pParse, /* Parser context */
- ExprList *pOrderBy, /* The ORDER BY clause */
- Select *pSelect /* The whole SELECT statement */
-){
- Vdbe *v = pParse->pVdbe;
- sqlite3ExprCodeExprList(pParse, pOrderBy);
- sqlite3VdbeAddOp(v, OP_Sequence, pOrderBy->iECursor, 0);
- sqlite3VdbeAddOp(v, OP_Pull, pOrderBy->nExpr + 1, 0);
- sqlite3VdbeAddOp(v, OP_MakeRecord, pOrderBy->nExpr + 2, 0);
- sqlite3VdbeAddOp(v, OP_IdxInsert, pOrderBy->iECursor, 0);
- if( pSelect->iLimit>=0 ){
- int addr1, addr2;
- addr1 = sqlite3VdbeAddOp(v, OP_IfMemZero, pSelect->iLimit+1, 0);
- sqlite3VdbeAddOp(v, OP_MemIncr, -1, pSelect->iLimit+1);
- addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
- sqlite3VdbeJumpHere(v, addr1);
- sqlite3VdbeAddOp(v, OP_Last, pOrderBy->iECursor, 0);
- sqlite3VdbeAddOp(v, OP_Delete, pOrderBy->iECursor, 0);
- sqlite3VdbeJumpHere(v, addr2);
- pSelect->iLimit = -1;
- }
+static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){
+ int i;
+ for(i=0; inExpr; 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
+** Add code to implement the OFFSET and LIMIT
*/
-static void codeOffset(
+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 && iContinue!=0 ){
- int addr;
- sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iOffset);
- addr = sqlite3VdbeAddOp(v, OP_IfMemNeg, p->iOffset, 0);
+ 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"));
- sqlite3VdbeJumpHere(v, addr);
- }
-}
-
-/*
-** Add code that will check to make sure the top N elements of the
-** stack are distinct. iTab is a sorting index that holds previously
-** seen combinations of the N values. A new entry is made in iTab
-** if the current N values are new.
-**
-** A jump to addrRepeat is made and the K values are popped from the
-** stack if the top N elements are not distinct.
-*/
-static void codeDistinct(
- Vdbe *v, /* Generate code into this VM */
- int iTab, /* A sorting index used to test for distinctness */
- int addrRepeat, /* Jump to here if not distinct */
- int N, /* The top N elements of the stack must be distinct */
- int K /* Pop K elements from the stack if indistinct */
-){
-#if NULL_ALWAYS_DISTINCT
- sqlite3VdbeAddOp(v, OP_IsNull, -N, sqlite3VdbeCurrentAddr(v)+6);
-#endif
- sqlite3VdbeAddOp(v, OP_MakeRecord, -N, 0);
- sqlite3VdbeAddOp(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3);
- sqlite3VdbeAddOp(v, OP_Pop, K, 0);
- sqlite3VdbeAddOp(v, OP_Goto, 0, addrRepeat);
- VdbeComment((v, "# skip indistinct records"));
- sqlite3VdbeAddOp(v, OP_IdxInsert, iTab, 0);
-}
-
+ }
+ 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.
**
@@ -458,11 +389,11 @@
/* 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 ){
- codeOffset(v, p, iContinue, 0);
+ codeLimiter(v, p, iContinue, iBreak, 0);
}
/* Pull the requested columns.
*/
if( nColumn>0 ){
@@ -469,36 +400,47 @@
for(i=0; inExpr;
- sqlite3ExprCodeExprList(pParse, pEList);
+ for(i=0; inExpr; 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 ){
- int n = pEList->nExpr;
- codeDistinct(v, distinct, iContinue, n, n+1);
+#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 ){
- codeOffset(v, p, iContinue, nColumn);
+ 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.
*/
-#ifndef SQLITE_OMIT_COMPOUND_SELECT
case SRT_Union: {
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);
- if( aff ){
- sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);
- }
- sqlite3VdbeAddOp(v, OP_IdxInsert, iParm, 0);
+ 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
@@ -515,18 +457,18 @@
#endif
/* Store the result as data using a unique key.
*/
case SRT_Table:
- case SRT_VirtualTab: {
+ case SRT_TempTable: {
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
if( pOrderBy ){
- pushOntoSorter(pParse, pOrderBy, p);
+ pushOntoSorter(pParse, v, pOrderBy);
}else{
- sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
+ sqlite3VdbeAddOp(v, OP_NewRecno, iParm, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
- sqlite3VdbeAddOp(v, OP_Insert, iParm, 0);
+ sqlite3VdbeAddOp(v, OP_PutIntKey, iParm, 0);
}
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
@@ -541,63 +483,62 @@
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 ){
- /* At first glance you would think we could optimize out the
- ** ORDER BY in this case since the order of entries in the set
- ** does not matter. But there might be a LIMIT clause, in which
- ** case the order does matter */
- pushOntoSorter(pParse, pOrderBy, p);
+ 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_IdxInsert, (iParm&0x0000FFFF), 0);
- }
- sqlite3VdbeJumpHere(v, addr2);
- break;
- }
-
- /* If any row exists in the result set, record that fact and abort.
- */
- case SRT_Exists: {
- sqlite3VdbeAddOp(v, OP_MemInt, 1, iParm);
- sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
- /* The LIMIT clause will terminate the loop for us */
+ 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, pOrderBy, p);
+ pushOntoSorter(pParse, v, pOrderBy);
}else{
sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
- /* The LIMIT clause will jump out of the loop for us */
+ sqlite3VdbeAddOp(v, OP_Goto, 0, iBreak);
}
break;
}
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */
- /* Send the data to the callback function or to a subroutine. In the
- ** case of a subroutine, the subroutine itself is responsible for
- ** popping the data from the stack.
+ /* 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:
- case SRT_Callback: {
+ case SRT_Subroutine: {
if( pOrderBy ){
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
- pushOntoSorter(pParse, pOrderBy, p);
- }else if( eDest==SRT_Subroutine ){
- sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);
+ pushOntoSorter(pParse, v, pOrderBy);
}else{
- sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0);
+ sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);
}
break;
}
#if !defined(SQLITE_OMIT_TRIGGER)
@@ -611,61 +552,12 @@
sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
break;
}
#endif
}
-
- /* Jump to the end of the loop if the LIMIT is reached.
- */
- if( p->iLimit>=0 && pOrderBy==0 ){
- sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit);
- sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, iBreak);
- }
return 0;
}
-
-/*
-** Given an expression list, generate a KeyInfo structure that records
-** the collating sequence for each expression in that expression list.
-**
-** If the ExprList is an ORDER BY or GROUP BY clause then the resulting
-** KeyInfo structure is appropriate for initializing a virtual index to
-** implement that clause. If the ExprList is the result set of a SELECT
-** then the KeyInfo structure is appropriate for initializing a virtual
-** index to implement a DISTINCT test.
-**
-** Space to hold the KeyInfo structure is obtain from malloc. The calling
-** function is responsible for seeing that this structure is eventually
-** freed. Add the KeyInfo structure to the P3 field of an opcode using
-** P3_KEYINFO_HANDOFF is the usual way of dealing with this.
-*/
-static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){
- sqlite3 *db = pParse->db;
- int nExpr;
- KeyInfo *pInfo;
- struct ExprList_item *pItem;
- int i;
-
- nExpr = pList->nExpr;
- pInfo = sqliteMalloc( sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) );
- if( pInfo ){
- pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr];
- pInfo->nField = nExpr;
- pInfo->enc = ENC(db);
- for(i=0, pItem=pList->a; ipExpr);
- if( !pColl ){
- pColl = db->pDfltColl;
- }
- pInfo->aColl[i] = pColl;
- pInfo->aSortOrder[i] = pItem->sortOrder;
- }
- }
- return pInfo;
-}
-
/*
** 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
@@ -677,42 +569,63 @@
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 brk = sqlite3VdbeMakeLabel(v);
- int cont = sqlite3VdbeMakeLabel(v);
+ int end1 = sqlite3VdbeMakeLabel(v);
+ int end2 = sqlite3VdbeMakeLabel(v);
int addr;
- int iTab;
- ExprList *pOrderBy = p->pOrderBy;
+ KeyInfo *pInfo;
+ ExprList *pOrderBy;
+ int nCol, i;
+ sqlite3 *db = pParse->db;
- iTab = pOrderBy->iECursor;
- addr = 1 + sqlite3VdbeAddOp(v, OP_Sort, iTab, brk);
- codeOffset(v, p, cont, 0);
- sqlite3VdbeAddOp(v, OP_Column, iTab, pOrderBy->nExpr + 1);
+ 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; ia[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_VirtualTab: {
- sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
+ case SRT_TempTable: {
+ sqlite3VdbeAddOp(v, OP_NewRecno, iParm, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
- sqlite3VdbeAddOp(v, OP_Insert, iParm, 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, "c", P3_STATIC);
- sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
+ 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);
- /* The LIMIT clause will terminate the loop for us */
+ sqlite3VdbeAddOp(v, OP_Goto, 0, end1);
break;
}
#endif
case SRT_Callback:
case SRT_Subroutine: {
@@ -733,23 +646,15 @@
default: {
/* Do nothing */
break;
}
}
-
- /* Jump to the end of the loop when the LIMIT is reached
- */
- if( p->iLimit>=0 ){
- sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit);
- sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, brk);
- }
-
- /* The bottom of the loop
- */
- sqlite3VdbeResolveLabel(v, cont);
- sqlite3VdbeAddOp(v, OP_Next, iTab, addr);
- sqlite3VdbeResolveLabel(v, brk);
+ 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.
@@ -782,24 +687,10 @@
pTab = pTabList->a[j].pTab;
}else{
pNC = pNC->pNext;
}
}
- if( pTab==0 ){
- /* FIX ME:
- ** This can occurs if you have something like "SELECT new.x;" inside
- ** a trigger. In other words, if you reference the special "new"
- ** table in the result set of a select. We do not have a good way
- ** to find the actual table type, so call it "TEXT". This is really
- ** something of a bug, but I do not know how to fix it.
- **
- ** This code does not produce the correct answer - it just prevents
- ** a segfault. See ticket #1229.
- */
- zType = "TEXT";
- break;
- }
assert( pTab );
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iColnCol) );
if( iCol<0 ){
zType = "INTEGER";
@@ -870,12 +761,11 @@
return;
}
#endif
assert( v!=0 );
- if( pParse->colNamesSet || v==0
- || sqlite3ThreadDataReadOnly()->mallocFailed ) return;
+ 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; inExpr; i++){
@@ -900,24 +790,24 @@
zCol = "rowid";
}else{
zCol = pTab->aCol[iCol].zName;
}
if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){
- sqlite3VdbeSetColName(v, i, (char*)p->span.z, p->span.n);
+ 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, (char*)0);
+ 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, (char*)p->span.z, p->span.n);
+ 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);
@@ -966,11 +856,10 @@
}
pTab = sqliteMalloc( sizeof(Table) );
if( pTab==0 ){
return 0;
}
- pTab->nRef = 1;
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 );
@@ -977,11 +866,10 @@
for(i=0, pCol=aCol; inCol; i++, pCol++){
Expr *p, *pR;
char *zType;
char *zName;
char *zBasename;
- CollSeq *pColl;
int cnt;
NameContext sNC;
/* Get an appropriate name for the column
*/
@@ -1000,25 +888,19 @@
}else{
/* If all else fails, make up a name */
zName = sqlite3MPrintf("column%d", i+1);
}
sqlite3Dequote(zName);
- if( sqlite3ThreadDataReadOnly()->mallocFailed ){
- sqliteFree(zName);
- sqlite3DeleteTable(0, pTab);
- return 0;
- }
/* 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; jzName = zName;
/* Get the typename, type affinity, and collating sequence for the
** column.
*/
- memset(&sNC, 0, sizeof(sNC));
sNC.pSrcList = pSelect->pSrc;
zType = sqliteStrDup(columnType(&sNC, p));
pCol->zType = zType;
pCol->affinity = sqlite3ExprAffinity(p);
- pColl = sqlite3ExprCollSeq(pParse, p);
- if( pColl ){
- pCol->zColl = sqliteStrDup(pColl->zName);
+ pCol->pColl = sqlite3ExprCollSeq(pParse, p);
+ if( !pCol->pColl ){
+ pCol->pColl = pParse->db->pDfltColl;
}
}
pTab->iPKey = -1;
return pTab;
}
@@ -1072,13 +953,11 @@
SrcList *pTabList;
ExprList *pEList;
Table *pTab;
struct SrcList_item *pFrom;
- if( p==0 || p->pSrc==0 || sqlite3ThreadDataReadOnly()->mallocFailed ){
- return 1;
- }
+ 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.
@@ -1102,11 +981,10 @@
assert( pFrom->pSelect!=0 );
if( pFrom->zAlias==0 ){
pFrom->zAlias =
sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect);
}
- assert( pFrom->pTab==0 );
pFrom->pTab = pTab =
sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect);
if( pTab==0 ){
return 1;
}
@@ -1116,17 +994,15 @@
** part of the schema. */
pTab->isTransient = 1;
#endif
}else{
/* An ordinary table or view name in the FROM clause */
- assert( pFrom->pTab==0 );
pFrom->pTab = pTab =
sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase);
if( pTab==0 ){
return 1;
}
- pTab->nRef++;
#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;
@@ -1171,26 +1047,18 @@
** 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;
- int flags = pParse->db->flags;
- int longNames = (flags & SQLITE_FullColNames)!=0 &&
- (flags & SQLITE_ShortColNames)==0;
-
for(k=0; knExpr; 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);
- if( pNew ){
- pNew->a[pNew->nExpr-1].zName = a[k].zName;
- }else{
- rc = 1;
- }
+ 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. */
@@ -1231,11 +1099,11 @@
}
}
pRight = sqlite3Expr(TK_ID, 0, 0, 0);
if( pRight==0 ) break;
setToken(&pRight->token, zName);
- if( zTabName && (longNames || pTabList->nSrc>1) ){
+ 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));
@@ -1245,15 +1113,11 @@
pExpr->token.dyn = 0;
}else{
pExpr = pRight;
pExpr->span = pExpr->token;
}
- if( longNames ){
- pNew = sqlite3ExprListAppend(pNew, pExpr, &pExpr->span);
- }else{
- pNew = sqlite3ExprListAppend(pNew, pExpr, &pRight->token);
- }
+ pNew = sqlite3ExprListAppend(pNew, pExpr, &pRight->token);
}
}
if( !tableSeen ){
if( zTName ){
sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
@@ -1269,10 +1133,44 @@
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; inSrc; 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
@@ -1367,108 +1265,118 @@
v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db);
}
return v;
}
-
/*
** Compute the iLimit and iOffset fields of the SELECT based on the
-** pLimit and pOffset expressions. pLimit and pOffset hold the expressions
+** 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 of iLimit and iOffset only if
-** a limit or offset is defined by pLimit and pOffset. iLimit and
+** 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 pLimit!=0 or pOffset!=0 do the limit registers get
+** 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, int iBreak){
- Vdbe *v;
- int iLimit;
- int iOffset;
- int addr1, addr2;
-
+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 ){
- p->iLimit = iLimit = pParse->nMem;
- pParse->nMem += 2;
- v = sqlite3GetVdbe(pParse);
+ 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_MemStore, iLimit, 0);
+ sqlite3VdbeAddOp(v, OP_Negative, 0, 0);
+ sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1);
VdbeComment((v, "# LIMIT counter"));
- sqlite3VdbeAddOp(v, OP_IfMemZero, iLimit, iBreak);
+ p->iLimit = iMem;
}
if( p->pOffset ){
- p->iOffset = iOffset = pParse->nMem++;
- v = sqlite3GetVdbe(pParse);
+ 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_MemStore, iOffset, p->pLimit==0);
+ sqlite3VdbeAddOp(v, OP_Negative, 0, 0);
+ sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1);
VdbeComment((v, "# OFFSET counter"));
- addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iOffset, 0);
- sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
- sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
- sqlite3VdbeJumpHere(v, addr1);
- if( p->pLimit ){
- sqlite3VdbeAddOp(v, OP_Add, 0, 0);
- }
- }
- if( p->pLimit ){
- addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iLimit, 0);
- sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
- sqlite3VdbeAddOp(v, OP_MemInt, -1, iLimit+1);
- addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
- sqlite3VdbeJumpHere(v, addr1);
- sqlite3VdbeAddOp(v, OP_MemStore, iLimit+1, 1);
- VdbeComment((v, "# LIMIT+OFFSET"));
- sqlite3VdbeJumpHere(v, addr2);
- }
-}
-
-/*
-** Allocate a virtual index to use for sorting.
-*/
-static void createSortingIndex(Parse *pParse, Select *p, ExprList *pOrderBy){
- if( pOrderBy ){
- int addr;
- assert( pOrderBy->iECursor==0 );
- pOrderBy->iECursor = pParse->nTab++;
- addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenVirtual,
- pOrderBy->iECursor, pOrderBy->nExpr+1);
- assert( p->addrOpenVirt[2] == -1 );
- p->addrOpenVirt[2] = addr;
- }
-}
-
-/*
-** The opcode at addr is an OP_OpenVirtual that created a sorting
-** index tha we ended up not needing. This routine changes that
-** opcode to OP_Noop.
-*/
-static void uncreateSortingIndex(Parse *pParse, int addr){
+ 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;
- VdbeOp *pOp = sqlite3VdbeGetOp(v, addr);
- sqlite3VdbeChangeP3(v, addr, 0, 0);
- pOp->opcode = OP_Noop;
- pOp->p1 = 0;
- pOp->p2 = 0;
+ 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; iaColl[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
@@ -1530,25 +1438,23 @@
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 */
- ExprList *pOrderBy; /* The ORDER BY clause on p */
- int aSetP2[2]; /* Set P2 value of these op to number of columns */
- int nSetP2 = 0; /* Number of slots in aSetP2[] used */
/* 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;
- assert( pPrior->pRightmost!=pPrior );
- assert( pPrior->pRightmost==p->pRightmost );
if( pPrior->pOrderBy ){
sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",
selectOpName(p->op));
rc = 1;
goto multi_select_end;
@@ -1565,51 +1471,54 @@
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_VirtualTab ){
+ if( eDest==SRT_TempTable ){
assert( p->pEList );
- assert( nSetP2pOrderBy;
switch( p->op ){
case TK_ALL: {
- if( pOrderBy==0 ){
- int addr = 0;
+ 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);
- p->pLimit = 0;
- p->pOffset = 0;
if( rc ){
goto multi_select_end;
}
p->pPrior = 0;
p->iLimit = pPrior->iLimit;
p->iOffset = pPrior->iOffset;
- if( p->iLimit>=0 ){
- addr = sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, 0);
- VdbeComment((v, "# Jump ahead if LIMIT reached"));
- }
+ 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;
}
- if( addr ){
- sqlite3VdbeJumpHere(v, addr);
- }
break;
}
/* For UNION ALL ... ORDER BY fall through to the next case */
}
case TK_EXCEPT:
@@ -1616,37 +1525,39 @@
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 && pOrderBy==0 && !p->pLimit && !p->pOffset ){
+ 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( pOrderBy && matchOrderbyToColumn(pParse, p, pOrderBy, unionTab,1) ){
+ if( p->pOrderBy
+ && matchOrderbyToColumn(pParse, p, p->pOrderBy, unionTab, 1) ){
rc = 1;
goto multi_select_end;
}
- addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, unionTab, 0);
- if( priorOp==SRT_Table ){
- assert( nSetP2addrOpenVirt[0] == -1 );
- p->addrOpenVirt[0] = addr;
- p->pRightmost->usesVirt = 1;
- }
- createSortingIndex(pParse, p, pOrderBy);
+ 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( nAddrpEList );
}
/* Code the SELECT statements to our left
*/
@@ -1662,12 +1573,12 @@
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;
- p->disallowOrderBy = pOrderBy!=0;
pLimit = p->pLimit;
p->pLimit = 0;
pOffset = p->pOffset;
p->pOffset = 0;
rc = sqlite3Select(pParse, p, op, unionTab, 0, 0, 0, aff);
@@ -1692,15 +1603,15 @@
if( eDest==SRT_Callback ){
generateColumnNames(pParse, 0, p->pEList);
}
iBreak = sqlite3VdbeMakeLabel(v);
iCont = sqlite3VdbeMakeLabel(v);
- computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp(v, OP_Rewind, unionTab, iBreak);
+ computeLimitRegisters(pParse, p);
iStart = sqlite3VdbeCurrentAddr(v);
rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
- pOrderBy, -1, eDest, iParm,
+ p->pOrderBy, -1, eDest, iParm,
iCont, iBreak, 0);
if( rc ){
rc = 1;
goto multi_select_end;
}
@@ -1721,20 +1632,23 @@
** two temporary tables. Hence it has its own case. Begin
** by allocating the tables we will need.
*/
tab1 = pParse->nTab++;
tab2 = pParse->nTab++;
- if( pOrderBy && matchOrderbyToColumn(pParse,p,pOrderBy,tab1,1) ){
+ if( p->pOrderBy && matchOrderbyToColumn(pParse,p,p->pOrderBy,tab1,1) ){
rc = 1;
goto multi_select_end;
}
- createSortingIndex(pParse, p, pOrderBy);
- addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab1, 0);
- assert( p->addrOpenVirt[0] == -1 );
- p->addrOpenVirt[0] = addr;
- p->pRightmost->usesVirt = 1;
+ 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( nAddrpEList );
/* Code the SELECTs to our left into temporary table "tab1".
*/
rc = sqlite3Select(pParse, pPrior, SRT_Union, tab1, 0, 0, 0, aff);
@@ -1742,13 +1656,18 @@
goto multi_select_end;
}
/* Code the current SELECT into temporary table "tab2"
*/
- addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab2, 0);
- assert( p->addrOpenVirt[1] == -1 );
- p->addrOpenVirt[1] = addr;
+ 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( nAddrpPrior = 0;
pLimit = p->pLimit;
p->pLimit = 0;
pOffset = p->pOffset;
p->pOffset = 0;
@@ -1768,16 +1687,16 @@
if( eDest==SRT_Callback ){
generateColumnNames(pParse, 0, p->pEList);
}
iBreak = sqlite3VdbeMakeLabel(v);
iCont = sqlite3VdbeMakeLabel(v);
- computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp(v, OP_Rewind, tab1, iBreak);
- iStart = sqlite3VdbeAddOp(v, OP_RowKey, tab1, 0);
+ 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,
- pOrderBy, -1, eDest, iParm,
+ p->pOrderBy, -1, eDest, iParm,
iCont, iBreak, 0);
if( rc ){
rc = 1;
goto multi_select_end;
}
@@ -1802,12 +1721,13 @@
}
/* Set the number of columns in temporary tables
*/
nCol = p->pEList->nExpr;
- while( nSetP2 ){
- sqlite3VdbeChangeP2(v, aSetP2[--nSetP2], nCol);
+ 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
@@ -1816,83 +1736,64 @@
** 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( pOrderBy || p->usesVirt ){
+ if( p->pOrderBy || (pOpenTemp && pOpenTemp->nId>0) ){
int i; /* Loop counter */
KeyInfo *pKeyInfo; /* Collating sequence for the result set */
- Select *pLoop; /* For looping through SELECT statements */
- CollSeq **apColl;
- CollSeq **aCopy;
- assert( p->pRightmost==p );
- pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nCol*2*sizeof(CollSeq*) + nCol);
+ assert( p->ppOpenTemp == &pOpenTemp );
+ pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nCol*sizeof(CollSeq*));
if( !pKeyInfo ){
rc = SQLITE_NOMEM;
goto multi_select_end;
}
- pKeyInfo->enc = ENC(pParse->db);
+ pKeyInfo->enc = pParse->db->enc;
pKeyInfo->nField = nCol;
- for(i=0, apColl=pKeyInfo->aColl; idb->pDfltColl;
- }
- }
-
- for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
- for(i=0; i<2; i++){
- int addr = pLoop->addrOpenVirt[i];
- if( addr<0 ){
- /* If [0] is unused then [1] is also unused. So we can
- ** always safely abort as soon as the first unused slot is found */
- assert( pLoop->addrOpenVirt[1]<0 );
- break;
- }
- sqlite3VdbeChangeP2(v, addr, nCol);
- sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO);
- }
- }
-
- if( pOrderBy ){
- struct ExprList_item *pOTerm = pOrderBy->a;
- int nOrderByExpr = pOrderBy->nExpr;
- int addr;
- u8 *pSortOrder;
-
- aCopy = (CollSeq**)&pKeyInfo[1];
- pSortOrder = pKeyInfo->aSortOrder = (u8*)&aCopy[nCol];
- memcpy(aCopy, pKeyInfo->aColl, nCol*sizeof(CollSeq*));
- apColl = pKeyInfo->aColl;
- for(i=0; ipExpr;
- char *zName = pOTerm->zName;
- assert( pExpr->op==TK_COLUMN && pExpr->iColumniColumn];
- }
- *pSortOrder = pOTerm->sortOrder;
- }
- assert( p->pRightmost==p );
- assert( p->addrOpenVirt[2]>=0 );
- addr = p->addrOpenVirt[2];
- sqlite3VdbeChangeP2(v, addr, p->pEList->nExpr+2);
- pKeyInfo->nField = nOrderByExpr;
- sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
- pKeyInfo = 0;
+ for(i=0; iaColl[i] = multiSelectCollSeq(pParse, p, i);
+ if( !pKeyInfo->aColl[i] ){
+ pKeyInfo->aColl[i] = pParse->db->pDfltColl;
+ }
+ }
+
+ for(i=0; pOpenTemp && i