diff --git a/api/backend.go b/api/backend.go
index 3d8cebe7f..97746a858 100644
--- a/api/backend.go
+++ b/api/backend.go
@@ -782,7 +782,7 @@ func (b *StatusBackend) SelectAccount(loginParams account.LoginParams) error {
return err
}
- if err := st.InitProtocolWithPassword(loginParams.ChatAddress.String(), loginParams.Password); err != nil {
+ if err := st.InitProtocol(b.appDB); err != nil {
return err
}
}
@@ -871,7 +871,7 @@ func (b *StatusBackend) InjectChatAccount(chatKeyHex, encryptionKeyHex string) e
return err
}
- if err := st.InitProtocolWithEncyptionKey(chatAccount.Address.Hex(), encryptionKeyHex); err != nil {
+ if err := st.InitProtocol(b.appDB); err != nil {
return err
}
}
diff --git a/go.mod b/go.mod
index 0685b16f2..0091c9074 100644
--- a/go.mod
+++ b/go.mod
@@ -15,15 +15,15 @@ require (
github.com/lib/pq v1.0.0
github.com/libp2p/go-libp2p-core v0.0.3
github.com/multiformats/go-multiaddr v0.0.4
- github.com/mutecomm/go-sqlcipher v0.0.0-20170920224653-f799951b4ab2
+ github.com/mutecomm/go-sqlcipher v0.0.0-20190227152316-55dbde17881f
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222
github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a
github.com/status-im/doubleratchet v2.0.0+incompatible
- github.com/status-im/migrate/v4 v4.3.1-status
+ github.com/status-im/migrate/v4 v4.0.0-20190821140204-a9d340ec8fb76af4afda06acf01740d45d2661ed
github.com/status-im/rendezvous v1.3.0
- github.com/status-im/status-protocol-go v0.0.0-20190701094942-9f0db157bf5a1ac9b52c47bbea37fc7dbe14e8fe
+ github.com/status-im/status-protocol-go v0.0.0-20190701094942-1dd03f74d712ac9b965b718963dc86ca9c3540fb
github.com/status-im/whisper v1.4.14
- github.com/stretchr/testify v1.3.0
+ github.com/stretchr/testify v1.3.1-0.20190712000136-221dbe5ed467
github.com/syndtr/goleveldb v1.0.0
go.uber.org/zap v1.10.0
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
diff --git a/go.sum b/go.sum
index 7ad9f12d5..f6d55b00e 100644
--- a/go.sum
+++ b/go.sum
@@ -365,8 +365,8 @@ github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs
github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po=
github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ=
github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg=
-github.com/mutecomm/go-sqlcipher v0.0.0-20170920224653-f799951b4ab2 h1:Q5L04ENac5Rx1K+vuxM7cjsrCgqSJNumYy3SHOQC4ec=
-github.com/mutecomm/go-sqlcipher v0.0.0-20170920224653-f799951b4ab2/go.mod h1:S9Hougr2LhvUtZGY1fCTj9nr9P53lfsCCQ2XqVMFZX8=
+github.com/mutecomm/go-sqlcipher v0.0.0-20190227152316-55dbde17881f h1:hd3r+uv9DNLScbOrnlj82rBldHQf3XWmCeXAWbw8euQ=
+github.com/mutecomm/go-sqlcipher v0.0.0-20190227152316-55dbde17881f/go.mod h1:MyUWrZlB1aI5bs7j9/pJ8ckLLZ4QcCYcNiSbsAW32D4=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA=
github.com/naoina/toml v0.0.0-20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
@@ -446,30 +446,31 @@ github.com/status-im/go-fcm v1.0.0-status h1:eUNKm4ooAXdEf9/GaTYeTELna5aVMOEbzjb
github.com/status-im/go-fcm v1.0.0-status/go.mod h1:0JGzul9SfemcbTdw0mkzLR42j+BTNci5aQWlI0o/uk8=
github.com/status-im/go-multiaddr-ethv4 v1.2.0 h1:OT84UsUzTCwguqCpJqkrCMiL4VZ1SvUtH9a5MsZupBk=
github.com/status-im/go-multiaddr-ethv4 v1.2.0/go.mod h1:2VQ3C+9zEurcceasz12gPAtmEzCeyLUGPeKLSXYQKHo=
-github.com/status-im/migrate/v4 v4.3.1-status h1:tJwsEYLgbFkvlTSMk89APwRDfpr4yG8wcwPeudsqPwo=
-github.com/status-im/migrate/v4 v4.3.1-status/go.mod h1:r8HggRBZ/k7TRwByq/Hp3P/ubFppIna0nvyavVK0pjA=
+github.com/status-im/migrate/v4 v4.0.0-20190821140204-a9d340ec8fb76af4afda06acf01740d45d2661ed h1:K2iga8l8OQIHnk2bBq2QsZTO2Q38YWy04xIspdITCdM=
+github.com/status-im/migrate/v4 v4.0.0-20190821140204-a9d340ec8fb76af4afda06acf01740d45d2661ed/go.mod h1:r8HggRBZ/k7TRwByq/Hp3P/ubFppIna0nvyavVK0pjA=
github.com/status-im/rendezvous v1.3.0 h1:7RK/MXXW+tlm0asKm1u7Qp7Yni6AO29a7j8+E4Lbjg4=
github.com/status-im/rendezvous v1.3.0/go.mod h1:+hzjuP+j/XzLPeF6E50b88pWOTLdTcwjvNYt+Gh1W1s=
-github.com/status-im/status-protocol-go v0.0.0-20190701094942-9f0db157bf5a1ac9b52c47bbea37fc7dbe14e8fe h1:QqpJe7fgZk8nKWfjUiYi9SCoN3Ozveyn60b8xWq3rik=
-github.com/status-im/status-protocol-go v0.0.0-20190701094942-9f0db157bf5a1ac9b52c47bbea37fc7dbe14e8fe/go.mod h1:thrQ4V0ZUmLZPDf74xVzub1gxgSNFaSTeTQdxtRJnTU=
+github.com/status-im/status-protocol-go v0.0.0-20190701094942-1dd03f74d712ac9b965b718963dc86ca9c3540fb h1:zJ7gHLGOw3CeTOri61Y6dO+j/vxlg8TKxFgydMWErnU=
+github.com/status-im/status-protocol-go v0.0.0-20190701094942-1dd03f74d712ac9b965b718963dc86ca9c3540fb/go.mod h1:ASO3pqc3cEFT3LPKfClp4f39jbP1m2XvSmIfBk9Ssxc=
github.com/status-im/whisper v1.4.14 h1:9VHqx4+PUYfhDnYYtDxHkg/3cfVvkHjPNciY4LO83yc=
github.com/status-im/whisper v1.4.14/go.mod h1:WS6z39YJQ8WJa9s+DmTuEM/s2nVF6Iz3B1SZYw5cYf0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v0.0.0-20190716104307-221dbe5ed46703ee255b1da0dec05086f5035f62/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.3.1-0.20190712000136-221dbe5ed467 h1:/pva5wyh0PKqe0bnHBbndEzbqsilMKFNXI0GPbO+L8c=
+github.com/stretchr/testify v1.3.1-0.20190712000136-221dbe5ed467/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v0.0.0-20180615202729-a51202d6f4a7/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
-github.com/vacp2p/mvds v0.0.19 h1:ZXopUNicQPzmIsggqa9Pbd6cqphFiyhthe3kneuJpC8=
-github.com/vacp2p/mvds v0.0.19/go.mod h1:MxvN/VFp5zkjhUfJdBft+NrsVDwMsvueDIP2x0h6Tx8=
+github.com/vacp2p/mvds v0.0.0-20190705123435-a8dc37599bf99958b0ea19431c9bb7a47bd7fa8f h1:iBJcVbX4RaPtufXJ/PJtCF1jYPzlmyEF+imcQq5pTDs=
+github.com/vacp2p/mvds v0.0.0-20190705123435-a8dc37599bf99958b0ea19431c9bb7a47bd7fa8f/go.mod h1:Xc3UWtA230lUzZoXStJHQd/BkqJK5BAZyXBsiR6XrXM=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo=
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM=
@@ -523,6 +524,7 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190225153610-fe579d43d832/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190227160552-c95aed5357e7 h1:C2F/nMkR/9sfUTpvR3QrjBuTdvMUC/cFajkphs1YLQo=
golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
diff --git a/services/shhext/db.go b/services/shhext/db.go
deleted file mode 100644
index 8e6c0876d..000000000
--- a/services/shhext/db.go
+++ /dev/null
@@ -1,173 +0,0 @@
-package shhext
-
-import (
- "fmt"
- "os"
-
- sqliteDriver "github.com/mutecomm/go-sqlcipher" // We require go sqlcipher that overrides default implementation
-
- "github.com/status-im/status-protocol-go/sqlite"
-)
-
-const exportDB = "SELECT sqlcipher_export('newdb')"
-
-// The default number of kdf iterations in sqlcipher (from version 3.0.0)
-// https://github.com/sqlcipher/sqlcipher/blob/fda4c68bb474da7e955be07a2b807bda1bb19bd2/CHANGELOG.md#300---2013-11-05
-// https://www.zetetic.net/sqlcipher/sqlcipher-api/#kdf_iter
-const defaultKdfIterationsNumber = 64000
-
-// The reduced number of kdf iterations (for performance reasons) which is
-// currently used for derivation of the database key
-// https://github.com/status-im/status-go/pull/1343
-// https://notes.status.im/i8Y_l7ccTiOYq09HVgoFwA
-const KdfIterationsNumber = 3200
-
-func migrateDBFile(oldPath string, newPath string, oldKey string, newKey string) error {
- _, err := os.Stat(oldPath)
-
- // No files, nothing to do
- if os.IsNotExist(err) {
- return nil
- }
-
- // Any other error, throws
- if err != nil {
- return err
- }
-
- if err := os.Rename(oldPath, newPath); err != nil {
- return err
- }
-
- db, err := sqlite.OpenWithIter(newPath, oldKey, defaultKdfIterationsNumber, sqlite.MigrationConfig{})
- if err != nil {
- return err
- }
-
- keyString := fmt.Sprintf("PRAGMA rekey = '%s'", newKey)
-
- if _, err = db.Exec(keyString); err != nil {
- return err
- }
-
- return nil
-}
-
-// migrateDBKeyKdfIterations changes the number of kdf iterations executed
-// during the database key derivation. This change is necessary because
-// of performance reasons.
-// https://github.com/status-im/status-go/pull/1343
-// `sqlcipher_export` is used for migration, check out this link for details:
-// https://www.zetetic.net/sqlcipher/sqlcipher-api/#sqlcipher_export
-func migrateDBKeyKdfIterations(oldPath string, newPath string, key string) error {
- _, err := os.Stat(oldPath)
-
- // No files, nothing to do
- if os.IsNotExist(err) {
- return nil
- }
-
- // Any other error, throws
- if err != nil {
- return err
- }
-
- isEncrypted, err := sqliteDriver.IsEncrypted(oldPath)
- if err != nil {
- return err
- }
-
- // Nothing to do, move db to the next migration
- if !isEncrypted {
- return os.Rename(oldPath, newPath)
- }
-
- db, err := sqlite.OpenWithIter(oldPath, key, defaultKdfIterationsNumber, sqlite.MigrationConfig{})
- if err != nil {
- return err
- }
-
- attach := fmt.Sprintf(
- "ATTACH DATABASE '%s' AS newdb KEY '%s'",
- newPath,
- key)
-
- if _, err = db.Exec(attach); err != nil {
- return err
- }
-
- changeKdfIter := fmt.Sprintf(
- "PRAGMA newdb.kdf_iter = %d",
- KdfIterationsNumber)
-
- if _, err = db.Exec(changeKdfIter); err != nil {
- return err
- }
-
- if _, err = db.Exec(exportDB); err != nil {
- return err
- }
-
- if err = db.Close(); err != nil {
- return err
- }
-
- return os.Remove(oldPath)
-}
-
-// encryptDatabase encrypts an unencrypted database with key
-func encryptDatabase(oldPath string, newPath string, key string) error {
- _, err := os.Stat(oldPath)
-
- // No files, nothing to do
- if os.IsNotExist(err) {
- return nil
- }
-
- // Any other error, throws
- if err != nil {
- return err
- }
-
- isEncrypted, err := sqliteDriver.IsEncrypted(oldPath)
- if err != nil {
- return err
- }
-
- // Nothing to do, already encrypted
- if isEncrypted {
- return os.Rename(oldPath, newPath)
- }
-
- db, err := sqlite.OpenWithIter(oldPath, "", defaultKdfIterationsNumber, sqlite.MigrationConfig{})
- if err != nil {
- return err
- }
-
- attach := fmt.Sprintf(
- "ATTACH DATABASE '%s' AS newdb KEY '%s'",
- newPath,
- key)
-
- if _, err = db.Exec(attach); err != nil {
- return err
- }
-
- changeKdfIter := fmt.Sprintf(
- "PRAGMA newdb.kdf_iter = %d",
- KdfIterationsNumber)
-
- if _, err = db.Exec(changeKdfIter); err != nil {
- return err
- }
-
- if _, err = db.Exec(exportDB); err != nil {
- return err
- }
-
- if err = db.Close(); err != nil {
- return err
- }
-
- return os.Remove(oldPath)
-}
diff --git a/services/shhext/service.go b/services/shhext/service.go
index c1569cad5..91c291042 100644
--- a/services/shhext/service.go
+++ b/services/shhext/service.go
@@ -3,6 +3,7 @@ package shhext
import (
"context"
"crypto/ecdsa"
+ "database/sql"
"fmt"
"github.com/status-im/status-go/logutils"
"os"
@@ -27,7 +28,6 @@ import (
whisper "github.com/status-im/whisper/whisperv6"
"github.com/syndtr/goleveldb/leveldb"
"go.uber.org/zap"
- "golang.org/x/crypto/sha3"
)
const (
@@ -97,18 +97,7 @@ func New(w *whisper.Whisper, handler EnvelopeEventsHandler, ldb *leveldb.DB, con
}
}
-func (s *Service) InitProtocolWithPassword(address string, password string) error {
- digest := sha3.Sum256([]byte(password))
- encKey := fmt.Sprintf("%x", digest)
- return s.initProtocol(address, encKey, password)
-}
-
-// InitProtocolWithEncyptionKey creates an instance of ProtocolService given an address and encryption key.
-func (s *Service) InitProtocolWithEncyptionKey(address string, encKey string) error {
- return s.initProtocol(address, encKey, "")
-}
-
-func (s *Service) initProtocol(address, encKey, password string) error { // nolint: gocyclo
+func (s *Service) InitProtocol(db *sql.DB) error { // nolint: gocyclo
if !s.config.PFSEnabled {
return nil
}
@@ -118,70 +107,6 @@ func (s *Service) initProtocol(address, encKey, password string) error { // noli
if err := os.MkdirAll(dataDir, os.ModePerm); err != nil {
return err
}
- v0Path := filepath.Join(dataDir, fmt.Sprintf("%x.db", address))
- v1Path := filepath.Join(dataDir, fmt.Sprintf("%s.db", s.config.InstallationID))
- v2Path := filepath.Join(dataDir, fmt.Sprintf("%s.v2.db", s.config.InstallationID))
- v3Path := filepath.Join(dataDir, fmt.Sprintf("%s.v3.db", s.config.InstallationID))
- v4Path := filepath.Join(dataDir, fmt.Sprintf("%s.v4.db", s.config.InstallationID))
-
- if password != "" {
- if err := migrateDBFile(v0Path, v1Path, "ON", password); err != nil {
- return err
- }
-
- if err := migrateDBFile(v1Path, v2Path, password, encKey); err != nil {
- // Remove db file as created with a blank password and never used,
- // and there's no need to rekey in this case
- os.Remove(v1Path)
- os.Remove(v2Path)
- }
- }
-
- if err := migrateDBKeyKdfIterations(v2Path, v3Path, encKey); err != nil {
- os.Remove(v2Path)
- os.Remove(v3Path)
- }
-
- // Fix IOS not encrypting database
- if err := encryptDatabase(v3Path, v4Path, encKey); err != nil {
- os.Remove(v3Path)
- os.Remove(v4Path)
- }
-
- // Desktop was passing a network dependent directory, which meant that
- // if running on testnet it would not access the right db. This copies
- // the db from mainnet to the root location.
- networkDependentPath := filepath.Join(dataDir, "ethereum", "mainnet_rpc", fmt.Sprintf("%s.v4.db", s.config.InstallationID))
- if _, err := os.Stat(networkDependentPath); err == nil {
- if err := os.Rename(networkDependentPath, v4Path); err != nil {
- return err
- }
- } else if !os.IsNotExist(err) {
- return err
- }
-
- // In one of the versions, we split the database file into multiple ones.
- // Later, we discovered that it really hurts the performance so we consolidated
- // it again but in a better way keeping migrations in separate packages.
- sessionsDatabasePath := filepath.Join(dataDir, fmt.Sprintf("%s.sessions.v4.sql", s.config.InstallationID))
- sessionsStat, sessionsStatErr := os.Stat(sessionsDatabasePath)
- v4PathStat, v4PathStatErr := os.Stat(v4Path)
-
- if sessionsStatErr == nil && os.IsNotExist(v4PathStatErr) {
- // This is a clear situation where we have the sessions.v4.sql file and v4Path does not exist.
- // In the previous migration, we removed v4Path when it is successfully copied into the sessions sql file.
- if err := os.Rename(sessionsDatabasePath, v4Path); err != nil {
- return err
- }
- } else if sessionsStatErr == nil && v4PathStatErr == nil {
- // Both files exist so probably the migration to split databases failed.
- if sessionsStat.ModTime().After(v4PathStat.ModTime()) {
- // Sessions sql file is newer.
- if err := os.Rename(sessionsDatabasePath, v4Path); err != nil {
- return err
- }
- }
- }
// Create a custom zap.Logger which will forward logs from status-protocol-go to status-go logger.
zapLogger, err := logutils.NewZapLoggerWithAdapter(logutils.Logger())
@@ -198,7 +123,7 @@ func (s *Service) initProtocol(address, encKey, password string) error { // noli
EnvelopeEventsHandler: EnvelopeSignalHandler{},
Logger: zapLogger,
}
- options := buildMessengerOptions(s.config, v4Path, encKey, envelopesMonitorConfig, zapLogger)
+ options := buildMessengerOptions(s.config, db, envelopesMonitorConfig, zapLogger)
selectedKeyID := s.w.SelectedKeyPairID()
identity, err := s.w.GetPrivateKey(selectedKeyID)
@@ -439,12 +364,34 @@ func (s *Service) syncMessages(ctx context.Context, mailServerID []byte, r whisp
}
}
-func buildMessengerOptions(config params.ShhextConfig, dbPath, dbKey string, envelopesMonitorConfig *protocolwhisper.EnvelopesMonitorConfig, logger *zap.Logger) []protocol.Option {
+func onNegotiatedFilters(filters []*protocolwhisper.Filter) {
+ var signalFilters []*signal.Filter
+ for _, filter := range filters {
+
+ signalFilter := &signal.Filter{
+ ChatID: filter.ChatID,
+ SymKeyID: filter.SymKeyID,
+ Listen: filter.Listen,
+ FilterID: filter.FilterID,
+ Identity: filter.Identity,
+ Topic: filter.Topic,
+ }
+
+ signalFilters = append(signalFilters, signalFilter)
+ }
+ if len(filters) != 0 {
+ handler := PublisherSignalHandler{}
+ handler.WhisperFilterAdded(signalFilters)
+ }
+}
+
+func buildMessengerOptions(config params.ShhextConfig, db *sql.DB, envelopesMonitorConfig *protocolwhisper.EnvelopesMonitorConfig, logger *zap.Logger) []protocol.Option {
options := []protocol.Option{
protocol.WithCustomLogger(logger),
- protocol.WithDatabaseConfig(dbPath, dbKey),
+ protocol.WithDatabase(db),
protocol.WithEnvelopesMonitorConfig(envelopesMonitorConfig),
+ protocol.WithOnNegotiatedFilters(onNegotiatedFilters),
}
if !config.DisableGenericDiscoveryTopic {
diff --git a/services/shhext/service_test.go b/services/shhext/service_test.go
index 3191446f7..ed55c7f74 100644
--- a/services/shhext/service_test.go
+++ b/services/shhext/service_test.go
@@ -20,13 +20,13 @@ import (
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/status-im/status-go/mailserver"
"github.com/status-im/status-go/params"
+ "github.com/status-im/status-go/sqlite"
"github.com/status-im/status-go/t/helpers"
"github.com/status-im/status-go/t/utils"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/stretchr/testify/suite"
"github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/storage"
- "golang.org/x/crypto/sha3"
)
const (
@@ -132,7 +132,14 @@ func (s *ShhExtSuite) SetupTest() {
db, err := leveldb.Open(storage.NewMemStorage(), nil)
s.Require().NoError(err)
s.services[i] = New(s.whisper[i], nil, db, config)
- s.Require().NoError(s.services[i].InitProtocolWithPassword(fmt.Sprintf("%d", i), "password"))
+
+ tmpdir, err := ioutil.TempDir("", "test-shhext-service")
+ s.Require().NoError(err)
+
+ sqlDB, err := sqlite.OpenDB(fmt.Sprintf("%s/%d", tmpdir, i), "password")
+ s.Require().NoError(err)
+
+ s.Require().NoError(s.services[i].InitProtocol(sqlDB))
s.NoError(stack.Register(func(n *node.ServiceContext) (node.Service, error) {
return s.services[i], nil
}))
@@ -163,12 +170,13 @@ func (s *ShhExtSuite) TestInitProtocol() {
service := New(shh, nil, db, config)
- err = service.InitProtocolWithPassword("example-address", "`090///\nhtaa\rhta9x8923)$$'23")
- s.NoError(err)
+ tmpdir, err := ioutil.TempDir("", "test-shhext-service-init-protocol")
+ s.Require().NoError(err)
- digest := sha3.Sum256([]byte("`090///\nhtaa\rhta9x8923)$$'23"))
- encKey := fmt.Sprintf("%x", digest)
- err = service.InitProtocolWithEncyptionKey("example-address", encKey)
+ sqlDB, err := sqlite.OpenDB(fmt.Sprintf("%s/db.sql", tmpdir), "password")
+ s.Require().NoError(err)
+
+ err = service.InitProtocol(sqlDB)
s.NoError(err)
}
@@ -307,7 +315,14 @@ func (s *ShhExtSuite) TestRequestMessagesSuccess() {
PFSEnabled: true,
}
service := New(shh, mock, nil, config)
- s.Require().NoError(service.InitProtocolWithPassword("abc", "password"))
+
+ tmpdir, err := ioutil.TempDir("", "test-shhext-service-request-messages")
+ s.Require().NoError(err)
+
+ sqlDB, err := sqlite.OpenDB(fmt.Sprintf("%s/db.sql", tmpdir), "password")
+ s.Require().NoError(err)
+
+ s.Require().NoError(service.InitProtocol(sqlDB))
s.Require().NoError(service.Start(aNode.Server()))
api := NewPublicAPI(service)
@@ -525,7 +540,14 @@ func (s *RequestWithTrackingHistorySuite) SetupTest() {
s.localContext = NewContextFromService(context.Background(), s.localService, s.localService.storage)
localPkey, err := crypto.GenerateKey()
s.Require().NoError(err)
- s.Require().NoError(s.localService.InitProtocolWithPassword("local-service", "password"))
+
+ tmpdir, err := ioutil.TempDir("", "test-shhext-service")
+ s.Require().NoError(err)
+
+ sqlDB, err := sqlite.OpenDB(fmt.Sprintf("%s/db.sql", tmpdir), "password")
+ s.Require().NoError(err)
+
+ s.Require().NoError(s.localService.InitProtocol(sqlDB))
s.Require().NoError(s.localService.Start(&p2p.Server{Config: p2p.Config{PrivateKey: localPkey}}))
s.localAPI = NewPublicAPI(s.localService)
@@ -535,7 +557,7 @@ func (s *RequestWithTrackingHistorySuite) SetupTest() {
s.remoteMailserver = &mailserver.WMailServer{}
remote.RegisterServer(s.remoteMailserver)
password := "test"
- tmpdir, err := ioutil.TempDir("", "tracking-history-tests-")
+ tmpdir, err = ioutil.TempDir("", "tracking-history-tests-")
s.Require().NoError(err)
s.Require().NoError(s.remoteMailserver.Init(remote, ¶ms.WhisperConfig{
DataDir: tmpdir,
diff --git a/sqlite/migrate.go b/sqlite/migrate.go
index 895c5c380..29b6ff960 100644
--- a/sqlite/migrate.go
+++ b/sqlite/migrate.go
@@ -15,7 +15,9 @@ func Migrate(db *sql.DB, resources *bindata.AssetSource) error {
return err
}
- driver, err := sqlcipher.WithInstance(db, &sqlcipher.Config{})
+ driver, err := sqlcipher.WithInstance(db, &sqlcipher.Config{
+ MigrationsTable: "status_go_" + sqlcipher.DefaultMigrationsTable,
+ })
if err != nil {
return err
}
diff --git a/vendor/github.com/mutecomm/go-sqlcipher/.travis.yml b/vendor/github.com/mutecomm/go-sqlcipher/.travis.yml
index 9e820def7..1a46db04a 100644
--- a/vendor/github.com/mutecomm/go-sqlcipher/.travis.yml
+++ b/vendor/github.com/mutecomm/go-sqlcipher/.travis.yml
@@ -1,6 +1,7 @@
language: go
-go: 1.8
+go: 1.12
before_install:
- go get github.com/frankbraun/gocheck
+ - go get -t github.com/mutecomm/go-sqlcipher
script:
- gocheck -g -c -e _example -e sqlite3_test
diff --git a/vendor/github.com/mutecomm/go-sqlcipher/MAINTENANCE b/vendor/github.com/mutecomm/go-sqlcipher/MAINTENANCE
index 972ce0a7e..490f17f81 100644
--- a/vendor/github.com/mutecomm/go-sqlcipher/MAINTENANCE
+++ b/vendor/github.com/mutecomm/go-sqlcipher/MAINTENANCE
@@ -26,7 +26,7 @@ sqlite3_test/sqltest.go
Update code from https://github.com/sqlcipher/sqlcipher
-------------------------------------------------------
-Current release: v3.4.1
+Current release: v3.4.2
Execute:
./configure
diff --git a/vendor/github.com/mutecomm/go-sqlcipher/Makefile b/vendor/github.com/mutecomm/go-sqlcipher/Makefile
new file mode 100644
index 000000000..e734b30a6
--- /dev/null
+++ b/vendor/github.com/mutecomm/go-sqlcipher/Makefile
@@ -0,0 +1,8 @@
+.PHONY: all update-modules
+
+all:
+ env GO111MODULE=on go build -v . ./_example/simple/...
+
+update-modules:
+ env GO111MODULE=on go get -u
+ env GO111MODULE=on go mod tidy -v
diff --git a/vendor/github.com/mutecomm/go-sqlcipher/README.md b/vendor/github.com/mutecomm/go-sqlcipher/README.md
index e34ccfabf..0d79ab053 100644
--- a/vendor/github.com/mutecomm/go-sqlcipher/README.md
+++ b/vendor/github.com/mutecomm/go-sqlcipher/README.md
@@ -11,6 +11,8 @@ conforming to the built-in database/sql interface. It is based on:
SQLite itself is part of SQLCipher.
+go-sqlcipher currently only supports the SQLCipher 3.x releases.
+
### Installation
diff --git a/vendor/github.com/mutecomm/go-sqlcipher/go.mod b/vendor/github.com/mutecomm/go-sqlcipher/go.mod
new file mode 100644
index 000000000..4e1b6e61e
--- /dev/null
+++ b/vendor/github.com/mutecomm/go-sqlcipher/go.mod
@@ -0,0 +1,9 @@
+module github.com/mutecomm/go-sqlcipher
+
+go 1.12
+
+require (
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/stretchr/testify v1.3.0
+ golang.org/x/net v0.0.0-20190225153610-fe579d43d832
+)
diff --git a/vendor/github.com/mutecomm/go-sqlcipher/go.sum b/vendor/github.com/mutecomm/go-sqlcipher/go.sum
new file mode 100644
index 000000000..ad18f81b2
--- /dev/null
+++ b/vendor/github.com/mutecomm/go-sqlcipher/go.sum
@@ -0,0 +1,11 @@
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+golang.org/x/net v0.0.0-20190225153610-fe579d43d832 h1:2IdId8zoI92l1bUzjAOygcAOkmCe13HY1j0rqPPPzB8=
+golang.org/x/net v0.0.0-20190225153610-fe579d43d832/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
diff --git a/vendor/github.com/mutecomm/go-sqlcipher/sqlite3.c b/vendor/github.com/mutecomm/go-sqlcipher/sqlite3.c
index 3aee1fb5a..cc40a9f4e 100644
--- a/vendor/github.com/mutecomm/go-sqlcipher/sqlite3.c
+++ b/vendor/github.com/mutecomm/go-sqlcipher/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.15.2. By combining all the individual C code files into this
+** version 3.20.1. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -22,6 +22,758 @@
#ifndef SQLITE_PRIVATE
# define SQLITE_PRIVATE static
#endif
+/************** Begin file ctime.c *******************************************/
+/*
+** 2010 February 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 implements routines used to report what compile-time options
+** SQLite was built with.
+*/
+
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+
+/*
+** Include the configuration header output by 'configure' if we're using the
+** autoconf-based build
+*/
+#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
+#include "config.h"
+#define SQLITECONFIG_H 1
+#endif
+
+/* These macros are provided to "stringify" the value of the define
+** for those options in which the value is meaningful. */
+#define CTIMEOPT_VAL_(opt) #opt
+#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
+
+/*
+** An array of names of all compile-time options. This array should
+** be sorted A-Z.
+**
+** This array looks large, but in a typical installation actually uses
+** only a handful of compile-time options, so most times this array is usually
+** rather short and uses little memory space.
+*/
+static const char * const sqlite3azCompileOpt[] = {
+
+/*
+** BEGIN CODE GENERATED BY tool/mkctime.tcl
+*/
+#if SQLITE_32BIT_ROWID
+ "32BIT_ROWID",
+#endif
+#if SQLITE_4_BYTE_ALIGNED_MALLOC
+ "4_BYTE_ALIGNED_MALLOC",
+#endif
+#if SQLITE_64BIT_STATS
+ "64BIT_STATS",
+#endif
+#if SQLITE_ALLOW_COVERING_INDEX_SCAN
+ "ALLOW_COVERING_INDEX_SCAN",
+#endif
+#if SQLITE_ALLOW_URI_AUTHORITY
+ "ALLOW_URI_AUTHORITY",
+#endif
+#ifdef SQLITE_BITMASK_TYPE
+ "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
+#endif
+#if SQLITE_BUG_COMPATIBLE_20160819
+ "BUG_COMPATIBLE_20160819",
+#endif
+#if SQLITE_CASE_SENSITIVE_LIKE
+ "CASE_SENSITIVE_LIKE",
+#endif
+#if SQLITE_CHECK_PAGES
+ "CHECK_PAGES",
+#endif
+#if defined(__clang__) && defined(__clang_major__)
+ "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
+ CTIMEOPT_VAL(__clang_minor__) "."
+ CTIMEOPT_VAL(__clang_patchlevel__),
+#elif defined(_MSC_VER)
+ "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
+#elif defined(__GNUC__) && defined(__VERSION__)
+ "COMPILER=gcc-" __VERSION__,
+#endif
+#if SQLITE_COVERAGE_TEST
+ "COVERAGE_TEST",
+#endif
+#if SQLITE_DEBUG
+ "DEBUG",
+#endif
+#if SQLITE_DEFAULT_AUTOMATIC_INDEX
+ "DEFAULT_AUTOMATIC_INDEX",
+#endif
+#if SQLITE_DEFAULT_AUTOVACUUM
+ "DEFAULT_AUTOVACUUM",
+#endif
+#ifdef SQLITE_DEFAULT_CACHE_SIZE
+ "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
+#endif
+#if SQLITE_DEFAULT_CKPTFULLFSYNC
+ "DEFAULT_CKPTFULLFSYNC",
+#endif
+#ifdef SQLITE_DEFAULT_FILE_FORMAT
+ "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT),
+#endif
+#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
+ "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
+#endif
+#if SQLITE_DEFAULT_FOREIGN_KEYS
+ "DEFAULT_FOREIGN_KEYS",
+#endif
+#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
+ "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT),
+#endif
+#ifdef SQLITE_DEFAULT_LOCKING_MODE
+ "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
+#endif
+#ifdef SQLITE_DEFAULT_LOOKASIDE
+ "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOOKASIDE),
+#endif
+#if SQLITE_DEFAULT_MEMSTATUS
+ "DEFAULT_MEMSTATUS",
+#endif
+#ifdef SQLITE_DEFAULT_MMAP_SIZE
+ "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
+#endif
+#ifdef SQLITE_DEFAULT_PAGE_SIZE
+ "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
+#endif
+#ifdef SQLITE_DEFAULT_PCACHE_INITSZ
+ "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ),
+#endif
+#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
+ "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
+#endif
+#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS
+ "DEFAULT_RECURSIVE_TRIGGERS",
+#endif
+#ifdef SQLITE_DEFAULT_ROWEST
+ "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST),
+#endif
+#ifdef SQLITE_DEFAULT_SECTOR_SIZE
+ "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE),
+#endif
+#ifdef SQLITE_DEFAULT_SYNCHRONOUS
+ "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
+#endif
+#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
+ "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT),
+#endif
+#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS
+ "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
+#endif
+#ifdef SQLITE_DEFAULT_WORKER_THREADS
+ "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
+#endif
+#if SQLITE_DIRECT_OVERFLOW_READ
+ "DIRECT_OVERFLOW_READ",
+#endif
+#if SQLITE_DISABLE_DIRSYNC
+ "DISABLE_DIRSYNC",
+#endif
+#if SQLITE_DISABLE_FTS3_UNICODE
+ "DISABLE_FTS3_UNICODE",
+#endif
+#if SQLITE_DISABLE_FTS4_DEFERRED
+ "DISABLE_FTS4_DEFERRED",
+#endif
+#if SQLITE_DISABLE_INTRINSIC
+ "DISABLE_INTRINSIC",
+#endif
+#if SQLITE_DISABLE_LFS
+ "DISABLE_LFS",
+#endif
+#if SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
+ "DISABLE_PAGECACHE_OVERFLOW_STATS",
+#endif
+#if SQLITE_DISABLE_SKIPAHEAD_DISTINCT
+ "DISABLE_SKIPAHEAD_DISTINCT",
+#endif
+#ifdef SQLITE_ENABLE_8_3_NAMES
+ "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
+#endif
+#if SQLITE_ENABLE_API_ARMOR
+ "ENABLE_API_ARMOR",
+#endif
+#if SQLITE_ENABLE_ATOMIC_WRITE
+ "ENABLE_ATOMIC_WRITE",
+#endif
+#if SQLITE_ENABLE_CEROD
+ "ENABLE_CEROD",
+#endif
+#if SQLITE_ENABLE_COLUMN_METADATA
+ "ENABLE_COLUMN_METADATA",
+#endif
+#if SQLITE_ENABLE_COLUMN_USED_MASK
+ "ENABLE_COLUMN_USED_MASK",
+#endif
+#if SQLITE_ENABLE_COSTMULT
+ "ENABLE_COSTMULT",
+#endif
+#if SQLITE_ENABLE_CURSOR_HINTS
+ "ENABLE_CURSOR_HINTS",
+#endif
+#if SQLITE_ENABLE_DBSTAT_VTAB
+ "ENABLE_DBSTAT_VTAB",
+#endif
+#if SQLITE_ENABLE_EXPENSIVE_ASSERT
+ "ENABLE_EXPENSIVE_ASSERT",
+#endif
+#if SQLITE_ENABLE_FTS1
+ "ENABLE_FTS1",
+#endif
+#if SQLITE_ENABLE_FTS2
+ "ENABLE_FTS2",
+#endif
+#if SQLITE_ENABLE_FTS3
+ "ENABLE_FTS3",
+#endif
+#if SQLITE_ENABLE_FTS3_PARENTHESIS
+ "ENABLE_FTS3_PARENTHESIS",
+#endif
+#if SQLITE_ENABLE_FTS3_TOKENIZER
+ "ENABLE_FTS3_TOKENIZER",
+#endif
+#if SQLITE_ENABLE_FTS4
+ "ENABLE_FTS4",
+#endif
+#if SQLITE_ENABLE_FTS5
+ "ENABLE_FTS5",
+#endif
+#if SQLITE_ENABLE_HIDDEN_COLUMNS
+ "ENABLE_HIDDEN_COLUMNS",
+#endif
+#if SQLITE_ENABLE_ICU
+ "ENABLE_ICU",
+#endif
+#if SQLITE_ENABLE_IOTRACE
+ "ENABLE_IOTRACE",
+#endif
+#if SQLITE_ENABLE_JSON1
+ "ENABLE_JSON1",
+#endif
+#if SQLITE_ENABLE_LOAD_EXTENSION
+ "ENABLE_LOAD_EXTENSION",
+#endif
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
+ "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
+#endif
+#if SQLITE_ENABLE_MEMORY_MANAGEMENT
+ "ENABLE_MEMORY_MANAGEMENT",
+#endif
+#if SQLITE_ENABLE_MEMSYS3
+ "ENABLE_MEMSYS3",
+#endif
+#if SQLITE_ENABLE_MEMSYS5
+ "ENABLE_MEMSYS5",
+#endif
+#if SQLITE_ENABLE_MULTIPLEX
+ "ENABLE_MULTIPLEX",
+#endif
+#if SQLITE_ENABLE_NULL_TRIM
+ "ENABLE_NULL_TRIM",
+#endif
+#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
+ "ENABLE_OVERSIZE_CELL_CHECK",
+#endif
+#if SQLITE_ENABLE_PREUPDATE_HOOK
+ "ENABLE_PREUPDATE_HOOK",
+#endif
+#if SQLITE_ENABLE_QPSG
+ "ENABLE_QPSG",
+#endif
+#if SQLITE_ENABLE_RBU
+ "ENABLE_RBU",
+#endif
+#if SQLITE_ENABLE_RTREE
+ "ENABLE_RTREE",
+#endif
+#if SQLITE_ENABLE_SELECTTRACE
+ "ENABLE_SELECTTRACE",
+#endif
+#if SQLITE_ENABLE_SESSION
+ "ENABLE_SESSION",
+#endif
+#if SQLITE_ENABLE_SNAPSHOT
+ "ENABLE_SNAPSHOT",
+#endif
+#if SQLITE_ENABLE_SQLLOG
+ "ENABLE_SQLLOG",
+#endif
+#if defined(SQLITE_ENABLE_STAT4)
+ "ENABLE_STAT4",
+#elif defined(SQLITE_ENABLE_STAT3)
+ "ENABLE_STAT3",
+#endif
+#if SQLITE_ENABLE_STMTVTAB
+ "ENABLE_STMTVTAB",
+#endif
+#if SQLITE_ENABLE_STMT_SCANSTATUS
+ "ENABLE_STMT_SCANSTATUS",
+#endif
+#if SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
+ "ENABLE_UNKNOWN_SQL_FUNCTION",
+#endif
+#if SQLITE_ENABLE_UNLOCK_NOTIFY
+ "ENABLE_UNLOCK_NOTIFY",
+#endif
+#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
+ "ENABLE_UPDATE_DELETE_LIMIT",
+#endif
+#if SQLITE_ENABLE_URI_00_ERROR
+ "ENABLE_URI_00_ERROR",
+#endif
+#if SQLITE_ENABLE_VFSTRACE
+ "ENABLE_VFSTRACE",
+#endif
+#if SQLITE_ENABLE_WHERETRACE
+ "ENABLE_WHERETRACE",
+#endif
+#if SQLITE_ENABLE_ZIPVFS
+ "ENABLE_ZIPVFS",
+#endif
+#if SQLITE_EXPLAIN_ESTIMATED_ROWS
+ "EXPLAIN_ESTIMATED_ROWS",
+#endif
+#if SQLITE_EXTRA_IFNULLROW
+ "EXTRA_IFNULLROW",
+#endif
+#ifdef SQLITE_EXTRA_INIT
+ "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
+#endif
+#ifdef SQLITE_EXTRA_SHUTDOWN
+ "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
+#endif
+#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
+ "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
+#endif
+#if SQLITE_FTS5_ENABLE_TEST_MI
+ "FTS5_ENABLE_TEST_MI",
+#endif
+#if SQLITE_FTS5_NO_WITHOUT_ROWID
+ "FTS5_NO_WITHOUT_ROWID",
+#endif
+#if SQLITE_HAS_CODEC
+ "HAS_CODEC",
+#endif
+#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
+ "HAVE_ISNAN",
+#endif
+#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+ "HOMEGROWN_RECURSIVE_MUTEX",
+#endif
+#if SQLITE_IGNORE_AFP_LOCK_ERRORS
+ "IGNORE_AFP_LOCK_ERRORS",
+#endif
+#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+ "IGNORE_FLOCK_LOCK_ERRORS",
+#endif
+#if SQLITE_INLINE_MEMCPY
+ "INLINE_MEMCPY",
+#endif
+#if SQLITE_INT64_TYPE
+ "INT64_TYPE",
+#endif
+#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
+ "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
+#endif
+#if SQLITE_LIKE_DOESNT_MATCH_BLOBS
+ "LIKE_DOESNT_MATCH_BLOBS",
+#endif
+#if SQLITE_LOCK_TRACE
+ "LOCK_TRACE",
+#endif
+#if SQLITE_LOG_CACHE_SPILL
+ "LOG_CACHE_SPILL",
+#endif
+#ifdef SQLITE_MALLOC_SOFT_LIMIT
+ "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT),
+#endif
+#ifdef SQLITE_MAX_ATTACHED
+ "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED),
+#endif
+#ifdef SQLITE_MAX_COLUMN
+ "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN),
+#endif
+#ifdef SQLITE_MAX_COMPOUND_SELECT
+ "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT),
+#endif
+#ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE
+ "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE),
+#endif
+#ifdef SQLITE_MAX_EXPR_DEPTH
+ "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH),
+#endif
+#ifdef SQLITE_MAX_FUNCTION_ARG
+ "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG),
+#endif
+#ifdef SQLITE_MAX_LENGTH
+ "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH),
+#endif
+#ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH
+ "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH),
+#endif
+#ifdef SQLITE_MAX_MEMORY
+ "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY),
+#endif
+#ifdef SQLITE_MAX_MMAP_SIZE
+ "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
+#endif
+#ifdef SQLITE_MAX_MMAP_SIZE_
+ "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_),
+#endif
+#ifdef SQLITE_MAX_PAGE_COUNT
+ "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT),
+#endif
+#ifdef SQLITE_MAX_PAGE_SIZE
+ "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE),
+#endif
+#ifdef SQLITE_MAX_SCHEMA_RETRY
+ "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
+#endif
+#ifdef SQLITE_MAX_SQL_LENGTH
+ "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH),
+#endif
+#ifdef SQLITE_MAX_TRIGGER_DEPTH
+ "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH),
+#endif
+#ifdef SQLITE_MAX_VARIABLE_NUMBER
+ "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER),
+#endif
+#ifdef SQLITE_MAX_VDBE_OP
+ "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP),
+#endif
+#ifdef SQLITE_MAX_WORKER_THREADS
+ "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
+#endif
+#if SQLITE_MEMDEBUG
+ "MEMDEBUG",
+#endif
+#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
+ "MIXED_ENDIAN_64BIT_FLOAT",
+#endif
+#if SQLITE_MMAP_READWRITE
+ "MMAP_READWRITE",
+#endif
+#if SQLITE_MUTEX_NOOP
+ "MUTEX_NOOP",
+#endif
+#if SQLITE_MUTEX_NREF
+ "MUTEX_NREF",
+#endif
+#if SQLITE_MUTEX_OMIT
+ "MUTEX_OMIT",
+#endif
+#if SQLITE_MUTEX_PTHREADS
+ "MUTEX_PTHREADS",
+#endif
+#if SQLITE_MUTEX_W32
+ "MUTEX_W32",
+#endif
+#if SQLITE_NEED_ERR_NAME
+ "NEED_ERR_NAME",
+#endif
+#if SQLITE_NOINLINE
+ "NOINLINE",
+#endif
+#if SQLITE_NO_SYNC
+ "NO_SYNC",
+#endif
+#if SQLITE_OMIT_ALTERTABLE
+ "OMIT_ALTERTABLE",
+#endif
+#if SQLITE_OMIT_ANALYZE
+ "OMIT_ANALYZE",
+#endif
+#if SQLITE_OMIT_ATTACH
+ "OMIT_ATTACH",
+#endif
+#if SQLITE_OMIT_AUTHORIZATION
+ "OMIT_AUTHORIZATION",
+#endif
+#if SQLITE_OMIT_AUTOINCREMENT
+ "OMIT_AUTOINCREMENT",
+#endif
+#if SQLITE_OMIT_AUTOINIT
+ "OMIT_AUTOINIT",
+#endif
+#if SQLITE_OMIT_AUTOMATIC_INDEX
+ "OMIT_AUTOMATIC_INDEX",
+#endif
+#if SQLITE_OMIT_AUTORESET
+ "OMIT_AUTORESET",
+#endif
+#if SQLITE_OMIT_AUTOVACUUM
+ "OMIT_AUTOVACUUM",
+#endif
+#if SQLITE_OMIT_BETWEEN_OPTIMIZATION
+ "OMIT_BETWEEN_OPTIMIZATION",
+#endif
+#if SQLITE_OMIT_BLOB_LITERAL
+ "OMIT_BLOB_LITERAL",
+#endif
+#if SQLITE_OMIT_BTREECOUNT
+ "OMIT_BTREECOUNT",
+#endif
+#if SQLITE_OMIT_CAST
+ "OMIT_CAST",
+#endif
+#if SQLITE_OMIT_CHECK
+ "OMIT_CHECK",
+#endif
+#if SQLITE_OMIT_COMPLETE
+ "OMIT_COMPLETE",
+#endif
+#if SQLITE_OMIT_COMPOUND_SELECT
+ "OMIT_COMPOUND_SELECT",
+#endif
+#if SQLITE_OMIT_CONFLICT_CLAUSE
+ "OMIT_CONFLICT_CLAUSE",
+#endif
+#if SQLITE_OMIT_CTE
+ "OMIT_CTE",
+#endif
+#if SQLITE_OMIT_DATETIME_FUNCS
+ "OMIT_DATETIME_FUNCS",
+#endif
+#if SQLITE_OMIT_DECLTYPE
+ "OMIT_DECLTYPE",
+#endif
+#if SQLITE_OMIT_DEPRECATED
+ "OMIT_DEPRECATED",
+#endif
+#if SQLITE_OMIT_DISKIO
+ "OMIT_DISKIO",
+#endif
+#if SQLITE_OMIT_EXPLAIN
+ "OMIT_EXPLAIN",
+#endif
+#if SQLITE_OMIT_FLAG_PRAGMAS
+ "OMIT_FLAG_PRAGMAS",
+#endif
+#if SQLITE_OMIT_FLOATING_POINT
+ "OMIT_FLOATING_POINT",
+#endif
+#if SQLITE_OMIT_FOREIGN_KEY
+ "OMIT_FOREIGN_KEY",
+#endif
+#if SQLITE_OMIT_GET_TABLE
+ "OMIT_GET_TABLE",
+#endif
+#if SQLITE_OMIT_HEX_INTEGER
+ "OMIT_HEX_INTEGER",
+#endif
+#if SQLITE_OMIT_INCRBLOB
+ "OMIT_INCRBLOB",
+#endif
+#if SQLITE_OMIT_INTEGRITY_CHECK
+ "OMIT_INTEGRITY_CHECK",
+#endif
+#if SQLITE_OMIT_LIKE_OPTIMIZATION
+ "OMIT_LIKE_OPTIMIZATION",
+#endif
+#if SQLITE_OMIT_LOAD_EXTENSION
+ "OMIT_LOAD_EXTENSION",
+#endif
+#if SQLITE_OMIT_LOCALTIME
+ "OMIT_LOCALTIME",
+#endif
+#if SQLITE_OMIT_LOOKASIDE
+ "OMIT_LOOKASIDE",
+#endif
+#if SQLITE_OMIT_MEMORYDB
+ "OMIT_MEMORYDB",
+#endif
+#if SQLITE_OMIT_OR_OPTIMIZATION
+ "OMIT_OR_OPTIMIZATION",
+#endif
+#if SQLITE_OMIT_PAGER_PRAGMAS
+ "OMIT_PAGER_PRAGMAS",
+#endif
+#if SQLITE_OMIT_PARSER_TRACE
+ "OMIT_PARSER_TRACE",
+#endif
+#if SQLITE_OMIT_POPEN
+ "OMIT_POPEN",
+#endif
+#if SQLITE_OMIT_PRAGMA
+ "OMIT_PRAGMA",
+#endif
+#if SQLITE_OMIT_PROGRESS_CALLBACK
+ "OMIT_PROGRESS_CALLBACK",
+#endif
+#if SQLITE_OMIT_QUICKBALANCE
+ "OMIT_QUICKBALANCE",
+#endif
+#if SQLITE_OMIT_REINDEX
+ "OMIT_REINDEX",
+#endif
+#if SQLITE_OMIT_SCHEMA_PRAGMAS
+ "OMIT_SCHEMA_PRAGMAS",
+#endif
+#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
+ "OMIT_SCHEMA_VERSION_PRAGMAS",
+#endif
+#if SQLITE_OMIT_SHARED_CACHE
+ "OMIT_SHARED_CACHE",
+#endif
+#if SQLITE_OMIT_SHUTDOWN_DIRECTORIES
+ "OMIT_SHUTDOWN_DIRECTORIES",
+#endif
+#if SQLITE_OMIT_SUBQUERY
+ "OMIT_SUBQUERY",
+#endif
+#if SQLITE_OMIT_TCL_VARIABLE
+ "OMIT_TCL_VARIABLE",
+#endif
+#if SQLITE_OMIT_TEMPDB
+ "OMIT_TEMPDB",
+#endif
+#if SQLITE_OMIT_TEST_CONTROL
+ "OMIT_TEST_CONTROL",
+#endif
+#if SQLITE_OMIT_TRACE
+ "OMIT_TRACE",
+#endif
+#if SQLITE_OMIT_TRIGGER
+ "OMIT_TRIGGER",
+#endif
+#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
+ "OMIT_TRUNCATE_OPTIMIZATION",
+#endif
+#if SQLITE_OMIT_UTF16
+ "OMIT_UTF16",
+#endif
+#if SQLITE_OMIT_VACUUM
+ "OMIT_VACUUM",
+#endif
+#if SQLITE_OMIT_VIEW
+ "OMIT_VIEW",
+#endif
+#if SQLITE_OMIT_VIRTUALTABLE
+ "OMIT_VIRTUALTABLE",
+#endif
+#if SQLITE_OMIT_WAL
+ "OMIT_WAL",
+#endif
+#if SQLITE_OMIT_WSD
+ "OMIT_WSD",
+#endif
+#if SQLITE_OMIT_XFER_OPT
+ "OMIT_XFER_OPT",
+#endif
+#if SQLITE_PCACHE_SEPARATE_HEADER
+ "PCACHE_SEPARATE_HEADER",
+#endif
+#if SQLITE_PERFORMANCE_TRACE
+ "PERFORMANCE_TRACE",
+#endif
+#if SQLITE_POWERSAFE_OVERWRITE
+ "POWERSAFE_OVERWRITE",
+#endif
+#if SQLITE_PREFER_PROXY_LOCKING
+ "PREFER_PROXY_LOCKING",
+#endif
+#if SQLITE_PROXY_DEBUG
+ "PROXY_DEBUG",
+#endif
+#if SQLITE_REVERSE_UNORDERED_SELECTS
+ "REVERSE_UNORDERED_SELECTS",
+#endif
+#if SQLITE_RTREE_INT_ONLY
+ "RTREE_INT_ONLY",
+#endif
+#if SQLITE_SECURE_DELETE
+ "SECURE_DELETE",
+#endif
+#if SQLITE_SMALL_STACK
+ "SMALL_STACK",
+#endif
+#ifdef SQLITE_SORTER_PMASZ
+ "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
+#endif
+#if SQLITE_SOUNDEX
+ "SOUNDEX",
+#endif
+#ifdef SQLITE_STAT4_SAMPLES
+ "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES),
+#endif
+#ifdef SQLITE_STMTJRNL_SPILL
+ "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
+#endif
+#if SQLITE_SUBSTR_COMPATIBILITY
+ "SUBSTR_COMPATIBILITY",
+#endif
+#if SQLITE_SYSTEM_MALLOC
+ "SYSTEM_MALLOC",
+#endif
+#if SQLITE_TCL
+ "TCL",
+#endif
+#ifdef SQLITE_TEMP_STORE
+ "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
+#endif
+#if SQLITE_TEST
+ "TEST",
+#endif
+#if defined(SQLITE_THREADSAFE)
+ "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
+#elif defined(THREADSAFE)
+ "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
+#else
+ "THREADSAFE=1",
+#endif
+#if SQLITE_UNLINK_AFTER_CLOSE
+ "UNLINK_AFTER_CLOSE",
+#endif
+#if SQLITE_UNTESTABLE
+ "UNTESTABLE",
+#endif
+#if SQLITE_USER_AUTHENTICATION
+ "USER_AUTHENTICATION",
+#endif
+#if SQLITE_USE_ALLOCA
+ "USE_ALLOCA",
+#endif
+#if SQLITE_USE_FCNTL_TRACE
+ "USE_FCNTL_TRACE",
+#endif
+#if SQLITE_USE_URI
+ "USE_URI",
+#endif
+#if SQLITE_VDBE_COVERAGE
+ "VDBE_COVERAGE",
+#endif
+#if SQLITE_WIN32_MALLOC
+ "WIN32_MALLOC",
+#endif
+#if SQLITE_ZERO_MALLOC
+ "ZERO_MALLOC",
+#endif
+/*
+** END CODE GENERATED BY tool/mkctime.tcl
+*/
+};
+
+SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){
+ *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]);
+ return (const char**)sqlite3azCompileOpt;
+}
+
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
+
+/************** End of ctime.c ***********************************************/
/************** Begin file sqliteInt.h ***************************************/
/*
** 2001 September 15
@@ -204,12 +956,29 @@
# define _LARGEFILE_SOURCE 1
#endif
-/* What version of GCC is being used. 0 means GCC is not being used */
-#ifdef __GNUC__
+/* The GCC_VERSION and MSVC_VERSION macros are used to
+** conditionally include optimizations for each of these compilers. A
+** value of 0 means that compiler is not being used. The
+** SQLITE_DISABLE_INTRINSIC macro means do not use any compiler-specific
+** optimizations, and hence set all compiler macros to 0
+**
+** There was once also a CLANG_VERSION macro. However, we learn that the
+** version numbers in clang are for "marketing" only and are inconsistent
+** and unreliable. Fortunately, all versions of clang also recognize the
+** gcc version numbers and have reasonable settings for gcc version numbers,
+** so the GCC_VERSION macro will be set to a correct non-zero value even
+** when compiling with clang.
+*/
+#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
#else
# define GCC_VERSION 0
#endif
+#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC)
+# define MSVC_VERSION _MSC_VER
+#else
+# define MSVC_VERSION 0
+#endif
/* Needed for various definitions... */
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
@@ -259,7 +1028,7 @@
/************** Include sqlite3.h in the middle of sqliteInt.h ***************/
/************** Begin file sqlite3.h *****************************************/
/*
-** 2001 September 15
+** 2001-09-15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -374,20 +1143,20 @@ extern "C" {
** system. ^The SQLITE_SOURCE_ID macro evaluates to
** a string which identifies a particular check-in of SQLite
** within its configuration management system. ^The SQLITE_SOURCE_ID
-** string contains the date and time of the check-in (UTC) and an SHA1
-** hash of the entire source tree.
+** string contains the date and time of the check-in (UTC) and a SHA1
+** or SHA3-256 hash of the entire source tree.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.15.2"
-#define SQLITE_VERSION_NUMBER 3015002
-#define SQLITE_SOURCE_ID "2016-11-28 19:13:37 bbd85d235f7037c6a033a9690534391ffeacecc8"
+#define SQLITE_VERSION "3.20.1"
+#define SQLITE_VERSION_NUMBER 3020001
+#define SQLITE_SOURCE_ID "2017-08-24 16:21:36 8d3a7ea6c5690d6b7c3767558f4f01b511c55463e3f9e64506801fe9b74dce34"
/*
** CAPI3REF: Run-Time Library Version Numbers
-** KEYWORDS: sqlite3_version, sqlite3_sourceid
+** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
@@ -519,7 +1288,11 @@ typedef struct sqlite3 sqlite3;
*/
#ifdef SQLITE_INT64_TYPE
typedef SQLITE_INT64_TYPE sqlite_int64;
- typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
+# ifdef SQLITE_UINT64_TYPE
+ typedef SQLITE_UINT64_TYPE sqlite_uint64;
+# else
+ typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
+# endif
#elif defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 sqlite_int64;
typedef unsigned __int64 sqlite_uint64;
@@ -673,7 +1446,7 @@ SQLITE_API int sqlite3_exec(
*/
#define SQLITE_OK 0 /* Successful result */
/* beginning-of-error-codes */
-#define SQLITE_ERROR 1 /* SQL error or missing database */
+#define SQLITE_ERROR 1 /* Generic error */
#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
#define SQLITE_PERM 3 /* Access permission denied */
#define SQLITE_ABORT 4 /* Callback routine requested an abort */
@@ -688,7 +1461,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_FULL 13 /* Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
-#define SQLITE_EMPTY 16 /* Database is empty */
+#define SQLITE_EMPTY 16 /* Not used */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */
@@ -696,7 +1469,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_MISUSE 21 /* Library used incorrectly */
#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
#define SQLITE_AUTH 23 /* Authorization denied */
-#define SQLITE_FORMAT 24 /* Auxiliary database format error */
+#define SQLITE_FORMAT 24 /* Not used */
#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */
#define SQLITE_NOTADB 26 /* File opened that is not a database file */
#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */
@@ -832,7 +1605,7 @@ SQLITE_API int sqlite3_exec(
** file that were written at the application level might have changed
** and that adjacent bytes, even bytes within the same sector are
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
-** flag indicate that a file cannot be deleted when open. The
+** flag indicates that a file cannot be deleted when open. The
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
** read-only media and cannot be changed even by processes with
** elevated privileges.
@@ -982,6 +1755,9 @@ struct sqlite3_file {
**
[SQLITE_IOCAP_ATOMIC64K]
** [SQLITE_IOCAP_SAFE_APPEND]
** [SQLITE_IOCAP_SEQUENTIAL]
+** [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN]
+** [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
+** [SQLITE_IOCAP_IMMUTABLE]
**
**
** The SQLITE_IOCAP_ATOMIC property means that all writes of
@@ -1110,7 +1886,7 @@ struct sqlite3_io_methods {
** opcode allows these two values (10 retries and 25 milliseconds of delay)
** to be adjusted. The values are changed for all database connections
** within the same process. The argument is a pointer to an array of two
-** integers where the first integer i the new retry count and the second
+** integers where the first integer is the new retry count and the second
** integer is the delay. If either integer is negative, then the setting
** is not changed but instead the prior value of that setting is written
** into the array entry, allowing the current retry settings to be
@@ -1295,6 +2071,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_VFS_POINTER 27
#define SQLITE_FCNTL_JOURNAL_POINTER 28
#define SQLITE_FCNTL_WIN32_GET_HANDLE 29
+#define SQLITE_FCNTL_PDB 30
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -2247,6 +3024,29 @@ struct sqlite3_mem_methods {
** until after the database connection closes.
**
**
+** SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
+** Usually, when a database in wal mode is closed or detached from a
+** database handle, SQLite checks if this will mean that there are now no
+** connections at all to the database. If so, it performs a checkpoint
+** operation before closing the connection. This option may be used to
+** override this behaviour. The first parameter passed to this operation
+** is an integer - non-zero to disable checkpoints-on-close, or zero (the
+** default) to enable them. The second parameter is a pointer to an integer
+** into which is written 0 or 1 to indicate whether checkpoints-on-close
+** have been disabled - 0 if they are not disabled, 1 if they are.
+**
+**
+** SQLITE_DBCONFIG_ENABLE_QPSG
+** ^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
+** the [query planner stability guarantee] (QPSG). When the QPSG is active,
+** a single SQL query statement will always use the same algorithm regardless
+** of values of [bound parameters].)^ The QPSG disables some query optimizations
+** that look at the values of bound parameters, which can make some queries
+** slower. But the QPSG has the advantage of more predictable behavior. With
+** the QPSG active, SQLite will always use the same query plan in the field as
+** was used during testing in the lab.
+**
+**
**
*/
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
@@ -2255,6 +3055,8 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
+#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
+#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
/*
@@ -2279,20 +3081,30 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
** the table has a column of type [INTEGER PRIMARY KEY] then that column
** is another alias for the rowid.
**
-** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the
-** most recent successful [INSERT] into a rowid table or [virtual table]
-** on database connection D.
-** ^Inserts into [WITHOUT ROWID] tables are not recorded.
-** ^If no successful [INSERT]s into rowid tables
-** have ever occurred on the database connection D,
-** then sqlite3_last_insert_rowid(D) returns zero.
+** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of
+** the most recent successful [INSERT] into a rowid table or [virtual table]
+** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not
+** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred
+** on the database connection D, then sqlite3_last_insert_rowid(D) returns
+** zero.
**
-** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
-** method, then this routine will return the [rowid] of the inserted
-** row as long as the trigger or virtual table method is running.
-** But once the trigger or virtual table method ends, the value returned
-** by this routine reverts to what it was before the trigger or virtual
-** table method began.)^
+** As well as being set automatically as rows are inserted into database
+** tables, the value returned by this function may be set explicitly by
+** [sqlite3_set_last_insert_rowid()]
+**
+** Some virtual table implementations may INSERT rows into rowid tables as
+** part of committing a transaction (e.g. to flush data accumulated in memory
+** to disk). In this case subsequent calls to this function return the rowid
+** associated with these internal INSERT operations, which leads to
+** unintuitive results. Virtual table implementations that do write to rowid
+** tables in this way can avoid this problem by restoring the original
+** rowid value using [sqlite3_set_last_insert_rowid()] before returning
+** control to the user.
+**
+** ^(If an [INSERT] occurs within a trigger then this routine will
+** return the [rowid] of the inserted row as long as the trigger is
+** running. Once the trigger program ends, the value returned
+** by this routine reverts to what it was before the trigger was fired.)^
**
** ^An [INSERT] that fails due to a constraint violation is not a
** successful [INSERT] and does not change the value returned by this
@@ -2319,6 +3131,16 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
*/
SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
+/*
+** CAPI3REF: Set the Last Insert Rowid value.
+** METHOD: sqlite3
+**
+** The sqlite3_set_last_insert_rowid(D, R) method allows the application to
+** set the value returned by calling sqlite3_last_insert_rowid(D) to R
+** without inserting a row into the database.
+*/
+SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
+
/*
** CAPI3REF: Count The Number Of Rows Modified
** METHOD: sqlite3
@@ -2430,9 +3252,6 @@ SQLITE_API int sqlite3_total_changes(sqlite3*);
** ^A call to sqlite3_interrupt(D) that occurs when there are no running
** SQL statements is a no-op and has no effect on SQL statements
** that are started after the sqlite3_interrupt() call returns.
-**
-** If the database connection closes while [sqlite3_interrupt()]
-** is running then bad things will likely happen.
*/
SQLITE_API void sqlite3_interrupt(sqlite3*);
@@ -2895,12 +3714,14 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
/*
** CAPI3REF: Compile-Time Authorization Callbacks
** METHOD: sqlite3
+** KEYWORDS: {authorizer callback}
**
** ^This routine registers an authorizer callback with a particular
** [database connection], supplied in the first argument.
** ^The authorizer callback is invoked as SQL statements are being compiled
** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()],
-** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. ^At various
+** [sqlite3_prepare_v3()], [sqlite3_prepare16()], [sqlite3_prepare16_v2()],
+** and [sqlite3_prepare16_v3()]. ^At various
** points during the compilation process, as logic is being created
** to perform various actions, the authorizer callback is invoked to
** see if those actions are allowed. ^The authorizer callback should
@@ -2922,8 +3743,10 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** parameter to the sqlite3_set_authorizer() interface. ^The second parameter
** to the callback is an integer [SQLITE_COPY | action code] that specifies
** the particular action to be authorized. ^The third through sixth parameters
-** to the callback are zero-terminated strings that contain additional
-** details about the action to be authorized.
+** to the callback are either NULL pointers or zero-terminated strings
+** that contain additional details about the action to be authorized.
+** Applications must always be prepared to encounter a NULL pointer in any
+** of the third through the sixth parameters of the authorization callback.
**
** ^If the action code is [SQLITE_READ]
** and the callback returns [SQLITE_IGNORE] then the
@@ -2932,6 +3755,10 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE]
** return can be used to deny an untrusted user access to individual
** columns of a table.
+** ^When a table is referenced by a [SELECT] but no column values are
+** extracted from that table (for example in a query like
+** "SELECT count(*) FROM tab") then the [SQLITE_READ] authorizer callback
+** is invoked once for that table with a column name that is an empty string.
** ^If the action code is [SQLITE_DELETE] and the callback returns
** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the
** [truncate optimization] is disabled and all rows are deleted individually.
@@ -3643,9 +4470,9 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
**
** [[SQLITE_LIMIT_VDBE_OP]] ^(SQLITE_LIMIT_VDBE_OP
** The maximum number of instructions in a virtual machine program
-** used to implement an SQL statement. This limit is not currently
-** enforced, though that might be added in some future release of
-** SQLite.)^
+** used to implement an SQL statement. If [sqlite3_prepare_v2()] or
+** the equivalent tries to allocate space for more than this many opcodes
+** in a single prepared statement, an SQLITE_NOMEM error is returned.)^
**
** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(SQLITE_LIMIT_FUNCTION_ARG
** The maximum number of arguments on a function.)^
@@ -3683,23 +4510,59 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
#define SQLITE_LIMIT_TRIGGER_DEPTH 10
#define SQLITE_LIMIT_WORKER_THREADS 11
+/*
+** CAPI3REF: Prepare Flags
+**
+** These constants define various flags that can be passed into
+** "prepFlags" parameter of the [sqlite3_prepare_v3()] and
+** [sqlite3_prepare16_v3()] interfaces.
+**
+** New flags may be added in future releases of SQLite.
+**
+**
+** [[SQLITE_PREPARE_PERSISTENT]] ^(- SQLITE_PREPARE_PERSISTENT
+** - The SQLITE_PREPARE_PERSISTENT flag is a hint to the query planner
+** that the prepared statement will be retained for a long time and
+** probably reused many times.)^ ^Without this flag, [sqlite3_prepare_v3()]
+** and [sqlite3_prepare16_v3()] assume that the prepared statement will
+** be used just once or at most a few times and then destroyed using
+** [sqlite3_finalize()] relatively soon. The current implementation acts
+** on this hint by avoiding the use of [lookaside memory] so as not to
+** deplete the limited store of lookaside memory. Future versions of
+** SQLite may act on this hint differently.
+**
+*/
+#define SQLITE_PREPARE_PERSISTENT 0x01
+
/*
** CAPI3REF: Compiling An SQL Statement
** KEYWORDS: {SQL statement compiler}
** METHOD: sqlite3
** CONSTRUCTOR: sqlite3_stmt
**
-** To execute an SQL query, it must first be compiled into a byte-code
-** program using one of these routines.
+** To execute an SQL statement, it must first be compiled into a byte-code
+** program using one of these routines. Or, in other words, these routines
+** are constructors for the [prepared statement] object.
+**
+** The preferred routine to use is [sqlite3_prepare_v2()]. The
+** [sqlite3_prepare()] interface is legacy and should be avoided.
+** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used
+** for special purposes.
+**
+** The use of the UTF-8 interfaces is preferred, as SQLite currently
+** does all parsing using UTF-8. The UTF-16 interfaces are provided
+** as a convenience. The UTF-16 interfaces work by converting the
+** input text into UTF-8, then invoking the corresponding UTF-8 interface.
**
** The first argument, "db", is a [database connection] obtained from a
** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or
** [sqlite3_open16()]. The database connection must not have been closed.
**
** The second argument, "zSql", is the statement to be compiled, encoded
-** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2()
-** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
-** use UTF-16.
+** as either UTF-8 or UTF-16. The sqlite3_prepare(), sqlite3_prepare_v2(),
+** and sqlite3_prepare_v3()
+** interfaces use UTF-8, and sqlite3_prepare16(), sqlite3_prepare16_v2(),
+** and sqlite3_prepare16_v3() use UTF-16.
**
** ^If the nByte argument is negative, then zSql is read up to the
** first zero terminator. ^If nByte is positive, then it is the
@@ -3726,10 +4589,11 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK];
** otherwise an [error code] is returned.
**
-** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are
-** recommended for all new programs. The two older interfaces are retained
-** for backwards compatibility, but their use is discouraged.
-** ^In the "v2" interfaces, the prepared statement
+** The sqlite3_prepare_v2(), sqlite3_prepare_v3(), sqlite3_prepare16_v2(),
+** and sqlite3_prepare16_v3() interfaces are recommended for all new programs.
+** The older interfaces (sqlite3_prepare() and sqlite3_prepare16())
+** are retained for backwards compatibility, but their use is discouraged.
+** ^In the "vX" interfaces, the prepared statement
** that is returned (the [sqlite3_stmt] object) contains a copy of the
** original SQL text. This causes the [sqlite3_step()] interface to
** behave differently in three ways:
@@ -3762,6 +4626,12 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
**
+**
+** ^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having
+** the extra prepFlags parameter, which is a bit array consisting of zero or
+** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The
+** sqlite3_prepare_v2() interface works exactly the same as
+** sqlite3_prepare_v3() with a zero prepFlags parameter.
**
*/
SQLITE_API int sqlite3_prepare(
@@ -3778,6 +4648,14 @@ SQLITE_API int sqlite3_prepare_v2(
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
+SQLITE_API int sqlite3_prepare_v3(
+ sqlite3 *db, /* Database handle */
+ const char *zSql, /* SQL statement, UTF-8 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const char **pzTail /* OUT: Pointer to unused portion of zSql */
+);
SQLITE_API int sqlite3_prepare16(
sqlite3 *db, /* Database handle */
const void *zSql, /* SQL statement, UTF-16 encoded */
@@ -3792,6 +4670,14 @@ SQLITE_API int sqlite3_prepare16_v2(
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const void **pzTail /* OUT: Pointer to unused portion of zSql */
);
+SQLITE_API int sqlite3_prepare16_v3(
+ sqlite3 *db, /* Database handle */
+ const void *zSql, /* SQL statement, UTF-16 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const void **pzTail /* OUT: Pointer to unused portion of zSql */
+);
/*
** CAPI3REF: Retrieving Statement SQL
@@ -3799,7 +4685,8 @@ SQLITE_API int sqlite3_prepare16_v2(
**
** ^The sqlite3_sql(P) interface returns a pointer to a copy of the UTF-8
** SQL text used to create [prepared statement] P if P was
-** created by either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()].
+** created by [sqlite3_prepare_v2()], [sqlite3_prepare_v3()],
+** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()].
** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8
** string containing the SQL text of prepared statement P with
** [bound parameters] expanded.
@@ -3856,6 +4743,10 @@ SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
** sqlite3_stmt_readonly() to return true since, while those statements
** change the configuration of a database connection, they do not make
** changes to the content of the database files on disk.
+** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since
+** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
+** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
+** sqlite3_stmt_readonly() returns false for those commands.
*/
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
@@ -3919,7 +4810,7 @@ SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
** The [sqlite3_value_blob | sqlite3_value_type()] family of
** interfaces require protected sqlite3_value objects.
*/
-typedef struct Mem sqlite3_value;
+typedef struct sqlite3_value sqlite3_value;
/*
** CAPI3REF: SQL Function Context Object
@@ -4021,6 +4912,15 @@ typedef struct sqlite3_context sqlite3_context;
** [sqlite3_blob_open | incremental BLOB I/O] routines.
** ^A negative value for the zeroblob results in a zero-length BLOB.
**
+** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in
+** [prepared statement] S to have an SQL value of NULL, but to also be
+** associated with the pointer P of type T. ^D is either a NULL pointer or
+** a pointer to a destructor function for P. ^SQLite will invoke the
+** destructor D with a single argument of P when it is finished using
+** P. The T parameter should be a static string, preferably a string
+** literal. The sqlite3_bind_pointer() routine is part of the
+** [pointer passing interface] added for SQLite 3.20.0.
+**
** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer
** for the [prepared statement] or with a prepared statement for which
** [sqlite3_step()] has been called more recently than [sqlite3_reset()],
@@ -4054,6 +4954,7 @@ SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)
SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
void(*)(void*), unsigned char encoding);
SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
+SQLITE_API int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
@@ -4097,8 +4998,8 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*);
** ^If the value N is out of range or if the N-th parameter is
** nameless, then NULL is returned. ^The returned string is
** always in UTF-8 encoding even if the named parameter was
-** originally specified as UTF-16 in [sqlite3_prepare16()] or
-** [sqlite3_prepare16_v2()].
+** originally specified as UTF-16 in [sqlite3_prepare16()],
+** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()].
**
** See also: [sqlite3_bind_blob|sqlite3_bind()],
** [sqlite3_bind_parameter_count()], and
@@ -4115,7 +5016,8 @@ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero
** is returned if no matching parameter is found. ^The parameter
** name must be given in UTF-8 even if the original statement
-** was prepared from UTF-16 text using [sqlite3_prepare16_v2()].
+** was prepared from UTF-16 text using [sqlite3_prepare16_v2()] or
+** [sqlite3_prepare16_v3()].
**
** See also: [sqlite3_bind_blob|sqlite3_bind()],
** [sqlite3_bind_parameter_count()], and
@@ -4138,8 +5040,12 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*);
** METHOD: sqlite3_stmt
**
** ^Return the number of columns in the result set returned by the
-** [prepared statement]. ^This routine returns 0 if pStmt is an SQL
-** statement that does not return data (for example an [UPDATE]).
+** [prepared statement]. ^If this routine returns 0, that means the
+** [prepared statement] returns no data (for example an [UPDATE]).
+** ^However, just because this routine returns a positive number does not
+** mean that one or more rows of data will be returned. ^A SELECT statement
+** will always have a positive sqlite3_column_count() but depending on the
+** WHERE clause constraints and the table content, it might return no rows.
**
** See also: [sqlite3_data_count()]
*/
@@ -4265,16 +5171,18 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** CAPI3REF: Evaluate An SQL Statement
** METHOD: sqlite3_stmt
**
-** After a [prepared statement] has been prepared using either
-** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy
+** After a [prepared statement] has been prepared using any of
+** [sqlite3_prepare_v2()], [sqlite3_prepare_v3()], [sqlite3_prepare16_v2()],
+** or [sqlite3_prepare16_v3()] or one of the legacy
** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function
** must be called one or more times to evaluate the statement.
**
** The details of the behavior of the sqlite3_step() interface depend
-** on whether the statement was prepared using the newer "v2" interface
-** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy
-** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the
-** new "v2" interface is recommended for new applications but the legacy
+** on whether the statement was prepared using the newer "vX" interfaces
+** [sqlite3_prepare_v3()], [sqlite3_prepare_v2()], [sqlite3_prepare16_v3()],
+** [sqlite3_prepare16_v2()] or the older legacy
+** interfaces [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the
+** new "vX" interface is recommended for new applications but the legacy
** interface will continue to be supported.
**
** ^In the legacy interface, the return value will be either [SQLITE_BUSY],
@@ -4320,7 +5228,7 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** other than [SQLITE_ROW] before any subsequent invocation of
** sqlite3_step(). Failure to reset the prepared statement using
** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
-** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
+** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1]),
** sqlite3_step() began
** calling [sqlite3_reset()] automatically in this circumstance rather
** than returning [SQLITE_MISUSE]. This is not considered a compatibility
@@ -4335,10 +5243,11 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** specific [error codes] that better describes the error.
** We admit that this is a goofy design. The problem has been fixed
** with the "v2" interface. If you prepare all of your SQL statements
-** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead
+** using [sqlite3_prepare_v3()] or [sqlite3_prepare_v2()]
+** or [sqlite3_prepare16_v2()] or [sqlite3_prepare16_v3()] instead
** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces,
** then the more specific [error codes] are returned directly
-** by sqlite3_step(). The use of the "v2" interface is recommended.
+** by sqlite3_step(). The use of the "vX" interfaces is recommended.
*/
SQLITE_API int sqlite3_step(sqlite3_stmt*);
@@ -4400,6 +5309,28 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** KEYWORDS: {column access functions}
** METHOD: sqlite3_stmt
**
+** Summary:
+**
+** sqlite3_column_blob | → | BLOB result
+** |
sqlite3_column_double | → | REAL result
+** |
sqlite3_column_int | → | 32-bit INTEGER result
+** |
sqlite3_column_int64 | → | 64-bit INTEGER result
+** |
sqlite3_column_text | → | UTF-8 TEXT result
+** |
sqlite3_column_text16 | → | UTF-16 TEXT result
+** |
sqlite3_column_value | → | The result as an
+** [sqlite3_value|unprotected sqlite3_value] object.
+** |
| |
+** |
sqlite3_column_bytes | → | Size of a BLOB
+** or a UTF-8 TEXT result in bytes
+** |
sqlite3_column_bytes16
+** | → | Size of UTF-16
+** TEXT in bytes
+** |
sqlite3_column_type | → | Default
+** datatype of the result
+** |
+**
+** Details:
+**
** ^These routines return information about a single column of the current
** result row of a query. ^In every case the first argument is a pointer
** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*]
@@ -4421,16 +5352,29 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** are called from a different thread while any of these routines
** are pending, then the results are undefined.
**
+** The first six interfaces (_blob, _double, _int, _int64, _text, and _text16)
+** each return the value of a result column in a specific data format. If
+** the result column is not initially in the requested format (for example,
+** if the query returns an integer but the sqlite3_column_text() interface
+** is used to extract the value) then an automatic type conversion is performed.
+**
** ^The sqlite3_column_type() routine returns the
** [SQLITE_INTEGER | datatype code] for the initial data type
** of the result column. ^The returned value is one of [SQLITE_INTEGER],
-** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value
-** returned by sqlite3_column_type() is only meaningful if no type
-** conversions have occurred as described below. After a type conversion,
-** the value returned by sqlite3_column_type() is undefined. Future
+** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL].
+** The return value of sqlite3_column_type() can be used to decide which
+** of the first six interface should be used to extract the column value.
+** The value returned by sqlite3_column_type() is only meaningful if no
+** automatic type conversions have occurred for the value in question.
+** After a type conversion, the result of calling sqlite3_column_type()
+** is undefined, though harmless. Future
** versions of SQLite may change the behavior of sqlite3_column_type()
** following a type conversion.
**
+** If the result is a BLOB or a TEXT string, then the sqlite3_column_bytes()
+** or sqlite3_column_bytes16() interfaces can be used to determine the size
+** of that BLOB or string.
+**
** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes()
** routine returns the number of bytes in that BLOB or string.
** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts
@@ -4467,9 +5411,13 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** [sqlite3_column_value()] is used in any other way, including calls
** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
** or [sqlite3_value_bytes()], the behavior is not threadsafe.
+** Hence, the sqlite3_column_value() interface
+** is normally only useful within the implementation of
+** [application-defined SQL functions] or [virtual tables], not within
+** top-level application code.
**
-** These routines attempt to convert the value where appropriate. ^For
-** example, if the internal representation is FLOAT and a text result
+** The these routines may attempt to convert the datatype of the result.
+** ^For example, if the internal representation is FLOAT and a text result
** is requested, [sqlite3_snprintf()] is used internally to perform the
** conversion automatically. ^(The following table details the conversions
** that are applied:
@@ -4541,7 +5489,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** ^The pointers returned are valid until a type conversion occurs as
** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
** [sqlite3_finalize()] is called. ^The memory space used to hold strings
-** and BLOBs is freed automatically. Do not pass the pointers returned
+** and BLOBs is freed automatically. Do not pass the pointers returned
** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
** [sqlite3_free()].
**
@@ -4552,15 +5500,15 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** [SQLITE_NOMEM].)^
*/
SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol);
SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
/*
** CAPI3REF: Destroy A Prepared Statement Object
@@ -4794,21 +5742,40 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** CAPI3REF: Obtaining SQL Values
** METHOD: sqlite3_value
**
-** The C-language implementation of SQL functions and aggregates uses
-** this set of interface routines to access the parameter values on
-** the function or aggregate.
+** Summary:
+**
+** sqlite3_value_blob | → | BLOB value
+** |
sqlite3_value_double | → | REAL value
+** |
sqlite3_value_int | → | 32-bit INTEGER value
+** |
sqlite3_value_int64 | → | 64-bit INTEGER value
+** |
sqlite3_value_pointer | → | Pointer value
+** |
sqlite3_value_text | → | UTF-8 TEXT value
+** |
sqlite3_value_text16 | → | UTF-16 TEXT value in
+** the native byteorder
+** |
sqlite3_value_text16be | → | UTF-16be TEXT value
+** |
sqlite3_value_text16le | → | UTF-16le TEXT value
+** |
| |
+** |
sqlite3_value_bytes | → | Size of a BLOB
+** or a UTF-8 TEXT in bytes
+** |
sqlite3_value_bytes16
+** | → | Size of UTF-16
+** TEXT in bytes
+** |
sqlite3_value_type | → | Default
+** datatype of the value
+** |
sqlite3_value_numeric_type
+** | → | Best numeric datatype of the value
+** |
**
-** The xFunc (for scalar functions) or xStep (for aggregates) parameters
-** to [sqlite3_create_function()] and [sqlite3_create_function16()]
-** define callbacks that implement the SQL functions and aggregates.
-** The 3rd parameter to these callbacks is an array of pointers to
-** [protected sqlite3_value] objects. There is one [sqlite3_value] object for
-** each parameter to the SQL function. These routines are used to
-** extract values from the [sqlite3_value] objects.
+** Details:
+**
+** These routines extract type, size, and content information from
+** [protected sqlite3_value] objects. Protected sqlite3_value objects
+** are used to pass parameter information into implementation of
+** [application-defined SQL functions] and [virtual tables].
**
** These routines work only with [protected sqlite3_value] objects.
** Any attempt to use these routines on an [unprotected sqlite3_value]
-** object results in undefined behavior.
+** is not threadsafe.
**
** ^These routines work just like the corresponding [column access functions]
** except that these routines take a single [protected sqlite3_value] object
@@ -4819,6 +5786,24 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
** extract UTF-16 strings as big-endian and little-endian respectively.
**
+** ^If [sqlite3_value] object V was initialized
+** using [sqlite3_bind_pointer(S,I,P,X,D)] or [sqlite3_result_pointer(C,P,X,D)]
+** and if X and Y are strings that compare equal according to strcmp(X,Y),
+** then sqlite3_value_pointer(V,Y) will return the pointer P. ^Otherwise,
+** sqlite3_value_pointer(V,Y) returns a NULL. The sqlite3_bind_pointer()
+** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
+**
+** ^(The sqlite3_value_type(V) interface returns the
+** [SQLITE_INTEGER | datatype code] for the initial datatype of the
+** [sqlite3_value] object V. The returned value is one of [SQLITE_INTEGER],
+** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL].)^
+** Other interfaces might change the datatype for an sqlite3_value object.
+** For example, if the datatype is initially SQLITE_INTEGER and
+** sqlite3_value_text(V) is called to extract a text value for that
+** integer, then subsequent calls to sqlite3_value_type(V) might return
+** SQLITE_TEXT. Whether or not a persistent internal datatype conversion
+** occurs is undefined and may change from one release of SQLite to the next.
+**
** ^(The sqlite3_value_numeric_type() interface attempts to apply
** numeric affinity to the value. This means that an attempt is
** made to convert the value to an integer or floating point. If
@@ -4837,15 +5822,16 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** the SQL function that supplied the [sqlite3_value*] parameters.
*/
SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
-SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
-SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
SQLITE_API double sqlite3_value_double(sqlite3_value*);
SQLITE_API int sqlite3_value_int(sqlite3_value*);
SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
+SQLITE_API void *sqlite3_value_pointer(sqlite3_value*, const char*);
SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*);
SQLITE_API const void *sqlite3_value_text16(sqlite3_value*);
SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*);
SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*);
+SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
+SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
SQLITE_API int sqlite3_value_type(sqlite3_value*);
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
@@ -4858,10 +5844,6 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
** information can be used to pass a limited amount of context from
** one SQL function to another. Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.
-**
-** SQLite makes no use of subtype itself. It merely passes the subtype
-** from the result of one [application-defined SQL function] into the
-** input of another.
*/
SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*);
@@ -4969,10 +5951,11 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
** the compiled regular expression can be reused on multiple
** invocations of the same function.
**
-** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata
-** associated by the sqlite3_set_auxdata() function with the Nth argument
-** value to the application-defined function. ^If there is no metadata
-** associated with the function argument, this sqlite3_get_auxdata() interface
+** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata
+** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument
+** value to the application-defined function. ^N is zero for the left-most
+** function argument. ^If there is no metadata
+** associated with the function argument, the sqlite3_get_auxdata(C,N) interface
** returns a NULL pointer.
**
** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
@@ -5003,6 +5986,10 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
** function parameters that are compile-time constants, including literal
** values and [parameters] and expressions composed from the same.)^
**
+** The value of the N parameter to these interfaces should be non-negative.
+** Future enhancements may make use of negative N values to define new
+** kinds of function caching behavior.
+**
** These routines must be called from the same thread in which
** the SQL function is running.
*/
@@ -5126,7 +6113,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** when it has finished using that result.
** ^If the 4th parameter to the sqlite3_result_text* interfaces
** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT
-** then SQLite makes a copy of the result into space obtained from
+** then SQLite makes a copy of the result into space obtained
** from [sqlite3_malloc()] before it returns.
**
** ^The sqlite3_result_value() interface sets the result of
@@ -5139,6 +6126,17 @@ typedef void (*sqlite3_destructor_type)(void*);
** [unprotected sqlite3_value] object is required, so either
** kind of [sqlite3_value] object can be used with this interface.
**
+** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an
+** SQL NULL value, just like [sqlite3_result_null(C)], except that it
+** also associates the host-language pointer P or type T with that
+** NULL value such that the pointer can be retrieved within an
+** [application-defined SQL function] using [sqlite3_value_pointer()].
+** ^If the D parameter is not NULL, then it is a pointer to a destructor
+** for the P parameter. ^SQLite invokes D with P as its only argument
+** when SQLite is finished with P. The T parameter should be a static
+** string and preferably a string literal. The sqlite3_result_pointer()
+** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
+**
** If these routines are called from within the different thread
** than the one containing the application-defined function that received
** the [sqlite3_context] pointer, the results are undefined.
@@ -5162,6 +6160,7 @@ SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*
SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
+SQLITE_API void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*));
SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
@@ -5648,7 +6647,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
**
** ^In the current implementation, the update hook
-** is not invoked when duplication rows are deleted because of an
+** is not invoked when conflicting rows are deleted because of an
** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
** invoked when rows are deleted using the [truncate optimization].
** The exceptions defined in this paragraph might change in a future
@@ -5821,7 +6820,9 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
** ^If the column-name parameter to sqlite3_table_column_metadata() is a
** NULL pointer, then this routine simply checks for the existence of the
** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
-** does not.
+** does not. If the table name parameter T in a call to
+** sqlite3_table_column_metadata(X,D,T,C,...) is NULL then the result is
+** undefined behavior.
**
** ^The column is identified by the second, third and fourth parameters to
** this function. ^(The second parameter is either the name of the database
@@ -6430,6 +7431,12 @@ typedef struct sqlite3_blob sqlite3_blob;
** [database connection] error code and message accessible via
** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
**
+** A BLOB referenced by sqlite3_blob_open() may be read using the
+** [sqlite3_blob_read()] interface and modified by using
+** [sqlite3_blob_write()]. The [BLOB handle] can be moved to a
+** different row of the same table using the [sqlite3_blob_reopen()]
+** interface. However, the column, table, or database of a [BLOB handle]
+** cannot be changed after the [BLOB handle] is opened.
**
** ^(If the row that a BLOB handle points to is modified by an
** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects
@@ -6453,6 +7460,10 @@ typedef struct sqlite3_blob sqlite3_blob;
**
** To avoid a resource leak, every open [BLOB handle] should eventually
** be released by a call to [sqlite3_blob_close()].
+**
+** See also: [sqlite3_blob_close()],
+** [sqlite3_blob_reopen()], [sqlite3_blob_read()],
+** [sqlite3_blob_bytes()], [sqlite3_blob_write()].
*/
SQLITE_API int sqlite3_blob_open(
sqlite3*,
@@ -6468,11 +7479,11 @@ SQLITE_API int sqlite3_blob_open(
** CAPI3REF: Move a BLOB Handle to a New Row
** METHOD: sqlite3_blob
**
-** ^This function is used to move an existing blob handle so that it points
+** ^This function is used to move an existing [BLOB handle] so that it points
** to a different row of the same database table. ^The new row is identified
** by the rowid value passed as the second argument. Only the row can be
** changed. ^The database, table and column on which the blob handle is open
-** remain the same. Moving an existing blob handle to a new row can be
+** remain the same. Moving an existing [BLOB handle] to a new row is
** faster than closing the existing handle and opening a new one.
**
** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] -
@@ -7324,6 +8335,24 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** used as a proxy for the total work done by the prepared statement.
** If the number of virtual machine operations exceeds 2147483647
** then the value returned by this statement status code is undefined.
+**
+** [[SQLITE_STMTSTATUS_REPREPARE]] SQLITE_STMTSTATUS_REPREPARE
+** ^This is the number of times that the prepare statement has been
+** automatically regenerated due to schema changes or change to
+** [bound parameters] that might affect the query plan.
+**
+** [[SQLITE_STMTSTATUS_RUN]] SQLITE_STMTSTATUS_RUN
+** ^This is the number of times that the prepared statement has
+** been run. A single "run" for the purposes of this counter is one
+** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()].
+** The counter is incremented on the first [sqlite3_step()] call of each
+** cycle.
+**
+** [[SQLITE_STMTSTATUS_MEMUSED]] SQLITE_STMTSTATUS_MEMUSED
+** ^This is the approximate number of bytes of heap memory
+** used to store the prepared statement. ^This value is not actually
+** a counter, and so the resetFlg parameter to sqlite3_stmt_status()
+** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED.
**
**
*/
@@ -7331,6 +8360,9 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
#define SQLITE_STMTSTATUS_SORT 2
#define SQLITE_STMTSTATUS_AUTOINDEX 3
#define SQLITE_STMTSTATUS_VM_STEP 4
+#define SQLITE_STMTSTATUS_REPREPARE 5
+#define SQLITE_STMTSTATUS_RUN 6
+#define SQLITE_STMTSTATUS_MEMUSED 99
/*
** CAPI3REF: Custom Page Cache Object
@@ -8401,7 +9433,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
**
** ^The [sqlite3_preupdate_hook()] interface registers a callback function
** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation
-** on a [rowid table].
+** on a database table.
** ^At most one preupdate hook may be registered at a time on a single
** [database connection]; each call to [sqlite3_preupdate_hook()] overrides
** the previous setting.
@@ -8410,9 +9442,9 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as
** the first parameter to callbacks.
**
-** ^The preupdate hook only fires for changes to [rowid tables]; the preupdate
-** hook is not invoked for changes to [virtual tables] or [WITHOUT ROWID]
-** tables.
+** ^The preupdate hook only fires for changes to real database tables; the
+** preupdate hook is not invoked for changes to [virtual tables] or to
+** system tables like sqlite_master or sqlite_stat1.
**
** ^The second parameter to the preupdate callback is a pointer to
** the [database connection] that registered the preupdate hook.
@@ -8426,12 +9458,16 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
** databases.)^
** ^The fifth parameter to the preupdate callback is the name of the
** table that is being modified.
-** ^The sixth parameter to the preupdate callback is the initial [rowid] of the
-** row being changes for SQLITE_UPDATE and SQLITE_DELETE changes and is
-** undefined for SQLITE_INSERT changes.
-** ^The seventh parameter to the preupdate callback is the final [rowid] of
-** the row being changed for SQLITE_UPDATE and SQLITE_INSERT changes and is
-** undefined for SQLITE_DELETE changes.
+**
+** For an UPDATE or DELETE operation on a [rowid table], the sixth
+** parameter passed to the preupdate callback is the initial [rowid] of the
+** row being modified or deleted. For an INSERT operation on a rowid table,
+** or any operation on a WITHOUT ROWID table, the value of the sixth
+** parameter is undefined. For an INSERT or UPDATE on a rowid table the
+** seventh parameter is the final rowid value of the row being inserted
+** or updated. The value of the seventh parameter passed to the callback
+** function is not defined for operations on WITHOUT ROWID tables, or for
+** INSERT operations on rowid tables.
**
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
@@ -8471,7 +9507,8 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
**
** See also: [sqlite3_update_hook()]
*/
-SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook(
+#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
+SQLITE_API void *sqlite3_preupdate_hook(
sqlite3 *db,
void(*xPreUpdate)(
void *pCtx, /* Copy of third arg to preupdate_hook() */
@@ -8484,10 +9521,11 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook(
),
void*
);
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *);
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_depth(sqlite3 *);
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
+SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
+SQLITE_API int sqlite3_preupdate_count(sqlite3 *);
+SQLITE_API int sqlite3_preupdate_depth(sqlite3 *);
+SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
+#endif
/*
** CAPI3REF: Low-level system error code
@@ -8503,7 +9541,7 @@ SQLITE_API int sqlite3_system_errno(sqlite3*);
/*
** CAPI3REF: Database Snapshot
-** KEYWORDS: {snapshot}
+** KEYWORDS: {snapshot} {sqlite3_snapshot}
** EXPERIMENTAL
**
** An instance of the snapshot object records the state of a [WAL mode]
@@ -8527,7 +9565,9 @@ SQLITE_API int sqlite3_system_errno(sqlite3*);
** to an historical snapshot (if possible). The destructor for
** sqlite3_snapshot objects is [sqlite3_snapshot_free()].
*/
-typedef struct sqlite3_snapshot sqlite3_snapshot;
+typedef struct sqlite3_snapshot {
+ unsigned char hidden[48];
+} sqlite3_snapshot;
/*
** CAPI3REF: Record A Database Snapshot
@@ -8538,9 +9578,32 @@ typedef struct sqlite3_snapshot sqlite3_snapshot;
** schema S in database connection D. ^On success, the
** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly
** created [sqlite3_snapshot] object into *P and returns SQLITE_OK.
-** ^If schema S of [database connection] D is not a [WAL mode] database
-** that is in a read transaction, then [sqlite3_snapshot_get(D,S,P)]
-** leaves the *P value unchanged and returns an appropriate [error code].
+** If there is not already a read-transaction open on schema S when
+** this function is called, one is opened automatically.
+**
+** The following must be true for this function to succeed. If any of
+** the following statements are false when sqlite3_snapshot_get() is
+** called, SQLITE_ERROR is returned. The final value of *P is undefined
+** in this case.
+**
+**
+** - The database handle must be in [autocommit mode].
+**
+**
- Schema S of [database connection] D must be a [WAL mode] database.
+**
+**
- There must not be a write transaction open on schema S of database
+** connection D.
+**
+**
- One or more transactions must have been written to the current wal
+** file since it was created on disk (by any connection). This means
+** that a snapshot cannot be taken on a wal mode database with no wal
+** file immediately after it is first opened. At least one transaction
+** must be written to it first.
+**
+**
+** This function may also return SQLITE_NOMEM. If it is called with the
+** database handle in autocommit mode but fails for some other reason,
+** whether or not a read transaction is opened on schema S is undefined.
**
** The [sqlite3_snapshot] object returned from a successful call to
** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()]
@@ -8633,6 +9696,28 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
sqlite3_snapshot *p2
);
+/*
+** CAPI3REF: Recover snapshots from a wal file
+** EXPERIMENTAL
+**
+** If all connections disconnect from a database file but do not perform
+** a checkpoint, the existing wal file is opened along with the database
+** file the next time the database is opened. At this point it is only
+** possible to successfully call sqlite3_snapshot_open() to open the most
+** recent snapshot of the database (the one at the head of the wal file),
+** even though the wal file may contain other valid snapshots for which
+** clients have sqlite3_snapshot handles.
+**
+** This function attempts to scan the wal file associated with database zDb
+** of database handle db and make all valid snapshots available to
+** sqlite3_snapshot_open(). It is an error if there is already a read
+** transaction open on the database, or if the database is not a wal mode
+** database.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+*/
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
+
/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
@@ -8818,7 +9903,7 @@ typedef struct sqlite3_changeset_iter sqlite3_changeset_iter;
** attached database. It is not an error if database zDb is not attached
** to the database when the session object is created.
*/
-int sqlite3session_create(
+SQLITE_API int sqlite3session_create(
sqlite3 *db, /* Database handle */
const char *zDb, /* Name of db (e.g. "main") */
sqlite3_session **ppSession /* OUT: New session object */
@@ -8836,7 +9921,7 @@ int sqlite3session_create(
** are attached is closed. Refer to the documentation for
** [sqlite3session_create()] for details.
*/
-void sqlite3session_delete(sqlite3_session *pSession);
+SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
/*
@@ -8856,7 +9941,7 @@ void sqlite3session_delete(sqlite3_session *pSession);
** The return value indicates the final state of the session object: 0 if
** the session is disabled, or 1 if it is enabled.
*/
-int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
+SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
/*
** CAPI3REF: Set Or Clear the Indirect Change Flag
@@ -8885,7 +9970,7 @@ int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
** The return value indicates the final state of the indirect flag: 0 if
** it is clear, or 1 if it is set.
*/
-int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect);
+SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect);
/*
** CAPI3REF: Attach A Table To A Session Object
@@ -8915,7 +10000,7 @@ int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect);
** SQLITE_OK is returned if the call completes without error. Or, if an error
** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned.
*/
-int sqlite3session_attach(
+SQLITE_API int sqlite3session_attach(
sqlite3_session *pSession, /* Session object */
const char *zTab /* Table name */
);
@@ -8929,7 +10014,7 @@ int sqlite3session_attach(
** If xFilter returns 0, changes is not tracked. Note that once a table is
** attached, xFilter will not be called again.
*/
-void sqlite3session_table_filter(
+SQLITE_API void sqlite3session_table_filter(
sqlite3_session *pSession, /* Session object */
int(*xFilter)(
void *pCtx, /* Copy of third arg to _filter_table() */
@@ -9042,7 +10127,7 @@ void sqlite3session_table_filter(
** another field of the same row is updated while the session is enabled, the
** resulting changeset will contain an UPDATE change that updates both fields.
*/
-int sqlite3session_changeset(
+SQLITE_API int sqlite3session_changeset(
sqlite3_session *pSession, /* Session object */
int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
void **ppChangeset /* OUT: Buffer containing changeset */
@@ -9086,7 +10171,8 @@ int sqlite3session_changeset(
** the from-table, a DELETE record is added to the session object.
**
** For each row (primary key) that exists in both tables, but features
-** different in each, an UPDATE record is added to the session.
+** different non-PK values in each, an UPDATE record is added to the
+** session.
**
**
** To clarify, if this function is called and then a changeset constructed
@@ -9103,7 +10189,7 @@ int sqlite3session_changeset(
** message. It is the responsibility of the caller to free this buffer using
** sqlite3_free().
*/
-int sqlite3session_diff(
+SQLITE_API int sqlite3session_diff(
sqlite3_session *pSession,
const char *zFromDb,
const char *zTbl,
@@ -9139,7 +10225,7 @@ int sqlite3session_diff(
** a single table are grouped together, tables appear in the order in which
** they were attached to the session object).
*/
-int sqlite3session_patchset(
+SQLITE_API int sqlite3session_patchset(
sqlite3_session *pSession, /* Session object */
int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */
void **ppPatchset /* OUT: Buffer containing changeset */
@@ -9160,7 +10246,7 @@ int sqlite3session_patchset(
** guaranteed that a call to sqlite3session_changeset() will return a
** changeset containing zero changes.
*/
-int sqlite3session_isempty(sqlite3_session *pSession);
+SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
/*
** CAPI3REF: Create An Iterator To Traverse A Changeset
@@ -9195,7 +10281,7 @@ int sqlite3session_isempty(sqlite3_session *pSession);
** the applies to table X, then one for table Y, and then later on visit
** another change for table X.
*/
-int sqlite3changeset_start(
+SQLITE_API int sqlite3changeset_start(
sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
int nChangeset, /* Size of changeset blob in bytes */
void *pChangeset /* Pointer to blob containing changeset */
@@ -9224,7 +10310,7 @@ int sqlite3changeset_start(
** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or
** SQLITE_NOMEM.
*/
-int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
+SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
/*
** CAPI3REF: Obtain The Current Operation From A Changeset Iterator
@@ -9252,7 +10338,7 @@ int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
** SQLite error code is returned. The values of the output variables may not
** be trusted in this case.
*/
-int sqlite3changeset_op(
+SQLITE_API int sqlite3changeset_op(
sqlite3_changeset_iter *pIter, /* Iterator object */
const char **pzTab, /* OUT: Pointer to table name */
int *pnCol, /* OUT: Number of columns in table */
@@ -9285,7 +10371,7 @@ int sqlite3changeset_op(
** SQLITE_OK is returned and the output variables populated as described
** above.
*/
-int sqlite3changeset_pk(
+SQLITE_API int sqlite3changeset_pk(
sqlite3_changeset_iter *pIter, /* Iterator object */
unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */
int *pnCol /* OUT: Number of entries in output array */
@@ -9315,7 +10401,7 @@ int sqlite3changeset_pk(
** If some other error occurs (e.g. an OOM condition), an SQLite error code
** is returned and *ppValue is set to NULL.
*/
-int sqlite3changeset_old(
+SQLITE_API int sqlite3changeset_old(
sqlite3_changeset_iter *pIter, /* Changeset iterator */
int iVal, /* Column number */
sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */
@@ -9348,7 +10434,7 @@ int sqlite3changeset_old(
** If some other error occurs (e.g. an OOM condition), an SQLite error code
** is returned and *ppValue is set to NULL.
*/
-int sqlite3changeset_new(
+SQLITE_API int sqlite3changeset_new(
sqlite3_changeset_iter *pIter, /* Changeset iterator */
int iVal, /* Column number */
sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */
@@ -9375,7 +10461,7 @@ int sqlite3changeset_new(
** If some other error occurs (e.g. an OOM condition), an SQLite error code
** is returned and *ppValue is set to NULL.
*/
-int sqlite3changeset_conflict(
+SQLITE_API int sqlite3changeset_conflict(
sqlite3_changeset_iter *pIter, /* Changeset iterator */
int iVal, /* Column number */
sqlite3_value **ppValue /* OUT: Value from conflicting row */
@@ -9391,7 +10477,7 @@ int sqlite3changeset_conflict(
**
** In all other cases this function returns SQLITE_MISUSE.
*/
-int sqlite3changeset_fk_conflicts(
+SQLITE_API int sqlite3changeset_fk_conflicts(
sqlite3_changeset_iter *pIter, /* Changeset iterator */
int *pnOut /* OUT: Number of FK violations */
);
@@ -9424,7 +10510,7 @@ int sqlite3changeset_fk_conflicts(
** // An error has occurred
** }
*/
-int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
+SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
/*
** CAPI3REF: Invert A Changeset
@@ -9454,7 +10540,7 @@ int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
** WARNING/TODO: This function currently assumes that the input is a valid
** changeset. If it is not, the results are undefined.
*/
-int sqlite3changeset_invert(
+SQLITE_API int sqlite3changeset_invert(
int nIn, const void *pIn, /* Input changeset */
int *pnOut, void **ppOut /* OUT: Inverse of input */
);
@@ -9483,7 +10569,7 @@ int sqlite3changeset_invert(
**
** Refer to the sqlite3_changegroup documentation below for details.
*/
-int sqlite3changeset_concat(
+SQLITE_API int sqlite3changeset_concat(
int nA, /* Number of bytes in buffer pA */
void *pA, /* Pointer to buffer containing changeset A */
int nB, /* Number of bytes in buffer pB */
@@ -9533,7 +10619,7 @@ typedef struct sqlite3_changegroup sqlite3_changegroup;
** sqlite3changegroup_output() functions, also available are the streaming
** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm().
*/
-int sqlite3changegroup_new(sqlite3_changegroup **pp);
+SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
/*
** CAPI3REF: Add A Changeset To A Changegroup
@@ -9610,7 +10696,7 @@ int sqlite3changegroup_new(sqlite3_changegroup **pp);
**
** If no error occurs, SQLITE_OK is returned.
*/
-int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
+SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
/*
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
@@ -9636,7 +10722,7 @@ int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
** responsibility of the caller to eventually free the buffer using a
** call to sqlite3_free().
*/
-int sqlite3changegroup_output(
+SQLITE_API int sqlite3changegroup_output(
sqlite3_changegroup*,
int *pnData, /* OUT: Size of output buffer in bytes */
void **ppData /* OUT: Pointer to output buffer */
@@ -9645,7 +10731,7 @@ int sqlite3changegroup_output(
/*
** CAPI3REF: Delete A Changegroup Object
*/
-void sqlite3changegroup_delete(sqlite3_changegroup*);
+SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
/*
** CAPI3REF: Apply A Changeset To A Database
@@ -9671,7 +10757,7 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
**
** - The table has the same name as the name recorded in the
** changeset, and
-**
- The table has the same number of columns as recorded in the
+**
- The table has at least as many columns as recorded in the
** changeset, and
**
- The table has primary key columns in the same position as
** recorded in the changeset.
@@ -9716,7 +10802,11 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
** If a row with matching primary key values is found, but one or more of
** the non-primary key fields contains a value different from the original
** row value stored in the changeset, the conflict-handler function is
-** invoked with [SQLITE_CHANGESET_DATA] as the second argument.
+** invoked with [SQLITE_CHANGESET_DATA] as the second argument. If the
+** database table has more columns than are recorded in the changeset,
+** only the values of those non-primary key fields are compared against
+** the current database contents - any trailing database table columns
+** are ignored.
**
** If no row with matching primary key values is found in the database,
** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND]
@@ -9731,7 +10821,9 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
**
**
- INSERT Changes
-
** For each INSERT change, an attempt is made to insert the new row into
-** the database.
+** the database. If the changeset row contains fewer fields than the
+** database table, the trailing fields are populated with their default
+** values.
**
** If the attempt to insert the row fails because the database already
** contains a row with the same primary key values, the conflict handler
@@ -9749,13 +10841,13 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
** For each UPDATE change, this function checks if the target database
** contains a row with the same primary key value (or values) as the
** original row values stored in the changeset. If it does, and the values
-** stored in all non-primary key columns also match the values stored in
-** the changeset the row is updated within the target database.
+** stored in all modified non-primary key columns also match the values
+** stored in the changeset the row is updated within the target database.
**
** If a row with matching primary key values is found, but one or more of
-** the non-primary key fields contains a value different from an original
-** row value stored in the changeset, the conflict-handler function is
-** invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since
+** the modified non-primary key fields contains a value different from an
+** original row value stored in the changeset, the conflict-handler function
+** is invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since
** UPDATE changes only contain values for non-primary key fields that are
** to be modified, only those fields need to match the original values to
** avoid the SQLITE_CHANGESET_DATA conflict-handler callback.
@@ -9783,7 +10875,7 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
** rolled back, restoring the target database to its original state, and an
** SQLite error code returned.
*/
-int sqlite3changeset_apply(
+SQLITE_API int sqlite3changeset_apply(
sqlite3 *db, /* Apply change to "main" db of this handle */
int nChangeset, /* Size of changeset in bytes */
void *pChangeset, /* Changeset blob */
@@ -9984,7 +11076,7 @@ int sqlite3changeset_apply(
** parameter set to a value less than or equal to zero. Other than this,
** no guarantees are made as to the size of the chunks of data returned.
*/
-int sqlite3changeset_apply_strm(
+SQLITE_API int sqlite3changeset_apply_strm(
sqlite3 *db, /* Apply change to "main" db of this handle */
int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
void *pIn, /* First arg for xInput */
@@ -9999,7 +11091,7 @@ int sqlite3changeset_apply_strm(
),
void *pCtx /* First argument passed to xConflict */
);
-int sqlite3changeset_concat_strm(
+SQLITE_API int sqlite3changeset_concat_strm(
int (*xInputA)(void *pIn, void *pData, int *pnData),
void *pInA,
int (*xInputB)(void *pIn, void *pData, int *pnData),
@@ -10007,32 +11099,32 @@ int sqlite3changeset_concat_strm(
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
-int sqlite3changeset_invert_strm(
+SQLITE_API int sqlite3changeset_invert_strm(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
-int sqlite3changeset_start_strm(
+SQLITE_API int sqlite3changeset_start_strm(
sqlite3_changeset_iter **pp,
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
);
-int sqlite3session_changeset_strm(
+SQLITE_API int sqlite3session_changeset_strm(
sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
-int sqlite3session_patchset_strm(
+SQLITE_API int sqlite3session_patchset_strm(
sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
-int sqlite3changegroup_add_strm(sqlite3_changegroup*,
+SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*,
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
);
-int sqlite3changegroup_output_strm(sqlite3_changegroup*,
+SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
@@ -10637,8 +11729,9 @@ struct fts5_api {
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
*/
-#ifdef _HAVE_SQLITE_CONFIG_H
-#include "config.h"
+#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
+/* #include "config.h" */
+#define SQLITECONFIG_H 1
#endif
/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
@@ -10732,7 +11825,7 @@ struct fts5_api {
** Not currently enforced.
*/
#ifndef SQLITE_MAX_VDBE_OP
-# define SQLITE_MAX_VDBE_OP 25000
+# define SQLITE_MAX_VDBE_OP 250000000
#endif
/*
@@ -10930,6 +12023,7 @@ struct fts5_api {
# include
# pragma intrinsic(_byteswap_ushort)
# pragma intrinsic(_byteswap_ulong)
+# pragma intrinsic(_byteswap_uint64)
# pragma intrinsic(_ReadWriteBarrier)
# else
# include
@@ -10947,6 +12041,11 @@ struct fts5_api {
**
** Older versions of SQLite used an optional THREADSAFE macro.
** We support that for legacy.
+**
+** To ensure that the correct value of "THREADSAFE" is reported when querying
+** for compile-time options at runtime (e.g. "PRAGMA compile_options"), this
+** logic is partially replicated in ctime.c. If it is updated here, it should
+** also be updated there.
*/
#if !defined(SQLITE_THREADSAFE)
# if defined(THREADSAFE)
@@ -11315,76 +12414,76 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_AS 24
#define TK_WITHOUT 25
#define TK_COMMA 26
-#define TK_OR 27
-#define TK_AND 28
-#define TK_IS 29
-#define TK_MATCH 30
-#define TK_LIKE_KW 31
-#define TK_BETWEEN 32
-#define TK_IN 33
-#define TK_ISNULL 34
-#define TK_NOTNULL 35
-#define TK_NE 36
-#define TK_EQ 37
-#define TK_GT 38
-#define TK_LE 39
-#define TK_LT 40
-#define TK_GE 41
-#define TK_ESCAPE 42
-#define TK_BITAND 43
-#define TK_BITOR 44
-#define TK_LSHIFT 45
-#define TK_RSHIFT 46
-#define TK_PLUS 47
-#define TK_MINUS 48
-#define TK_STAR 49
-#define TK_SLASH 50
-#define TK_REM 51
-#define TK_CONCAT 52
-#define TK_COLLATE 53
-#define TK_BITNOT 54
-#define TK_ID 55
-#define TK_INDEXED 56
-#define TK_ABORT 57
-#define TK_ACTION 58
-#define TK_AFTER 59
-#define TK_ANALYZE 60
-#define TK_ASC 61
-#define TK_ATTACH 62
-#define TK_BEFORE 63
-#define TK_BY 64
-#define TK_CASCADE 65
-#define TK_CAST 66
-#define TK_COLUMNKW 67
-#define TK_CONFLICT 68
-#define TK_DATABASE 69
-#define TK_DESC 70
-#define TK_DETACH 71
-#define TK_EACH 72
-#define TK_FAIL 73
-#define TK_FOR 74
-#define TK_IGNORE 75
-#define TK_INITIALLY 76
-#define TK_INSTEAD 77
-#define TK_NO 78
-#define TK_KEY 79
-#define TK_OF 80
-#define TK_OFFSET 81
-#define TK_PRAGMA 82
-#define TK_RAISE 83
-#define TK_RECURSIVE 84
-#define TK_REPLACE 85
-#define TK_RESTRICT 86
-#define TK_ROW 87
-#define TK_TRIGGER 88
-#define TK_VACUUM 89
-#define TK_VIEW 90
-#define TK_VIRTUAL 91
-#define TK_WITH 92
-#define TK_REINDEX 93
-#define TK_RENAME 94
-#define TK_CTIME_KW 95
-#define TK_ANY 96
+#define TK_ID 27
+#define TK_ABORT 28
+#define TK_ACTION 29
+#define TK_AFTER 30
+#define TK_ANALYZE 31
+#define TK_ASC 32
+#define TK_ATTACH 33
+#define TK_BEFORE 34
+#define TK_BY 35
+#define TK_CASCADE 36
+#define TK_CAST 37
+#define TK_COLUMNKW 38
+#define TK_CONFLICT 39
+#define TK_DATABASE 40
+#define TK_DESC 41
+#define TK_DETACH 42
+#define TK_EACH 43
+#define TK_FAIL 44
+#define TK_FOR 45
+#define TK_IGNORE 46
+#define TK_INITIALLY 47
+#define TK_INSTEAD 48
+#define TK_LIKE_KW 49
+#define TK_MATCH 50
+#define TK_NO 51
+#define TK_KEY 52
+#define TK_OF 53
+#define TK_OFFSET 54
+#define TK_PRAGMA 55
+#define TK_RAISE 56
+#define TK_RECURSIVE 57
+#define TK_REPLACE 58
+#define TK_RESTRICT 59
+#define TK_ROW 60
+#define TK_TRIGGER 61
+#define TK_VACUUM 62
+#define TK_VIEW 63
+#define TK_VIRTUAL 64
+#define TK_WITH 65
+#define TK_REINDEX 66
+#define TK_RENAME 67
+#define TK_CTIME_KW 68
+#define TK_ANY 69
+#define TK_OR 70
+#define TK_AND 71
+#define TK_IS 72
+#define TK_BETWEEN 73
+#define TK_IN 74
+#define TK_ISNULL 75
+#define TK_NOTNULL 76
+#define TK_NE 77
+#define TK_EQ 78
+#define TK_GT 79
+#define TK_LE 80
+#define TK_LT 81
+#define TK_GE 82
+#define TK_ESCAPE 83
+#define TK_BITAND 84
+#define TK_BITOR 85
+#define TK_LSHIFT 86
+#define TK_RSHIFT 87
+#define TK_PLUS 88
+#define TK_MINUS 89
+#define TK_STAR 90
+#define TK_SLASH 91
+#define TK_REM 92
+#define TK_CONCAT 93
+#define TK_COLLATE 94
+#define TK_BITNOT 95
+#define TK_INDEXED 96
#define TK_STRING 97
#define TK_JOIN_KW 98
#define TK_CONSTRAINT 99
@@ -11448,10 +12547,11 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_REGISTER 157
#define TK_VECTOR 158
#define TK_SELECT_COLUMN 159
-#define TK_ASTERISK 160
-#define TK_SPAN 161
-#define TK_SPACE 162
-#define TK_ILLEGAL 163
+#define TK_IF_NULL_ROW 160
+#define TK_ASTERISK 161
+#define TK_SPAN 162
+#define TK_SPACE 163
+#define TK_ILLEGAL 164
/* The token codes above must all fit in 8 bits */
#define TKFLG_MASK 0xff
@@ -11468,6 +12568,18 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#include
#include
+/*
+** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY.
+** This allows better measurements of where memcpy() is used when running
+** cachegrind. But this macro version of memcpy() is very slow so it
+** should not be used in production. This is a performance measurement
+** hack only.
+*/
+#ifdef SQLITE_INLINE_MEMCPY
+# define memcpy(D,S,N) {char*xxd=(char*)(D);const char*xxs=(const char*)(S);\
+ int xxn=(N);while(xxn-->0)*(xxd++)=*(xxs++);}
+#endif
+
/*
** If compiling for a processor that lacks floating point support,
** substitute integer for floating-point
@@ -11524,7 +12636,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
*/
#ifndef SQLITE_TEMP_STORE
# define SQLITE_TEMP_STORE 1
-# define SQLITE_TEMP_STORE_xc 1 /* Exclude from ctime.c */
#endif
/*
@@ -11552,9 +12663,12 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
** pagecaches for each database connection. A positive number is the
** number of pages. A negative number N translations means that a buffer
** of -1024*N bytes is allocated and used for as many pages as it will hold.
+**
+** The default value of "20" was choosen to minimize the run-time of the
+** speedtest1 test program with options: --shrink-memory --reprepare
*/
#ifndef SQLITE_DEFAULT_PCACHE_INITSZ
-# define SQLITE_DEFAULT_PCACHE_INITSZ 100
+# define SQLITE_DEFAULT_PCACHE_INITSZ 20
#endif
/*
@@ -11729,32 +12843,35 @@ typedef INT16_TYPE LogEst;
**
** For best performance, an attempt is made to guess at the byte-order
** using C-preprocessor macros. If that is unsuccessful, or if
-** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
+** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined
** at run-time.
*/
-#if (defined(i386) || defined(__i386__) || defined(_M_IX86) || \
+#ifndef SQLITE_BYTEORDER
+# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER)
-# define SQLITE_BYTEORDER 1234
-# define SQLITE_BIGENDIAN 0
-# define SQLITE_LITTLEENDIAN 1
-# define SQLITE_UTF16NATIVE SQLITE_UTF16LE
+ defined(__arm__)
+# define SQLITE_BYTEORDER 1234
+# elif defined(sparc) || defined(__ppc__)
+# define SQLITE_BYTEORDER 4321
+# else
+# define SQLITE_BYTEORDER 0
+# endif
#endif
-#if (defined(sparc) || defined(__ppc__)) \
- && !defined(SQLITE_RUNTIME_BYTEORDER)
-# define SQLITE_BYTEORDER 4321
+#if SQLITE_BYTEORDER==4321
# define SQLITE_BIGENDIAN 1
# define SQLITE_LITTLEENDIAN 0
# define SQLITE_UTF16NATIVE SQLITE_UTF16BE
-#endif
-#if !defined(SQLITE_BYTEORDER)
+#elif SQLITE_BYTEORDER==1234
+# define SQLITE_BIGENDIAN 0
+# define SQLITE_LITTLEENDIAN 1
+# define SQLITE_UTF16NATIVE SQLITE_UTF16LE
+#else
# ifdef SQLITE_AMALGAMATION
const int sqlite3one = 1;
# else
extern const int sqlite3one;
# endif
-# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */
# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
@@ -11819,7 +12936,6 @@ typedef INT16_TYPE LogEst;
# else
# define SQLITE_MAX_MMAP_SIZE 0
# endif
-# define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */
#endif
/*
@@ -11829,7 +12945,6 @@ typedef INT16_TYPE LogEst;
*/
#ifndef SQLITE_DEFAULT_MMAP_SIZE
# define SQLITE_DEFAULT_MMAP_SIZE 0
-# define SQLITE_DEFAULT_MMAP_SIZE_xc 1 /* Exclude from ctime.c */
#endif
#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE
# undef SQLITE_DEFAULT_MMAP_SIZE
@@ -12011,6 +13126,14 @@ typedef struct Walker Walker;
typedef struct WhereInfo WhereInfo;
typedef struct With With;
+/* A VList object records a mapping between parameters/variables/wildcards
+** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer
+** variable number associated with that parameter. See the format description
+** on the sqlite3VListAdd() routine for more information. A VList is really
+** just an array of integers.
+*/
+typedef int VList;
+
/*
** Defer sourcing vdbe.h and btree.h until after the "u8" and
** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
@@ -12269,9 +13392,10 @@ SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*);
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags);
-/* Allowed flags for the 2nd argument to sqlite3BtreeDelete() */
+/* Allowed flags for sqlite3BtreeDelete() and sqlite3BtreeInsert() */
#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */
#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */
+#define BTREE_APPEND 0x08 /* Insert is likely an append */
/* An instance of the BtreePayload object describes the content of a single
** entry in either an index or table btree.
@@ -12295,27 +13419,30 @@ struct BtreePayload {
const void *pKey; /* Key content for indexes. NULL for tables */
sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */
const void *pData; /* Data for tables. NULL for indexes */
+ sqlite3_value *aMem; /* First of nMem value in the unpacked pKey */
+ u16 nMem; /* Number of aMem[] value. Might be zero */
int nData; /* Size of pData. 0 if none. */
int nZero; /* Extra zero data appended after pData,nData */
};
SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
- int bias, int seekResult);
+ int flags, int seekResult);
SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes);
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes);
-SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes);
+SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags);
SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*);
-SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes);
+SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags);
SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*);
-SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
+SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*);
-SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
+SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor*);
#ifndef SQLITE_OMIT_INCRBLOB
+SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *);
#endif
@@ -12328,6 +13455,7 @@ SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void);
#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
#endif
+SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*);
#ifndef SQLITE_OMIT_BTREECOUNT
SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *);
@@ -12421,7 +13549,7 @@ typedef struct Vdbe Vdbe;
** The names of the following types declared in vdbeInt.h are required
** for the VdbeOp definition.
*/
-typedef struct Mem Mem;
+typedef struct sqlite3_value Mem;
typedef struct SubProgram SubProgram;
/*
@@ -12432,8 +13560,7 @@ typedef struct SubProgram SubProgram;
struct VdbeOp {
u8 opcode; /* What operation to perform */
signed char p4type; /* One of the P4_xxx constants for p4 */
- u8 notUsed1;
- u8 p5; /* Fifth parameter is an unsigned character */
+ u16 p5; /* Fifth parameter is an unsigned 16-bit integer */
int p1; /* First operand */
int p2; /* Second parameter (often the jump destination) */
int p3; /* The third parameter */
@@ -12455,7 +13582,7 @@ struct VdbeOp {
#ifdef SQLITE_ENABLE_CURSOR_HINTS
Expr *pExpr; /* Used when p4type is P4_EXPR */
#endif
- int (*xAdvance)(BtCursor *, int *);
+ int (*xAdvance)(BtCursor *, int);
} p4;
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
char *zComment; /* Comment to improve readability */
@@ -12479,6 +13606,7 @@ struct SubProgram {
int nOp; /* Elements in aOp[] */
int nMem; /* Number of memory cells required */
int nCsr; /* Number of cursors required */
+ u8 *aOnce; /* Array of OP_Once flags */
void *token; /* id that may be used to recursive triggers */
SubProgram *pNext; /* Next sub-program already visited */
};
@@ -12498,25 +13626,26 @@ typedef struct VdbeOpList VdbeOpList;
/*
** Allowed values of VdbeOp.p4type
*/
-#define P4_NOTUSED 0 /* The P4 parameter is not used */
-#define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */
-#define P4_STATIC (-2) /* Pointer to a static string */
-#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */
-#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */
-#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */
-#define P4_EXPR (-7) /* P4 is a pointer to an Expr tree */
-#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */
-#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
-#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */
-#define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */
-#define P4_REAL (-12) /* P4 is a 64-bit floating point value */
-#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */
-#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */
-#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
-#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */
-#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */
-#define P4_TABLE (-20) /* P4 is a pointer to a Table structure */
-#define P4_FUNCCTX (-21) /* P4 is a pointer to an sqlite3_context object */
+#define P4_NOTUSED 0 /* The P4 parameter is not used */
+#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
+#define P4_STATIC (-1) /* Pointer to a static string */
+#define P4_COLLSEQ (-2) /* P4 is a pointer to a CollSeq structure */
+#define P4_INT32 (-3) /* P4 is a 32-bit signed integer */
+#define P4_SUBPROGRAM (-4) /* P4 is a pointer to a SubProgram structure */
+#define P4_ADVANCE (-5) /* P4 is a pointer to BtreeNext() or BtreePrev() */
+#define P4_TABLE (-6) /* P4 is a pointer to a Table structure */
+/* Above do not own any resources. Must free those below */
+#define P4_FREE_IF_LE (-7)
+#define P4_DYNAMIC (-7) /* Pointer to memory from sqliteMalloc() */
+#define P4_FUNCDEF (-8) /* P4 is a pointer to a FuncDef structure */
+#define P4_KEYINFO (-9) /* P4 is a pointer to a KeyInfo structure */
+#define P4_EXPR (-10) /* P4 is a pointer to an Expr tree */
+#define P4_MEM (-11) /* P4 is a pointer to a Mem* structure */
+#define P4_VTAB (-12) /* P4 is a pointer to an sqlite3_vtab structure */
+#define P4_REAL (-13) /* P4 is a 64-bit floating point value */
+#define P4_INT64 (-14) /* P4 is a 64-bit signed integer */
+#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
+#define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */
/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1
@@ -12582,79 +13711,79 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Once 20
#define OP_If 21
#define OP_IfNot 22
-#define OP_SeekLT 23 /* synopsis: key=r[P3@P4] */
-#define OP_SeekLE 24 /* synopsis: key=r[P3@P4] */
-#define OP_SeekGE 25 /* synopsis: key=r[P3@P4] */
-#define OP_SeekGT 26 /* synopsis: key=r[P3@P4] */
-#define OP_Or 27 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
-#define OP_And 28 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
-#define OP_NoConflict 29 /* synopsis: key=r[P3@P4] */
-#define OP_NotFound 30 /* synopsis: key=r[P3@P4] */
-#define OP_Found 31 /* synopsis: key=r[P3@P4] */
-#define OP_SeekRowid 32 /* synopsis: intkey=r[P3] */
-#define OP_NotExists 33 /* synopsis: intkey=r[P3] */
-#define OP_IsNull 34 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
-#define OP_NotNull 35 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
-#define OP_Ne 36 /* same as TK_NE, synopsis: IF r[P3]!=r[P1] */
-#define OP_Eq 37 /* same as TK_EQ, synopsis: IF r[P3]==r[P1] */
-#define OP_Gt 38 /* same as TK_GT, synopsis: IF r[P3]>r[P1] */
-#define OP_Le 39 /* same as TK_LE, synopsis: IF r[P3]<=r[P1] */
-#define OP_Lt 40 /* same as TK_LT, synopsis: IF r[P3]=r[P1] */
-#define OP_ElseNotEq 42 /* same as TK_ESCAPE */
-#define OP_BitAnd 43 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-#define OP_BitOr 44 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-#define OP_ShiftLeft 45 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */
-#define OP_Add 47 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-#define OP_Subtract 48 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-#define OP_Multiply 49 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-#define OP_Divide 50 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-#define OP_Remainder 51 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-#define OP_Concat 52 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-#define OP_Last 53
-#define OP_BitNot 54 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
-#define OP_SorterSort 55
-#define OP_Sort 56
-#define OP_Rewind 57
-#define OP_IdxLE 58 /* synopsis: key=r[P3@P4] */
-#define OP_IdxGT 59 /* synopsis: key=r[P3@P4] */
-#define OP_IdxLT 60 /* synopsis: key=r[P3@P4] */
-#define OP_IdxGE 61 /* synopsis: key=r[P3@P4] */
-#define OP_RowSetRead 62 /* synopsis: r[P3]=rowset(P1) */
-#define OP_RowSetTest 63 /* synopsis: if r[P3] in rowset(P1) goto P2 */
-#define OP_Program 64
-#define OP_FkIfZero 65 /* synopsis: if fkctr[P1]==0 goto P2 */
-#define OP_IfPos 66 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
-#define OP_IfNotZero 67 /* synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 */
-#define OP_DecrJumpZero 68 /* synopsis: if (--r[P1])==0 goto P2 */
-#define OP_IncrVacuum 69
-#define OP_VNext 70
-#define OP_Init 71 /* synopsis: Start at P2 */
-#define OP_Return 72
-#define OP_EndCoroutine 73
-#define OP_HaltIfNull 74 /* synopsis: if r[P3]=null halt */
-#define OP_Halt 75
-#define OP_Integer 76 /* synopsis: r[P2]=P1 */
-#define OP_Int64 77 /* synopsis: r[P2]=P4 */
-#define OP_String 78 /* synopsis: r[P2]='P4' (len=P1) */
-#define OP_Null 79 /* synopsis: r[P2..P3]=NULL */
-#define OP_SoftNull 80 /* synopsis: r[P1]=NULL */
-#define OP_Blob 81 /* synopsis: r[P2]=P4 (len=P1) */
-#define OP_Variable 82 /* synopsis: r[P2]=parameter(P1,P4) */
-#define OP_Move 83 /* synopsis: r[P2@P3]=r[P1@P3] */
-#define OP_Copy 84 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
-#define OP_SCopy 85 /* synopsis: r[P2]=r[P1] */
-#define OP_IntCopy 86 /* synopsis: r[P2]=r[P1] */
-#define OP_ResultRow 87 /* synopsis: output=r[P1@P2] */
-#define OP_CollSeq 88
-#define OP_Function0 89 /* synopsis: r[P3]=func(r[P2@P5]) */
-#define OP_Function 90 /* synopsis: r[P3]=func(r[P2@P5]) */
-#define OP_AddImm 91 /* synopsis: r[P1]=r[P1]+P2 */
-#define OP_RealAffinity 92
-#define OP_Cast 93 /* synopsis: affinity(r[P1]) */
-#define OP_Permutation 94
-#define OP_Compare 95 /* synopsis: r[P1@P3] <-> r[P2@P3] */
+#define OP_IfNullRow 23 /* synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
+#define OP_SeekLT 24 /* synopsis: key=r[P3@P4] */
+#define OP_SeekLE 25 /* synopsis: key=r[P3@P4] */
+#define OP_SeekGE 26 /* synopsis: key=r[P3@P4] */
+#define OP_SeekGT 27 /* synopsis: key=r[P3@P4] */
+#define OP_NoConflict 28 /* synopsis: key=r[P3@P4] */
+#define OP_NotFound 29 /* synopsis: key=r[P3@P4] */
+#define OP_Found 30 /* synopsis: key=r[P3@P4] */
+#define OP_SeekRowid 31 /* synopsis: intkey=r[P3] */
+#define OP_NotExists 32 /* synopsis: intkey=r[P3] */
+#define OP_Last 33
+#define OP_IfSmaller 34
+#define OP_SorterSort 35
+#define OP_Sort 36
+#define OP_Rewind 37
+#define OP_IdxLE 38 /* synopsis: key=r[P3@P4] */
+#define OP_IdxGT 39 /* synopsis: key=r[P3@P4] */
+#define OP_IdxLT 40 /* synopsis: key=r[P3@P4] */
+#define OP_IdxGE 41 /* synopsis: key=r[P3@P4] */
+#define OP_RowSetRead 42 /* synopsis: r[P3]=rowset(P1) */
+#define OP_RowSetTest 43 /* synopsis: if r[P3] in rowset(P1) goto P2 */
+#define OP_Program 44
+#define OP_FkIfZero 45 /* synopsis: if fkctr[P1]==0 goto P2 */
+#define OP_IfPos 46 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+#define OP_IfNotZero 47 /* synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
+#define OP_DecrJumpZero 48 /* synopsis: if (--r[P1])==0 goto P2 */
+#define OP_IncrVacuum 49
+#define OP_VNext 50
+#define OP_Init 51 /* synopsis: Start at P2 */
+#define OP_Return 52
+#define OP_EndCoroutine 53
+#define OP_HaltIfNull 54 /* synopsis: if r[P3]=null halt */
+#define OP_Halt 55
+#define OP_Integer 56 /* synopsis: r[P2]=P1 */
+#define OP_Int64 57 /* synopsis: r[P2]=P4 */
+#define OP_String 58 /* synopsis: r[P2]='P4' (len=P1) */
+#define OP_Null 59 /* synopsis: r[P2..P3]=NULL */
+#define OP_SoftNull 60 /* synopsis: r[P1]=NULL */
+#define OP_Blob 61 /* synopsis: r[P2]=P4 (len=P1) */
+#define OP_Variable 62 /* synopsis: r[P2]=parameter(P1,P4) */
+#define OP_Move 63 /* synopsis: r[P2@P3]=r[P1@P3] */
+#define OP_Copy 64 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
+#define OP_SCopy 65 /* synopsis: r[P2]=r[P1] */
+#define OP_IntCopy 66 /* synopsis: r[P2]=r[P1] */
+#define OP_ResultRow 67 /* synopsis: output=r[P1@P2] */
+#define OP_CollSeq 68
+#define OP_AddImm 69 /* synopsis: r[P1]=r[P1]+P2 */
+#define OP_Or 70 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
+#define OP_And 71 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
+#define OP_RealAffinity 72
+#define OP_Cast 73 /* synopsis: affinity(r[P1]) */
+#define OP_Permutation 74
+#define OP_IsNull 75 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
+#define OP_NotNull 76 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
+#define OP_Ne 77 /* same as TK_NE, synopsis: IF r[P3]!=r[P1] */
+#define OP_Eq 78 /* same as TK_EQ, synopsis: IF r[P3]==r[P1] */
+#define OP_Gt 79 /* same as TK_GT, synopsis: IF r[P3]>r[P1] */
+#define OP_Le 80 /* same as TK_LE, synopsis: IF r[P3]<=r[P1] */
+#define OP_Lt 81 /* same as TK_LT, synopsis: IF r[P3]=r[P1] */
+#define OP_ElseNotEq 83 /* same as TK_ESCAPE */
+#define OP_BitAnd 84 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr 85 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft 86 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */
+#define OP_Add 88 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract 89 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply 90 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide 91 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder 92 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat 93 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
+#define OP_Compare 94 /* synopsis: r[P1@P3] <-> r[P2@P3] */
+#define OP_BitNot 95 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
#define OP_Column 96 /* synopsis: r[P3]=PX */
#define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */
#define OP_Affinity 98 /* synopsis: affinity(r[P1@P2]) */
@@ -12665,29 +13794,29 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_ReopenIdx 103 /* synopsis: root=P2 iDb=P3 */
#define OP_OpenRead 104 /* synopsis: root=P2 iDb=P3 */
#define OP_OpenWrite 105 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenAutoindex 106 /* synopsis: nColumn=P2 */
-#define OP_OpenEphemeral 107 /* synopsis: nColumn=P2 */
-#define OP_SorterOpen 108
-#define OP_SequenceTest 109 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
-#define OP_OpenPseudo 110 /* synopsis: P3 columns in r[P2] */
-#define OP_Close 111
-#define OP_ColumnsUsed 112
-#define OP_Sequence 113 /* synopsis: r[P2]=cursor[P1].ctr++ */
-#define OP_NewRowid 114 /* synopsis: r[P2]=rowid */
-#define OP_Insert 115 /* synopsis: intkey=r[P3] data=r[P2] */
-#define OP_InsertInt 116 /* synopsis: intkey=P3 data=r[P2] */
-#define OP_Delete 117
-#define OP_ResetCount 118
-#define OP_SorterCompare 119 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
-#define OP_SorterData 120 /* synopsis: r[P2]=data */
-#define OP_RowKey 121 /* synopsis: r[P2]=key */
+#define OP_OpenDup 106
+#define OP_OpenAutoindex 107 /* synopsis: nColumn=P2 */
+#define OP_OpenEphemeral 108 /* synopsis: nColumn=P2 */
+#define OP_SorterOpen 109
+#define OP_SequenceTest 110 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
+#define OP_OpenPseudo 111 /* synopsis: P3 columns in r[P2] */
+#define OP_Close 112
+#define OP_ColumnsUsed 113
+#define OP_Sequence 114 /* synopsis: r[P2]=cursor[P1].ctr++ */
+#define OP_NewRowid 115 /* synopsis: r[P2]=rowid */
+#define OP_Insert 116 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_InsertInt 117 /* synopsis: intkey=P3 data=r[P2] */
+#define OP_Delete 118
+#define OP_ResetCount 119
+#define OP_SorterCompare 120 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_SorterData 121 /* synopsis: r[P2]=data */
#define OP_RowData 122 /* synopsis: r[P2]=data */
#define OP_Rowid 123 /* synopsis: r[P2]=rowid */
#define OP_NullRow 124
-#define OP_SorterInsert 125
+#define OP_SorterInsert 125 /* synopsis: key=r[P2] */
#define OP_IdxInsert 126 /* synopsis: key=r[P2] */
#define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */
-#define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */
+#define OP_DeferredSeek 128 /* synopsis: Move P3 to P1.rowid if needed */
#define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */
#define OP_Destroy 130
#define OP_Clear 131
@@ -12695,33 +13824,38 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_ResetSorter 133
#define OP_CreateIndex 134 /* synopsis: r[P2]=root iDb=P1 */
#define OP_CreateTable 135 /* synopsis: r[P2]=root iDb=P1 */
-#define OP_ParseSchema 136
-#define OP_LoadAnalysis 137
-#define OP_DropTable 138
-#define OP_DropIndex 139
-#define OP_DropTrigger 140
-#define OP_IntegrityCk 141
-#define OP_RowSetAdd 142 /* synopsis: rowset(P1)=r[P2] */
-#define OP_Param 143
-#define OP_FkCounter 144 /* synopsis: fkctr[P1]+=P2 */
-#define OP_MemMax 145 /* synopsis: r[P1]=max(r[P1],r[P2]) */
-#define OP_OffsetLimit 146 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
-#define OP_AggStep0 147 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggStep 148 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggFinal 149 /* synopsis: accum=r[P1] N=P2 */
-#define OP_Expire 150
-#define OP_TableLock 151 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 152
-#define OP_VCreate 153
-#define OP_VDestroy 154
-#define OP_VOpen 155
-#define OP_VColumn 156 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VRename 157
-#define OP_Pagecount 158
-#define OP_MaxPgcnt 159
-#define OP_CursorHint 160
-#define OP_Noop 161
-#define OP_Explain 162
+#define OP_SqlExec 136
+#define OP_ParseSchema 137
+#define OP_LoadAnalysis 138
+#define OP_DropTable 139
+#define OP_DropIndex 140
+#define OP_DropTrigger 141
+#define OP_IntegrityCk 142
+#define OP_RowSetAdd 143 /* synopsis: rowset(P1)=r[P2] */
+#define OP_Param 144
+#define OP_FkCounter 145 /* synopsis: fkctr[P1]+=P2 */
+#define OP_MemMax 146 /* synopsis: r[P1]=max(r[P1],r[P2]) */
+#define OP_OffsetLimit 147 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
+#define OP_AggStep0 148 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggStep 149 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggFinal 150 /* synopsis: accum=r[P1] N=P2 */
+#define OP_Expire 151
+#define OP_TableLock 152 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 153
+#define OP_VCreate 154
+#define OP_VDestroy 155
+#define OP_VOpen 156
+#define OP_VColumn 157 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VRename 158
+#define OP_Pagecount 159
+#define OP_MaxPgcnt 160
+#define OP_PureFunc0 161
+#define OP_Function0 162 /* synopsis: r[P3]=func(r[P2@P5]) */
+#define OP_PureFunc 163
+#define OP_Function 164 /* synopsis: r[P3]=func(r[P2@P5]) */
+#define OP_CursorHint 165
+#define OP_Noop 166
+#define OP_Explain 167
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
@@ -12736,25 +13870,26 @@ typedef struct VdbeOpList VdbeOpList;
#define OPFLG_INITIALIZER {\
/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,\
/* 8 */ 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01,\
-/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x09,\
-/* 24 */ 0x09, 0x09, 0x09, 0x26, 0x26, 0x09, 0x09, 0x09,\
-/* 32 */ 0x09, 0x09, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
-/* 40 */ 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26, 0x26,\
-/* 48 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x01, 0x12, 0x01,\
-/* 56 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x23, 0x0b,\
-/* 64 */ 0x01, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01,\
-/* 72 */ 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10, 0x10,\
-/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00,\
-/* 88 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\
+/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x01,\
+/* 24 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\
+/* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
+/* 40 */ 0x01, 0x01, 0x23, 0x0b, 0x01, 0x01, 0x03, 0x03,\
+/* 48 */ 0x03, 0x01, 0x01, 0x01, 0x02, 0x02, 0x08, 0x00,\
+/* 56 */ 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00,\
+/* 64 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x02, 0x26, 0x26,\
+/* 72 */ 0x02, 0x02, 0x00, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\
+/* 80 */ 0x0b, 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26,\
+/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\
/* 96 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
/* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 112 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 112 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\
/* 120 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x04, 0x00,\
/* 128 */ 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,\
-/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10,\
-/* 144 */ 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\
-/* 160 */ 0x00, 0x00, 0x00,}
+/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,\
+/* 144 */ 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00,\
+/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
+/* 160 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+}
/* The sqlite3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
@@ -12762,11 +13897,17 @@ typedef struct VdbeOpList VdbeOpList;
** generated this include file strives to group all JUMP opcodes
** together near the beginning of the list.
*/
-#define SQLITE_MX_JUMP_OPCODE 71 /* Maximum JUMP opcode */
+#define SQLITE_MX_JUMP_OPCODE 83 /* Maximum JUMP opcode */
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
+/*
+** Additional non-public SQLITE_PREPARE_* flags
+*/
+#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
+#define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */
+
/*
** Prototypes for the VDBE interface. See comments on the implementation
** for a description of what each of these routines does.
@@ -12785,8 +13926,10 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe*,int);
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N);
+SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p);
#else
# define sqlite3VdbeVerifyNoMallocRequired(A,B)
+# define sqlite3VdbeVerifyNoResultRow(A)
#endif
SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
@@ -12794,11 +13937,12 @@ SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
-SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
+SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
+SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
@@ -12821,7 +13965,8 @@ SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int);
SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*);
SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*);
-SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int);
+SQLITE_PRIVATE u8 sqlite3VdbePrepareFlags(Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8);
SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
@@ -12834,7 +13979,7 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
-SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
+SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
@@ -12843,6 +13988,8 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif
+SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
+
/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
** each VDBE opcode.
**
@@ -13039,7 +14186,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
int,
void(*)(DbPage*)
);
-SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*);
SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
/* Functions used to configure a Pager object. */
@@ -13090,18 +14237,21 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
#ifndef SQLITE_OMIT_WAL
-SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
+SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*);
SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
-SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
+# ifdef SQLITE_DIRECT_OVERFLOW_READ
+SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno);
+# endif
# ifdef SQLITE_ENABLE_SNAPSHOT
SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
+SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager);
# endif
#else
-# define sqlite3PagerUseWal(x) 0
+# define sqlite3PagerUseWal(x,y) 0
#endif
#ifdef SQLITE_ENABLE_ZIPVFS
@@ -13184,6 +14334,7 @@ struct PgHdr {
sqlite3_pcache_page *pPage; /* Pcache object page handle */
void *pData; /* Page data */
void *pExtra; /* Extra content */
+ PCache *pCache; /* PRIVATE: Cache that owns this page */
PgHdr *pDirty; /* Transient list of dirty sorted by pgno */
Pager *pPager; /* The pager this page is part of */
Pgno pgno; /* Page number for this page */
@@ -13193,12 +14344,11 @@ struct PgHdr {
u16 flags; /* PGHDR flags defined below */
/**********************************************************************
- ** Elements above are public. All that follows is private to pcache.c
- ** and should not be accessed by other modules.
+ ** Elements above, except pCache, are public. All that follow are
+ ** private to pcache.c and should not be accessed by other modules.
+ ** pCache is grouped with the public elements for efficiency.
*/
i16 nRef; /* Number of users of this page */
- PCache *pCache; /* Cache that owns this page */
-
PgHdr *pDirtyNext; /* Next element in list of dirty pages */
PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */
};
@@ -13720,7 +14870,7 @@ SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *);
** and the one-based values are used internally.
*/
#ifndef SQLITE_DEFAULT_SYNCHRONOUS
-# define SQLITE_DEFAULT_SYNCHRONOUS (PAGER_SYNCHRONOUS_FULL-1)
+# define SQLITE_DEFAULT_SYNCHRONOUS 2
#endif
#ifndef SQLITE_DEFAULT_WAL_SYNCHRONOUS
# define SQLITE_DEFAULT_WAL_SYNCHRONOUS SQLITE_DEFAULT_SYNCHRONOUS
@@ -13925,6 +15075,8 @@ struct sqlite3 {
u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */
u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */
u8 mTrace; /* zero or more SQLITE_TRACE flags */
+ u8 skipBtreeMutex; /* True if no shared-cache backends */
+ u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
int nextPagesize; /* Pagesize after VACUUM if >0 */
u32 magic; /* Magic number for detect library misuse */
int nChange; /* Value returned by sqlite3_changes() */
@@ -14038,8 +15190,8 @@ struct sqlite3 {
** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC
** SQLITE_CacheSpill == PAGER_CACHE_SPILL
*/
-#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
-#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */
+#define SQLITE_WriteSchema 0x00000001 /* OK to update SQLITE_MASTER */
+#define SQLITE_LegacyFileFmt 0x00000002 /* Create new databases in format 1 */
#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */
#define SQLITE_FullFSync 0x00000008 /* Use full fsync on the backend */
#define SQLITE_CkptFullFSync 0x00000010 /* Use full fsync for checkpoint */
@@ -14050,28 +15202,34 @@ struct sqlite3 {
/* the count using a callback. */
#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
/* result set is empty */
-#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */
-#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */
-#define SQLITE_VdbeAddopTrace 0x00001000 /* Trace sqlite3VdbeAddOp() calls */
-#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */
-#define SQLITE_ReadUncommitted 0x0004000 /* For shared-cache mode */
-#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */
-#define SQLITE_RecoveryMode 0x00010000 /* Ignore schema errors */
-#define SQLITE_ReverseOrder 0x00020000 /* Reverse unordered SELECTs */
-#define SQLITE_RecTriggers 0x00040000 /* Enable recursive triggers */
-#define SQLITE_ForeignKeys 0x00080000 /* Enforce foreign key constraints */
-#define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */
-#define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */
-#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */
-#define SQLITE_LoadExtFunc 0x00800000 /* Enable load_extension() SQL func */
-#define SQLITE_EnableTrigger 0x01000000 /* True to enable triggers */
-#define SQLITE_DeferFKs 0x02000000 /* Defer all FK constraints */
-#define SQLITE_QueryOnly 0x04000000 /* Disable database changes */
-#define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */
-#define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */
-#define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */
-#define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */
+#define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */
+#define SQLITE_ReadUncommit 0x00000400 /* READ UNCOMMITTED in shared-cache */
+#define SQLITE_NoCkptOnClose 0x00000800 /* No checkpoint on close()/DETACH */
+#define SQLITE_ReverseOrder 0x00001000 /* Reverse unordered SELECTs */
+#define SQLITE_RecTriggers 0x00002000 /* Enable recursive triggers */
+#define SQLITE_ForeignKeys 0x00004000 /* Enforce foreign key constraints */
+#define SQLITE_AutoIndex 0x00008000 /* Enable automatic indexes */
+#define SQLITE_LoadExtension 0x00010000 /* Enable load_extension */
+#define SQLITE_EnableTrigger 0x00020000 /* True to enable triggers */
+#define SQLITE_DeferFKs 0x00040000 /* Defer all FK constraints */
+#define SQLITE_QueryOnly 0x00080000 /* Disable database changes */
+#define SQLITE_CellSizeCk 0x00100000 /* Check btree cell sizes on load */
+#define SQLITE_Fts3Tokenizer 0x00200000 /* Enable fts3_tokenizer(2) */
+#define SQLITE_EnableQPSG 0x00400000 /* Query Planner Stability Guarantee */
+/* The next four values are not used by PRAGMAs or by sqlite3_dbconfig() and
+** could be factored out into a separate bit vector of the sqlite3 object. */
+#define SQLITE_InternChanges 0x00800000 /* Uncommitted Hash table changes */
+#define SQLITE_LoadExtFunc 0x01000000 /* Enable load_extension() SQL func */
+#define SQLITE_PreferBuiltin 0x02000000 /* Preference to built-in funcs */
+#define SQLITE_Vacuum 0x04000000 /* Currently in a VACUUM */
+/* Flags used only if debugging */
+#ifdef SQLITE_DEBUG
+#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing 0x10000000 /* Debug listings of VDBE programs */
+#define SQLITE_VdbeTrace 0x20000000 /* True to trace VDBE execution */
+#define SQLITE_VdbeAddopTrace 0x40000000 /* Trace sqlite3VdbeAddOp() calls */
+#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */
+#endif
/*
@@ -14091,19 +15249,15 @@ struct sqlite3 {
#define SQLITE_Transitive 0x0200 /* Transitive constraints */
#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
+#define SQLITE_CountOfView 0x1000 /* The count-of-view optimization */
#define SQLITE_CursorHints 0x2000 /* Add OP_CursorHint opcodes */
#define SQLITE_AllOpts 0xffff /* All optimizations */
/*
** Macros for testing whether or not optimizations are enabled or disabled.
*/
-#ifndef SQLITE_OMIT_BUILTIN_TEST
#define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0)
#define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0)
-#else
-#define OptimizationDisabled(db, mask) 0
-#define OptimizationEnabled(db, mask) 1
-#endif
/*
** Return true if it OK to factor constant expressions into the initialization
@@ -14194,6 +15348,7 @@ struct FuncDestructor {
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
** single query - might change over time */
+#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -14213,7 +15368,14 @@ struct FuncDestructor {
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
** adds the SQLITE_FUNC_SLOCHNG flag. Used for date & time functions
** and functions like sqlite_version() that can change, but not during
-** a single query.
+** a single query. The iArg is ignored. The user-data is always set
+** to a NULL pointer. The bNC parameter is not used.
+**
+** PURE_DATE(zName, nArg, iArg, bNC, xFunc)
+** Used for "pure" date/time functions, this macro is like DFUNCTION
+** except that it does set the SQLITE_FUNC_CONSTANT flags. iArg is
+** ignored and the user-data for these functions is set to an
+** arbitrary non-NULL pointer. The bNC parameter is not used.
**
** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
** Used to create an aggregate function definition implemented by
@@ -14236,8 +15398,11 @@ struct FuncDestructor {
{nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
+ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
+ 0, 0, xFunc, 0, #zName, {0} }
+#define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \
+ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
+ (void*)&sqlite3Config, 0, xFunc, 0, #zName, {0} }
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
{nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
@@ -14442,15 +15607,15 @@ struct Table {
ExprList *pCheck; /* All CHECK constraints */
/* ... also used as column name list in a VIEW */
int tnum; /* Root BTree page for this table */
+ u32 nTabRef; /* Number of pointers to this Table */
+ u32 tabFlags; /* Mask of TF_* values */
i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
i16 nCol; /* Number of columns in this table */
- u16 nRef; /* Number of pointers to this Table */
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
LogEst szTabRow; /* Estimated size of each table row in bytes */
#ifdef SQLITE_ENABLE_COSTMULT
LogEst costMult; /* Cost multiplier for using this table */
#endif
- u8 tabFlags; /* Mask of TF_* values */
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
#ifndef SQLITE_OMIT_ALTERTABLE
int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
@@ -14474,15 +15639,17 @@ struct Table {
** the TF_OOOHidden attribute would apply in this case. Such tables require
** special handling during INSERT processing.
*/
-#define TF_Readonly 0x01 /* Read-only system table */
-#define TF_Ephemeral 0x02 /* An ephemeral table */
-#define TF_HasPrimaryKey 0x04 /* Table has a primary key */
-#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */
-#define TF_Virtual 0x10 /* Is a virtual table */
-#define TF_WithoutRowid 0x20 /* No rowid. PRIMARY KEY is the key */
-#define TF_NoVisibleRowid 0x40 /* No user-visible "rowid" column */
-#define TF_OOOHidden 0x80 /* Out-of-Order hidden columns */
-
+#define TF_Readonly 0x0001 /* Read-only system table */
+#define TF_Ephemeral 0x0002 /* An ephemeral table */
+#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */
+#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */
+#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */
+#define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */
+#define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */
+#define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */
+#define TF_StatsUsed 0x0100 /* Query planner decisions affected by
+ ** Index.aiRowLogEst[] values */
+#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -14490,7 +15657,7 @@ struct Table {
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
-# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0)
+# define IsVirtual(X) ((X)->nModuleArg)
#else
# define IsVirtual(X) 0
#endif
@@ -14725,6 +15892,7 @@ struct Index {
unsigned isResized:1; /* True if resizeIndexObject() has been called */
unsigned isCovering:1; /* True if this is a covering index */
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
+ unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
int nSample; /* Number of elements in aSample[] */
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
@@ -14954,8 +16122,8 @@ struct Expr {
*/
#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
#define EP_Agg 0x000002 /* Contains one or more aggregate functions */
-#define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */
-#define EP_Error 0x000008 /* Expression contains one or more errors */
+ /* 0x000004 // available for use */
+ /* 0x000008 // available for use */
#define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
@@ -15034,8 +16202,9 @@ struct Expr {
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
+ int nAlloc; /* Number of a[] slots allocated */
struct ExprList_item { /* For each expression in the list */
- Expr *pExpr; /* The list of expressions */
+ Expr *pExpr; /* The parse tree for this expression */
char *zName; /* Token associated with this expression */
char *zSpan; /* Original text of the expression */
u8 sortOrder; /* 1 for DESC or 0 for ASC */
@@ -15049,7 +16218,7 @@ struct ExprList {
} x;
int iConstExprReg; /* Register in which Expr value is cached */
} u;
- } *a; /* Alloc a power of two greater or equal to nExpr */
+ } a[1]; /* One slot for each expression in the list */
};
/*
@@ -15200,7 +16369,7 @@ struct SrcList {
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
#define WHERE_SEEK_TABLE 0x0400 /* Do not defer seeks on main table */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
- /* 0x1000 not currently used */
+#define WHERE_SEEK_UNIQ_TABLE 0x1000 /* Do not defer seeks if unique */
/* 0x2000 not currently used */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
@@ -15421,10 +16590,10 @@ struct Select {
*/
struct SelectDest {
u8 eDest; /* How to dispose of the results. On of SRT_* above. */
- char *zAffSdst; /* Affinity used when eDest==SRT_Set */
int iSDParm; /* A parameter used by the eDest disposal method */
int iSdst; /* Base register where results are written */
int nSdst; /* Number of registers allocated */
+ char *zAffSdst; /* Affinity used when eDest==SRT_Set */
ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */
};
@@ -15534,8 +16703,8 @@ struct Parse {
int nMem; /* Number of memory cells used so far */
int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
- int ckBase; /* Base register of data during check constraints */
- int iSelfTab; /* Table of an index whose exprs are being coded */
+ int iSelfTab; /* Table for associated with an index on expr, or negative
+ ** of the base register during check-constraint eval */
int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
int iCacheCnt; /* Counter used to generate aColCache[].lru values */
int nLabel; /* Number of labels used */
@@ -15593,7 +16762,6 @@ struct Parse {
Token sLastToken; /* The last token parsed */
ynVar nVar; /* Number of '?' variables seen in the SQL so far */
- int nzVar; /* Number of available slots in azVar[] */
u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
u8 explain; /* True if the EXPLAIN flag is found on the query */
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -15605,7 +16773,7 @@ struct Parse {
int iSelectId; /* ID of current select for EXPLAIN output */
int iNextSelectId; /* Next available select ID for EXPLAIN output */
#endif
- char **azVar; /* Pointers to names of parameters */
+ VList *pVList; /* Mapping between variable names and numbers */
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
const char *zTail; /* All SQL text past the last semicolon parsed */
Table *pNewTable; /* A table being constructed by CREATE TABLE */
@@ -15662,13 +16830,11 @@ struct AuthContext {
#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */
/* Also used in P2 (not P5) of OP_Delete */
#define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */
-#define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */
+#define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
#define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */
-#endif
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
@@ -15676,7 +16842,7 @@ struct AuthContext {
#define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */
#define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
-#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete: keep cursor position */
+#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
/*
@@ -15873,7 +17039,7 @@ struct Sqlite3Config {
void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
#endif
int bLocaltimeFault; /* True to fail localtime() calls */
@@ -15909,14 +17075,17 @@ struct Walker {
int walkerDepth; /* Number of subqueries */
u8 eCode; /* A small processing code */
union { /* Extra data for callback */
- NameContext *pNC; /* Naming context */
- int n; /* A counter */
- int iCur; /* A cursor number */
- SrcList *pSrcList; /* FROM clause */
- struct SrcCount *pSrcCount; /* Counting column references */
- struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
- int *aiCol; /* array of column indexes */
- struct IdxCover *pIdxCover; /* Check for index coverage */
+ NameContext *pNC; /* Naming context */
+ int n; /* A counter */
+ int iCur; /* A cursor number */
+ SrcList *pSrcList; /* FROM clause */
+ struct SrcCount *pSrcCount; /* Counting column references */
+ struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
+ int *aiCol; /* array of column indexes */
+ struct IdxCover *pIdxCover; /* Check for index coverage */
+ struct IdxExprTrans *pIdxTrans; /* Convert indexed expr to column */
+ ExprList *pGroupBy; /* GROUP BY clause */
+ struct HavingToWhereCtx *pHavingCtx; /* HAVING to WHERE clause ctx */
} u;
};
@@ -15927,6 +17096,10 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*);
SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*);
+SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*);
+#endif
/*
** Return code from the parse-tree walking primitives and their
@@ -15988,11 +17161,14 @@ SQLITE_PRIVATE int sqlite3CantopenError(int);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3NomemError(int);
SQLITE_PRIVATE int sqlite3IoerrnomemError(int);
+SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
# define SQLITE_NOMEM_BKPT sqlite3NomemError(__LINE__)
# define SQLITE_IOERR_NOMEM_BKPT sqlite3IoerrnomemError(__LINE__)
+# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P))
#else
# define SQLITE_NOMEM_BKPT SQLITE_NOMEM
# define SQLITE_IOERR_NOMEM_BKPT SQLITE_IOERR_NOMEM
+# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__)
#endif
/*
@@ -16070,6 +17246,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void*, u64);
SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64);
SQLITE_PRIVATE void sqlite3DbFree(sqlite3*, void*);
+SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3*, void*);
SQLITE_PRIVATE int sqlite3MallocSize(void*);
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, void*);
SQLITE_PRIVATE void *sqlite3ScratchMalloc(int);
@@ -16077,7 +17254,7 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void*);
SQLITE_PRIVATE void *sqlite3PageMalloc(int);
SQLITE_PRIVATE void sqlite3PageFree(void*);
SQLITE_PRIVATE void sqlite3MemSetDefault(void);
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
#endif
SQLITE_PRIVATE int sqlite3HeapNearlyFull(void);
@@ -16188,7 +17365,7 @@ SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse*,int,int);
SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*);
SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
-SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
+SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
@@ -16204,6 +17381,9 @@ SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
+#endif
SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*);
SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int);
SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
@@ -16232,7 +17412,7 @@ SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlite3_vfs**,char**,char **);
SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
-#ifdef SQLITE_OMIT_BUILTIN_TEST
+#ifdef SQLITE_UNTESTABLE
# define sqlite3FaultSim(X) SQLITE_OK
#else
SQLITE_PRIVATE int sqlite3FaultSim(int);
@@ -16245,7 +17425,7 @@ SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32);
SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*);
SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*);
SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*);
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*);
#endif
@@ -16334,7 +17514,7 @@ SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int);
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
-SQLITE_PRIVATE void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8);
+SQLITE_PRIVATE int sqlite3ExprCodeAtInit(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
@@ -16342,6 +17522,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */
#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
#define SQLITE_ECEL_REF 0x04 /* Use ExprList.u.x.iOrderByCol */
+#define SQLITE_ECEL_OMITREF 0x08 /* Omit if ExprList.u.x.iOrderByCol */
SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int);
@@ -16356,15 +17537,16 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*);
SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int);
SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*);
-SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprCompare(Parse*,Expr*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int);
-SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
SQLITE_PRIVATE void sqlite3PrngSaveState(void);
SQLITE_PRIVATE void sqlite3PrngRestoreState(void);
#endif
@@ -16372,14 +17554,14 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int);
SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int);
SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int);
-SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*);
-SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*);
+SQLITE_PRIVATE void sqlite3EndTransaction(Parse*,int);
SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*);
SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *);
SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8);
+SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
@@ -16395,6 +17577,11 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,I
SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int);
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
u8,u8,int,int*,int*);
+#ifdef SQLITE_ENABLE_NULL_TRIM
+SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe*,Table*);
+#else
+# define sqlite3SetMakeRecordP5(A,B)
+#endif
SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
@@ -16488,7 +17675,9 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8);
SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
SQLITE_PRIVATE int sqlite3Atoi(const char*);
+#ifndef SQLITE_OMIT_UTF16
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
+#endif
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
SQLITE_PRIVATE LogEst sqlite3LogEst(u64);
@@ -16501,6 +17690,9 @@ SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double);
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst);
#endif
+SQLITE_PRIVATE VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int);
+SQLITE_PRIVATE const char *sqlite3VListNumToName(VList*,int);
+SQLITE_PRIVATE int sqlite3VListNameToNum(VList*,const char*,int);
/*
** Routines to read and write variable-length integers. These used to
@@ -16574,7 +17766,9 @@ SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value*);
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*);
SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *);
+#ifndef SQLITE_OMIT_UTF16
SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
+#endif
SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
@@ -16670,8 +17864,10 @@ SQLITE_PRIVATE char sqlite3IndexColumnAffinity(sqlite3*, Index*, int);
/*
** The interface to the LEMON-generated parser
*/
-SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64));
-SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*));
+#ifndef SQLITE_AMALGAMATION
+SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64));
+SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*));
+#endif
SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*);
#ifdef YYTRACKMAXSTACKDEPTH
SQLITE_PRIVATE int sqlite3ParserStackPeak(void*);
@@ -16717,6 +17913,13 @@ SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*);
SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int);
SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*);
+SQLITE_PRIVATE Module *sqlite3VtabCreateModule(
+ sqlite3*,
+ const char*,
+ const sqlite3_module*,
+ void*,
+ void(*)(void*)
+ );
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
@@ -16774,6 +17977,7 @@ SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *);
#define sqlite3FkDropTable(a,b,c)
#define sqlite3FkOldmask(a,b) 0
#define sqlite3FkRequired(a,b,c,d) 0
+ #define sqlite3FkReferences(a) 0
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*);
@@ -16792,10 +17996,10 @@ SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
/*
** The interface to the code in fault.c used for identifying "benign"
-** malloc failures. This is only present if SQLITE_OMIT_BUILTIN_TEST
+** malloc failures. This is only present if SQLITE_UNTESTABLE
** is not defined.
*/
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void);
SQLITE_PRIVATE void sqlite3EndBenignMalloc(void);
#else
@@ -16926,6 +18130,11 @@ SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr);
SQLITE_PRIVATE int sqlite3ExprIsVector(Expr *pExpr);
SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr*, int);
SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int);
+SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*);
+
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt);
+#endif
#endif /* SQLITEINT_H */
@@ -17229,37 +18438,39 @@ typedef struct CellInfo CellInfo;
#define PTF_LEAF 0x08
/*
-** As each page of the file is loaded into memory, an instance of the following
-** structure is appended and initialized to zero. This structure stores
-** information about the page that is decoded from the raw file page.
+** An instance of this object stores information about each a single database
+** page that has been loaded into memory. The information in this object
+** is derived from the raw on-disk page content.
**
-** The pParent field points back to the parent page. This allows us to
-** walk up the BTree from any leaf to the root. Care must be taken to
-** unref() the parent page pointer when this page is no longer referenced.
-** The pageDestructor() routine handles that chore.
+** As each database page is loaded into memory, the pager allocats an
+** instance of this object and zeros the first 8 bytes. (This is the
+** "extra" information associated with each page of the pager.)
**
** Access to all fields of this structure is controlled by the mutex
** stored in MemPage.pBt->mutex.
*/
struct MemPage {
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
- u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
+ u8 bBusy; /* Prevent endless loops on corrupt database files */
u8 intKey; /* True if table b-trees. False for index b-trees */
u8 intKeyLeaf; /* True if the leaf of an intKey table */
+ Pgno pgno; /* Page number for this page */
+ /* Only the first 8 bytes (above) are zeroed by pager.c when a new page
+ ** is allocated. All fields that follow must be initialized before use */
u8 leaf; /* True if a leaf page */
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
u8 max1bytePayload; /* min(maxLocal,127) */
- u8 bBusy; /* Prevent endless loops on corrupt database files */
+ u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
u16 cellOffset; /* Index in aData of first cell pointer */
u16 nFree; /* Number of free bytes on the page */
u16 nCell; /* Number of cells on this page, local and ovfl */
u16 maskPage; /* Mask for page offset */
- u16 aiOvfl[5]; /* Insert the i-th overflow cell before the aiOvfl-th
+ u16 aiOvfl[4]; /* Insert the i-th overflow cell before the aiOvfl-th
** non-overflow cell */
- u8 *apOvfl[5]; /* Pointers to the body of overflow cells */
+ u8 *apOvfl[4]; /* Pointers to the body of overflow cells */
BtShared *pBt; /* Pointer to BtShared that this page is part of */
u8 *aData; /* Pointer to disk image of the page data */
u8 *aDataEnd; /* One byte past the end of usable data */
@@ -17268,16 +18479,8 @@ struct MemPage {
DbPage *pDbPage; /* Pager page handle */
u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */
void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */
- Pgno pgno; /* Page number for this page */
};
-/*
-** The in-memory image of a disk page has the auxiliary information appended
-** to the end. EXTRA_SIZE is the number of bytes of space needed to hold
-** that extra information.
-*/
-#define EXTRA_SIZE sizeof(MemPage)
-
/*
** 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
@@ -17424,10 +18627,12 @@ struct BtShared {
#define BTS_READ_ONLY 0x0001 /* Underlying file is readonly */
#define BTS_PAGESIZE_FIXED 0x0002 /* Page size can no longer be changed */
#define BTS_SECURE_DELETE 0x0004 /* PRAGMA secure_delete is enabled */
-#define BTS_INITIALLY_EMPTY 0x0008 /* Database was empty at trans start */
-#define BTS_NO_WAL 0x0010 /* Do not open write-ahead-log files */
-#define BTS_EXCLUSIVE 0x0020 /* pWriter has an exclusive lock */
-#define BTS_PENDING 0x0040 /* Waiting for read-locks to clear */
+#define BTS_OVERWRITE 0x0008 /* Overwrite deleted content with zeros */
+#define BTS_FAST_SECURE 0x000c /* Combination of the previous two */
+#define BTS_INITIALLY_EMPTY 0x0010 /* Database was empty at trans start */
+#define BTS_NO_WAL 0x0020 /* Do not open write-ahead-log files */
+#define BTS_EXCLUSIVE 0x0040 /* pWriter has an exclusive lock */
+#define BTS_PENDING 0x0080 /* Waiting for read-locks to clear */
/*
** An instance of the following structure is used to hold information
@@ -17493,10 +18698,10 @@ struct BtCursor {
** initialized. */
i8 iPage; /* Index of current page in apPage */
u8 curIntKey; /* Value of apPage[0]->intKey */
- struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
- void *padding1; /* Make object size a multiple of 16 */
- u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */
- MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
+ u16 ix; /* Current index for apPage[iPage] */
+ u16 aiIdx[BTCURSOR_MAX_DEPTH-1]; /* Current index in apPage[i] */
+ struct KeyInfo *pKeyInfo; /* Arg passed to comparison function */
+ MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
};
/*
@@ -17668,11 +18873,9 @@ struct IntegrityCk {
*/
#if SQLITE_BYTEORDER==4321
# define get2byteAligned(x) (*(u16*)(x))
-#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
- && GCC_VERSION>=4008000
+#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4008000
# define get2byteAligned(x) __builtin_bswap16(*(u16*)(x))
-#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
- && defined(_MSC_VER) && _MSC_VER>=1300
+#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
# define get2byteAligned(x) _byteswap_ushort(*(u16*)(x))
#else
# define get2byteAligned(x) ((x)[0]<<8 | (x)[1])
@@ -17729,9 +18932,9 @@ struct IntegrityCk {
#ifndef CIPHER_VERSION
#ifdef SQLCIPHER_FIPS
-#define CIPHER_VERSION "3.4.1 FIPS"
+#define CIPHER_VERSION "3.4.2 FIPS"
#else
-#define CIPHER_VERSION "3.4.1"
+#define CIPHER_VERSION "3.4.2"
#endif
#endif
@@ -17784,11 +18987,28 @@ struct IntegrityCk {
#define CIPHER_MAX_KEY_SZ 64
#endif
+#ifdef __ANDROID__
+#include
+#endif
+
+#ifdef CODEC_DEBUG_MUTEX
+#ifdef __ANDROID__
+#define CODEC_TRACE_MUTEX(...) {__android_log_print(ANDROID_LOG_DEBUG, "sqlcipher", __VA_ARGS__);}
+#else
+#define CODEC_TRACE_MUTEX(...) {fprintf(stderr, __VA_ARGS__);fflush(stderr);}
+#endif
+#else
+#define CODEC_TRACE_MUTEX(...)
+#endif
#ifdef CODEC_DEBUG
-#define CODEC_TRACE(X) {printf X;fflush(stdout);}
+#ifdef __ANDROID__
+#define CODEC_TRACE(...) {__android_log_print(ANDROID_LOG_DEBUG, "sqlcipher", __VA_ARGS__);}
#else
-#define CODEC_TRACE(X)
+#define CODEC_TRACE(...) {fprintf(stderr, __VA_ARGS__);fflush(stderr);}
+#endif
+#else
+#define CODEC_TRACE(...)
#endif
#ifdef CODEC_DEBUG_PAGEDATA
@@ -17919,12 +19139,14 @@ const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx);
int sqlcipher_codec_ctx_migrate(codec_ctx *ctx);
int sqlcipher_codec_add_random(codec_ctx *ctx, const char *data, int random_sz);
int sqlcipher_cipher_profile(sqlite3 *db, const char *destination);
-static void sqlcipher_profile_callback(void *file, const char *sql, sqlite3_uint64 run_time);
-static int sqlcipher_codec_get_store_pass(codec_ctx *ctx);
-static void sqlcipher_codec_get_pass(codec_ctx *ctx, void **zKey, int *nKey);
-static void sqlcipher_codec_set_store_pass(codec_ctx *ctx, int value);
+int sqlcipher_codec_get_store_pass(codec_ctx *ctx);
+void sqlcipher_codec_get_pass(codec_ctx *ctx, void **zKey, int *nKey);
+void sqlcipher_codec_set_store_pass(codec_ctx *ctx, int value);
int sqlcipher_codec_fips_status(codec_ctx *ctx);
const char* sqlcipher_codec_get_provider_version(codec_ctx *ctx);
+int sqlcipher_codec_hmac(const codec_ctx *ctx, const unsigned char *hmac_key, int key_sz,
+ unsigned char* in, int in_sz, unsigned char *in2, int in2_sz,
+ unsigned char *out);
#endif
#endif
/* END SQLCIPHER */
@@ -17951,21 +19173,30 @@ static int codec_set_btree_to_codec_pagesize(sqlite3 *db, Db *pDb, codec_ctx *ct
page_sz = sqlcipher_codec_ctx_get_pagesize(ctx);
reserve_sz = sqlcipher_codec_ctx_get_reservesize(ctx);
+ CODEC_TRACE("codec_set_btree_to_codec_pagesize: sqlite3BtreeSetPageSize() size=%d reserve=%d\n", page_sz, reserve_sz);
+
+ CODEC_TRACE_MUTEX("codec_set_btree_to_codec_pagesize: entering database mutex %p\n", db->mutex);
sqlite3_mutex_enter(db->mutex);
+ CODEC_TRACE_MUTEX("codec_set_btree_to_codec_pagesize: entered database mutex %p\n", db->mutex);
db->nextPagesize = page_sz;
/* before forcing the page size we need to unset the BTS_PAGESIZE_FIXED flag, else
sqliteBtreeSetPageSize will block the change */
pDb->pBt->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
- CODEC_TRACE(("codec_set_btree_to_codec_pagesize: sqlite3BtreeSetPageSize() size=%d reserve=%d\n", page_sz, reserve_sz));
rc = sqlite3BtreeSetPageSize(pDb->pBt, page_sz, reserve_sz, 0);
+
+ CODEC_TRACE("codec_set_btree_to_codec_pagesize: sqlite3BtreeSetPageSize returned %d\n", rc);
+
+ CODEC_TRACE_MUTEX("codec_set_btree_to_codec_pagesize: leaving database mutex %p\n", db->mutex);
sqlite3_mutex_leave(db->mutex);
+ CODEC_TRACE_MUTEX("codec_set_btree_to_codec_pagesize: left database mutex %p\n", db->mutex);
+
return rc;
}
static int codec_set_pass_key(sqlite3* db, int nDb, const void *zKey, int nKey, int for_ctx) {
struct Db *pDb = &db->aDb[nDb];
- CODEC_TRACE(("codec_set_pass_key: entered db=%p nDb=%d zKey=%s nKey=%d for_ctx=%d\n", db, nDb, (char *)zKey, nKey, for_ctx));
+ CODEC_TRACE("codec_set_pass_key: entered db=%p nDb=%d zKey=%s nKey=%d for_ctx=%d\n", db, nDb, (char *)zKey, nKey, for_ctx);
if(pDb->pBt) {
codec_ctx *ctx;
sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
@@ -17984,7 +19215,7 @@ int sqlcipher_codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLef
sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
}
- CODEC_TRACE(("sqlcipher_codec_pragma: entered db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p\n", db, iDb, pParse, zLeft, zRight, ctx));
+ CODEC_TRACE("sqlcipher_codec_pragma: entered db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p\n", db, iDb, pParse, zLeft, zRight, ctx);
if( sqlite3StrICmp(zLeft, "cipher_fips_status")== 0 && !zRight ){
if(ctx) {
@@ -18196,7 +19427,7 @@ void* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) {
unsigned char *pData = (unsigned char *) data;
void *buffer = sqlcipher_codec_ctx_get_data(ctx);
void *kdf_salt = sqlcipher_codec_ctx_get_kdf_salt(ctx);
- CODEC_TRACE(("sqlite3Codec: entered pgno=%d, mode=%d, page_sz=%d\n", pgno, mode, page_sz));
+ CODEC_TRACE("sqlite3Codec: entered pgno=%d, mode=%d, page_sz=%d\n", pgno, mode, page_sz);
/* call to derive keys if not present yet */
if((rc = sqlcipher_codec_key_derive(ctx)) != SQLITE_OK) {
@@ -18206,7 +19437,7 @@ void* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) {
if(pgno == 1) offset = FILE_HEADER_SZ; /* adjust starting pointers in data page for header offset on first page*/
- CODEC_TRACE(("sqlite3Codec: switch mode=%d offset=%d\n", mode, offset));
+ CODEC_TRACE("sqlite3Codec: switch mode=%d offset=%d\n", mode, offset);
switch(mode) {
case 0: /* decrypt */
case 2:
@@ -18245,7 +19476,7 @@ SQLITE_PRIVATE void sqlite3FreeCodecArg(void *pCodecArg) {
SQLITE_PRIVATE int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) {
struct Db *pDb = &db->aDb[nDb];
- CODEC_TRACE(("sqlite3CodecAttach: entered nDb=%d zKey=%s, nKey=%d\n", nDb, (char *)zKey, nKey));
+ CODEC_TRACE("sqlite3CodecAttach: entered db=%p, nDb=%d zKey=%s, nKey=%d\n", db, nDb, (char *)zKey, nKey);
if(nKey && zKey && pDb->pBt) {
@@ -18254,35 +19485,48 @@ SQLITE_PRIVATE int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, in
sqlite3_file *fd = sqlite3Pager_get_fd(pPager);
codec_ctx *ctx;
+ CODEC_TRACE("sqlite3CodecAttach: calling sqlcipher_activate()\n");
sqlcipher_activate(); /* perform internal initialization for sqlcipher */
+ CODEC_TRACE_MUTEX("sqlite3CodecAttach: entering database mutex %p\n", db->mutex);
sqlite3_mutex_enter(db->mutex);
+ CODEC_TRACE_MUTEX("sqlite3CodecAttach: entered database mutex %p\n", db->mutex);
/* point the internal codec argument against the contet to be prepared */
+ CODEC_TRACE("sqlite3CodecAttach: calling sqlcipher_codec_ctx_init()\n");
rc = sqlcipher_codec_ctx_init(&ctx, pDb, pDb->pBt->pBt->pPager, fd, zKey, nKey);
if(rc != SQLITE_OK) {
/* initialization failed, do not attach potentially corrupted context */
+ CODEC_TRACE("sqlite3CodecAttach: context initialization failed with rc=%d\n", rc);
+ CODEC_TRACE_MUTEX("sqlite3CodecAttach: leaving database mutex %p (early return on rc=%d)\n", db->mutex, rc);
sqlite3_mutex_leave(db->mutex);
+ CODEC_TRACE_MUTEX("sqlite3CodecAttach: left database mutex %p (early return on rc=%d)\n", db->mutex, rc);
return rc;
}
+ CODEC_TRACE("sqlite3CodecAttach: calling sqlite3pager_sqlite3PagerSetCodec()\n");
sqlite3pager_sqlite3PagerSetCodec(sqlite3BtreePager(pDb->pBt), sqlite3Codec, NULL, sqlite3FreeCodecArg, (void *) ctx);
+ CODEC_TRACE("sqlite3CodecAttach: calling codec_set_btree_to_codec_pagesize()\n");
codec_set_btree_to_codec_pagesize(db, pDb, ctx);
/* force secure delete. This has the benefit of wiping internal data when deleted
and also ensures that all pages are written to disk (i.e. not skipped by
sqlite3PagerDontWrite optimizations) */
+ CODEC_TRACE("sqlite3CodecAttach: calling sqlite3BtreeSecureDelete()\n");
sqlite3BtreeSecureDelete(pDb->pBt, 1);
/* if fd is null, then this is an in-memory database and
we dont' want to overwrite the AutoVacuum settings
if not null, then set to the default */
if(fd != NULL) {
+ CODEC_TRACE("sqlite3CodecAttach: calling sqlite3BtreeSetAutoVacuum()\n");
sqlite3BtreeSetAutoVacuum(pDb->pBt, SQLITE_DEFAULT_AUTOVACUUM);
}
+ CODEC_TRACE_MUTEX("sqlite3CodecAttach: leaving database mutex %p\n", db->mutex);
sqlite3_mutex_leave(db->mutex);
+ CODEC_TRACE_MUTEX("sqlite3CodecAttach: left database mutex %p\n", db->mutex);
}
return SQLITE_OK;
}
@@ -18306,12 +19550,12 @@ static int sqlcipher_find_db_index(sqlite3 *db, const char *zDb) {
}
SQLITE_API int sqlite3_key(sqlite3 *db, const void *pKey, int nKey) {
- CODEC_TRACE(("sqlite3_key entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey));
+ CODEC_TRACE("sqlite3_key entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey);
return sqlite3_key_v2(db, "main", pKey, nKey);
}
SQLITE_API int sqlite3_key_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) {
- CODEC_TRACE(("sqlite3_key_v2: entered db=%p zDb=%s pKey=%s nKey=%d\n", db, zDb, (char *)pKey, nKey));
+ CODEC_TRACE("sqlite3_key_v2: entered db=%p zDb=%s pKey=%s nKey=%d\n", db, zDb, (char *)pKey, nKey);
/* attach key if db and pKey are not null and nKey is > 0 */
if(db && pKey && nKey) {
int db_index = sqlcipher_find_db_index(db, zDb);
@@ -18321,7 +19565,7 @@ SQLITE_API int sqlite3_key_v2(sqlite3 *db, const char *zDb, const void *pKey, in
}
SQLITE_API int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) {
- CODEC_TRACE(("sqlite3_rekey entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey));
+ CODEC_TRACE("sqlite3_rekey entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey);
return sqlite3_rekey_v2(db, "main", pKey, nKey);
}
@@ -18336,11 +19580,11 @@ SQLITE_API int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) {
** 3. If there is a key present, re-encrypt the database with the new key
*/
SQLITE_API int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) {
- CODEC_TRACE(("sqlite3_rekey_v2: entered db=%p zDb=%s pKey=%s, nKey=%d\n", db, zDb, (char *)pKey, nKey));
+ CODEC_TRACE("sqlite3_rekey_v2: entered db=%p zDb=%s pKey=%s, nKey=%d\n", db, zDb, (char *)pKey, nKey);
if(db && pKey && nKey) {
int db_index = sqlcipher_find_db_index(db, zDb);
struct Db *pDb = &db->aDb[db_index];
- CODEC_TRACE(("sqlite3_rekey_v2: database pDb=%p db_index:%d\n", pDb, db_index));
+ CODEC_TRACE("sqlite3_rekey_v2: database pDb=%p db_index:%d\n", pDb, db_index);
if(pDb->pBt) {
codec_ctx *ctx;
int rc, page_count;
@@ -18352,11 +19596,13 @@ SQLITE_API int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey,
if(ctx == NULL) {
/* there was no codec attached to this database, so this should do nothing! */
- CODEC_TRACE(("sqlite3_rekey_v2: no codec attached to db, exiting\n"));
+ CODEC_TRACE("sqlite3_rekey_v2: no codec attached to db, exiting\n");
return SQLITE_OK;
}
+ CODEC_TRACE_MUTEX("sqlite3_rekey_v2: entering database mutex %p\n", db->mutex);
sqlite3_mutex_enter(db->mutex);
+ CODEC_TRACE_MUTEX("sqlite3_rekey_v2: entered database mutex %p\n", db->mutex);
codec_set_pass_key(db, db_index, pKey, nKey, CIPHER_WRITE_CTX);
@@ -18376,25 +19622,27 @@ SQLITE_API int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey,
if(rc == SQLITE_OK) {
sqlite3PagerUnref(page);
} else {
- CODEC_TRACE(("sqlite3_rekey_v2: error %d occurred writing page %d\n", rc, pgno));
+ CODEC_TRACE("sqlite3_rekey_v2: error %d occurred writing page %d\n", rc, pgno);
}
} else {
- CODEC_TRACE(("sqlite3_rekey_v2: error %d occurred getting page %d\n", rc, pgno));
+ CODEC_TRACE("sqlite3_rekey_v2: error %d occurred getting page %d\n", rc, pgno);
}
}
}
/* if commit was successful commit and copy the rekey data to current key, else rollback to release locks */
if(rc == SQLITE_OK) {
- CODEC_TRACE(("sqlite3_rekey_v2: committing\n"));
+ CODEC_TRACE("sqlite3_rekey_v2: committing\n");
rc = sqlite3BtreeCommit(pDb->pBt);
sqlcipher_codec_key_copy(ctx, CIPHER_WRITE_CTX);
} else {
- CODEC_TRACE(("sqlite3_rekey_v2: rollback\n"));
+ CODEC_TRACE("sqlite3_rekey_v2: rollback\n");
sqlite3BtreeRollback(pDb->pBt, SQLITE_ABORT_ROLLBACK, 0);
}
+ CODEC_TRACE_MUTEX("sqlite3_rekey_v2: leaving database mutex %p\n", db->mutex);
sqlite3_mutex_leave(db->mutex);
+ CODEC_TRACE_MUTEX("sqlite3_rekey_v2: left database mutex %p\n", db->mutex);
}
return SQLITE_OK;
}
@@ -18403,7 +19651,7 @@ SQLITE_API int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey,
SQLITE_PRIVATE void sqlite3CodecGetKey(sqlite3* db, int nDb, void **zKey, int *nKey) {
struct Db *pDb = &db->aDb[nDb];
- CODEC_TRACE(("sqlite3CodecGetKey: entered db=%p, nDb=%d\n", db, nDb));
+ CODEC_TRACE("sqlite3CodecGetKey: entered db=%p, nDb=%d\n", db, nDb);
if( pDb->pBt ) {
codec_ctx *ctx;
sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
@@ -18506,6 +19754,7 @@ void sqlcipher_exportFunc(sqlite3_context *context, int argc, sqlite3_value **ar
int saved_flags; /* Saved value of the db->flags */
int saved_nChange; /* Saved value of db->nChange */
int saved_nTotalChange; /* Saved value of db->nTotalChange */
+ u8 saved_mTrace; /* Saved value of db->mTrace */
int (*saved_xTrace)(u32,void*,void*,void*); /* Saved db->xTrace */
int rc = SQLITE_OK; /* Return code from service routines */
char *zSql = NULL; /* SQL statements */
@@ -18515,9 +19764,11 @@ void sqlcipher_exportFunc(sqlite3_context *context, int argc, sqlite3_value **ar
saved_nChange = db->nChange;
saved_nTotalChange = db->nTotalChange;
saved_xTrace = db->xTrace;
+ saved_mTrace = db->mTrace;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin;
db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder);
db->xTrace = 0;
+ db->mTrace = 0;
/* Query the schema of the main database. Create a mirror schema
** in the temporary database.
@@ -18603,6 +19854,7 @@ end_of_export:
db->nChange = saved_nChange;
db->nTotalChange = saved_nTotalChange;
db->xTrace = saved_xTrace;
+ db->mTrace = saved_mTrace;
sqlite3_free(zSql);
@@ -18743,9 +19995,12 @@ sqlcipher_provider* sqlcipher_get_provider();
/* #include "crypto.h" */
#ifndef OMIT_MEMLOCK
#if defined(__unix__) || defined(__APPLE__) || defined(_AIX)
+#include
+#include
+#include
#include
#elif defined(_WIN32)
-# include
+#include
#endif
#endif
@@ -18795,7 +20050,10 @@ struct codec_ctx {
};
int sqlcipher_register_provider(sqlcipher_provider *p) {
+ CODEC_TRACE_MUTEX("sqlcipher_register_provider: entering sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
sqlite3_mutex_enter(sqlcipher_provider_mutex);
+ CODEC_TRACE_MUTEX("sqlcipher_register_provider: entered sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
+
if(default_provider != NULL && default_provider != p) {
/* only free the current registerd provider if it has been initialized
and it isn't a pointer to the same provider passed to the function
@@ -18803,7 +20061,10 @@ int sqlcipher_register_provider(sqlcipher_provider *p) {
sqlcipher_free(default_provider, sizeof(sqlcipher_provider));
}
default_provider = p;
+ CODEC_TRACE_MUTEX("sqlcipher_register_provider: leaving sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
sqlite3_mutex_leave(sqlcipher_provider_mutex);
+ CODEC_TRACE_MUTEX("sqlcipher_register_provider: left sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
+
return SQLITE_OK;
}
@@ -18815,11 +20076,15 @@ sqlcipher_provider* sqlcipher_get_provider() {
}
void sqlcipher_activate() {
+ CODEC_TRACE_MUTEX("sqlcipher_activate: entering static master mutex\n");
sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ CODEC_TRACE_MUTEX("sqlcipher_activate: entered static master mutex\n");
if(sqlcipher_provider_mutex == NULL) {
/* allocate a new mutex to guard access to the provider */
+ CODEC_TRACE_MUTEX("sqlcipher_activate: allocating sqlcipher provider mutex\n");
sqlcipher_provider_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ CODEC_TRACE_MUTEX("sqlcipher_activate: allocated sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
}
/* check to see if there is a provider registered at this point
@@ -18839,33 +20104,53 @@ void sqlcipher_activate() {
#else
#error "NO DEFAULT SQLCIPHER CRYPTO PROVIDER DEFINED"
#endif
+ CODEC_TRACE("sqlcipher_activate: calling sqlcipher_register_provider(%p)\n", p);
sqlcipher_register_provider(p);
+ CODEC_TRACE("sqlcipher_activate: called sqlcipher_register_provider(%p)\n",p);
}
sqlcipher_activate_count++; /* increment activation count */
+ CODEC_TRACE_MUTEX("sqlcipher_activate: leaving static master mutex\n");
sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ CODEC_TRACE_MUTEX("sqlcipher_activate: left static master mutex\n");
}
void sqlcipher_deactivate() {
+ CODEC_TRACE_MUTEX("sqlcipher_deactivate: entering static master mutex\n");
sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ CODEC_TRACE_MUTEX("sqlcipher_deactivate: entered static master mutex\n");
+
sqlcipher_activate_count--;
/* if no connections are using sqlcipher, cleanup globals */
if(sqlcipher_activate_count < 1) {
+ int rc;
+ CODEC_TRACE_MUTEX("sqlcipher_deactivate: entering sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
sqlite3_mutex_enter(sqlcipher_provider_mutex);
+ CODEC_TRACE_MUTEX("sqlcipher_deactivate: entered sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
+
if(default_provider != NULL) {
sqlcipher_free(default_provider, sizeof(sqlcipher_provider));
default_provider = NULL;
}
+
+ CODEC_TRACE_MUTEX("sqlcipher_deactivate: leaving sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
sqlite3_mutex_leave(sqlcipher_provider_mutex);
+ CODEC_TRACE_MUTEX("sqlcipher_deactivate: left sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
/* last connection closed, free provider mutex*/
+ CODEC_TRACE_MUTEX("sqlcipher_deactivate: freeing sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
sqlite3_mutex_free(sqlcipher_provider_mutex);
+ CODEC_TRACE_MUTEX("sqlcipher_deactivate: freed sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
+
sqlcipher_provider_mutex = NULL;
sqlcipher_activate_count = 0; /* reset activation count */
}
+
+ CODEC_TRACE_MUTEX("sqlcipher_deactivate: leaving static master mutex\n");
sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ CODEC_TRACE_MUTEX("sqlcipher_deactivate: left static master mutex\n");
}
/* constant time memset using volitile to avoid having the memset
@@ -18878,6 +20163,7 @@ void* sqlcipher_memset(void *v, unsigned char value, int len) {
if (v == NULL) return v;
+ CODEC_TRACE("sqlcipher_memset: setting %p[0-%d]=%d)\n", a, len, value);
for(i = 0; i < len; i++) {
a[i] = value;
}
@@ -18923,13 +20209,28 @@ int sqlcipher_memcmp(const void *v0, const void *v1, int len) {
void sqlcipher_free(void *ptr, int sz) {
if(ptr) {
if(sz > 0) {
+#ifndef OMIT_MEMLOCK
+ int rc;
+#if defined(__unix__) || defined(__APPLE__)
+ unsigned long pagesize = sysconf(_SC_PAGESIZE);
+ unsigned long offset = (unsigned long) ptr % pagesize;
+#endif
+#endif
+ CODEC_TRACE("sqlcipher_free: calling sqlcipher_memset(%p,0,%d)\n", ptr, sz);
sqlcipher_memset(ptr, 0, sz);
#ifndef OMIT_MEMLOCK
#if defined(__unix__) || defined(__APPLE__)
- munlock(ptr, sz);
+ CODEC_TRACE("sqlcipher_free: calling munlock(%p,%lu)\n", ptr - offset, sz + offset);
+ rc = munlock(ptr - offset, sz + offset);
+ if(rc!=0) {
+ CODEC_TRACE("sqlcipher_free: munlock(%p,%lu) returned %d errno=%d\n", ptr - offset, sz + offset, rc, errno);
+ }
#elif defined(_WIN32)
#if !(defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP || WINAPI_FAMILY == WINAPI_FAMILY_APP))
-VirtualUnlock(ptr, sz);
+ rc = VirtualUnlock(ptr, sz);
+ if(!rc) {
+ CODEC_TRACE("sqlcipher_free: VirtualUnlock(%p,%d) returned %d LastError=%d\n", ptr, sz, rc, GetLastError());
+ }
#endif
#endif
#endif
@@ -18944,15 +20245,28 @@ VirtualUnlock(ptr, sz);
* attempts to lock the memory pages so sensitive information won't be swapped
*/
void* sqlcipher_malloc(int sz) {
- void *ptr = sqlite3Malloc(sz);
+ void *ptr;
+ CODEC_TRACE("sqlcipher_malloc: calling sqlite3Malloc(%d)\n", sz);
+ ptr = sqlite3Malloc(sz);
+ CODEC_TRACE("sqlcipher_malloc: calling sqlcipher_memset(%p,0,%d)\n", ptr, sz);
sqlcipher_memset(ptr, 0, sz);
#ifndef OMIT_MEMLOCK
if(ptr) {
+ int rc;
#if defined(__unix__) || defined(__APPLE__)
- mlock(ptr, sz);
+ unsigned long pagesize = sysconf(_SC_PAGESIZE);
+ unsigned long offset = (unsigned long) ptr % pagesize;
+ CODEC_TRACE("sqlcipher_malloc: calling mlock(%p,%lu); _SC_PAGESIZE=%lu\n", ptr - offset, sz + offset, pagesize);
+ rc = mlock(ptr - offset, sz + offset);
+ if(rc!=0) {
+ CODEC_TRACE("sqlcipher_malloc: mlock(%p,%lu) returned %d errno=%d\n", ptr - offset, sz + offset, rc, errno);
+ }
#elif defined(_WIN32)
#if !(defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP || WINAPI_FAMILY == WINAPI_FAMILY_APP))
- VirtualLock(ptr, sz);
+ rc = VirtualLock(ptr, sz);
+ if(rc==0) {
+ CODEC_TRACE("sqlcipher_malloc: VirtualLock(%p,%d) returned %d LastError=%d\n", ptr, sz, rc, GetLastError());
+ }
#endif
#endif
}
@@ -18971,21 +20285,35 @@ void* sqlcipher_malloc(int sz) {
static int sqlcipher_cipher_ctx_init(cipher_ctx **iCtx) {
int rc;
cipher_ctx *ctx;
+ CODEC_TRACE("sqlcipher_cipher_ctx_init: allocating context\n");
*iCtx = (cipher_ctx *) sqlcipher_malloc(sizeof(cipher_ctx));
ctx = *iCtx;
if(ctx == NULL) return SQLITE_NOMEM;
+ CODEC_TRACE("sqlcipher_cipher_ctx_init: allocating provider\n");
ctx->provider = (sqlcipher_provider *) sqlcipher_malloc(sizeof(sqlcipher_provider));
if(ctx->provider == NULL) return SQLITE_NOMEM;
/* make a copy of the provider to be used for the duration of the context */
+ CODEC_TRACE_MUTEX("sqlcipher_cipher_ctx_init: entering sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
sqlite3_mutex_enter(sqlcipher_provider_mutex);
- memcpy(ctx->provider, default_provider, sizeof(sqlcipher_provider));
- sqlite3_mutex_leave(sqlcipher_provider_mutex);
+ CODEC_TRACE_MUTEX("sqlcipher_cipher_ctx_init: entered sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
+ memcpy(ctx->provider, default_provider, sizeof(sqlcipher_provider));
+
+ CODEC_TRACE_MUTEX("sqlcipher_cipher_ctx_init: leaving sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
+ sqlite3_mutex_leave(sqlcipher_provider_mutex);
+ CODEC_TRACE_MUTEX("sqlcipher_cipher_ctx_init: left sqlcipher provider mutex %p\n", sqlcipher_provider_mutex);
+
+ CODEC_TRACE("sqlcipher_cipher_ctx_init: calling provider ctx_init\n");
if((rc = ctx->provider->ctx_init(&ctx->provider_ctx)) != SQLITE_OK) return rc;
+
+ CODEC_TRACE("sqlcipher_cipher_ctx_init: allocating key\n");
ctx->key = (unsigned char *) sqlcipher_malloc(CIPHER_MAX_KEY_SZ);
+
+ CODEC_TRACE("sqlcipher_cipher_ctx_init: allocating hmac_key\n");
ctx->hmac_key = (unsigned char *) sqlcipher_malloc(CIPHER_MAX_KEY_SZ);
+
if(ctx->key == NULL) return SQLITE_NOMEM;
if(ctx->hmac_key == NULL) return SQLITE_NOMEM;
@@ -19000,7 +20328,7 @@ static int sqlcipher_cipher_ctx_init(cipher_ctx **iCtx) {
*/
static void sqlcipher_cipher_ctx_free(cipher_ctx **iCtx) {
cipher_ctx *ctx = *iCtx;
- CODEC_TRACE(("cipher_ctx_free: entered iCtx=%p\n", iCtx));
+ CODEC_TRACE("cipher_ctx_free: entered iCtx=%p\n", iCtx);
ctx->provider->ctx_free(&ctx->provider_ctx);
sqlcipher_free(ctx->provider, sizeof(sqlcipher_provider));
sqlcipher_free(ctx->key, ctx->key_sz);
@@ -19033,7 +20361,7 @@ static int sqlcipher_cipher_ctx_cmp(cipher_ctx *c1, cipher_ctx *c2) {
c1->pass_sz)
));
- CODEC_TRACE(("sqlcipher_cipher_ctx_cmp: entered \
+ CODEC_TRACE("sqlcipher_cipher_ctx_cmp: entered \
c1=%p c2=%p \
c1->iv_sz=%d c2->iv_sz=%d \
c1->kdf_iter=%d c2->kdf_iter=%d \
@@ -19061,11 +20389,13 @@ static int sqlcipher_cipher_ctx_cmp(cipher_ctx *c1, cipher_ctx *c2) {
c1->pass, c2->pass,
c1->pass, c2->pass,
c1->provider->ctx_cmp(c1->provider_ctx, c2->provider_ctx),
- sqlcipher_memcmp((const unsigned char*)c1->pass,
- (const unsigned char*)c2->pass,
- c1->pass_sz),
+ (c1->pass == NULL || c2->pass == NULL)
+ ? -1 : sqlcipher_memcmp(
+ (const unsigned char*)c1->pass,
+ (const unsigned char*)c2->pass,
+ c1->pass_sz),
are_equal
- ));
+ );
return !are_equal; /* return 0 if they are the same, 1 otherwise */
}
@@ -19084,7 +20414,7 @@ static int sqlcipher_cipher_ctx_copy(cipher_ctx *target, cipher_ctx *source) {
void *provider = target->provider;
void *provider_ctx = target->provider_ctx;
- CODEC_TRACE(("sqlcipher_cipher_ctx_copy: entered target=%p, source=%p\n", target, source));
+ CODEC_TRACE("sqlcipher_cipher_ctx_copy: entered target=%p, source=%p\n", target, source);
sqlcipher_free(target->pass, target->pass_sz);
sqlcipher_free(target->keyspec, target->keyspec_sz);
memcpy(target, source, sizeof(cipher_ctx));
@@ -19293,8 +20623,8 @@ int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use) {
reserve = ((reserve % ctx->read_ctx->block_sz) == 0) ? reserve :
((reserve / ctx->read_ctx->block_sz) + 1) * ctx->read_ctx->block_sz;
- CODEC_TRACE(("sqlcipher_codec_ctx_set_use_hmac: use=%d block_sz=%d md_size=%d reserve=%d\n",
- use, ctx->read_ctx->block_sz, ctx->read_ctx->hmac_sz, reserve));
+ CODEC_TRACE("sqlcipher_codec_ctx_set_use_hmac: use=%d block_sz=%d md_size=%d reserve=%d\n",
+ use, ctx->read_ctx->block_sz, ctx->read_ctx->hmac_sz, reserve);
if(use) {
@@ -19331,7 +20661,7 @@ int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, unsigned int flag, int for_ctx)
}
void sqlcipher_codec_ctx_set_error(codec_ctx *ctx, int error) {
- CODEC_TRACE(("sqlcipher_codec_ctx_set_error: ctx=%p, error=%d\n", ctx, error));
+ CODEC_TRACE("sqlcipher_codec_ctx_set_error: ctx=%p, error=%d\n", ctx, error);
sqlite3pager_sqlite3PagerSetError(ctx->pBt->pBt->pPager, error);
ctx->pBt->pBt->db->errCode = error;
}
@@ -19354,6 +20684,10 @@ void sqlcipher_codec_get_keyspec(codec_ctx *ctx, void **zKey, int *nKey) {
}
int sqlcipher_codec_ctx_set_pagesize(codec_ctx *ctx, int size) {
+ if(!((size != 0) && ((size & (size - 1)) == 0)) || size < 512 || size > 65536) {
+ CODEC_TRACE(("cipher_page_size not a power of 2 and between 512 and 65536 inclusive\n"));
+ return SQLITE_ERROR;
+ }
/* attempt to free the existing page buffer */
sqlcipher_free(ctx->buffer,ctx->page_sz);
ctx->page_sz = size;
@@ -19382,6 +20716,9 @@ int sqlcipher_get_default_pagesize() {
int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_file *fd, const void *zKey, int nKey) {
int rc;
codec_ctx *ctx;
+
+ CODEC_TRACE("sqlcipher_codec_ctx_init: allocating context\n");
+
*iCtx = sqlcipher_malloc(sizeof(codec_ctx));
ctx = *iCtx;
@@ -19393,6 +20730,7 @@ int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_f
directly off the database file. This is the salt for the
key derivation function. If we get a short read allocate
a new random salt value */
+ CODEC_TRACE("sqlcipher_codec_ctx_init: allocating kdf_salt\n");
ctx->kdf_salt_sz = FILE_HEADER_SZ;
ctx->kdf_salt = sqlcipher_malloc(ctx->kdf_salt_sz);
if(ctx->kdf_salt == NULL) return SQLITE_NOMEM;
@@ -19400,6 +20738,7 @@ int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_f
/* allocate space for separate hmac salt data. We want the
HMAC derivation salt to be different than the encryption
key derivation salt */
+ CODEC_TRACE("sqlcipher_codec_ctx_init: allocating hmac_kdf_salt\n");
ctx->hmac_kdf_salt = sqlcipher_malloc(ctx->kdf_salt_sz);
if(ctx->hmac_kdf_salt == NULL) return SQLITE_NOMEM;
@@ -19409,24 +20748,38 @@ int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_f
in encrypted and thus sqlite can't effectively determine the pagesize. this causes an issue in
cases where bytes 16 & 17 of the page header are a power of 2 as reported by John Lehman
*/
+ CODEC_TRACE("sqlcipher_codec_ctx_init: calling sqlcipher_codec_ctx_set_pagesize with %d\n", default_page_size);
if((rc = sqlcipher_codec_ctx_set_pagesize(ctx, default_page_size)) != SQLITE_OK) return rc;
+ CODEC_TRACE("sqlcipher_codec_ctx_init: initializing read_ctx\n");
if((rc = sqlcipher_cipher_ctx_init(&ctx->read_ctx)) != SQLITE_OK) return rc;
+
+ CODEC_TRACE("sqlcipher_codec_ctx_init: initializing write_ctx\n");
if((rc = sqlcipher_cipher_ctx_init(&ctx->write_ctx)) != SQLITE_OK) return rc;
+ CODEC_TRACE("sqlcipher_codec_ctx_init: reading file header\n");
if(fd == NULL || sqlite3OsRead(fd, ctx->kdf_salt, FILE_HEADER_SZ, 0) != SQLITE_OK) {
ctx->need_kdf_salt = 1;
}
+ CODEC_TRACE("sqlcipher_codec_ctx_init: setting cipher\n");
if((rc = sqlcipher_codec_ctx_set_cipher(ctx, CIPHER, 0)) != SQLITE_OK) return rc;
+
+ CODEC_TRACE("sqlcipher_codec_ctx_init: setting default_kdf_iter\n");
if((rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, default_kdf_iter, 0)) != SQLITE_OK) return rc;
+
+ CODEC_TRACE("sqlcipher_codec_ctx_init: setting fast_kdf_iter\n");
if((rc = sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, FAST_PBKDF2_ITER, 0)) != SQLITE_OK) return rc;
+
+ CODEC_TRACE("sqlcipher_codec_ctx_init: setting pass key\n");
if((rc = sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, 0)) != SQLITE_OK) return rc;
/* Note that use_hmac is a special case that requires recalculation of page size
so we call set_use_hmac to perform setup */
+ CODEC_TRACE("sqlcipher_codec_ctx_init: setting use_hmac\n");
if((rc = sqlcipher_codec_ctx_set_use_hmac(ctx, default_flags & CIPHER_FLAG_HMAC)) != SQLITE_OK) return rc;
+ CODEC_TRACE("sqlcipher_codec_ctx_init: copying write_ctx to read_ctx\n");
if((rc = sqlcipher_cipher_ctx_copy(ctx->write_ctx, ctx->read_ctx)) != SQLITE_OK) return rc;
return SQLITE_OK;
@@ -19438,7 +20791,7 @@ int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_f
*/
void sqlcipher_codec_ctx_free(codec_ctx **iCtx) {
codec_ctx *ctx = *iCtx;
- CODEC_TRACE(("codec_ctx_free: entered iCtx=%p\n", iCtx));
+ CODEC_TRACE("codec_ctx_free: entered iCtx=%p\n", iCtx);
sqlcipher_free(ctx->kdf_salt, ctx->kdf_salt_sz);
sqlcipher_free(ctx->hmac_kdf_salt, ctx->kdf_salt_sz);
sqlcipher_free(ctx->buffer, 0);
@@ -19508,12 +20861,12 @@ int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int
hmac_out = out + size + c_ctx->iv_sz;
out_start = out; /* note the original position of the output buffer pointer, as out will be rewritten during encryption */
- CODEC_TRACE(("codec_cipher:entered pgno=%d, mode=%d, size=%d\n", pgno, mode, size));
+ CODEC_TRACE("codec_cipher:entered pgno=%d, mode=%d, size=%d\n", pgno, mode, size);
CODEC_HEXDUMP("codec_cipher: input page data", in, page_sz);
/* the key size should never be zero. If it is, error out. */
if(c_ctx->key_sz == 0) {
- CODEC_TRACE(("codec_cipher: error possible context corruption, key_sz is zero for pgno=%d\n", pgno));
+ CODEC_TRACE("codec_cipher: error possible context corruption, key_sz is zero for pgno=%d\n", pgno);
sqlcipher_memset(out, 0, page_sz);
return SQLITE_ERROR;
}
@@ -19528,25 +20881,25 @@ int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int
if((c_ctx->flags & CIPHER_FLAG_HMAC) && (mode == CIPHER_DECRYPT) && !ctx->skip_read_hmac) {
if(sqlcipher_page_hmac(c_ctx, pgno, in, size + c_ctx->iv_sz, hmac_out) != SQLITE_OK) {
sqlcipher_memset(out, 0, page_sz);
- CODEC_TRACE(("codec_cipher: hmac operations failed for pgno=%d\n", pgno));
+ CODEC_TRACE("codec_cipher: hmac operations failed for pgno=%d\n", pgno);
return SQLITE_ERROR;
}
- CODEC_TRACE(("codec_cipher: comparing hmac on in=%p out=%p hmac_sz=%d\n", hmac_in, hmac_out, c_ctx->hmac_sz));
+ CODEC_TRACE("codec_cipher: comparing hmac on in=%p out=%p hmac_sz=%d\n", hmac_in, hmac_out, c_ctx->hmac_sz);
if(sqlcipher_memcmp(hmac_in, hmac_out, c_ctx->hmac_sz) != 0) { /* the hmac check failed */
if(sqlcipher_ismemset(in, 0, page_sz) == 0) {
/* first check if the entire contents of the page is zeros. If so, this page
resulted from a short read (i.e. sqlite attempted to pull a page after the end of the file. these
short read failures must be ignored for autovaccum mode to work so wipe the output buffer
and return SQLITE_OK to skip the decryption step. */
- CODEC_TRACE(("codec_cipher: zeroed page (short read) for pgno %d, encryption but returning SQLITE_OK\n", pgno));
+ CODEC_TRACE("codec_cipher: zeroed page (short read) for pgno %d, encryption but returning SQLITE_OK\n", pgno);
sqlcipher_memset(out, 0, page_sz);
return SQLITE_OK;
} else {
/* if the page memory is not all zeros, it means the there was data and a hmac on the page.
since the check failed, the page was either tampered with or corrupted. wipe the output buffer,
and return SQLITE_ERROR to the caller */
- CODEC_TRACE(("codec_cipher: hmac check failed for pgno=%d returning SQLITE_ERROR\n", pgno));
+ CODEC_TRACE("codec_cipher: hmac check failed for pgno=%d returning SQLITE_ERROR\n", pgno);
sqlcipher_memset(out, 0, page_sz);
return SQLITE_ERROR;
}
@@ -19581,11 +20934,11 @@ int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int
*/
static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) {
int rc;
- CODEC_TRACE(("cipher_ctx_key_derive: entered c_ctx->pass=%s, c_ctx->pass_sz=%d \
+ CODEC_TRACE("cipher_ctx_key_derive: entered c_ctx->pass=%s, c_ctx->pass_sz=%d \
ctx->kdf_salt=%p ctx->kdf_salt_sz=%d c_ctx->kdf_iter=%d \
ctx->hmac_kdf_salt=%p, c_ctx->fast_kdf_iter=%d c_ctx->key_sz=%d\n",
c_ctx->pass, c_ctx->pass_sz, ctx->kdf_salt, ctx->kdf_salt_sz, c_ctx->kdf_iter,
- ctx->hmac_kdf_salt, c_ctx->fast_kdf_iter, c_ctx->key_sz));
+ ctx->hmac_kdf_salt, c_ctx->fast_kdf_iter, c_ctx->key_sz);
if(c_ctx->pass && c_ctx->pass_sz) { // if pass is not null
@@ -19597,15 +20950,15 @@ static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) {
if (c_ctx->pass_sz == ((c_ctx->key_sz * 2) + 3) && sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0 && cipher_isHex(c_ctx->pass + 2, c_ctx->key_sz * 2)) {
int n = c_ctx->pass_sz - 3; /* adjust for leading x' and tailing ' */
const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */
- CODEC_TRACE(("cipher_ctx_key_derive: using raw key from hex\n"));
+ CODEC_TRACE("cipher_ctx_key_derive: using raw key from hex\n");
cipher_hex2bin(z, n, c_ctx->key);
} else if (c_ctx->pass_sz == (((c_ctx->key_sz + ctx->kdf_salt_sz) * 2) + 3) && sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0 && cipher_isHex(c_ctx->pass + 2, (c_ctx->key_sz + ctx->kdf_salt_sz) * 2)) {
const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */
- CODEC_TRACE(("cipher_ctx_key_derive: using raw key from hex\n"));
+ CODEC_TRACE("cipher_ctx_key_derive: using raw key from hex\n");
cipher_hex2bin(z, (c_ctx->key_sz * 2), c_ctx->key);
cipher_hex2bin(z + (c_ctx->key_sz * 2), (ctx->kdf_salt_sz * 2), ctx->kdf_salt);
} else {
- CODEC_TRACE(("cipher_ctx_key_derive: deriving key using full PBKDF2 with %d iterations\n", c_ctx->kdf_iter));
+ CODEC_TRACE("cipher_ctx_key_derive: deriving key using full PBKDF2 with %d iterations\n", c_ctx->kdf_iter);
c_ctx->provider->kdf(c_ctx->provider_ctx, c_ctx->pass, c_ctx->pass_sz,
ctx->kdf_salt, ctx->kdf_salt_sz, c_ctx->kdf_iter,
c_ctx->key_sz, c_ctx->key);
@@ -19630,8 +20983,8 @@ static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) {
ctx->hmac_kdf_salt[i] ^= hmac_salt_mask;
}
- CODEC_TRACE(("cipher_ctx_key_derive: deriving hmac key from encryption key using PBKDF2 with %d iterations\n",
- c_ctx->fast_kdf_iter));
+ CODEC_TRACE("cipher_ctx_key_derive: deriving hmac key from encryption key using PBKDF2 with %d iterations\n",
+ c_ctx->fast_kdf_iter);
c_ctx->provider->kdf(c_ctx->provider_ctx, c_ctx->key, c_ctx->key_sz,
@@ -19728,6 +21081,7 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
int saved_flags;
int saved_nChange;
int saved_nTotalChange;
+ u8 saved_mTrace;
int (*saved_xTrace)(u32,void*,void*,void*); /* Saved db->xTrace */
Db *pDb = 0;
sqlite3 *db = ctx->pBt->db;
@@ -19763,14 +21117,14 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
int rc = sqlcipher_check_connection(db_filename, key, ctx->read_ctx->pass_sz, "", &user_version);
if(rc == SQLITE_OK){
- CODEC_TRACE(("No upgrade required - exiting\n"));
+ CODEC_TRACE("No upgrade required - exiting\n");
goto exit;
}
// Version 2 - check for 4k with hmac format
rc = sqlcipher_check_connection(db_filename, key, ctx->read_ctx->pass_sz, pragma_4k_kdf_iter, &user_version);
if(rc == SQLITE_OK) {
- CODEC_TRACE(("Version 2 format found\n"));
+ CODEC_TRACE("Version 2 format found\n");
upgrade_4k_format = 1;
}
@@ -19780,13 +21134,13 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
rc = sqlcipher_check_connection(db_filename, key, ctx->read_ctx->pass_sz, pragma_1x_and_4k, &user_version);
sqlite3_free(pragma_1x_and_4k);
if(rc == SQLITE_OK) {
- CODEC_TRACE(("Version 1 format found\n"));
+ CODEC_TRACE("Version 1 format found\n");
upgrade_1x_format = 1;
upgrade_4k_format = 1;
}
if(upgrade_1x_format == 0 && upgrade_4k_format == 0) {
- CODEC_TRACE(("Upgrade format not determined\n"));
+ CODEC_TRACE("Upgrade format not determined\n");
goto handle_error;
}
@@ -19817,11 +21171,11 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
int i = 0;
if( !db->autoCommit ){
- CODEC_TRACE(("cannot migrate from within a transaction"));
+ CODEC_TRACE("cannot migrate from within a transaction");
goto handle_error;
}
if( db->nVdbeActive>1 ){
- CODEC_TRACE(("cannot migrate - SQL statements in progress"));
+ CODEC_TRACE("cannot migrate - SQL statements in progress");
goto handle_error;
}
@@ -19832,9 +21186,11 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
saved_nChange = db->nChange;
saved_nTotalChange = db->nTotalChange;
saved_xTrace = db->xTrace;
+ saved_mTrace = db->mTrace;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin;
db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder);
db->xTrace = 0;
+ db->mTrace = 0;
pDest = db->aDb[0].pBt;
pDb = &(db->aDb[db->nDb-1]);
@@ -19866,6 +21222,7 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
db->nChange = saved_nChange;
db->nTotalChange = saved_nTotalChange;
db->xTrace = saved_xTrace;
+ db->mTrace = saved_mTrace;
db->autoCommit = 1;
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
@@ -19874,14 +21231,14 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
remove(migrated_db_filename);
sqlite3_free(migrated_db_filename);
} else {
- CODEC_TRACE(("*** migration failure** \n\n"));
+ CODEC_TRACE("*** migration failure** \n\n");
}
}
goto exit;
handle_error:
- CODEC_TRACE(("An error occurred attempting to migrate the database\n"));
+ CODEC_TRACE("An error occurred attempting to migrate the database\n");
rc = SQLITE_ERROR;
exit:
@@ -19899,7 +21256,7 @@ int sqlcipher_codec_add_random(codec_ctx *ctx, const char *zRight, int random_sz
int buffer_sz = n / 2;
unsigned char *random;
const unsigned char *z = (const unsigned char *)zRight + 2; /* adjust lead offset of x' */
- CODEC_TRACE(("sqlcipher_codec_add_random: using raw random blob from hex\n"));
+ CODEC_TRACE("sqlcipher_codec_add_random: using raw random blob from hex\n");
random = sqlcipher_malloc(buffer_sz);
memset(random, 0, buffer_sz);
cipher_hex2bin(z, n, random);
@@ -19910,7 +21267,16 @@ int sqlcipher_codec_add_random(codec_ctx *ctx, const char *zRight, int random_sz
return SQLITE_ERROR;
}
+static void sqlcipher_profile_callback(void *file, const char *sql, sqlite3_uint64 run_time){
+ FILE *f = (FILE*)file;
+ double elapsed = run_time/1000000.0;
+ if(f) fprintf(f, "Elapsed time:%.3f ms - %s\n", elapsed, sql);
+}
+
int sqlcipher_cipher_profile(sqlite3 *db, const char *destination){
+#if defined(SQLITE_OMIT_TRACE) || defined(SQLITE_OMIT_DEPRECATED)
+ return SQLITE_ERROR;
+#else
FILE *f;
if(sqlite3StrICmp(destination, "stdout") == 0){
f = stdout;
@@ -19931,12 +21297,7 @@ int sqlcipher_cipher_profile(sqlite3 *db, const char *destination){
}
sqlite3_profile(db, sqlcipher_profile_callback, f);
return SQLITE_OK;
-}
-
-static void sqlcipher_profile_callback(void *file, const char *sql, sqlite3_uint64 run_time){
- FILE *f = (FILE*)file;
- double elapsed = run_time/1000000.0;
- if(f) fprintf(f, "Elapsed time:%.3f ms - %s\n", elapsed, sql);
+#endif
}
int sqlcipher_codec_fips_status(codec_ctx *ctx) {
@@ -19947,6 +21308,14 @@ const char* sqlcipher_codec_get_provider_version(codec_ctx *ctx) {
return ctx->read_ctx->provider->get_provider_version(ctx->read_ctx);
}
+int sqlcipher_codec_hmac(const codec_ctx *ctx, const unsigned char *hmac_key, int key_sz,
+ unsigned char* in, int in_sz, unsigned char *in2, int in2_sz,
+ unsigned char *out) {
+ ctx->read_ctx->provider->hmac(ctx->read_ctx, (unsigned char *)hmac_key, key_sz, in, in_sz, in2, in2_sz, out);
+ return SQLITE_OK;
+}
+
+
#endif
/* END SQLCIPHER */
@@ -20099,9 +21468,10 @@ static int sqlcipher_ltc_hmac(void *ctx, unsigned char *hmac_key, int key_sz, un
unsigned long outlen = key_sz;
hash_idx = find_hash("sha1");
+ if(in == NULL) return SQLITE_ERROR;
if((rc = hmac_init(&hmac, hash_idx, hmac_key, key_sz)) != CRYPT_OK) return SQLITE_ERROR;
if((rc = hmac_process(&hmac, in, in_sz)) != CRYPT_OK) return SQLITE_ERROR;
- if((rc = hmac_process(&hmac, in2, in2_sz)) != CRYPT_OK) return SQLITE_ERROR;
+ if(in2 != NULL && (rc = hmac_process(&hmac, in2, in2_sz)) != CRYPT_OK) return SQLITE_ERROR;
if((rc = hmac_done(&hmac, out, &outlen)) != CRYPT_OK) return SQLITE_ERROR;
return SQLITE_OK;
}
@@ -20258,6 +21628,7 @@ int sqlcipher_ltc_setup(sqlcipher_provider *p) {
#include
#include
#include
+#include
typedef struct {
EVP_CIPHER *evp_cipher;
@@ -20267,7 +21638,7 @@ static unsigned int openssl_external_init = 0;
static unsigned int openssl_init_count = 0;
static sqlite3_mutex* openssl_rand_mutex = NULL;
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
static HMAC_CTX *HMAC_CTX_new(void)
{
HMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
@@ -20292,11 +21663,15 @@ static void HMAC_CTX_free(HMAC_CTX *ctx)
static int sqlcipher_openssl_add_random(void *ctx, void *buffer, int length) {
#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: entering openssl_rand_mutex %p\n", openssl_rand_mutex);
sqlite3_mutex_enter(openssl_rand_mutex);
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: entered openssl_rand_mutex %p\n", openssl_rand_mutex);
#endif
RAND_add(buffer, length, 0);
#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: leaving openssl_rand_mutex %p\n", openssl_rand_mutex);
sqlite3_mutex_leave(openssl_rand_mutex);
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: left openssl_rand_mutex %p\n", openssl_rand_mutex);
#endif
return SQLITE_OK;
}
@@ -20311,7 +21686,9 @@ static int sqlcipher_openssl_activate(void *ctx) {
/* initialize openssl and increment the internal init counter
but only if it hasn't been initalized outside of SQLCipher by this program
e.g. on startup */
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entering static master mutex");
sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entered static master mutex");
if(openssl_init_count == 0 && EVP_get_cipherbyname(CIPHER) != NULL) {
/* if openssl has not yet been initialized by this library, but
@@ -20331,18 +21708,24 @@ static int sqlcipher_openssl_activate(void *ctx) {
if(openssl_init_count == 0 && openssl_external_init == 0) {
/* if the library was not externally initialized, then should be now */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
OpenSSL_add_all_algorithms();
+#endif
}
#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
if(openssl_rand_mutex == NULL) {
/* allocate a mutex to guard against concurrent calls to RAND_bytes() */
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: allocating openssl_rand_mutex");
openssl_rand_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: allocated openssl_rand_mutex %p", openssl_rand_mutex);
}
#endif
openssl_init_count++;
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: leaving static master mutex");
sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: left static master mutex");
return SQLITE_OK;
}
@@ -20350,7 +21733,9 @@ static int sqlcipher_openssl_activate(void *ctx) {
freeing the EVP structures on the final deactivation to ensure that
OpenSSL memory is cleaned up */
static int sqlcipher_openssl_deactivate(void *ctx) {
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: entering static master mutex");
sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: entered static master mutex");
openssl_init_count--;
if(openssl_init_count == 0) {
@@ -20360,16 +21745,22 @@ static int sqlcipher_openssl_deactivate(void *ctx) {
Note: this code will only be reached if OpensSSL_add_all_algorithms()
is called by SQLCipher internally. This should prevent SQLCipher from
"cleaning up" openssl when it was initialized externally by the program */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_cleanup();
+#endif
} else {
openssl_external_init = 0;
}
#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: freeing openssl_rand_mutex %p", openssl_rand_mutex);
sqlite3_mutex_free(openssl_rand_mutex);
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: freed openssl_rand_mutex %p", openssl_rand_mutex);
openssl_rand_mutex = NULL;
#endif
}
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: leaving static master mutex");
sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: left static master mutex");
return SQLITE_OK;
}
@@ -20391,11 +21782,15 @@ static int sqlcipher_openssl_random (void *ctx, void *buffer, int length) {
but a more proper solution is that applications setup platform-appropriate
thread saftey in openssl externally */
#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_random: entering openssl_rand_mutex %p", openssl_rand_mutex);
sqlite3_mutex_enter(openssl_rand_mutex);
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_random: entered openssl_rand_mutex %p", openssl_rand_mutex);
#endif
rc = RAND_bytes((unsigned char *)buffer, length);
#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_random: leaving openssl_rand_mutex %p", openssl_rand_mutex);
sqlite3_mutex_leave(openssl_rand_mutex);
+ CODEC_TRACE_MUTEX("sqlcipher_openssl_random: left openssl_rand_mutex %p", openssl_rand_mutex);
#endif
return (rc == 1) ? SQLITE_OK : SQLITE_ERROR;
}
@@ -20403,10 +21798,10 @@ static int sqlcipher_openssl_random (void *ctx, void *buffer, int length) {
static int sqlcipher_openssl_hmac(void *ctx, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out) {
unsigned int outlen;
HMAC_CTX* hctx = HMAC_CTX_new();
- if(hctx == NULL) return SQLITE_ERROR;
+ if(hctx == NULL || in == NULL) return SQLITE_ERROR;
HMAC_Init_ex(hctx, hmac_key, key_sz, EVP_sha1(), NULL);
HMAC_Update(hctx, in, in_sz);
- HMAC_Update(hctx, in2, in2_sz);
+ if(in2 != NULL) HMAC_Update(hctx, in2, in2_sz);
HMAC_Final(hctx, out, &outlen);
HMAC_CTX_free(hctx);
return SQLITE_OK;
@@ -20591,9 +21986,10 @@ static const char* sqlcipher_cc_get_provider_version(void *ctx) {
static int sqlcipher_cc_hmac(void *ctx, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out) {
CCHmacContext hmac_context;
+ if(in == NULL) return SQLITE_ERROR;
CCHmacInit(&hmac_context, kCCHmacAlgSHA1, hmac_key, key_sz);
CCHmacUpdate(&hmac_context, in, in_sz);
- CCHmacUpdate(&hmac_context, in2, in2_sz);
+ if(in2 != NULL) CCHmacUpdate(&hmac_context, in2, in2_sz);
CCHmacFinal(&hmac_context, out);
return SQLITE_OK;
}
@@ -20831,9 +22227,16 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally
** disabled. The default value may be changed by compiling with the
** SQLITE_USE_URI symbol defined.
+**
+** URI filenames are enabled by default if SQLITE_HAS_CODEC is
+** enabled.
*/
#ifndef SQLITE_USE_URI
-# define SQLITE_USE_URI 0
+# ifdef SQLITE_HAS_CODEC
+# define SQLITE_USE_URI 1
+# else
+# define SQLITE_USE_URI 0
+# endif
#endif
/* EVIDENCE-OF: R-38720-18127 The default setting is determined by the
@@ -20863,6 +22266,19 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
# define SQLITE_STMTJRNL_SPILL (64*1024)
#endif
+/*
+** The default lookaside-configuration, the format "SZ,N". SZ is the
+** number of bytes in each lookaside slot (should be a multiple of 8)
+** and N is the number of slots. The lookaside-configuration can be
+** changed as start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE)
+** or at run-time for an individual database connection using
+** sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE);
+*/
+#ifndef SQLITE_DEFAULT_LOOKASIDE
+# define SQLITE_DEFAULT_LOOKASIDE 1200,100
+#endif
+
+
/*
** The following singleton contains the global configuration for
** the SQLite library.
@@ -20875,8 +22291,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
- 128, /* szLookaside */
- 500, /* nLookaside */
+ SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
SQLITE_STMTJRNL_SPILL, /* nStmtSpill */
{0,0,0,0,0,0,0,0}, /* m */
{0,0,0,0,0,0,0,0,0}, /* mutex */
@@ -20913,7 +22328,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xVdbeBranch */
0, /* pVbeBranchArg */
#endif
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
0, /* xTestCallback */
#endif
0, /* bLocaltimeFault */
@@ -20973,460 +22388,6 @@ SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY";
/************** End of global.c **********************************************/
-/************** Begin file ctime.c *******************************************/
-/*
-** 2010 February 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 implements routines used to report what compile-time options
-** SQLite was built with.
-*/
-
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-
-/* #include "sqliteInt.h" */
-
-/*
-** An array of names of all compile-time options. This array should
-** be sorted A-Z.
-**
-** This array looks large, but in a typical installation actually uses
-** only a handful of compile-time options, so most times this array is usually
-** rather short and uses little memory space.
-*/
-static const char * const azCompileOpt[] = {
-
-/* These macros are provided to "stringify" the value of the define
-** for those options in which the value is meaningful. */
-#define CTIMEOPT_VAL_(opt) #opt
-#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
-
-#if SQLITE_32BIT_ROWID
- "32BIT_ROWID",
-#endif
-#if SQLITE_4_BYTE_ALIGNED_MALLOC
- "4_BYTE_ALIGNED_MALLOC",
-#endif
-#if SQLITE_CASE_SENSITIVE_LIKE
- "CASE_SENSITIVE_LIKE",
-#endif
-#if SQLITE_CHECK_PAGES
- "CHECK_PAGES",
-#endif
-#if defined(__clang__) && defined(__clang_major__)
- "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
- CTIMEOPT_VAL(__clang_minor__) "."
- CTIMEOPT_VAL(__clang_patchlevel__),
-#elif defined(_MSC_VER)
- "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
-#elif defined(__GNUC__) && defined(__VERSION__)
- "COMPILER=gcc-" __VERSION__,
-#endif
-#if SQLITE_COVERAGE_TEST
- "COVERAGE_TEST",
-#endif
-#if SQLITE_DEBUG
- "DEBUG",
-#endif
-#if SQLITE_DEFAULT_LOCKING_MODE
- "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
-#endif
-#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
- "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
-#endif
-#if SQLITE_DISABLE_DIRSYNC
- "DISABLE_DIRSYNC",
-#endif
-#if SQLITE_DISABLE_LFS
- "DISABLE_LFS",
-#endif
-#if SQLITE_ENABLE_8_3_NAMES
- "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
-#endif
-#if SQLITE_ENABLE_API_ARMOR
- "ENABLE_API_ARMOR",
-#endif
-#if SQLITE_ENABLE_ATOMIC_WRITE
- "ENABLE_ATOMIC_WRITE",
-#endif
-#if SQLITE_ENABLE_CEROD
- "ENABLE_CEROD",
-#endif
-#if SQLITE_ENABLE_COLUMN_METADATA
- "ENABLE_COLUMN_METADATA",
-#endif
-#if SQLITE_ENABLE_DBSTAT_VTAB
- "ENABLE_DBSTAT_VTAB",
-#endif
-#if SQLITE_ENABLE_EXPENSIVE_ASSERT
- "ENABLE_EXPENSIVE_ASSERT",
-#endif
-#if SQLITE_ENABLE_FTS1
- "ENABLE_FTS1",
-#endif
-#if SQLITE_ENABLE_FTS2
- "ENABLE_FTS2",
-#endif
-#if SQLITE_ENABLE_FTS3
- "ENABLE_FTS3",
-#endif
-#if SQLITE_ENABLE_FTS3_PARENTHESIS
- "ENABLE_FTS3_PARENTHESIS",
-#endif
-#if SQLITE_ENABLE_FTS4
- "ENABLE_FTS4",
-#endif
-#if SQLITE_ENABLE_FTS5
- "ENABLE_FTS5",
-#endif
-#if SQLITE_ENABLE_ICU
- "ENABLE_ICU",
-#endif
-#if SQLITE_ENABLE_IOTRACE
- "ENABLE_IOTRACE",
-#endif
-#if SQLITE_ENABLE_JSON1
- "ENABLE_JSON1",
-#endif
-#if SQLITE_ENABLE_LOAD_EXTENSION
- "ENABLE_LOAD_EXTENSION",
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE
- "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
-#endif
-#if SQLITE_ENABLE_MEMORY_MANAGEMENT
- "ENABLE_MEMORY_MANAGEMENT",
-#endif
-#if SQLITE_ENABLE_MEMSYS3
- "ENABLE_MEMSYS3",
-#endif
-#if SQLITE_ENABLE_MEMSYS5
- "ENABLE_MEMSYS5",
-#endif
-#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
- "ENABLE_OVERSIZE_CELL_CHECK",
-#endif
-#if SQLITE_ENABLE_RTREE
- "ENABLE_RTREE",
-#endif
-#if defined(SQLITE_ENABLE_STAT4)
- "ENABLE_STAT4",
-#elif defined(SQLITE_ENABLE_STAT3)
- "ENABLE_STAT3",
-#endif
-#if SQLITE_ENABLE_UNLOCK_NOTIFY
- "ENABLE_UNLOCK_NOTIFY",
-#endif
-#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
- "ENABLE_UPDATE_DELETE_LIMIT",
-#endif
-#if SQLITE_HAS_CODEC
- "HAS_CODEC",
-#endif
-#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
- "HAVE_ISNAN",
-#endif
-#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX
- "HOMEGROWN_RECURSIVE_MUTEX",
-#endif
-#if SQLITE_IGNORE_AFP_LOCK_ERRORS
- "IGNORE_AFP_LOCK_ERRORS",
-#endif
-#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- "IGNORE_FLOCK_LOCK_ERRORS",
-#endif
-#ifdef SQLITE_INT64_TYPE
- "INT64_TYPE",
-#endif
-#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
- "LIKE_DOESNT_MATCH_BLOBS",
-#endif
-#if SQLITE_LOCK_TRACE
- "LOCK_TRACE",
-#endif
-#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc)
- "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
-#endif
-#ifdef SQLITE_MAX_SCHEMA_RETRY
- "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
-#endif
-#if SQLITE_MEMDEBUG
- "MEMDEBUG",
-#endif
-#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
- "MIXED_ENDIAN_64BIT_FLOAT",
-#endif
-#if SQLITE_NO_SYNC
- "NO_SYNC",
-#endif
-#if SQLITE_OMIT_ALTERTABLE
- "OMIT_ALTERTABLE",
-#endif
-#if SQLITE_OMIT_ANALYZE
- "OMIT_ANALYZE",
-#endif
-#if SQLITE_OMIT_ATTACH
- "OMIT_ATTACH",
-#endif
-#if SQLITE_OMIT_AUTHORIZATION
- "OMIT_AUTHORIZATION",
-#endif
-#if SQLITE_OMIT_AUTOINCREMENT
- "OMIT_AUTOINCREMENT",
-#endif
-#if SQLITE_OMIT_AUTOINIT
- "OMIT_AUTOINIT",
-#endif
-#if SQLITE_OMIT_AUTOMATIC_INDEX
- "OMIT_AUTOMATIC_INDEX",
-#endif
-#if SQLITE_OMIT_AUTORESET
- "OMIT_AUTORESET",
-#endif
-#if SQLITE_OMIT_AUTOVACUUM
- "OMIT_AUTOVACUUM",
-#endif
-#if SQLITE_OMIT_BETWEEN_OPTIMIZATION
- "OMIT_BETWEEN_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_BLOB_LITERAL
- "OMIT_BLOB_LITERAL",
-#endif
-#if SQLITE_OMIT_BTREECOUNT
- "OMIT_BTREECOUNT",
-#endif
-#if SQLITE_OMIT_BUILTIN_TEST
- "OMIT_BUILTIN_TEST",
-#endif
-#if SQLITE_OMIT_CAST
- "OMIT_CAST",
-#endif
-#if SQLITE_OMIT_CHECK
- "OMIT_CHECK",
-#endif
-#if SQLITE_OMIT_COMPLETE
- "OMIT_COMPLETE",
-#endif
-#if SQLITE_OMIT_COMPOUND_SELECT
- "OMIT_COMPOUND_SELECT",
-#endif
-#if SQLITE_OMIT_CTE
- "OMIT_CTE",
-#endif
-#if SQLITE_OMIT_DATETIME_FUNCS
- "OMIT_DATETIME_FUNCS",
-#endif
-#if SQLITE_OMIT_DECLTYPE
- "OMIT_DECLTYPE",
-#endif
-#if SQLITE_OMIT_DEPRECATED
- "OMIT_DEPRECATED",
-#endif
-#if SQLITE_OMIT_DISKIO
- "OMIT_DISKIO",
-#endif
-#if SQLITE_OMIT_EXPLAIN
- "OMIT_EXPLAIN",
-#endif
-#if SQLITE_OMIT_FLAG_PRAGMAS
- "OMIT_FLAG_PRAGMAS",
-#endif
-#if SQLITE_OMIT_FLOATING_POINT
- "OMIT_FLOATING_POINT",
-#endif
-#if SQLITE_OMIT_FOREIGN_KEY
- "OMIT_FOREIGN_KEY",
-#endif
-#if SQLITE_OMIT_GET_TABLE
- "OMIT_GET_TABLE",
-#endif
-#if SQLITE_OMIT_INCRBLOB
- "OMIT_INCRBLOB",
-#endif
-#if SQLITE_OMIT_INTEGRITY_CHECK
- "OMIT_INTEGRITY_CHECK",
-#endif
-#if SQLITE_OMIT_LIKE_OPTIMIZATION
- "OMIT_LIKE_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_LOAD_EXTENSION
- "OMIT_LOAD_EXTENSION",
-#endif
-#if SQLITE_OMIT_LOCALTIME
- "OMIT_LOCALTIME",
-#endif
-#if SQLITE_OMIT_LOOKASIDE
- "OMIT_LOOKASIDE",
-#endif
-#if SQLITE_OMIT_MEMORYDB
- "OMIT_MEMORYDB",
-#endif
-#if SQLITE_OMIT_OR_OPTIMIZATION
- "OMIT_OR_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_PAGER_PRAGMAS
- "OMIT_PAGER_PRAGMAS",
-#endif
-#if SQLITE_OMIT_PRAGMA
- "OMIT_PRAGMA",
-#endif
-#if SQLITE_OMIT_PROGRESS_CALLBACK
- "OMIT_PROGRESS_CALLBACK",
-#endif
-#if SQLITE_OMIT_QUICKBALANCE
- "OMIT_QUICKBALANCE",
-#endif
-#if SQLITE_OMIT_REINDEX
- "OMIT_REINDEX",
-#endif
-#if SQLITE_OMIT_SCHEMA_PRAGMAS
- "OMIT_SCHEMA_PRAGMAS",
-#endif
-#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
- "OMIT_SCHEMA_VERSION_PRAGMAS",
-#endif
-#if SQLITE_OMIT_SHARED_CACHE
- "OMIT_SHARED_CACHE",
-#endif
-#if SQLITE_OMIT_SUBQUERY
- "OMIT_SUBQUERY",
-#endif
-#if SQLITE_OMIT_TCL_VARIABLE
- "OMIT_TCL_VARIABLE",
-#endif
-#if SQLITE_OMIT_TEMPDB
- "OMIT_TEMPDB",
-#endif
-#if SQLITE_OMIT_TRACE
- "OMIT_TRACE",
-#endif
-#if SQLITE_OMIT_TRIGGER
- "OMIT_TRIGGER",
-#endif
-#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
- "OMIT_TRUNCATE_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_UTF16
- "OMIT_UTF16",
-#endif
-#if SQLITE_OMIT_VACUUM
- "OMIT_VACUUM",
-#endif
-#if SQLITE_OMIT_VIEW
- "OMIT_VIEW",
-#endif
-#if SQLITE_OMIT_VIRTUALTABLE
- "OMIT_VIRTUALTABLE",
-#endif
-#if SQLITE_OMIT_WAL
- "OMIT_WAL",
-#endif
-#if SQLITE_OMIT_WSD
- "OMIT_WSD",
-#endif
-#if SQLITE_OMIT_XFER_OPT
- "OMIT_XFER_OPT",
-#endif
-#if SQLITE_PERFORMANCE_TRACE
- "PERFORMANCE_TRACE",
-#endif
-#if SQLITE_PROXY_DEBUG
- "PROXY_DEBUG",
-#endif
-#if SQLITE_RTREE_INT_ONLY
- "RTREE_INT_ONLY",
-#endif
-#if SQLITE_SECURE_DELETE
- "SECURE_DELETE",
-#endif
-#if SQLITE_SMALL_STACK
- "SMALL_STACK",
-#endif
-#if SQLITE_SOUNDEX
- "SOUNDEX",
-#endif
-#if SQLITE_SYSTEM_MALLOC
- "SYSTEM_MALLOC",
-#endif
-#if SQLITE_TCL
- "TCL",
-#endif
-#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc)
- "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
-#endif
-#if SQLITE_TEST
- "TEST",
-#endif
-#if defined(SQLITE_THREADSAFE)
- "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
-#endif
-#if SQLITE_USE_ALLOCA
- "USE_ALLOCA",
-#endif
-#if SQLITE_USER_AUTHENTICATION
- "USER_AUTHENTICATION",
-#endif
-#if SQLITE_WIN32_MALLOC
- "WIN32_MALLOC",
-#endif
-#if SQLITE_ZERO_MALLOC
- "ZERO_MALLOC"
-#endif
-};
-
-/*
-** Given the name of a compile-time option, return true if that option
-** was used and false if not.
-**
-** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
-** is not required for a match.
-*/
-SQLITE_API int sqlite3_compileoption_used(const char *zOptName){
- int i, n;
-
-#if SQLITE_ENABLE_API_ARMOR
- if( zOptName==0 ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
- n = sqlite3Strlen30(zOptName);
-
- /* Since ArraySize(azCompileOpt) is normally in single digits, a
- ** linear search is adequate. No need for a binary search. */
- for(i=0; i=0 && NaDb[] (or -1) */
- u8 nullRow; /* True if pointing to a row with no data */
- u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
- u8 isTable; /* True for rowid tables. False for indexes */
+ u8 eCurType; /* One of the CURTYPE_* values above */
+ i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */
+ u8 nullRow; /* True if pointing to a row with no data */
+ u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
+ u8 isTable; /* True for rowid tables. False for indexes */
#ifdef SQLITE_DEBUG
- u8 seekOp; /* Most recent seek operation on this cursor */
- u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */
+ u8 seekOp; /* Most recent seek operation on this cursor */
+ u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */
#endif
- Bool isEphemeral:1; /* True for an ephemeral table */
- Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
- Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
- Pgno pgnoRoot; /* Root page of the open btree cursor */
- i16 nField; /* Number of fields in the header */
- u16 nHdrParsed; /* Number of header fields parsed so far */
+ Bool isEphemeral:1; /* True for an ephemeral table */
+ Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
+ Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
+ Btree *pBtx; /* Separate file holding temporary table */
+ i64 seqCount; /* Sequence counter */
+ int *aAltMap; /* Mapping from table to index column numbers */
+
+ /* Cached OP_Column parse information is only valid if cacheStatus matches
+ ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
+ ** CACHE_STALE (0) and so setting cacheStatus=CACHE_STALE guarantees that
+ ** the cache is out of date. */
+ u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
+ int seekResult; /* Result of previous sqlite3BtreeMoveto() or 0
+ ** if there have been no prior seeks on the cursor. */
+ /* NB: seekResult does not distinguish between "no seeks have ever occurred
+ ** on this cursor" and "the most recent seek was an exact match". */
+
+ /* When a new VdbeCursor is allocated, only the fields above are zeroed.
+ ** The fields that follow are uninitialized, and must be individually
+ ** initialized prior to first use. */
+ VdbeCursor *pAltCursor; /* Associated index cursor from which to read */
union {
BtCursor *pCursor; /* CURTYPE_BTREE. Btree cursor */
sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */
int pseudoTableReg; /* CURTYPE_PSEUDO. Reg holding content. */
VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */
} uc;
- Btree *pBt; /* Separate file holding temporary table */
- KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
- int seekResult; /* Result of previous sqlite3BtreeMoveto() */
- i64 seqCount; /* Sequence counter */
- i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
- VdbeCursor *pAltCursor; /* Associated index cursor from which to read */
- int *aAltMap; /* Mapping from table to index column numbers */
+ KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
+ u32 iHdrOffset; /* Offset to next unparsed byte of the header */
+ Pgno pgnoRoot; /* Root page of the open btree cursor */
+ i16 nField; /* Number of fields in the header */
+ u16 nHdrParsed; /* Number of header fields parsed so far */
+ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
+ u32 *aOffset; /* Pointer to aType[nField] */
+ const u8 *aRow; /* Data for the current row, if all on one page */
+ u32 payloadSize; /* Total number of bytes in the record */
+ u32 szRow; /* Byte available in aRow */
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
- u64 maskUsed; /* Mask of columns used by this cursor */
+ u64 maskUsed; /* Mask of columns used by this cursor */
#endif
- /* Cached information about the header for the data record that the
- ** cursor is currently pointing to. Only valid if cacheStatus matches
- ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
- ** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that
- ** the cache is out of date.
- **
- ** aRow might point to (ephemeral) data for the current row, or it might
- ** be NULL.
- */
- u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
- u32 payloadSize; /* Total number of bytes in the record */
- u32 szRow; /* Byte available in aRow */
- u32 iHdrOffset; /* Offset to next unparsed byte of the header */
- const u8 *aRow; /* Data for the current row, if all on one page */
- u32 *aOffset; /* Pointer to aType[nField] */
- u32 aType[1]; /* Type values for all entries in the record */
/* 2*nField extra array elements allocated for aType[], beyond the one
** static element declared in the structure. nField total array slots for
** aType[] and nField+1 array slots for aOffset[] */
+ u32 aType[1]; /* Type values record decode. MUST BE LAST */
};
@@ -21609,6 +22573,7 @@ struct VdbeFrame {
i64 *anExec; /* Event counters from parent frame */
Mem *aMem; /* Array of memory cells for parent frame */
VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
+ u8 *aOnce; /* Bitmask used by OP_Once */
void *token; /* Copy of SubProgram.token */
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
AuxData *pAuxData; /* Linked list of auxdata allocations */
@@ -21629,11 +22594,12 @@ struct VdbeFrame {
** structures. Each Mem struct may cache multiple representations (string,
** integer etc.) of the same value.
*/
-struct Mem {
+struct sqlite3_value {
union MemValue {
double r; /* Real value used when MEM_Real is set in flags */
i64 i; /* Integer value used when MEM_Int is set in flags */
- int nZero; /* Used when bit MEM_Zero is set in flags */
+ int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */
+ const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
FuncDef *pDef; /* Used only when flags==MEM_Agg */
RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
@@ -21665,7 +22631,8 @@ struct Mem {
** representations of the value stored in the Mem struct.
**
** If the MEM_Null flag is set, then the value is an SQL NULL value.
-** No other flags may be set in this case.
+** For a pointer type created using sqlite3_bind_pointer() or
+** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set.
**
** If the MEM_Str flag is set then Mem.z points at a string representation.
** Usually this is encoded in the same unicode encoding as the main
@@ -21673,7 +22640,7 @@ struct Mem {
** set, then the string is nul terminated. The MEM_Int and MEM_Real
** flags may coexist with the MEM_Str flag.
*/
-#define MEM_Null 0x0001 /* Value is NULL */
+#define MEM_Null 0x0001 /* Value is NULL (or a pointer) */
#define MEM_Str 0x0002 /* Value is a string */
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
@@ -21683,7 +22650,7 @@ struct Mem {
#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
#define MEM_Undefined 0x0080 /* Value is undefined */
#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
-#define MEM_TypeMask 0x81ff /* Mask of type bits */
+#define MEM_TypeMask 0xc1ff /* Mask of type bits */
/* Whenever Mem contains a valid string or blob representation, one of
@@ -21691,7 +22658,7 @@ struct Mem {
** policy for Mem.z. The MEM_Term flag tells us whether or not the
** string is \000 or \u0000 terminated
*/
-#define MEM_Term 0x0200 /* String rep is nul terminated */
+#define MEM_Term 0x0200 /* String in Mem.z is zero terminated */
#define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */
#define MEM_Static 0x0800 /* Mem.z points to a static string */
#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
@@ -21731,11 +22698,11 @@ struct Mem {
** when the VM is halted (if not before).
*/
struct AuxData {
- int iOp; /* Instruction number of OP_Function opcode */
- int iArg; /* Index of function argument. */
+ int iAuxOp; /* Instruction number of OP_Function opcode */
+ int iAuxArg; /* Index of function argument. */
void *pAux; /* Aux data pointer */
- void (*xDelete)(void *); /* Destructor for the aux data */
- AuxData *pNext; /* Next element in list */
+ void (*xDeleteAux)(void*); /* Destructor for the aux data */
+ AuxData *pNextAux; /* Next element in list */
};
/*
@@ -21791,7 +22758,6 @@ struct Vdbe {
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
Parse *pParse; /* Parsing context used to create this Vdbe */
ynVar nVar; /* Number of entries in aVar[] */
- ynVar nzVar; /* Number of entries in azVar[] */
u32 magic; /* Magic number for sanity checking */
int nMem; /* Number of memory locations currently allocated */
int nCursor; /* Number of slots in apCsr[] */
@@ -21816,7 +22782,7 @@ struct Vdbe {
char *zErrMsg; /* Error message written here */
VdbeCursor **apCsr; /* One element of this array for each open cursor */
Mem *aVar; /* Values for the OP_Variable opcode. */
- char **azVar; /* Name of variables */
+ VList *pVList; /* Name of variables */
#ifndef SQLITE_OMIT_TRACE
i64 startTime; /* Time when query started - used for profiling */
#endif
@@ -21827,6 +22793,7 @@ struct Vdbe {
u16 nResColumn; /* Number of columns in one row of the result set */
u8 errorAction; /* Recovery action to do in case of an error */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
+ u8 prepFlags; /* SQLITE_PREPARE_* flags */
bft expired:1; /* True if the VM needs to be recompiled */
bft doingRerun:1; /* True if rerunning after an auto-reprepare */
bft explain:2; /* True if EXPLAIN present on SQL command */
@@ -21835,10 +22802,9 @@ struct Vdbe {
bft usesStmtJournal:1; /* True if uses a statement journal */
bft readOnly:1; /* True for statements that do not write */
bft bIsReader:1; /* True for statements that read */
- bft isPrepareV2:1; /* True if prepared with prepare_v2() */
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
- u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */
+ u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */
char *zSql; /* Text of the SQL statement that generated this */
void *pFree; /* Free this when deleting the vdbe */
VdbeFrame *pFrame; /* Parent frame */
@@ -21880,6 +22846,7 @@ struct PreUpdate {
i64 iKey2; /* Second key value passed to hook */
Mem *aNew; /* Array of new.* values */
Table *pTab; /* Schema object being upated */
+ Index *pPk; /* PK index if pTab is WITHOUT ROWID */
};
/*
@@ -21919,6 +22886,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
#else
SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double);
#endif
+SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*));
SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16);
SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
@@ -21932,7 +22900,7 @@ SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8);
-SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
@@ -21950,7 +22918,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
-SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
+SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *);
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
@@ -21978,12 +22946,14 @@ SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
# define sqlite3VdbeCheckFk(p,i) 0
#endif
-SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
#endif
-SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem);
+#ifndef SQLITE_OMIT_UTF16
+SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8);
+SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem);
+#endif
#ifndef SQLITE_OMIT_INCRBLOB
SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *);
@@ -22401,16 +23371,18 @@ struct tm *__cdecl localtime(const time_t *);
*/
typedef struct DateTime DateTime;
struct DateTime {
- sqlite3_int64 iJD; /* The julian day number times 86400000 */
- int Y, M, D; /* Year, month, and day */
- int h, m; /* Hour and minutes */
- int tz; /* Timezone offset in minutes */
- double s; /* Seconds */
- char validYMD; /* True (1) if Y,M,D are valid */
- char validHMS; /* True (1) if h,m,s are valid */
- char validJD; /* True (1) if iJD is valid */
- char validTZ; /* True (1) if tz is valid */
- char tzSet; /* Timezone was set explicitly */
+ sqlite3_int64 iJD; /* The julian day number times 86400000 */
+ int Y, M, D; /* Year, month, and day */
+ int h, m; /* Hour and minutes */
+ int tz; /* Timezone offset in minutes */
+ double s; /* Seconds */
+ char validJD; /* True (1) if iJD is valid */
+ char rawS; /* Raw numeric value stored in s */
+ char validYMD; /* True (1) if Y,M,D are valid */
+ char validHMS; /* True (1) if h,m,s are valid */
+ char validTZ; /* True (1) if tz is valid */
+ char tzSet; /* Timezone was set explicitly */
+ char isError; /* An overflow has occurred */
};
@@ -22558,6 +23530,7 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
s = 0;
}
p->validJD = 0;
+ p->rawS = 0;
p->validHMS = 1;
p->h = h;
p->m = m;
@@ -22567,6 +23540,14 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
return 0;
}
+/*
+** Put the DateTime object into its error state.
+*/
+static void datetimeError(DateTime *p){
+ memset(p, 0, sizeof(*p));
+ p->isError = 1;
+}
+
/*
** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume
** that the YYYY-MM-DD is according to the Gregorian calendar.
@@ -22586,6 +23567,10 @@ static void computeJD(DateTime *p){
M = 1;
D = 1;
}
+ if( Y<-4713 || Y>9999 || p->rawS ){
+ datetimeError(p);
+ return;
+ }
if( M<=2 ){
Y--;
M += 12;
@@ -22666,6 +23651,21 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
}
}
+/*
+** Input "r" is a numeric quantity which might be a julian day number,
+** or the number of seconds since 1970. If the value if r is within
+** range of a julian day number, install it as such and set validJD.
+** If the value is a valid unix timestamp, put it in p->s and set p->rawS.
+*/
+static void setRawDateNumber(DateTime *p, double r){
+ p->s = r;
+ p->rawS = 1;
+ if( r>=0.0 && r<5373484.5 ){
+ p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
+ p->validJD = 1;
+ }
+}
+
/*
** Attempt to parse the given string into a julian day number. Return
** the number of errors.
@@ -22692,16 +23692,33 @@ static int parseDateOrTime(
return 0;
}else if( parseHhMmSs(zDate, p)==0 ){
return 0;
- }else if( sqlite3StrICmp(zDate,"now")==0){
+ }else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){
return setDateTimeToCurrent(context, p);
}else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
- p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
- p->validJD = 1;
+ setRawDateNumber(p, r);
return 0;
}
return 1;
}
+/* The julian day number for 9999-12-31 23:59:59.999 is 5373484.4999999.
+** Multiplying this by 86400000 gives 464269060799999 as the maximum value
+** for DateTime.iJD.
+**
+** But some older compilers (ex: gcc 4.2.1 on older Macs) cannot deal with
+** such a large integer literal, so we have to encode it.
+*/
+#define INT_464269060799999 ((((i64)0x1a640)<<32)|0x1072fdff)
+
+/*
+** Return TRUE if the given julian day number is within range.
+**
+** The input is the JulianDay times 86400000.
+*/
+static int validJulianDay(sqlite3_int64 iJD){
+ return iJD>=0 && iJD<=INT_464269060799999;
+}
+
/*
** Compute the Year, Month, and Day from the julian day number.
*/
@@ -22712,6 +23729,9 @@ static void computeYMD(DateTime *p){
p->Y = 2000;
p->M = 1;
p->D = 1;
+ }else if( !validJulianDay(p->iJD) ){
+ datetimeError(p);
+ return;
}else{
Z = (int)((p->iJD + 43200000)/86400000);
A = (int)((Z - 1867216.25)/36524.25);
@@ -22743,6 +23763,7 @@ static void computeHMS(DateTime *p){
s -= p->h*3600;
p->m = s/60;
p->s += s - p->m*60;
+ p->rawS = 0;
p->validHMS = 1;
}
@@ -22804,14 +23825,14 @@ static int osLocaltime(time_t *t, struct tm *pTm){
#endif
sqlite3_mutex_enter(mutex);
pX = localtime(t);
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
#endif
if( pX ) *pTm = *pX;
sqlite3_mutex_leave(mutex);
rc = pX==0;
#else
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
#endif
#if HAVE_LOCALTIME_R
@@ -22882,13 +23903,38 @@ static sqlite3_int64 localtimeOffset(
y.validYMD = 1;
y.validHMS = 1;
y.validJD = 0;
+ y.rawS = 0;
y.validTZ = 0;
+ y.isError = 0;
computeJD(&y);
*pRc = SQLITE_OK;
return y.iJD - x.iJD;
}
#endif /* SQLITE_OMIT_LOCALTIME */
+/*
+** The following table defines various date transformations of the form
+**
+** 'NNN days'
+**
+** Where NNN is an arbitrary floating-point number and "days" can be one
+** of several units of time.
+*/
+static const struct {
+ u8 eType; /* Transformation type code */
+ u8 nName; /* Length of th name */
+ char *zName; /* Name of the transformation */
+ double rLimit; /* Maximum NNN value for this transform */
+ double rXform; /* Constant used for this transform */
+} aXformType[] = {
+ { 0, 6, "second", 464269060800.0, 86400000.0/(24.0*60.0*60.0) },
+ { 0, 6, "minute", 7737817680.0, 86400000.0/(24.0*60.0) },
+ { 0, 4, "hour", 128963628.0, 86400000.0/24.0 },
+ { 0, 3, "day", 5373485.0, 86400000.0 },
+ { 1, 5, "month", 176546.0, 30.0*86400000.0 },
+ { 2, 4, "year", 14713.0, 365.0*86400000.0 },
+};
+
/*
** Process a modifier to a date-time stamp. The modifiers are
** as follows:
@@ -22913,17 +23959,15 @@ static sqlite3_int64 localtimeOffset(
** to context pCtx. If the error is an unrecognized modifier, no error is
** written to pCtx.
*/
-static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
+static int parseModifier(
+ sqlite3_context *pCtx, /* Function context */
+ const char *z, /* The text of the modifier */
+ int n, /* Length of zMod in bytes */
+ DateTime *p /* The date/time value to be modified */
+){
int rc = 1;
- int n;
double r;
- char *z, zBuf[30];
- z = zBuf;
- for(n=0; niJD += localtimeOffset(p, pCtx, &rc);
clearYMD_HMS_TZ(p);
@@ -22943,16 +23987,21 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
/*
** unixepoch
**
- ** Treat the current value of p->iJD as the number of
+ ** Treat the current value of p->s as the number of
** seconds since 1970. Convert to a real julian day number.
*/
- if( strcmp(z, "unixepoch")==0 && p->validJD ){
- p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000;
- clearYMD_HMS_TZ(p);
- rc = 0;
+ if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){
+ r = p->s*1000.0 + 210866760000000.0;
+ if( r>=0.0 && r<464269060800000.0 ){
+ clearYMD_HMS_TZ(p);
+ p->iJD = (sqlite3_int64)r;
+ p->validJD = 1;
+ p->rawS = 0;
+ rc = 0;
+ }
}
#ifndef SQLITE_OMIT_LOCALTIME
- else if( strcmp(z, "utc")==0 ){
+ else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){
if( p->tzSet==0 ){
sqlite3_int64 c1;
computeJD(p);
@@ -22978,7 +24027,7 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
** weekday N where 0==Sunday, 1==Monday, and so forth. If the
** date is already on the appropriate weekday, this is a no-op.
*/
- if( strncmp(z, "weekday ", 8)==0
+ if( sqlite3_strnicmp(z, "weekday ", 8)==0
&& sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)
&& (n=(int)r)==r && n>=0 && r<7 ){
sqlite3_int64 Z;
@@ -23001,23 +24050,24 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
** Move the date backwards to the beginning of the current day,
** or month or year.
*/
- if( strncmp(z, "start of ", 9)!=0 ) break;
+ if( sqlite3_strnicmp(z, "start of ", 9)!=0 ) break;
+ if( !p->validJD && !p->validYMD && !p->validHMS ) break;
z += 9;
computeYMD(p);
p->validHMS = 1;
p->h = p->m = 0;
p->s = 0.0;
+ p->rawS = 0;
p->validTZ = 0;
p->validJD = 0;
- if( strcmp(z,"month")==0 ){
+ if( sqlite3_stricmp(z,"month")==0 ){
p->D = 1;
rc = 0;
- }else if( strcmp(z,"year")==0 ){
- computeYMD(p);
+ }else if( sqlite3_stricmp(z,"year")==0 ){
p->M = 1;
p->D = 1;
rc = 0;
- }else if( strcmp(z,"day")==0 ){
+ }else if( sqlite3_stricmp(z,"day")==0 ){
rc = 0;
}
break;
@@ -23035,6 +24085,7 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
case '8':
case '9': {
double rRounder;
+ int i;
for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
rc = 1;
@@ -23063,46 +24114,48 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
rc = 0;
break;
}
+
+ /* If control reaches this point, it means the transformation is
+ ** one of the forms like "+NNN days". */
z += n;
while( sqlite3Isspace(*z) ) z++;
n = sqlite3Strlen30(z);
if( n>10 || n<3 ) break;
- if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
+ if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--;
computeJD(p);
- rc = 0;
+ rc = 1;
rRounder = r<0 ? -0.5 : +0.5;
- if( n==3 && strcmp(z,"day")==0 ){
- p->iJD += (sqlite3_int64)(r*86400000.0 + rRounder);
- }else if( n==4 && strcmp(z,"hour")==0 ){
- p->iJD += (sqlite3_int64)(r*(86400000.0/24.0) + rRounder);
- }else if( n==6 && strcmp(z,"minute")==0 ){
- p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0)) + rRounder);
- }else if( n==6 && strcmp(z,"second")==0 ){
- p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0*60.0)) + rRounder);
- }else if( n==5 && strcmp(z,"month")==0 ){
- int x, y;
- computeYMD_HMS(p);
- p->M += (int)r;
- x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
- p->Y += x;
- p->M -= x*12;
- p->validJD = 0;
- computeJD(p);
- y = (int)r;
- if( y!=r ){
- p->iJD += (sqlite3_int64)((r - y)*30.0*86400000.0 + rRounder);
+ for(i=0; i-aXformType[i].rLimit && rM += (int)r;
+ x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
+ p->Y += x;
+ p->M -= x*12;
+ p->validJD = 0;
+ r -= (int)r;
+ break;
+ }
+ case 2: { /* Special processing to add years */
+ int y = (int)r;
+ computeYMD_HMS(p);
+ p->Y += y;
+ p->validJD = 0;
+ r -= (int)r;
+ break;
+ }
+ }
+ computeJD(p);
+ p->iJD += (sqlite3_int64)(r*aXformType[i].rXform + rRounder);
+ rc = 0;
+ break;
}
- }else if( n==4 && strcmp(z,"year")==0 ){
- int y = (int)r;
- computeYMD_HMS(p);
- p->Y += y;
- p->validJD = 0;
- computeJD(p);
- if( y!=r ){
- p->iJD += (sqlite3_int64)((r - y)*365.0*86400000.0 + rRounder);
- }
- }else{
- rc = 1;
}
clearYMD_HMS_TZ(p);
break;
@@ -23129,7 +24182,7 @@ static int isDate(
sqlite3_value **argv,
DateTime *p
){
- int i;
+ int i, n;
const unsigned char *z;
int eType;
memset(p, 0, sizeof(*p));
@@ -23138,8 +24191,7 @@ static int isDate(
}
if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
|| eType==SQLITE_INTEGER ){
- p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*86400000.0 + 0.5);
- p->validJD = 1;
+ setRawDateNumber(p, sqlite3_value_double(argv[0]));
}else{
z = sqlite3_value_text(argv[0]);
if( !z || parseDateOrTime(context, (char*)z, p) ){
@@ -23148,8 +24200,11 @@ static int isDate(
}
for(i=1; iisError || !validJulianDay(p->iJD) ) return 1;
return 0;
}
@@ -23482,11 +24537,11 @@ static void currentTimeFunc(
SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
static FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS
- DFUNCTION(julianday, -1, 0, 0, juliandayFunc ),
- DFUNCTION(date, -1, 0, 0, dateFunc ),
- DFUNCTION(time, -1, 0, 0, timeFunc ),
- DFUNCTION(datetime, -1, 0, 0, datetimeFunc ),
- DFUNCTION(strftime, -1, 0, 0, strftimeFunc ),
+ PURE_DATE(julianday, -1, 0, 0, juliandayFunc ),
+ PURE_DATE(date, -1, 0, 0, dateFunc ),
+ PURE_DATE(time, -1, 0, 0, timeFunc ),
+ PURE_DATE(datetime, -1, 0, 0, datetimeFunc ),
+ PURE_DATE(strftime, -1, 0, 0, strftimeFunc ),
DFUNCTION(current_time, 0, 0, 0, ctimeFunc ),
DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
DFUNCTION(current_date, 0, 0, 0, cdateFunc ),
@@ -23947,7 +25002,7 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
/* #include "sqliteInt.h" */
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
/*
** Global variables.
@@ -24005,7 +25060,7 @@ SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){
}
}
-#endif /* #ifndef SQLITE_OMIT_BUILTIN_TEST */
+#endif /* #ifndef SQLITE_UNTESTABLE */
/************** End of fault.c ***********************************************/
/************** Begin file mem0.c ********************************************/
@@ -24130,7 +25185,9 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
*/
#include
#include
+#ifdef SQLITE_MIGHT_BE_SINGLE_CORE
#include
+#endif /* SQLITE_MIGHT_BE_SINGLE_CORE */
static malloc_zone_t* _sqliteZone_;
#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
@@ -24198,7 +25255,9 @@ static malloc_zone_t* _sqliteZone_;
*/
static void *sqlite3MemMalloc(int nByte){
#ifdef SQLITE_MALLOCSIZE
- void *p = SQLITE_MALLOC( nByte );
+ void *p;
+ testcase( ROUND8(nByte)==nByte );
+ p = SQLITE_MALLOC( nByte );
if( p==0 ){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
@@ -24207,7 +25266,7 @@ static void *sqlite3MemMalloc(int nByte){
#else
sqlite3_int64 *p;
assert( nByte>0 );
- nByte = ROUND8(nByte);
+ testcase( ROUND8(nByte)!=nByte );
p = SQLITE_MALLOC( nByte+8 );
if( p ){
p[0] = nByte;
@@ -24321,19 +25380,10 @@ static int sqlite3MemInit(void *NotUsed){
}else{
/* only 1 core, use our own zone to contention over global locks,
** e.g. we have our own dedicated locks */
- bool success;
- malloc_zone_t* newzone = malloc_create_zone(4096, 0);
- malloc_set_zone_name(newzone, "Sqlite_Heap");
- do{
- success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone,
- (void * volatile *)&_sqliteZone_);
- }while(!_sqliteZone_);
- if( !success ){
- /* somebody registered a zone first */
- malloc_destroy_zone(newzone);
- }
+ _sqliteZone_ = malloc_create_zone(4096, 0);
+ malloc_set_zone_name(_sqliteZone_, "Sqlite_Heap");
}
-#endif
+#endif /* defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) */
UNUSED_PARAMETER(NotUsed);
return SQLITE_OK;
}
@@ -27198,7 +28248,7 @@ SQLITE_API extern int sqlite3_open_file_count;
#ifdef __CYGWIN__
# include
-# include /* amalgamator: dontcache */
+/* # include ** amalgamator: dontcache ** */
#endif
/*
@@ -27329,8 +28379,7 @@ SQLITE_PRIVATE void sqlite3MemoryBarrier(void){
SQLITE_MEMORY_BARRIER;
#elif defined(__GNUC__)
__sync_synchronize();
-#elif !defined(SQLITE_DISABLE_INTRINSIC) && \
- defined(_MSC_VER) && _MSC_VER>=1300
+#elif MSVC_VERSION>=1300
_ReadWriteBarrier();
#elif defined(MemoryBarrier)
MemoryBarrier();
@@ -27541,8 +28590,8 @@ static void winMutexEnter(sqlite3_mutex *p){
p->owner = tid;
p->nRef++;
if( p->trace ){
- OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
- tid, p, p->trace, p->nRef));
+ OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
+ tid, p->id, p, p->trace, p->nRef));
}
#endif
}
@@ -27584,8 +28633,8 @@ static int winMutexTry(sqlite3_mutex *p){
#endif
#ifdef SQLITE_DEBUG
if( p->trace ){
- OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
- tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
+ OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
+ tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
}
#endif
return rc;
@@ -27613,8 +28662,8 @@ static void winMutexLeave(sqlite3_mutex *p){
LeaveCriticalSection(&p->mutex);
#ifdef SQLITE_DEBUG
if( p->trace ){
- OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
- tid, p, p->trace, p->nRef));
+ OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
+ tid, p->id, p, p->trace, p->nRef));
}
#endif
}
@@ -27862,11 +28911,26 @@ static void sqlite3MallocAlarm(int nByte){
** Do a memory allocation with statistics and alarms. Assume the
** lock is already held.
*/
-static int mallocWithAlarm(int n, void **pp){
- int nFull;
+static void mallocWithAlarm(int n, void **pp){
void *p;
+ int nFull;
assert( sqlite3_mutex_held(mem0.mutex) );
+ assert( n>0 );
+
+ /* In Firefox (circa 2017-02-08), xRoundup() is remapped to an internal
+ ** implementation of malloc_good_size(), which must be called in debug
+ ** mode and specifically when the DMD "Dark Matter Detector" is enabled
+ ** or else a crash results. Hence, do not attempt to optimize out the
+ ** following xRoundup() call. */
nFull = sqlite3GlobalConfig.m.xRoundup(n);
+
+#ifdef SQLITE_MAX_MEMORY
+ if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nFull>SQLITE_MAX_MEMORY ){
+ *pp = 0;
+ return;
+ }
+#endif
+
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
if( mem0.alarmThreshold>0 ){
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
@@ -27890,7 +28954,6 @@ static int mallocWithAlarm(int n, void **pp){
sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
}
*pp = p;
- return nFull;
}
/*
@@ -28056,7 +29119,7 @@ SQLITE_PRIVATE int sqlite3MallocSize(void *p){
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
assert( p!=0 );
if( db==0 || !isLookaside(db,p) ){
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
if( db==0 ){
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
@@ -28105,11 +29168,12 @@ static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){
/*
** Free memory that might be associated with a particular database
-** connection.
+** connection. Calling sqlite3DbFree(D,X) for X==0 is a harmless no-op.
+** The sqlite3DbFreeNN(D,X) version requires that X be non-NULL.
*/
-SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
+SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){
assert( db==0 || sqlite3_mutex_held(db->mutex) );
- if( p==0 ) return;
+ assert( p!=0 );
if( db ){
if( db->pnBytesFreed ){
measureAllocationSize(db, p);
@@ -28117,7 +29181,7 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
}
if( isLookaside(db, p) ){
LookasideSlot *pBuf = (LookasideSlot*)p;
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
/* Trash all content in the buffer being freed */
memset(p, 0xaa, db->lookaside.sz);
#endif
@@ -28133,6 +29197,10 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
sqlite3_free(p);
}
+SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
+ assert( db==0 || sqlite3_mutex_held(db->mutex) );
+ if( p ) sqlite3DbFreeNN(db, p);
+}
/*
** Change the size of an existing memory allocation
@@ -28164,7 +29232,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
nDiff = nNew - nOld;
- if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
+ if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
mem0.alarmThreshold-nDiff ){
sqlite3MallocAlarm(nDiff);
}
@@ -28371,9 +29439,8 @@ SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){
if( z==0 ){
return 0;
}
- n = sqlite3Strlen30(z) + 1;
- assert( (n&0x7fffffff)==n );
- zNew = sqlite3DbMallocRaw(db, (int)n);
+ n = strlen(z) + 1;
+ zNew = sqlite3DbMallocRaw(db, n);
if( zNew ){
memcpy(zNew, z, n);
}
@@ -28487,7 +29554,7 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
** Conversion types fall into various categories as defined by the
** following enumeration.
*/
-#define etRADIX 0 /* Integer types. %d, %x, %o, and so forth */
+#define etRADIX 0 /* non-decimal integer types. %x %o */
#define etFLOAT 1 /* Floating point. %f */
#define etEXP 2 /* Exponentional notation. %e and %E */
#define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */
@@ -28505,8 +29572,9 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
#define etPOINTER 13 /* The %p conversion */
#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
+#define etDECIMAL 16 /* %d or %u, but not %x, %o */
-#define etINVALID 16 /* Any unrecognized conversion type */
+#define etINVALID 17 /* Any unrecognized conversion type */
/*
@@ -28530,9 +29598,8 @@ typedef struct et_info { /* Information about each format field */
/*
** Allowed values for et_info.flags
*/
-#define FLAG_SIGNED 1 /* True if the value to convert is signed */
-#define FLAG_INTERN 2 /* True if for internal use only */
-#define FLAG_STRING 4 /* Allow infinity precision */
+#define FLAG_SIGNED 1 /* True if the value to convert is signed */
+#define FLAG_STRING 4 /* Allow infinite precision */
/*
@@ -28542,7 +29609,7 @@ typedef struct et_info { /* Information about each format field */
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
static const char aPrefix[] = "-x0\000X0";
static const et_info fmtinfo[] = {
- { 'd', 10, 1, etRADIX, 0, 0 },
+ { 'd', 10, 1, etDECIMAL, 0, 0 },
{ 's', 0, 4, etSTRING, 0, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 },
{ 'z', 0, 4, etDYNSTRING, 0, 0 },
@@ -28551,7 +29618,7 @@ static const et_info fmtinfo[] = {
{ 'w', 0, 4, etSQLESCAPE3, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 },
{ 'o', 8, 0, etRADIX, 0, 2 },
- { 'u', 10, 0, etRADIX, 0, 0 },
+ { 'u', 10, 0, etDECIMAL, 0, 0 },
{ 'x', 16, 0, etRADIX, 16, 1 },
{ 'X', 16, 0, etRADIX, 0, 4 },
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -28560,16 +29627,15 @@ static const et_info fmtinfo[] = {
{ 'E', 0, 1, etEXP, 14, 0 },
{ 'G', 0, 1, etGENERIC, 14, 0 },
#endif
- { 'i', 10, 1, etRADIX, 0, 0 },
+ { 'i', 10, 1, etDECIMAL, 0, 0 },
{ 'n', 0, 0, etSIZE, 0, 0 },
{ '%', 0, 0, etPERCENT, 0, 0 },
{ 'p', 16, 0, etPOINTER, 0, 1 },
-/* All the rest have the FLAG_INTERN bit set and are thus for internal
-** use only */
- { 'T', 0, 2, etTOKEN, 0, 0 },
- { 'S', 0, 2, etSRCLIST, 0, 0 },
- { 'r', 10, 3, etORDINAL, 0, 0 },
+ /* All the rest are undocumented and are for internal use only */
+ { 'T', 0, 0, etTOKEN, 0, 0 },
+ { 'S', 0, 0, etSRCLIST, 0, 0 },
+ { 'r', 10, 1, etORDINAL, 0, 0 },
};
/*
@@ -28653,17 +29719,15 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
int idx; /* A general purpose loop counter */
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_prefix; /* '+' or ' ' or 0 for prefix */
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 flag_long; /* 1 for the "l" flag, 2 for "ll", 0 by default */
etByte done; /* Loop termination flag */
+ etByte cThousand; /* Thousands separator for %d and %u */
etByte xtype = etINVALID; /* Conversion paradigm */
u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
- u8 useIntern; /* Ok to use internal conversions (ex: %T) */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
sqlite_uint64 longvalue; /* Value for integer types */
LONGDOUBLE_TYPE realvalue; /* Value for real types */
@@ -28682,13 +29746,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
char buf[etBUFSIZE]; /* Conversion buffer */
bufpt = 0;
- if( pAccum->printfFlags ){
- if( (bArgList = (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){
- pArgList = va_arg(ap, PrintfArguments*);
- }
- useIntern = pAccum->printfFlags & SQLITE_PRINTF_INTERNAL;
+ if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){
+ pArgList = va_arg(ap, PrintfArguments*);
+ bArgList = 1;
}else{
- bArgList = useIntern = 0;
+ bArgList = 0;
}
for(; (c=(*fmt))!=0; ++fmt){
if( c!='%' ){
@@ -28706,17 +29768,18 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
break;
}
/* Find out what flags are present */
- flag_leftjustify = flag_plussign = flag_blanksign =
+ flag_leftjustify = flag_prefix = cThousand =
flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0;
do{
switch( c ){
case '-': flag_leftjustify = 1; break;
- case '+': flag_plussign = 1; break;
- case ' ': flag_blanksign = 1; break;
+ case '+': flag_prefix = '+'; break;
+ case ' ': flag_prefix = ' '; break;
case '#': flag_alternateform = 1; break;
case '!': flag_altform2 = 1; break;
case '0': flag_zeropad = 1; break;
+ case ',': cThousand = ','; break;
default: done = 1; break;
}
}while( !done && (c=(*++fmt))!=0 );
@@ -28786,13 +29849,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
flag_long = 1;
c = *++fmt;
if( c=='l' ){
- flag_longlong = 1;
+ flag_long = 2;
c = *++fmt;
- }else{
- flag_longlong = 0;
}
}else{
- flag_long = flag_longlong = 0;
+ flag_long = 0;
}
/* Fetch the info entry for the field */
infop = &fmtinfo[0];
@@ -28800,11 +29861,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
for(idx=0; idxflags & FLAG_INTERN)==0 ){
- xtype = infop->type;
- }else{
- return;
- }
+ xtype = infop->type;
break;
}
}
@@ -28814,15 +29871,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
**
** flag_alternateform TRUE if a '#' is present.
** flag_altform2 TRUE if a '!' is present.
- ** flag_plussign TRUE if a '+' is present.
+ ** flag_prefix '+' or ' ' or zero
** flag_leftjustify TRUE if a '-' is present or if the
** field width was negative.
** flag_zeropad TRUE if the width began with 0.
- ** flag_long TRUE if the letter 'l' (ell) prefixed
- ** the conversion character.
- ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
- ** the conversion character.
- ** flag_blanksign TRUE if a ' ' is present.
+ ** flag_long 1 for "l", 2 for "ll"
** width The specified field width. This is
** always non-negative. Zero is the default.
** precision The specified precision. The default
@@ -28832,19 +29885,24 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
*/
switch( xtype ){
case etPOINTER:
- flag_longlong = sizeof(char*)==sizeof(i64);
- flag_long = sizeof(char*)==sizeof(long int);
+ flag_long = sizeof(char*)==sizeof(i64) ? 2 :
+ sizeof(char*)==sizeof(long int) ? 1 : 0;
/* Fall through into the next case */
case etORDINAL:
- case etRADIX:
+ case etRADIX:
+ cThousand = 0;
+ /* Fall through into the next case */
+ case etDECIMAL:
if( infop->flags & FLAG_SIGNED ){
i64 v;
if( bArgList ){
v = getIntArg(pArgList);
- }else if( flag_longlong ){
- v = va_arg(ap,i64);
}else if( flag_long ){
- v = va_arg(ap,long int);
+ if( flag_long==2 ){
+ v = va_arg(ap,i64) ;
+ }else{
+ v = va_arg(ap,long int);
+ }
}else{
v = va_arg(ap,int);
}
@@ -28857,17 +29915,17 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
prefix = '-';
}else{
longvalue = v;
- if( flag_plussign ) prefix = '+';
- else if( flag_blanksign ) prefix = ' ';
- else prefix = 0;
+ prefix = flag_prefix;
}
}else{
if( bArgList ){
longvalue = (u64)getIntArg(pArgList);
- }else if( flag_longlong ){
- longvalue = va_arg(ap,u64);
}else if( flag_long ){
- longvalue = va_arg(ap,unsigned long int);
+ if( flag_long==2 ){
+ longvalue = va_arg(ap,u64);
+ }else{
+ longvalue = va_arg(ap,unsigned long int);
+ }
}else{
longvalue = va_arg(ap,unsigned int);
}
@@ -28877,16 +29935,17 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
if( flag_zeropad && precision0 );
}
length = (int)(&zOut[nOut-1]-bufpt);
- for(idx=precision-length; idx>0; idx--){
+ while( precision>length ){
*(--bufpt) = '0'; /* Zero pad */
+ length++;
+ }
+ if( cThousand ){
+ int nn = (length - 1)/3; /* Number of "," to insert */
+ int ix = (length - 1)%3 + 1;
+ bufpt -= nn;
+ for(idx=0; nn>0; idx++){
+ bufpt[idx] = bufpt[idx+nn];
+ ix--;
+ if( ix==0 ){
+ bufpt[++idx] = cThousand;
+ nn--;
+ ix = 3;
+ }
+ }
}
if( prefix ) *(--bufpt) = prefix; /* Add sign */
if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
@@ -28935,9 +30009,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
realvalue = -realvalue;
prefix = '-';
}else{
- if( flag_plussign ) prefix = '+';
- else if( flag_blanksign ) prefix = ' ';
- else prefix = 0;
+ prefix = flag_prefix;
}
if( xtype==etGENERIC && precision>0 ) precision--;
testcase( precision>0xfff );
@@ -29173,7 +30245,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
break;
}
case etTOKEN: {
- Token *pToken = va_arg(ap, Token*);
+ Token *pToken;
+ if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
+ pToken = va_arg(ap, Token*);
assert( bArgList==0 );
if( pToken && pToken->n ){
sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
@@ -29182,9 +30256,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
break;
}
case etSRCLIST: {
- SrcList *pSrc = va_arg(ap, SrcList*);
- int k = va_arg(ap, int);
- struct SrcList_item *pItem = &pSrc->a[k];
+ SrcList *pSrc;
+ int k;
+ struct SrcList_item *pItem;
+ if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
+ pSrc = va_arg(ap, SrcList*);
+ k = va_arg(ap, int);
+ pItem = &pSrc->a[k];
assert( bArgList==0 );
assert( k>=0 && knSrc );
if( pItem->zDatabase ){
@@ -29206,9 +30284,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
** the output.
*/
width -= length;
- if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
- sqlite3StrAccumAppend(pAccum, bufpt, length);
- if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
+ if( width>0 ){
+ if( !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
+ sqlite3StrAccumAppend(pAccum, bufpt, length);
+ if( flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
+ }else{
+ sqlite3StrAccumAppend(pAccum, bufpt, length);
+ }
if( zExtra ){
sqlite3DbFree(pAccum->db, zExtra);
@@ -29313,7 +30395,7 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
assert( p->accError==0 || p->nAlloc==0 );
if( p->nChar+N >= p->nAlloc ){
enlargeAndAppend(p,z,N);
- }else{
+ }else if( N ){
assert( p->zText );
p->nChar += N;
memcpy(&p->zText[p->nChar-N], z, N);
@@ -29333,18 +30415,23 @@ SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){
** Return a pointer to the resulting string. Return a NULL
** pointer if any kind of error was encountered.
*/
+static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){
+ assert( p->mxAlloc>0 && !isMalloced(p) );
+ p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
+ if( p->zText ){
+ memcpy(p->zText, p->zBase, p->nChar+1);
+ p->printfFlags |= SQLITE_PRINTF_MALLOCED;
+ }else{
+ setStrAccumError(p, STRACCUM_NOMEM);
+ }
+ return p->zText;
+}
SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
if( p->zText ){
assert( (p->zText==p->zBase)==!isMalloced(p) );
p->zText[p->nChar] = 0;
if( p->mxAlloc>0 && !isMalloced(p) ){
- p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
- if( p->zText ){
- memcpy(p->zText, p->zBase, p->nChar+1);
- p->printfFlags |= SQLITE_PRINTF_MALLOCED;
- }else{
- setStrAccumError(p, STRACCUM_NOMEM);
- }
+ return strAccumFinishRealloc(p);
}
}
return p->zText;
@@ -29484,7 +30571,8 @@ SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_li
#endif
sqlite3StrAccumInit(&acc, 0, zBuf, n, 0);
sqlite3VXPrintf(&acc, zFormat, ap);
- return sqlite3StrAccumFinish(&acc);
+ zBuf[acc.nChar] = 0;
+ return zBuf;
}
SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
char *z;
@@ -29632,6 +30720,7 @@ static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_start(ap, zFormat);
sqlite3VXPrintf(&acc, zFormat, ap);
va_end(ap);
+ assert( acc.nChar>0 );
if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
sqlite3StrAccumFinish(&acc);
fprintf(stdout,"%s", zBuf);
@@ -29692,6 +30781,10 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m
SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
int cnt = 0;
+ if( p==0 ){
+ sqlite3TreeViewLine(pView, "nil-SELECT");
+ return;
+ }
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( p->pWith ){
sqlite3TreeViewWith(pView, p->pWith, 1);
@@ -29800,7 +30893,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
const char *zBinOp = 0; /* Binary operator */
const char *zUniOp = 0; /* Unary operator */
- char zFlgs[30];
+ char zFlgs[60];
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( pExpr==0 ){
sqlite3TreeViewLine(pView, "nil");
@@ -29808,7 +30901,12 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
return;
}
if( pExpr->flags ){
- sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x",pExpr->flags);
+ if( ExprHasProperty(pExpr, EP_FromJoin) ){
+ sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x iRJT=%d",
+ pExpr->flags, pExpr->iRightJoinTable);
+ }else{
+ sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x",pExpr->flags);
+ }
}else{
zFlgs[0] = 0;
}
@@ -29939,17 +31037,17 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS: {
- sqlite3TreeViewLine(pView, "EXISTS-expr");
+ sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_SELECT: {
- sqlite3TreeViewLine(pView, "SELECT-expr");
+ sqlite3TreeViewLine(pView, "SELECT-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
- sqlite3TreeViewLine(pView, "IN");
+ sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
@@ -30027,6 +31125,11 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
break;
}
+ case TK_IF_NULL_ROW: {
+ sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
+ sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
+ break;
+ }
default: {
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
@@ -30192,7 +31295,7 @@ SQLITE_API void sqlite3_randomness(int N, void *pBuf){
sqlite3_mutex_leave(mutex);
}
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
/*
** For testing purposes, we sometimes want to preserve the state of
** PRNG and restore the PRNG to its saved state at a later time, or
@@ -30217,7 +31320,7 @@ SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
sizeof(sqlite3Prng)
);
}
-#endif /* SQLITE_OMIT_BUILTIN_TEST */
+#endif /* SQLITE_UNTESTABLE */
/************** End of random.c **********************************************/
/************** Begin file threads.c *****************************************/
@@ -30832,7 +31935,9 @@ translate_out:
#endif
return SQLITE_OK;
}
+#endif /* SQLITE_OMIT_UTF16 */
+#ifndef SQLITE_OMIT_UTF16
/*
** This routine checks for a byte-order mark at the beginning of the
** UTF-16 string stored in *pMem. If one is present, it is removed and
@@ -31075,7 +32180,7 @@ SQLITE_PRIVATE void sqlite3Coverage(int x){
** Return whatever integer value the test callback returns, or return
** SQLITE_OK if no test callback is installed.
*/
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
SQLITE_PRIVATE int sqlite3FaultSim(int iTest){
int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback;
return xCallback ? xCallback(iTest) : SQLITE_OK;
@@ -31746,6 +32851,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){
}
}
#endif
+ if( !sqlite3Isdigit(zNum[0]) ) return 0;
while( zNum[0]=='0' ) zNum++;
for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
v = v*10 + c;
@@ -32173,13 +33279,11 @@ SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
u32 x;
memcpy(&x,p,4);
return x;
-#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
- && defined(__GNUC__) && GCC_VERSION>=4003000
+#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
u32 x;
memcpy(&x,p,4);
return __builtin_bswap32(x);
-#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
- && defined(_MSC_VER) && _MSC_VER>=1300
+#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
u32 x;
memcpy(&x,p,4);
return _byteswap_ulong(x);
@@ -32191,12 +33295,10 @@ SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
#if SQLITE_BYTEORDER==4321
memcpy(p,&v,4);
-#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
- && defined(__GNUC__) && GCC_VERSION>=4003000
+#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
u32 x = __builtin_bswap32(v);
memcpy(p,&x,4);
-#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
- && defined(_MSC_VER) && _MSC_VER>=1300
+#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
u32 x = _byteswap_ulong(v);
memcpy(p,&x,4);
#else
@@ -32312,6 +33414,9 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
** overflow, leave *pA unchanged and return 1.
*/
SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
+#if GCC_VERSION>=5004000
+ return __builtin_add_overflow(*pA, iB, pA);
+#else
i64 iA = *pA;
testcase( iA==0 ); testcase( iA==1 );
testcase( iB==-1 ); testcase( iB==0 );
@@ -32326,8 +33431,12 @@ SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
}
*pA += iB;
return 0;
+#endif
}
SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
+#if GCC_VERSION>=5004000
+ return __builtin_sub_overflow(*pA, iB, pA);
+#else
testcase( iB==SMALLEST_INT64+1 );
if( iB==SMALLEST_INT64 ){
testcase( (*pA)==(-1) ); testcase( (*pA)==0 );
@@ -32337,8 +33446,12 @@ SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
}else{
return sqlite3AddInt64(pA, -iB);
}
+#endif
}
SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
+#if GCC_VERSION>=5004000
+ return __builtin_mul_overflow(*pA, iB, pA);
+#else
i64 iA = *pA;
if( iB>0 ){
if( iA>LARGEST_INT64/iB ) return 1;
@@ -32354,6 +33467,7 @@ SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
}
*pA = iA*iB;
return 0;
+#endif
}
/*
@@ -32487,6 +33601,109 @@ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
}
#endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */
+/*
+** Add a new name/number pair to a VList. This might require that the
+** VList object be reallocated, so return the new VList. If an OOM
+** error occurs, the original VList returned and the
+** db->mallocFailed flag is set.
+**
+** A VList is really just an array of integers. To destroy a VList,
+** simply pass it to sqlite3DbFree().
+**
+** The first integer is the number of integers allocated for the whole
+** VList. The second integer is the number of integers actually used.
+** Each name/number pair is encoded by subsequent groups of 3 or more
+** integers.
+**
+** Each name/number pair starts with two integers which are the numeric
+** value for the pair and the size of the name/number pair, respectively.
+** The text name overlays one or more following integers. The text name
+** is always zero-terminated.
+**
+** Conceptually:
+**
+** struct VList {
+** int nAlloc; // Number of allocated slots
+** int nUsed; // Number of used slots
+** struct VListEntry {
+** int iValue; // Value for this entry
+** int nSlot; // Slots used by this entry
+** // ... variable name goes here
+** } a[0];
+** }
+**
+** During code generation, pointers to the variable names within the
+** VList are taken. When that happens, nAlloc is set to zero as an
+** indication that the VList may never again be enlarged, since the
+** accompanying realloc() would invalidate the pointers.
+*/
+SQLITE_PRIVATE VList *sqlite3VListAdd(
+ sqlite3 *db, /* The database connection used for malloc() */
+ VList *pIn, /* The input VList. Might be NULL */
+ const char *zName, /* Name of symbol to add */
+ int nName, /* Bytes of text in zName */
+ int iVal /* Value to associate with zName */
+){
+ int nInt; /* number of sizeof(int) objects needed for zName */
+ char *z; /* Pointer to where zName will be stored */
+ int i; /* Index in pIn[] where zName is stored */
+
+ nInt = nName/4 + 3;
+ assert( pIn==0 || pIn[0]>=3 ); /* Verify ok to add new elements */
+ if( pIn==0 || pIn[1]+nInt > pIn[0] ){
+ /* Enlarge the allocation */
+ int nAlloc = (pIn ? pIn[0]*2 : 10) + nInt;
+ VList *pOut = sqlite3DbRealloc(db, pIn, nAlloc*sizeof(int));
+ if( pOut==0 ) return pIn;
+ if( pIn==0 ) pOut[1] = 2;
+ pIn = pOut;
+ pIn[0] = nAlloc;
+ }
+ i = pIn[1];
+ pIn[i] = iVal;
+ pIn[i+1] = nInt;
+ z = (char*)&pIn[i+2];
+ pIn[1] = i+nInt;
+ assert( pIn[1]<=pIn[0] );
+ memcpy(z, zName, nName);
+ z[nName] = 0;
+ return pIn;
+}
+
+/*
+** Return a pointer to the name of a variable in the given VList that
+** has the value iVal. Or return a NULL if there is no such variable in
+** the list
+*/
+SQLITE_PRIVATE const char *sqlite3VListNumToName(VList *pIn, int iVal){
+ int i, mx;
+ if( pIn==0 ) return 0;
+ mx = pIn[1];
+ i = 2;
+ do{
+ if( pIn[i]==iVal ) return (char*)&pIn[i+2];
+ i += pIn[i+1];
+ }while( iht ){ /*OPTIMIZATION-IF-TRUE*/
struct _ht *pEntry;
@@ -32654,7 +33873,7 @@ static HashElem *findElementWithHash(
elem = pH->first;
count = pH->count;
}
- *pHash = h;
+ if( pHash ) *pHash = h;
while( count-- ){
assert( elem!=0 );
if( sqlite3StrICmp(elem->pKey,pKey)==0 ){
@@ -32662,7 +33881,7 @@ static HashElem *findElementWithHash(
}
elem = elem->next;
}
- return 0;
+ return &nullElement;
}
/* Remove a single entry from the hash table given a pointer to that
@@ -32704,13 +33923,9 @@ static void removeElementGivenHash(
** found, or NULL if there is no match.
*/
SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey){
- HashElem *elem; /* The element that matches key */
- unsigned int h; /* A hash on key */
-
assert( pH!=0 );
assert( pKey!=0 );
- elem = findElementWithHash(pH, pKey, &h);
- return elem ? elem->data : 0;
+ return findElementWithHash(pH, pKey, 0)->data;
}
/* Insert an element into the hash table pH. The key is pKey
@@ -32735,7 +33950,7 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
assert( pH!=0 );
assert( pKey!=0 );
elem = findElementWithHash(pH,pKey,&h);
- if( elem ){
+ if( elem->data ){
void *old_data = elem->data;
if( data==0 ){
removeElementGivenHash(pH,elem,h);
@@ -32798,79 +34013,79 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 20 */ "Once" OpHelp(""),
/* 21 */ "If" OpHelp(""),
/* 22 */ "IfNot" OpHelp(""),
- /* 23 */ "SeekLT" OpHelp("key=r[P3@P4]"),
- /* 24 */ "SeekLE" OpHelp("key=r[P3@P4]"),
- /* 25 */ "SeekGE" OpHelp("key=r[P3@P4]"),
- /* 26 */ "SeekGT" OpHelp("key=r[P3@P4]"),
- /* 27 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
- /* 28 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
- /* 29 */ "NoConflict" OpHelp("key=r[P3@P4]"),
- /* 30 */ "NotFound" OpHelp("key=r[P3@P4]"),
- /* 31 */ "Found" OpHelp("key=r[P3@P4]"),
- /* 32 */ "SeekRowid" OpHelp("intkey=r[P3]"),
- /* 33 */ "NotExists" OpHelp("intkey=r[P3]"),
- /* 34 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
- /* 35 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
- /* 36 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
- /* 37 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
- /* 38 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
- /* 39 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
- /* 40 */ "Lt" OpHelp("IF r[P3]=r[P1]"),
- /* 42 */ "ElseNotEq" OpHelp(""),
- /* 43 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
- /* 44 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
- /* 45 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"),
- /* 47 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
- /* 48 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
- /* 49 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
- /* 50 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
- /* 51 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
- /* 52 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
- /* 53 */ "Last" OpHelp(""),
- /* 54 */ "BitNot" OpHelp("r[P1]= ~r[P1]"),
- /* 55 */ "SorterSort" OpHelp(""),
- /* 56 */ "Sort" OpHelp(""),
- /* 57 */ "Rewind" OpHelp(""),
- /* 58 */ "IdxLE" OpHelp("key=r[P3@P4]"),
- /* 59 */ "IdxGT" OpHelp("key=r[P3@P4]"),
- /* 60 */ "IdxLT" OpHelp("key=r[P3@P4]"),
- /* 61 */ "IdxGE" OpHelp("key=r[P3@P4]"),
- /* 62 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
- /* 63 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
- /* 64 */ "Program" OpHelp(""),
- /* 65 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
- /* 66 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
- /* 67 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]-=P3, goto P2"),
- /* 68 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
- /* 69 */ "IncrVacuum" OpHelp(""),
- /* 70 */ "VNext" OpHelp(""),
- /* 71 */ "Init" OpHelp("Start at P2"),
- /* 72 */ "Return" OpHelp(""),
- /* 73 */ "EndCoroutine" OpHelp(""),
- /* 74 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
- /* 75 */ "Halt" OpHelp(""),
- /* 76 */ "Integer" OpHelp("r[P2]=P1"),
- /* 77 */ "Int64" OpHelp("r[P2]=P4"),
- /* 78 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
- /* 79 */ "Null" OpHelp("r[P2..P3]=NULL"),
- /* 80 */ "SoftNull" OpHelp("r[P1]=NULL"),
- /* 81 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
- /* 82 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
- /* 83 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
- /* 84 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
- /* 85 */ "SCopy" OpHelp("r[P2]=r[P1]"),
- /* 86 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
- /* 87 */ "ResultRow" OpHelp("output=r[P1@P2]"),
- /* 88 */ "CollSeq" OpHelp(""),
- /* 89 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"),
- /* 90 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"),
- /* 91 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
- /* 92 */ "RealAffinity" OpHelp(""),
- /* 93 */ "Cast" OpHelp("affinity(r[P1])"),
- /* 94 */ "Permutation" OpHelp(""),
- /* 95 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
+ /* 23 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
+ /* 24 */ "SeekLT" OpHelp("key=r[P3@P4]"),
+ /* 25 */ "SeekLE" OpHelp("key=r[P3@P4]"),
+ /* 26 */ "SeekGE" OpHelp("key=r[P3@P4]"),
+ /* 27 */ "SeekGT" OpHelp("key=r[P3@P4]"),
+ /* 28 */ "NoConflict" OpHelp("key=r[P3@P4]"),
+ /* 29 */ "NotFound" OpHelp("key=r[P3@P4]"),
+ /* 30 */ "Found" OpHelp("key=r[P3@P4]"),
+ /* 31 */ "SeekRowid" OpHelp("intkey=r[P3]"),
+ /* 32 */ "NotExists" OpHelp("intkey=r[P3]"),
+ /* 33 */ "Last" OpHelp(""),
+ /* 34 */ "IfSmaller" OpHelp(""),
+ /* 35 */ "SorterSort" OpHelp(""),
+ /* 36 */ "Sort" OpHelp(""),
+ /* 37 */ "Rewind" OpHelp(""),
+ /* 38 */ "IdxLE" OpHelp("key=r[P3@P4]"),
+ /* 39 */ "IdxGT" OpHelp("key=r[P3@P4]"),
+ /* 40 */ "IdxLT" OpHelp("key=r[P3@P4]"),
+ /* 41 */ "IdxGE" OpHelp("key=r[P3@P4]"),
+ /* 42 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
+ /* 43 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
+ /* 44 */ "Program" OpHelp(""),
+ /* 45 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
+ /* 46 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+ /* 47 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
+ /* 48 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
+ /* 49 */ "IncrVacuum" OpHelp(""),
+ /* 50 */ "VNext" OpHelp(""),
+ /* 51 */ "Init" OpHelp("Start at P2"),
+ /* 52 */ "Return" OpHelp(""),
+ /* 53 */ "EndCoroutine" OpHelp(""),
+ /* 54 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
+ /* 55 */ "Halt" OpHelp(""),
+ /* 56 */ "Integer" OpHelp("r[P2]=P1"),
+ /* 57 */ "Int64" OpHelp("r[P2]=P4"),
+ /* 58 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
+ /* 59 */ "Null" OpHelp("r[P2..P3]=NULL"),
+ /* 60 */ "SoftNull" OpHelp("r[P1]=NULL"),
+ /* 61 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
+ /* 62 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
+ /* 63 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
+ /* 64 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
+ /* 65 */ "SCopy" OpHelp("r[P2]=r[P1]"),
+ /* 66 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
+ /* 67 */ "ResultRow" OpHelp("output=r[P1@P2]"),
+ /* 68 */ "CollSeq" OpHelp(""),
+ /* 69 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
+ /* 70 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
+ /* 71 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
+ /* 72 */ "RealAffinity" OpHelp(""),
+ /* 73 */ "Cast" OpHelp("affinity(r[P1])"),
+ /* 74 */ "Permutation" OpHelp(""),
+ /* 75 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
+ /* 76 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
+ /* 77 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
+ /* 78 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
+ /* 79 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
+ /* 80 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
+ /* 81 */ "Lt" OpHelp("IF r[P3]=r[P1]"),
+ /* 83 */ "ElseNotEq" OpHelp(""),
+ /* 84 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
+ /* 85 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
+ /* 86 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"),
+ /* 88 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
+ /* 89 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
+ /* 90 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
+ /* 91 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
+ /* 92 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
+ /* 93 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
+ /* 94 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
+ /* 95 */ "BitNot" OpHelp("r[P1]= ~r[P1]"),
/* 96 */ "Column" OpHelp("r[P3]=PX"),
/* 97 */ "String8" OpHelp("r[P2]='P4'"),
/* 98 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
@@ -32881,29 +34096,29 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 103 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
/* 104 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
/* 105 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
- /* 106 */ "OpenAutoindex" OpHelp("nColumn=P2"),
- /* 107 */ "OpenEphemeral" OpHelp("nColumn=P2"),
- /* 108 */ "SorterOpen" OpHelp(""),
- /* 109 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
- /* 110 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
- /* 111 */ "Close" OpHelp(""),
- /* 112 */ "ColumnsUsed" OpHelp(""),
- /* 113 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
- /* 114 */ "NewRowid" OpHelp("r[P2]=rowid"),
- /* 115 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
- /* 116 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
- /* 117 */ "Delete" OpHelp(""),
- /* 118 */ "ResetCount" OpHelp(""),
- /* 119 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
- /* 120 */ "SorterData" OpHelp("r[P2]=data"),
- /* 121 */ "RowKey" OpHelp("r[P2]=key"),
+ /* 106 */ "OpenDup" OpHelp(""),
+ /* 107 */ "OpenAutoindex" OpHelp("nColumn=P2"),
+ /* 108 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 109 */ "SorterOpen" OpHelp(""),
+ /* 110 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
+ /* 111 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
+ /* 112 */ "Close" OpHelp(""),
+ /* 113 */ "ColumnsUsed" OpHelp(""),
+ /* 114 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
+ /* 115 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 116 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 117 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
+ /* 118 */ "Delete" OpHelp(""),
+ /* 119 */ "ResetCount" OpHelp(""),
+ /* 120 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+ /* 121 */ "SorterData" OpHelp("r[P2]=data"),
/* 122 */ "RowData" OpHelp("r[P2]=data"),
/* 123 */ "Rowid" OpHelp("r[P2]=rowid"),
/* 124 */ "NullRow" OpHelp(""),
- /* 125 */ "SorterInsert" OpHelp(""),
+ /* 125 */ "SorterInsert" OpHelp("key=r[P2]"),
/* 126 */ "IdxInsert" OpHelp("key=r[P2]"),
/* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
- /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"),
+ /* 128 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
/* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"),
/* 130 */ "Destroy" OpHelp(""),
/* 131 */ "Clear" OpHelp(""),
@@ -32911,33 +34126,38 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 133 */ "ResetSorter" OpHelp(""),
/* 134 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"),
/* 135 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"),
- /* 136 */ "ParseSchema" OpHelp(""),
- /* 137 */ "LoadAnalysis" OpHelp(""),
- /* 138 */ "DropTable" OpHelp(""),
- /* 139 */ "DropIndex" OpHelp(""),
- /* 140 */ "DropTrigger" OpHelp(""),
- /* 141 */ "IntegrityCk" OpHelp(""),
- /* 142 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
- /* 143 */ "Param" OpHelp(""),
- /* 144 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
- /* 145 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
- /* 146 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
- /* 147 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 148 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 149 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
- /* 150 */ "Expire" OpHelp(""),
- /* 151 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 152 */ "VBegin" OpHelp(""),
- /* 153 */ "VCreate" OpHelp(""),
- /* 154 */ "VDestroy" OpHelp(""),
- /* 155 */ "VOpen" OpHelp(""),
- /* 156 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 157 */ "VRename" OpHelp(""),
- /* 158 */ "Pagecount" OpHelp(""),
- /* 159 */ "MaxPgcnt" OpHelp(""),
- /* 160 */ "CursorHint" OpHelp(""),
- /* 161 */ "Noop" OpHelp(""),
- /* 162 */ "Explain" OpHelp(""),
+ /* 136 */ "SqlExec" OpHelp(""),
+ /* 137 */ "ParseSchema" OpHelp(""),
+ /* 138 */ "LoadAnalysis" OpHelp(""),
+ /* 139 */ "DropTable" OpHelp(""),
+ /* 140 */ "DropIndex" OpHelp(""),
+ /* 141 */ "DropTrigger" OpHelp(""),
+ /* 142 */ "IntegrityCk" OpHelp(""),
+ /* 143 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
+ /* 144 */ "Param" OpHelp(""),
+ /* 145 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 146 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
+ /* 147 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
+ /* 148 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 149 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 150 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 151 */ "Expire" OpHelp(""),
+ /* 152 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 153 */ "VBegin" OpHelp(""),
+ /* 154 */ "VCreate" OpHelp(""),
+ /* 155 */ "VDestroy" OpHelp(""),
+ /* 156 */ "VOpen" OpHelp(""),
+ /* 157 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 158 */ "VRename" OpHelp(""),
+ /* 159 */ "Pagecount" OpHelp(""),
+ /* 160 */ "MaxPgcnt" OpHelp(""),
+ /* 161 */ "PureFunc0" OpHelp(""),
+ /* 162 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"),
+ /* 163 */ "PureFunc" OpHelp(""),
+ /* 164 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"),
+ /* 165 */ "CursorHint" OpHelp(""),
+ /* 166 */ "Noop" OpHelp(""),
+ /* 167 */ "Explain" OpHelp(""),
};
return azName[i];
}
@@ -33037,10 +34257,10 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
#include
#include
#include
-#include
+/* #include */
/* #include */
#include
-#include
+/* #include */
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
/* # include */
#endif
@@ -34206,7 +35426,14 @@ struct unixFileId {
#if OS_VXWORKS
struct vxworksFileId *pId; /* Unique file ID for vxworks. */
#else
- ino_t ino; /* Inode number */
+ /* We are told that some versions of Android contain a bug that
+ ** sizes ino_t at only 32-bits instead of 64-bits. (See
+ ** https://android-review.googlesource.com/#/c/115351/3/dist/sqlite3.c)
+ ** To work around this, always allocate 64-bits for the inode number.
+ ** On small machines that only have 32-bit inodes, this wastes 4 bytes,
+ ** but that should not be a big deal. */
+ /* WAS: ino_t ino; */
+ u64 ino; /* Inode number */
#endif
};
@@ -34451,7 +35678,7 @@ static int findInodeInfo(
#if OS_VXWORKS
fileId.pId = pFile->pId;
#else
- fileId.ino = statbuf.st_ino;
+ fileId.ino = (u64)statbuf.st_ino;
#endif
pInode = inodeList;
while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
@@ -34485,7 +35712,8 @@ static int fileHasMoved(unixFile *pFile){
#else
struct stat buf;
return pFile->pInode!=0 &&
- (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
+ (osStat(pFile->zPath, &buf)!=0
+ || (u64)buf.st_ino!=pFile->pInode->fileId.ino);
#endif
}
@@ -38657,7 +39885,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
unixEnterMutex();
pInode = inodeList;
while( pInode && (pInode->fileId.dev!=sStat.st_dev
- || pInode->fileId.ino!=sStat.st_ino) ){
+ || pInode->fileId.ino!=(u64)sStat.st_ino) ){
pInode = pInode->pNext;
}
if( pInode ){
@@ -41311,7 +42539,34 @@ struct winVfsAppData {
******************************************************************************
*/
#ifndef SQLITE_WIN32_HEAP_CREATE
-# define SQLITE_WIN32_HEAP_CREATE (TRUE)
+# define SQLITE_WIN32_HEAP_CREATE (TRUE)
+#endif
+
+/*
+ * This is the maximum possible initial size of the Win32-specific heap, in
+ * bytes.
+ */
+#ifndef SQLITE_WIN32_HEAP_MAX_INIT_SIZE
+# define SQLITE_WIN32_HEAP_MAX_INIT_SIZE (4294967295U)
+#endif
+
+/*
+ * This is the extra space for the initial size of the Win32-specific heap,
+ * in bytes. This value may be zero.
+ */
+#ifndef SQLITE_WIN32_HEAP_INIT_EXTRA
+# define SQLITE_WIN32_HEAP_INIT_EXTRA (4194304)
+#endif
+
+/*
+ * Calculate the maximum legal cache size, in pages, based on the maximum
+ * possible initial heap size and the default page size, setting aside the
+ * needed extra space.
+ */
+#ifndef SQLITE_WIN32_MAX_CACHE_SIZE
+# define SQLITE_WIN32_MAX_CACHE_SIZE (((SQLITE_WIN32_HEAP_MAX_INIT_SIZE) - \
+ (SQLITE_WIN32_HEAP_INIT_EXTRA)) / \
+ (SQLITE_DEFAULT_PAGE_SIZE))
#endif
/*
@@ -41320,25 +42575,36 @@ struct winVfsAppData {
*/
#ifndef SQLITE_WIN32_CACHE_SIZE
# if SQLITE_DEFAULT_CACHE_SIZE>=0
-# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE)
+# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE)
# else
-# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE))
+# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE))
# endif
#endif
+/*
+ * Make sure that the calculated cache size, in pages, cannot cause the
+ * initial size of the Win32-specific heap to exceed the maximum amount
+ * of memory that can be specified in the call to HeapCreate.
+ */
+#if SQLITE_WIN32_CACHE_SIZE>SQLITE_WIN32_MAX_CACHE_SIZE
+# undef SQLITE_WIN32_CACHE_SIZE
+# define SQLITE_WIN32_CACHE_SIZE (2000)
+#endif
+
/*
* The initial size of the Win32-specific heap. This value may be zero.
*/
#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
-# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \
- (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
+# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \
+ (SQLITE_DEFAULT_PAGE_SIZE) + \
+ (SQLITE_WIN32_HEAP_INIT_EXTRA))
#endif
/*
* The maximum size of the Win32-specific heap. This value may be zero.
*/
#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
-# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
+# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
#endif
/*
@@ -41346,7 +42612,7 @@ struct winVfsAppData {
* zero for the default behavior.
*/
#ifndef SQLITE_WIN32_HEAP_FLAGS
-# define SQLITE_WIN32_HEAP_FLAGS (0)
+# define SQLITE_WIN32_HEAP_FLAGS (0)
#endif
@@ -47218,7 +48484,7 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
return p->iSize;
}
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
/*
** Let V[] be an array of unsigned characters sufficient to hold
** up to N bits. Let I be an integer between 0 and N. 0<=Ipgno>0 ); /* Page number is 1 or more */
+ assert( pPg->pgno>0 || pPg->pPager==0 ); /* Page number is 1 or more */
pCache = pPg->pCache;
assert( pCache!=0 ); /* Every page has an associated PCache */
if( pPg->flags & PGHDR_CLEAN ){
@@ -47623,6 +48889,12 @@ SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); }
** has already been allocated and is passed in as the p pointer.
** The caller discovers how much space needs to be allocated by
** calling sqlite3PcacheSize().
+**
+** szExtra is some extra space allocated for each page. The first
+** 8 bytes of the extra space will be zeroed as the page is allocated,
+** but remaining content will be uninitialized. Though it is opaque
+** to this module, the extra space really ends up being the MemPage
+** structure in the pager.
*/
SQLITE_PRIVATE int sqlite3PcacheOpen(
int szPage, /* Size of every page */
@@ -47635,6 +48907,7 @@ SQLITE_PRIVATE int sqlite3PcacheOpen(
memset(p, 0, sizeof(PCache));
p->szPage = 1;
p->szExtra = szExtra;
+ assert( szExtra>=8 ); /* First 8 bytes will be zeroed */
p->bPurgeable = bPurgeable;
p->eCreate = 2;
p->xStress = xStress;
@@ -47704,7 +48977,6 @@ SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch(
assert( pCache!=0 );
assert( pCache->pCache!=0 );
assert( createFlag==3 || createFlag==0 );
- assert( pgno>0 );
assert( pCache->eCreate==((pCache->bPurgeable && pCache->pDirty) ? 1 : 2) );
/* eCreate defines what to do if the page does not exist.
@@ -47804,7 +49076,7 @@ static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit(
pPgHdr->pPage = pPage;
pPgHdr->pData = pPage->pBuf;
pPgHdr->pExtra = (void *)&pPgHdr[1];
- memset(pPgHdr->pExtra, 0, pCache->szExtra);
+ memset(pPgHdr->pExtra, 0, 8);
pPgHdr->pCache = pCache;
pPgHdr->pgno = pgno;
pPgHdr->flags = PGHDR_CLEAN;
@@ -48500,8 +49772,7 @@ static int pcache1InitBulk(PCache1 *pCache){
sqlite3EndBenignMalloc();
if( zBulk ){
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
- int i;
- for(i=0; iszPage];
pX->page.pBuf = zBulk;
pX->page.pExtra = &pX[1];
@@ -48510,7 +49781,7 @@ static int pcache1InitBulk(PCache1 *pCache){
pX->pNext = pCache->pFree;
pCache->pFree = pX;
zBulk += pCache->szAlloc;
- }
+ }while( --nBulk );
}
return pCache->pFree!=0;
}
@@ -49426,7 +50697,7 @@ SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
int nFree = 0;
assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
assert( sqlite3_mutex_notheld(pcache1.mutex) );
- if( sqlite3GlobalConfig.nPage==0 ){
+ if( sqlite3GlobalConfig.pPage==0 ){
PgHdr1 *p;
pcache1EnterMutex(&pcache1.grp);
while( (nReq<0 || nFreepMethods!=0)
/*
-** Return true if this pager uses a write-ahead log instead of the usual
-** rollback journal. Otherwise false.
+** Return true if this pager uses a write-ahead log to read page pgno.
+** Return false if the pager reads pgno directly from the database.
*/
-#ifndef SQLITE_OMIT_WAL
-SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager){
- return (pPager->pWal!=0);
+#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ)
+SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){
+ u32 iRead = 0;
+ int rc;
+ if( pPager->pWal==0 ) return 0;
+ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
+ return rc || iRead;
}
-# define pagerUseWal(x) sqlite3PagerUseWal(x)
+#endif
+#ifndef SQLITE_OMIT_WAL
+# define pagerUseWal(x) ((x)->pWal!=0)
#else
# define pagerUseWal(x) 0
# define pagerRollbackWal(x) 0
@@ -51145,6 +52425,33 @@ static char *print_pager_state(Pager *p){
}
#endif
+/* Forward references to the various page getters */
+static int getPageNormal(Pager*,Pgno,DbPage**,int);
+static int getPageError(Pager*,Pgno,DbPage**,int);
+#if SQLITE_MAX_MMAP_SIZE>0
+static int getPageMMap(Pager*,Pgno,DbPage**,int);
+#endif
+
+/*
+** Set the Pager.xGet method for the appropriate routine used to fetch
+** content from the pager.
+*/
+static void setGetterMethod(Pager *pPager){
+ if( pPager->errCode ){
+ pPager->xGet = getPageError;
+#if SQLITE_MAX_MMAP_SIZE>0
+ }else if( USEFETCH(pPager)
+#ifdef SQLITE_HAS_CODEC
+ && pPager->xCodec==0
+#endif
+ ){
+ pPager->xGet = getPageMMap;
+#endif /* SQLITE_MAX_MMAP_SIZE>0 */
+ }else{
+ pPager->xGet = getPageNormal;
+ }
+}
+
/*
** Return true if it is necessary to write page *pPg into the sub-journal.
** A page needs to be written into the sub-journal if there exists one
@@ -51959,6 +53266,7 @@ static void pager_unlock(Pager *pPager){
}
if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
pPager->errCode = SQLITE_OK;
+ setGetterMethod(pPager);
}
pPager->journalOff = 0;
@@ -51996,6 +53304,7 @@ static int pager_error(Pager *pPager, int rc){
if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){
pPager->errCode = rc;
pPager->eState = PAGER_ERROR;
+ setGetterMethod(pPager);
}
return rc;
}
@@ -52164,7 +53473,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
pPager->pInJournal = 0;
pPager->nRec = 0;
if( rc==SQLITE_OK ){
- if( pagerFlushOnCommit(pPager, bCommit) ){
+ if( MEMDB || pagerFlushOnCommit(pPager, bCommit) ){
sqlite3PcacheCleanAll(pPager->pPCache);
}else{
sqlite3PcacheClearWritable(pPager->pPCache);
@@ -52348,6 +53657,11 @@ static int pager_playback_one_page(
char *aData; /* Temporary storage for the page */
sqlite3_file *jfd; /* The file descriptor for the journal file */
int isSynced; /* True if journal page is synced */
+#ifdef SQLITE_HAS_CODEC
+ /* The jrnlEnc flag is true if Journal pages should be passed through
+ ** the codec. It is false for pure in-memory journals. */
+ const int jrnlEnc = (isMainJrnl || pPager->subjInMemory==0);
+#endif
assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */
assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */
@@ -52471,14 +53785,34 @@ static int pager_playback_one_page(
i64 ofst = (pgno-1)*(i64)pPager->pageSize;
testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
assert( !pagerUseWal(pPager) );
+
+ /* Write the data read from the journal back into the database file.
+ ** This is usually safe even for an encrypted database - as the data
+ ** was encrypted before it was written to the journal file. The exception
+ ** is if the data was just read from an in-memory sub-journal. In that
+ ** case it must be encrypted here before it is copied into the database
+ ** file. */
+#ifdef SQLITE_HAS_CODEC
+ if( !jrnlEnc ){
+ CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData);
+ rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
+ CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
+ }else
+#endif
rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
+
if( pgno>pPager->dbFileSize ){
pPager->dbFileSize = pgno;
}
if( pPager->pBackup ){
- CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
+#ifdef SQLITE_HAS_CODEC
+ if( jrnlEnc ){
+ CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
+ sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
+ CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT,aData);
+ }else
+#endif
sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
- CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData);
}
}else if( !isMainJrnl && pPg==0 ){
/* If this is a rollback of a savepoint and data was not written to
@@ -52530,7 +53864,9 @@ static int pager_playback_one_page(
}
/* Decode the page just read from disk */
- CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT);
+#if SQLITE_HAS_CODEC
+ if( jrnlEnc ){ CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT); }
+#endif
sqlite3PcacheRelease(pPg);
}
return rc;
@@ -53316,7 +54652,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
nPage = sqlite3WalDbsize(pPager->pWal);
/* If the number of pages in the database is not available from the
- ** WAL sub-system, determine the page counte based on the size of
+ ** WAL sub-system, determine the page count based on the size of
** the database file. If the size of the database file is not an
** integer multiple of the page-size, round up the result.
*/
@@ -53367,23 +54703,21 @@ static int pagerOpenWalIfPresent(Pager *pPager){
if( !pPager->tempFile ){
int isWal; /* True if WAL file exists */
- Pgno nPage; /* Size of the database file */
-
- rc = pagerPagecount(pPager, &nPage);
- if( rc ) return rc;
- if( nPage==0 ){
- rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
- if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
- isWal = 0;
- }else{
- rc = sqlite3OsAccess(
- pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
- );
- }
+ rc = sqlite3OsAccess(
+ pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
+ );
if( rc==SQLITE_OK ){
if( isWal ){
- testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
- rc = sqlite3PagerOpenWal(pPager, 0);
+ Pgno nPage; /* Size of the database file */
+
+ rc = pagerPagecount(pPager, &nPage);
+ if( rc ) return rc;
+ if( nPage==0 ){
+ rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
+ }else{
+ testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
+ rc = sqlite3PagerOpenWal(pPager, 0);
+ }
}else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
pPager->journalMode = PAGER_JOURNALMODE_DELETE;
}
@@ -53563,6 +54897,7 @@ static void pagerFixMaplimit(Pager *pPager){
sqlite3_int64 sz;
sz = pPager->szMmap;
pPager->bUseFetch = (sz>0);
+ setGetterMethod(pPager);
sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
}
#endif
@@ -54059,6 +55394,7 @@ static int pagerSyncHotJournal(Pager *pPager){
return rc;
}
+#if SQLITE_MAX_MMAP_SIZE>0
/*
** Obtain a reference to a memory mapped page object for page number pgno.
** The new object will use the pointer pData, obtained from xFetch().
@@ -54081,7 +55417,8 @@ static int pagerAcquireMapPage(
*ppPage = p = pPager->pMmapFreelist;
pPager->pMmapFreelist = p->pDirty;
p->pDirty = 0;
- memset(p->pExtra, 0, pPager->nExtra);
+ assert( pPager->nExtra>=8 );
+ memset(p->pExtra, 0, 8);
}else{
*ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
if( p==0 ){
@@ -54106,6 +55443,7 @@ static int pagerAcquireMapPage(
return SQLITE_OK;
}
+#endif
/*
** Release a reference to page pPg. pPg must have been returned by an
@@ -54148,9 +55486,10 @@ static void pagerFreeMapHdrs(Pager *pPager){
** a hot journal may be left in the filesystem but no error is returned
** to the caller.
*/
-SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
+SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
u8 *pTmp = (u8 *)pPager->pTmpSpace;
+ assert( db || pagerUseWal(pPager)==0 );
assert( assert_pager_state(pPager) );
disable_simulated_io_errors();
sqlite3BeginBenignMalloc();
@@ -54158,7 +55497,10 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
/* pPager->errCode = 0; */
pPager->exclusiveMode = 0;
#ifndef SQLITE_OMIT_WAL
- sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
+ assert( db || pPager->pWal==0 );
+ sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, pPager->pageSize,
+ (db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp)
+ );
pPager->pWal = 0;
#endif
pager_reset(pPager);
@@ -54534,8 +55876,13 @@ static int subjournalPage(PgHdr *pPg){
void *pData = pPg->pData;
i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
char *pData2;
-
- CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
+
+#if SQLITE_HAS_CODEC
+ if( !pPager->subjInMemory ){
+ CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
+ }else
+#endif
+ pData2 = pData;
PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
rc = write32bits(pPager->sjfd, offset, pPg->pgno);
if( rc==SQLITE_OK ){
@@ -54677,7 +56024,9 @@ SQLITE_PRIVATE int sqlite3PagerFlush(Pager *pPager){
**
** The nExtra parameter specifies the number of bytes of space allocated
** along with each page reference. This space is available to the user
-** via the sqlite3PagerGetExtra() API.
+** via the sqlite3PagerGetExtra() API. When a new page is allocated, the
+** first 8 bytes of this space are zeroed but the remainder is uninitialized.
+** (The extra space is used by btree as the MemPage object.)
**
** The flags argument is used to specify properties that affect the
** operation of the pager. It should be passed some bitwise combination
@@ -54907,8 +56256,8 @@ act_like_temp_file:
/* Initialize the PCache object. */
if( rc==SQLITE_OK ){
- assert( nExtra<1000 );
nExtra = ROUND8(nExtra);
+ assert( nExtra>=8 && nExtra<1000 );
rc = sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
!memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
}
@@ -54973,6 +56322,7 @@ act_like_temp_file:
/* pPager->xBusyHandler = 0; */
/* pPager->pBusyHandlerArg = 0; */
pPager->xReiniter = xReinit;
+ setGetterMethod(pPager);
/* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
/* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */
@@ -55310,19 +56660,14 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
** detected. The chance of an undetected change is so small that
** it can be neglected.
*/
- Pgno nPage = 0;
char dbFileVers[sizeof(pPager->dbFileVers)];
- rc = pagerPagecount(pPager, &nPage);
- if( rc ) goto failed;
-
- if( nPage>0 ){
- IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
- rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
- if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
+ IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
+ rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
+ if( rc!=SQLITE_OK ){
+ if( rc!=SQLITE_IOERR_SHORT_READ ){
goto failed;
}
- }else{
memset(dbFileVers, 0, sizeof(dbFileVers));
}
@@ -55386,10 +56731,17 @@ static void pagerUnlockIfUnused(Pager *pPager){
}
/*
-** Acquire a reference to page number pgno in pager pPager (a page
-** reference has type DbPage*). If the requested reference is
+** The page getter methods each try to acquire a reference to a
+** page with page number pgno. If the requested reference is
** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
**
+** There are different implementations of the getter method depending
+** on the current state of the pager.
+**
+** getPageNormal() -- The normal getter
+** getPageError() -- Used if the pager is in an error state
+** getPageMmap() -- Used if memory-mapped I/O is enabled
+**
** If the requested page is already in the cache, it is returned.
** Otherwise, a new page object is allocated and populated with data
** read from the database file. In some cases, the pcache module may
@@ -55401,14 +56753,14 @@ static void pagerUnlockIfUnused(Pager *pPager){
** already in the cache when this function is called, then the extra
** data is left as it was when the page object was last used.
**
-** If the database image is smaller than the requested page or if a
-** non-zero value is passed as the noContent parameter and the
+** If the database image is smaller than the requested page or if
+** the flags parameter contains the PAGER_GET_NOCONTENT bit and the
** requested page is not already stored in the cache, then no
** actual disk read occurs. In this case the memory image of the
** page is initialized to all zeros.
**
-** If noContent is true, it means that we do not care about the contents
-** of the page. This occurs in two scenarios:
+** If PAGER_GET_NOCONTENT is true, it means that we do not care about
+** the contents of the page. This occurs in two scenarios:
**
** a) When reading a free-list leaf page from the database, and
**
@@ -55416,8 +56768,8 @@ static void pagerUnlockIfUnused(Pager *pPager){
** a new page into the cache to be filled with the data read
** from the savepoint journal.
**
-** If noContent is true, then the data returned is zeroed instead of
-** being read from the database. Additionally, the bits corresponding
+** If PAGER_GET_NOCONTENT is true, then the data returned is zeroed instead
+** of being read from the database. Additionally, the bits corresponding
** to pgno in Pager.pInJournal (bitvec of pages already written to the
** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open
** savepoints are set. This means if the page is made writable at any
@@ -55435,106 +56787,39 @@ static void pagerUnlockIfUnused(Pager *pPager){
** Since Lookup() never goes to disk, it never has to deal with locks
** or journal files.
*/
-SQLITE_PRIVATE int sqlite3PagerGet(
+static int getPageNormal(
Pager *pPager, /* The pager open on the database file */
Pgno pgno, /* Page number to fetch */
DbPage **ppPage, /* Write a pointer to the page here */
int flags /* PAGER_GET_XXX flags */
){
int rc = SQLITE_OK;
- PgHdr *pPg = 0;
- u32 iFrame = 0; /* Frame to read from WAL file */
- const int noContent = (flags & PAGER_GET_NOCONTENT);
+ PgHdr *pPg;
+ u8 noContent; /* True if PAGER_GET_NOCONTENT is set */
+ sqlite3_pcache_page *pBase;
- /* It is acceptable to use a read-only (mmap) page for any page except
- ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
- ** flag was specified by the caller. And so long as the db is not a
- ** temporary or in-memory database. */
- const int bMmapOk = (pgno>1 && USEFETCH(pPager)
- && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
-#ifdef SQLITE_HAS_CODEC
- && pPager->xCodec==0
-#endif
- );
-
- /* Optimization note: Adding the "pgno<=1" term before "pgno==0" here
- ** allows the compiler optimizer to reuse the results of the "pgno>1"
- ** test in the previous statement, and avoid testing pgno==0 in the
- ** common case where pgno is large. */
- if( pgno<=1 && pgno==0 ){
- return SQLITE_CORRUPT_BKPT;
- }
+ assert( pPager->errCode==SQLITE_OK );
assert( pPager->eState>=PAGER_READER );
assert( assert_pager_state(pPager) );
- assert( noContent==0 || bMmapOk==0 );
-
assert( pPager->hasHeldSharedLock==1 );
- /* If the pager is in the error state, return an error immediately.
- ** Otherwise, request the page from the PCache layer. */
- if( pPager->errCode!=SQLITE_OK ){
- rc = pPager->errCode;
- }else{
- if( bMmapOk && pagerUseWal(pPager) ){
- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
- if( rc!=SQLITE_OK ) goto pager_acquire_err;
- }
-
- if( bMmapOk && iFrame==0 ){
- void *pData = 0;
-
- rc = sqlite3OsFetch(pPager->fd,
- (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
- );
-
- if( rc==SQLITE_OK && pData ){
- if( pPager->eState>PAGER_READER || pPager->tempFile ){
- pPg = sqlite3PagerLookup(pPager, pgno);
- }
- if( pPg==0 ){
- rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
- }else{
- sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
- }
- if( pPg ){
- assert( rc==SQLITE_OK );
- *ppPage = pPg;
- return SQLITE_OK;
- }
- }
- if( rc!=SQLITE_OK ){
- goto pager_acquire_err;
- }
- }
-
- {
- sqlite3_pcache_page *pBase;
- pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3);
- if( pBase==0 ){
- rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase);
- if( rc!=SQLITE_OK ) goto pager_acquire_err;
- if( pBase==0 ){
- pPg = *ppPage = 0;
- rc = SQLITE_NOMEM_BKPT;
- goto pager_acquire_err;
- }
- }
- pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase);
- assert( pPg!=0 );
- }
- }
-
- if( rc!=SQLITE_OK ){
- /* Either the call to sqlite3PcacheFetch() returned an error or the
- ** pager was already in the error-state when this function was called.
- ** Set pPg to 0 and jump to the exception handler. */
+ if( pgno==0 ) return SQLITE_CORRUPT_BKPT;
+ pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3);
+ if( pBase==0 ){
pPg = 0;
- goto pager_acquire_err;
+ rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase);
+ if( rc!=SQLITE_OK ) goto pager_acquire_err;
+ if( pBase==0 ){
+ rc = SQLITE_NOMEM_BKPT;
+ goto pager_acquire_err;
+ }
}
+ pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase);
assert( pPg==(*ppPage) );
assert( pPg->pgno==pgno );
assert( pPg->pPager==pPager || pPg->pPager==0 );
+ noContent = (flags & PAGER_GET_NOCONTENT)!=0;
if( pPg->pPager && !noContent ){
/* In this case the pcache already contains an initialized copy of
** the page. Return without further ado. */
@@ -55544,17 +56829,18 @@ SQLITE_PRIVATE int sqlite3PagerGet(
}else{
/* The pager cache has created a new page. Its content needs to
- ** be initialized. */
-
- pPg->pPager = pPager;
-
- /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
- ** number greater than this, or the unused locking-page, is requested. */
+ ** be initialized. But first some error checks:
+ **
+ ** (1) The maximum page number is 2^31
+ ** (2) Never try to fetch the locking page
+ */
if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
rc = SQLITE_CORRUPT_BKPT;
goto pager_acquire_err;
}
+ pPg->pPager = pPager;
+
assert( !isOpen(pPager->fd) || !MEMDB );
if( !isOpen(pPager->fd) || pPager->dbSizepPager->mxPgno ){
@@ -55580,7 +56866,8 @@ SQLITE_PRIVATE int sqlite3PagerGet(
memset(pPg->pData, 0, pPager->pageSize);
IOTRACE(("ZERO %p %d\n", pPager, pgno));
}else{
- if( pagerUseWal(pPager) && bMmapOk==0 ){
+ u32 iFrame = 0; /* Frame to read from WAL file */
+ if( pagerUseWal(pPager) ){
rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
if( rc!=SQLITE_OK ) goto pager_acquire_err;
}
@@ -55593,7 +56880,6 @@ SQLITE_PRIVATE int sqlite3PagerGet(
}
pager_set_pagehash(pPg);
}
-
return SQLITE_OK;
pager_acquire_err:
@@ -55602,11 +56888,109 @@ pager_acquire_err:
sqlite3PcacheDrop(pPg);
}
pagerUnlockIfUnused(pPager);
-
*ppPage = 0;
return rc;
}
+#if SQLITE_MAX_MMAP_SIZE>0
+/* The page getter for when memory-mapped I/O is enabled */
+static int getPageMMap(
+ Pager *pPager, /* The pager open on the database file */
+ Pgno pgno, /* Page number to fetch */
+ DbPage **ppPage, /* Write a pointer to the page here */
+ int flags /* PAGER_GET_XXX flags */
+){
+ int rc = SQLITE_OK;
+ PgHdr *pPg = 0;
+ u32 iFrame = 0; /* Frame to read from WAL file */
+
+ /* It is acceptable to use a read-only (mmap) page for any page except
+ ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
+ ** flag was specified by the caller. And so long as the db is not a
+ ** temporary or in-memory database. */
+ const int bMmapOk = (pgno>1
+ && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
+ );
+
+ assert( USEFETCH(pPager) );
+#ifdef SQLITE_HAS_CODEC
+ assert( pPager->xCodec==0 );
+#endif
+
+ /* Optimization note: Adding the "pgno<=1" term before "pgno==0" here
+ ** allows the compiler optimizer to reuse the results of the "pgno>1"
+ ** test in the previous statement, and avoid testing pgno==0 in the
+ ** common case where pgno is large. */
+ if( pgno<=1 && pgno==0 ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ assert( pPager->eState>=PAGER_READER );
+ assert( assert_pager_state(pPager) );
+ assert( pPager->hasHeldSharedLock==1 );
+ assert( pPager->errCode==SQLITE_OK );
+
+ if( bMmapOk && pagerUseWal(pPager) ){
+ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
+ if( rc!=SQLITE_OK ){
+ *ppPage = 0;
+ return rc;
+ }
+ }
+ if( bMmapOk && iFrame==0 ){
+ void *pData = 0;
+ rc = sqlite3OsFetch(pPager->fd,
+ (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
+ );
+ if( rc==SQLITE_OK && pData ){
+ if( pPager->eState>PAGER_READER || pPager->tempFile ){
+ pPg = sqlite3PagerLookup(pPager, pgno);
+ }
+ if( pPg==0 ){
+ rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
+ }else{
+ sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
+ }
+ if( pPg ){
+ assert( rc==SQLITE_OK );
+ *ppPage = pPg;
+ return SQLITE_OK;
+ }
+ }
+ if( rc!=SQLITE_OK ){
+ *ppPage = 0;
+ return rc;
+ }
+ }
+ return getPageNormal(pPager, pgno, ppPage, flags);
+}
+#endif /* SQLITE_MAX_MMAP_SIZE>0 */
+
+/* The page getter method for when the pager is an error state */
+static int getPageError(
+ Pager *pPager, /* The pager open on the database file */
+ Pgno pgno, /* Page number to fetch */
+ DbPage **ppPage, /* Write a pointer to the page here */
+ int flags /* PAGER_GET_XXX flags */
+){
+ UNUSED_PARAMETER(pgno);
+ UNUSED_PARAMETER(flags);
+ assert( pPager->errCode!=SQLITE_OK );
+ *ppPage = 0;
+ return pPager->errCode;
+}
+
+
+/* Dispatch all page fetch requests to the appropriate getter method.
+*/
+SQLITE_PRIVATE int sqlite3PagerGet(
+ Pager *pPager, /* The pager open on the database file */
+ Pgno pgno, /* Page number to fetch */
+ DbPage **ppPage, /* Write a pointer to the page here */
+ int flags /* PAGER_GET_XXX flags */
+){
+ return pPager->xGet(pPager, pgno, ppPage, flags);
+}
+
/*
** Acquire a page if it is already in the in-memory cache. Do
** not read the page from disk. Return a pointer to the page,
@@ -56080,11 +57464,11 @@ SQLITE_PRIVATE int sqlite3PagerWrite(PgHdr *pPg){
assert( (pPg->flags & PGHDR_MMAP)==0 );
assert( pPager->eState>=PAGER_WRITER_LOCKED );
assert( assert_pager_state(pPager) );
- if( pPager->errCode ){
- return pPager->errCode;
- }else if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){
+ if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){
if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg);
return SQLITE_OK;
+ }else if( pPager->errCode ){
+ return pPager->errCode;
}else if( pPager->sectorSize > (u32)pPager->pageSize ){
assert( pPager->tempFile==0 );
return pagerWriteLargeSector(pPg);
@@ -56579,6 +57963,7 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
*/
pPager->errCode = SQLITE_ABORT;
pPager->eState = PAGER_ERROR;
+ setGetterMethod(pPager);
return rc;
}
}else{
@@ -56840,6 +58225,7 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
){
pPager->errCode = SQLITE_ABORT;
pPager->eState = PAGER_ERROR;
+ setGetterMethod(pPager);
}
#endif
}
@@ -56912,6 +58298,7 @@ SQLITE_PRIVATE void sqlite3PagerSetCodec(
pPager->xCodecSizeChng = xCodecSizeChng;
pPager->xCodecFree = xCodecFree;
pPager->pCodec = pCodec;
+ setGetterMethod(pPager);
pagerReportSize(pPager);
}
SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
@@ -57321,10 +58708,16 @@ SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *pPager){
**
** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
*/
-SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
+SQLITE_PRIVATE int sqlite3PagerCheckpoint(
+ Pager *pPager, /* Checkpoint on this pager */
+ sqlite3 *db, /* Db handle used to check for interrupts */
+ int eMode, /* Type of checkpoint */
+ int *pnLog, /* OUT: Final number of frames in log */
+ int *pnCkpt /* OUT: Final number of checkpointed frames */
+){
int rc = SQLITE_OK;
if( pPager->pWal ){
- rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
+ rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
(eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
pPager->pBusyHandlerArg,
pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
@@ -57456,7 +58849,7 @@ SQLITE_PRIVATE int sqlite3PagerOpenWal(
** error (SQLITE_BUSY) is returned and the log connection is not closed.
** If successful, the EXCLUSIVE lock is not released before returning.
*/
-SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
+SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
int rc = SQLITE_OK;
assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
@@ -57484,7 +58877,7 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
if( rc==SQLITE_OK && pPager->pWal ){
rc = pagerExclusiveLock(pPager);
if( rc==SQLITE_OK ){
- rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
+ rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags,
pPager->pageSize, (u8*)pPager->pTmpSpace);
pPager->pWal = 0;
pagerFixMaplimit(pPager);
@@ -57521,6 +58914,20 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSn
}
return rc;
}
+
+/*
+** If this is a WAL database, call sqlite3WalSnapshotRecover(). If this
+** is not a WAL database, return an error.
+*/
+SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager){
+ int rc;
+ if( pPager->pWal ){
+ rc = sqlite3WalSnapshotRecover(pPager->pWal);
+ }else{
+ rc = SQLITE_ERROR;
+ }
+ return rc;
+}
#endif /* SQLITE_ENABLE_SNAPSHOT */
#endif /* !SQLITE_OMIT_WAL */
@@ -57566,6 +58973,7 @@ SQLITE_API void sqlite3pager_sqlite3PagerSetCodec(
SQLITE_API void sqlite3pager_sqlite3PagerSetError( Pager *pPager, int error) {
pPager->errCode = error;
+ setGetterMethod(pPager);
}
#endif
@@ -59299,6 +60707,7 @@ static void walRestartHdr(Wal *pWal, u32 salt1){
*/
static int walCheckpoint(
Wal *pWal, /* Wal connection */
+ sqlite3 *db, /* Check for interrupts on this handle */
int eMode, /* One of PASSIVE, FULL or RESTART */
int (*xBusy)(void*), /* Function to call when busy */
void *pBusyArg, /* Context argument for xBusyHandler */
@@ -59393,6 +60802,10 @@ static int walCheckpoint(
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
i64 iOffset;
assert( walFramePgno(pWal, iFrame)==iDbpage );
+ if( db->u1.isInterrupted ){
+ rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
+ break;
+ }
if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
continue;
}
@@ -59497,6 +60910,7 @@ static void walLimitSize(Wal *pWal, i64 nMax){
*/
SQLITE_PRIVATE int sqlite3WalClose(
Wal *pWal, /* Wal to close */
+ sqlite3 *db, /* For interrupt flag */
int sync_flags, /* Flags to pass to OsSync() (or 0) */
int nBuf,
u8 *zBuf /* Buffer of at least nBuf bytes */
@@ -59513,13 +60927,14 @@ SQLITE_PRIVATE int sqlite3WalClose(
**
** The EXCLUSIVE lock is not released before returning.
*/
- rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
- if( rc==SQLITE_OK ){
+ if( zBuf!=0
+ && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE))
+ ){
if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
}
- rc = sqlite3WalCheckpoint(
- pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
+ rc = sqlite3WalCheckpoint(pWal, db,
+ SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
);
if( rc==SQLITE_OK ){
int bPersist = -1;
@@ -59948,6 +61363,84 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
return rc;
}
+#ifdef SQLITE_ENABLE_SNAPSHOT
+/*
+** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted
+** variable so that older snapshots can be accessed. To do this, loop
+** through all wal frames from nBackfillAttempted to (nBackfill+1),
+** comparing their content to the corresponding page with the database
+** file, if any. Set nBackfillAttempted to the frame number of the
+** first frame for which the wal file content matches the db file.
+**
+** This is only really safe if the file-system is such that any page
+** writes made by earlier checkpointers were atomic operations, which
+** is not always true. It is also possible that nBackfillAttempted
+** may be left set to a value larger than expected, if a wal frame
+** contains content that duplicate of an earlier version of the same
+** page.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code if an
+** error occurs. It is not an error if nBackfillAttempted cannot be
+** decreased at all.
+*/
+SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){
+ int rc;
+
+ assert( pWal->readLock>=0 );
+ rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
+ if( rc==SQLITE_OK ){
+ volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
+ int szPage = (int)pWal->szPage;
+ i64 szDb; /* Size of db file in bytes */
+
+ rc = sqlite3OsFileSize(pWal->pDbFd, &szDb);
+ if( rc==SQLITE_OK ){
+ void *pBuf1 = sqlite3_malloc(szPage);
+ void *pBuf2 = sqlite3_malloc(szPage);
+ if( pBuf1==0 || pBuf2==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ u32 i = pInfo->nBackfillAttempted;
+ for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
+ volatile ht_slot *dummy;
+ volatile u32 *aPgno; /* Array of page numbers */
+ u32 iZero; /* Frame corresponding to aPgno[0] */
+ u32 pgno; /* Page number in db file */
+ i64 iDbOff; /* Offset of db file entry */
+ i64 iWalOff; /* Offset of wal file entry */
+
+ rc = walHashGet(pWal, walFramePage(i), &dummy, &aPgno, &iZero);
+ if( rc!=SQLITE_OK ) break;
+ pgno = aPgno[i-iZero];
+ iDbOff = (i64)(pgno-1) * szPage;
+
+ if( iDbOff+szPage<=szDb ){
+ iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE;
+ rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff);
+
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff);
+ }
+
+ if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){
+ break;
+ }
+ }
+
+ pInfo->nBackfillAttempted = i-1;
+ }
+ }
+
+ sqlite3_free(pBuf1);
+ sqlite3_free(pBuf2);
+ }
+ walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
+ }
+
+ return rc;
+}
+#endif /* SQLITE_ENABLE_SNAPSHOT */
+
/*
** Begin a read transaction on the database.
**
@@ -60010,7 +61503,11 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
** has not yet set the pInfo->nBackfillAttempted variable to indicate
** its intent. To avoid the race condition this leads to, ensure that
** there is no checkpointer process by taking a shared CKPT lock
- ** before checking pInfo->nBackfillAttempted. */
+ ** before checking pInfo->nBackfillAttempted.
+ **
+ ** TODO: Does the aReadMark[] lock prevent a checkpointer from doing
+ ** this already?
+ */
rc = walLockShared(pWal, WAL_CKPT_LOCK);
if( rc==SQLITE_OK ){
@@ -60767,6 +62264,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
*/
SQLITE_PRIVATE int sqlite3WalCheckpoint(
Wal *pWal, /* Wal connection */
+ sqlite3 *db, /* Check this handle's interrupt flag */
int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */
int (*xBusy)(void*), /* Function to call when busy */
void *pBusyArg, /* Context argument for xBusyHandler */
@@ -60841,7 +62339,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
rc = SQLITE_CORRUPT_BKPT;
}else{
- rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
+ rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
}
/* If no error occurred, set the output variables. */
@@ -60961,9 +62459,14 @@ SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){
SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){
int rc = SQLITE_OK;
WalIndexHdr *pRet;
+ static const u32 aZero[4] = { 0, 0, 0, 0 };
assert( pWal->readLock>=0 && pWal->writeLock==0 );
+ if( memcmp(&pWal->hdr.aFrameCksum[0],aZero,16)==0 ){
+ *ppSnapshot = 0;
+ return SQLITE_ERROR;
+ }
pRet = (WalIndexHdr*)sqlite3_malloc(sizeof(WalIndexHdr));
if( pRet==0 ){
rc = SQLITE_NOMEM_BKPT;
@@ -61206,16 +62709,24 @@ SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){
** two or more btrees in common both try to lock all their btrees
** at the same instant.
*/
-SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){
+static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){
int i;
+ int skipOk = 1;
Btree *p;
assert( sqlite3_mutex_held(db->mutex) );
for(i=0; inDb; i++){
p = db->aDb[i].pBt;
- if( p ) sqlite3BtreeEnter(p);
+ if( p && p->sharable ){
+ sqlite3BtreeEnter(p);
+ skipOk = 0;
+ }
}
+ db->skipBtreeMutex = skipOk;
}
-SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){
+SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){
+ if( db->skipBtreeMutex==0 ) btreeEnterAll(db);
+}
+static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){
int i;
Btree *p;
assert( sqlite3_mutex_held(db->mutex) );
@@ -61224,6 +62735,9 @@ SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){
if( p ) sqlite3BtreeLeave(p);
}
}
+SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){
+ if( db->skipBtreeMutex==0 ) btreeLeaveAll(db);
+}
#ifndef NDEBUG
/*
@@ -61475,7 +62989,7 @@ static int hasSharedCacheTableLock(
** Return true immediately.
*/
if( (pBtree->sharable==0)
- || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommitted))
+ || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommit))
){
return 1;
}
@@ -61552,7 +63066,7 @@ static int hasReadConflicts(Btree *pBtree, Pgno iRoot){
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
if( p->pgnoRoot==iRoot
&& p->pBtree!=pBtree
- && 0==(p->pBtree->db->flags & SQLITE_ReadUncommitted)
+ && 0==(p->pBtree->db->flags & SQLITE_ReadUncommit)
){
return 1;
}
@@ -61574,7 +63088,7 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
assert( sqlite3BtreeHoldsMutex(p) );
assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
assert( p->db!=0 );
- assert( !(p->db->flags&SQLITE_ReadUncommitted)||eLock==WRITE_LOCK||iTab==1 );
+ assert( !(p->db->flags&SQLITE_ReadUncommit)||eLock==WRITE_LOCK||iTab==1 );
/* If requesting a write-lock, then the Btree must have an open write
** transaction on this file. And, obviously, for this to be so there
@@ -61652,7 +63166,7 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
** obtain a read-lock using this function. The only read-lock obtained
** by a connection in read-uncommitted mode is on the sqlite_master
** table, and that lock is obtained in BtreeBeginTrans(). */
- assert( 0==(p->db->flags&SQLITE_ReadUncommitted) || eLock==WRITE_LOCK );
+ assert( 0==(p->db->flags&SQLITE_ReadUncommit) || eLock==WRITE_LOCK );
/* This function should only be called on a sharable b-tree after it
** has been determined that no other b-tree holds a conflicting lock. */
@@ -61822,6 +63336,7 @@ static void invalidateAllOverflowCache(BtShared *pBt){
*/
static void invalidateIncrblobCursors(
Btree *pBtree, /* The database file to check */
+ Pgno pgnoRoot, /* The table that might be changing */
i64 iRow, /* The rowid that might be changing */
int isClearTable /* True if all rows are being deleted */
){
@@ -61832,7 +63347,7 @@ static void invalidateIncrblobCursors(
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
if( (p->curFlags & BTCF_Incrblob)!=0 ){
pBtree->hasIncrblobCur = 1;
- if( isClearTable || p->info.nKey==iRow ){
+ if( p->pgnoRoot==pgnoRoot && (isClearTable || p->info.nKey==iRow) ){
p->eState = CURSOR_INVALID;
}
}
@@ -61841,7 +63356,7 @@ static void invalidateIncrblobCursors(
#else
/* Stub function when INCRBLOB is omitted */
- #define invalidateIncrblobCursors(x,y,z)
+ #define invalidateIncrblobCursors(w,x,y,z)
#endif /* SQLITE_OMIT_INCRBLOB */
/*
@@ -61955,7 +63470,7 @@ static int saveCursorKey(BtCursor *pCur){
pCur->nKey = sqlite3BtreePayloadSize(pCur);
pKey = sqlite3Malloc( pCur->nKey );
if( pKey ){
- rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey);
+ rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
if( rc==SQLITE_OK ){
pCur->pKey = pKey;
}else{
@@ -62086,26 +63601,23 @@ static int btreeMoveto(
){
int rc; /* Status code */
UnpackedRecord *pIdxKey; /* Unpacked index key */
- char aSpace[384]; /* Temp space for pIdxKey - to avoid a malloc */
- char *pFree = 0;
if( pKey ){
assert( nKey==(i64)(int)nKey );
- pIdxKey = sqlite3VdbeAllocUnpackedRecord(
- pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree
- );
+ pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo);
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
if( pIdxKey->nField==0 ){
- sqlite3DbFree(pCur->pKeyInfo->db, pFree);
- return SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno);
+ goto moveto_done;
}
}else{
pIdxKey = 0;
}
rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
- if( pFree ){
- sqlite3DbFree(pCur->pKeyInfo->db, pFree);
+moveto_done:
+ if( pIdxKey ){
+ sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
}
return rc;
}
@@ -62325,7 +63837,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
sqlite3PagerUnref(pDbPage);
- if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT;
+ if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_PGNO(iPtrmap);
return SQLITE_OK;
}
@@ -62643,17 +64155,18 @@ static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
/*
-** 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.
+** Defragment the page given. This routine reorganizes cells within the
+** page so that there are no free-blocks on the free-block list.
+**
+** Parameter nMaxFrag is the maximum amount of fragmented space that may be
+** present in the page after this routine returns.
**
** EVIDENCE-OF: R-44582-60138 SQLite may from time to time reorganize a
** b-tree page so that there are no freeblocks or fragment bytes, all
** unused bytes are contained in the unallocated space region, and all
** cells are packed tightly at the end of the page.
*/
-static int defragmentPage(MemPage *pPage){
+static int defragmentPage(MemPage *pPage, int nMaxFrag){
int i; /* Loop counter */
int pc; /* Address of the i-th cell */
int hdr; /* Offset to the page header */
@@ -62668,7 +64181,6 @@ static int defragmentPage(MemPage *pPage){
int iCellFirst; /* First allowable cell index */
int iCellLast; /* Last possible cell index */
-
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( pPage->pBt!=0 );
assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
@@ -62680,9 +64192,56 @@ static int defragmentPage(MemPage *pPage){
cellOffset = pPage->cellOffset;
nCell = pPage->nCell;
assert( nCell==get2byte(&data[hdr+3]) );
- usableSize = pPage->pBt->usableSize;
- cbrk = usableSize;
iCellFirst = cellOffset + 2*nCell;
+ usableSize = pPage->pBt->usableSize;
+
+ /* This block handles pages with two or fewer free blocks and nMaxFrag
+ ** or fewer fragmented bytes. In this case it is faster to move the
+ ** two (or one) blocks of cells using memmove() and add the required
+ ** offsets to each pointer in the cell-pointer array than it is to
+ ** reconstruct the entire page. */
+ if( (int)data[hdr+7]<=nMaxFrag ){
+ int iFree = get2byte(&data[hdr+1]);
+ if( iFree ){
+ int iFree2 = get2byte(&data[iFree]);
+
+ /* pageFindSlot() has already verified that free blocks are sorted
+ ** in order of offset within the page, and that no block extends
+ ** past the end of the page. Provided the two free slots do not
+ ** overlap, this guarantees that the memmove() calls below will not
+ ** overwrite the usableSize byte buffer, even if the database page
+ ** is corrupt. */
+ assert( iFree2==0 || iFree2>iFree );
+ assert( iFree+get2byte(&data[iFree+2]) <= usableSize );
+ assert( iFree2==0 || iFree2+get2byte(&data[iFree2+2]) <= usableSize );
+
+ if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
+ u8 *pEnd = &data[cellOffset + nCell*2];
+ u8 *pAddr;
+ int sz2 = 0;
+ int sz = get2byte(&data[iFree+2]);
+ int top = get2byte(&data[hdr+5]);
+ if( iFree2 ){
+ if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ sz2 = get2byte(&data[iFree2+2]);
+ assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
+ memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
+ sz += sz2;
+ }
+ cbrk = top+sz;
+ assert( cbrk+(iFree-top) <= usableSize );
+ memmove(&data[cbrk], &data[top], iFree-top);
+ for(pAddr=&data[cellOffset]; pAddriCellLast ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
assert( pc>=iCellFirst && pc<=iCellLast );
size = pPage->xCellSize(pPage, &src[pc]);
cbrk -= size;
if( cbrkusableSize ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
testcase( cbrk+size==usableSize );
@@ -62716,16 +64275,18 @@ static int defragmentPage(MemPage *pPage){
}
memcpy(&data[cbrk], &src[pc], size);
}
+ data[hdr+7] = 0;
+
+ defragment_out:
+ if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ }
assert( cbrk>=iCellFirst );
put2byte(&data[hdr+5], cbrk);
data[hdr+1] = 0;
data[hdr+2] = 0;
- data[hdr+7] = 0;
memset(&data[iCellFirst], 0, cbrk-iCellFirst);
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
- if( cbrk-iCellFirst!=pPage->nFree ){
- return SQLITE_CORRUPT_BKPT;
- }
return SQLITE_OK;
}
@@ -62757,7 +64318,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
/* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of
** increasing offset. */
if( pc>usableSize-4 || pcpgno);
return 0;
}
/* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
@@ -62768,7 +64329,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
testcase( x==4 );
testcase( x==3 );
if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){
- *pRc = SQLITE_CORRUPT_BKPT;
+ *pRc = SQLITE_CORRUPT_PGNO(pPg->pgno);
return 0;
}else if( x<4 ){
/* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
@@ -62835,7 +64396,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
if( top==0 && pPage->pBt->usableSize==65536 ){
top = 65536;
}else{
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
}
@@ -62863,10 +64424,10 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
testcase( gap+2+nByte==top );
if( gap+2+nByte>top ){
assert( pPage->nCell>0 || CORRUPT_DB );
- rc = defragmentPage(pPage);
+ rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte)));
if( rc ) return rc;
top = get2byteNotZero(&data[hdr+5]);
- assert( gap+nByte<=top );
+ assert( gap+2+nByte<=top );
}
@@ -62916,7 +64477,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
/* Overwrite deleted information with zeros when the secure_delete
** option is enabled */
- if( pPage->pBt->btsFlags & BTS_SECURE_DELETE ){
+ if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){
memset(&data[iStart], 0, iSize);
}
@@ -62931,11 +64492,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
while( (iFreeBlk = get2byte(&data[iPtr]))pgno);
}
iPtr = iFreeBlk;
}
- if( iFreeBlk>iLast ) return SQLITE_CORRUPT_BKPT;
+ if( iFreeBlk>iLast ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
assert( iFreeBlk>iPtr || iFreeBlk==0 );
/* At this point:
@@ -62946,9 +64507,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
*/
if( iFreeBlk && iEnd+3>=iFreeBlk ){
nFrag = iFreeBlk - iEnd;
- if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT;
+ if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]);
- if( iEnd > pPage->pBt->usableSize ) return SQLITE_CORRUPT_BKPT;
+ if( iEnd > pPage->pBt->usableSize ){
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ }
iSize = iEnd - iStart;
iFreeBlk = get2byte(&data[iFreeBlk]);
}
@@ -62960,20 +64523,20 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
if( iPtr>hdr+1 ){
int iPtrEnd = iPtr + get2byte(&data[iPtr+2]);
if( iPtrEnd+3>=iStart ){
- if( iPtrEnd>iStart ) return SQLITE_CORRUPT_BKPT;
+ if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
nFrag += iStart - iPtrEnd;
iSize = iEnd - iPtr;
iStart = iPtr;
}
}
- if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_BKPT;
+ if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
data[hdr+7] -= nFrag;
}
if( iStart==get2byte(&data[hdr+5]) ){
/* The new freeblock is at the beginning of the cell content area,
** so just extend the cell content area rather than create another
** freelist entry */
- if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_BKPT;
+ if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
put2byte(&data[hdr+1], iFreeBlk);
put2byte(&data[hdr+5], iEnd);
}else{
@@ -63041,7 +64604,7 @@ static int decodeFlags(MemPage *pPage, int flagByte){
}else{
/* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is
** an error. */
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
pPage->max1bytePayload = pBt->max1bytePayload;
return SQLITE_OK;
@@ -63057,6 +64620,16 @@ static int decodeFlags(MemPage *pPage, int flagByte){
** we failed to detect any corruption.
*/
static int btreeInitPage(MemPage *pPage){
+ int pc; /* Address of a freeblock within pPage->aData[] */
+ u8 hdr; /* Offset to beginning of page header */
+ u8 *data; /* Equal to pPage->aData */
+ BtShared *pBt; /* The main btree structure */
+ int usableSize; /* Amount of usable space on each page */
+ u16 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 */
+ int iCellFirst; /* First allowable cell or freeblock offset */
+ int iCellLast; /* Last possible cell or freeblock offset */
assert( pPage->pBt!=0 );
assert( pPage->pBt->db!=0 );
@@ -63064,122 +64637,119 @@ static int btreeInitPage(MemPage *pPage){
assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
+ assert( pPage->isInit==0 );
- if( !pPage->isInit ){
- u16 pc; /* Address of a freeblock within pPage->aData[] */
- u8 hdr; /* Offset to beginning of page header */
- u8 *data; /* Equal to pPage->aData */
- BtShared *pBt; /* The main btree structure */
- int usableSize; /* Amount of usable space on each page */
- u16 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 */
- int iCellFirst; /* First allowable cell or freeblock offset */
- int iCellLast; /* Last possible cell or freeblock offset */
+ pBt = pPage->pBt;
+ hdr = pPage->hdrOffset;
+ data = pPage->aData;
+ /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
+ ** the b-tree page type. */
+ if( decodeFlags(pPage, data[hdr]) ){
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ }
+ assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
+ pPage->maskPage = (u16)(pBt->pageSize - 1);
+ pPage->nOverflow = 0;
+ usableSize = pBt->usableSize;
+ pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize;
+ pPage->aDataEnd = &data[usableSize];
+ pPage->aCellIdx = &data[cellOffset];
+ pPage->aDataOfst = &data[pPage->childPtrSize];
+ /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
+ ** the start of the cell content area. A zero value for this integer is
+ ** interpreted as 65536. */
+ top = get2byteNotZero(&data[hdr+5]);
+ /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
+ ** number of cells on the page. */
+ 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_PGNO(pPage->pgno);
+ }
+ testcase( pPage->nCell==MX_CELL(pBt) );
+ /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
+ ** possible for a root page of a table that contains no rows) then the
+ ** offset to the cell content area will equal the page size minus the
+ ** bytes of reserved space. */
+ assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB );
- pBt = pPage->pBt;
+ /* A malformed database page might cause us to read past the end
+ ** of page when parsing a cell.
+ **
+ ** The following block of code checks early to see if a cell extends
+ ** past the end of a page boundary and causes SQLITE_CORRUPT to be
+ ** returned if it does.
+ */
+ iCellFirst = cellOffset + 2*pPage->nCell;
+ iCellLast = usableSize - 4;
+ if( pBt->db->flags & SQLITE_CellSizeCk ){
+ int i; /* Index into the cell pointer array */
+ int sz; /* Size of a cell */
- hdr = pPage->hdrOffset;
- data = pPage->aData;
- /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
- ** the b-tree page type. */
- if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
- assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
- pPage->maskPage = (u16)(pBt->pageSize - 1);
- pPage->nOverflow = 0;
- usableSize = pBt->usableSize;
- pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize;
- pPage->aDataEnd = &data[usableSize];
- pPage->aCellIdx = &data[cellOffset];
- pPage->aDataOfst = &data[pPage->childPtrSize];
- /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
- ** the start of the cell content area. A zero value for this integer is
- ** interpreted as 65536. */
- top = get2byteNotZero(&data[hdr+5]);
- /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
- ** number of cells on the page. */
- 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;
- }
- testcase( pPage->nCell==MX_CELL(pBt) );
- /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
- ** possible for a root page of a table that contains no rows) then the
- ** offset to the cell content area will equal the page size minus the
- ** bytes of reserved space. */
- assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB );
-
- /* A malformed database page might cause us to read past the end
- ** of page when parsing a cell.
- **
- ** The following block of code checks early to see if a cell extends
- ** past the end of a page boundary and causes SQLITE_CORRUPT to be
- ** returned if it does.
- */
- iCellFirst = cellOffset + 2*pPage->nCell;
- iCellLast = usableSize - 4;
- if( pBt->db->flags & SQLITE_CellSizeCk ){
- int i; /* Index into the cell pointer array */
- int sz; /* Size of a cell */
-
- if( !pPage->leaf ) iCellLast--;
- for(i=0; inCell; i++){
- pc = get2byteAligned(&data[cellOffset+i*2]);
- testcase( pc==iCellFirst );
- testcase( pc==iCellLast );
- if( pciCellLast ){
- return SQLITE_CORRUPT_BKPT;
- }
- sz = pPage->xCellSize(pPage, &data[pc]);
- testcase( pc+sz==usableSize );
- if( pc+sz>usableSize ){
- return SQLITE_CORRUPT_BKPT;
- }
- }
- if( !pPage->leaf ) iCellLast++;
- }
-
- /* Compute the total free space on the page
- ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
- ** start of the first freeblock on the page, or is zero if there are no
- ** freeblocks. */
- pc = get2byte(&data[hdr+1]);
- nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */
- while( pc>0 ){
- u16 next, size;
+ if( !pPage->leaf ) iCellLast--;
+ for(i=0; inCell; i++){
+ pc = get2byteAligned(&data[cellOffset+i*2]);
+ testcase( pc==iCellFirst );
+ testcase( pc==iCellLast );
if( pciCellLast ){
- /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will
- ** always be at least one cell before the first freeblock.
- **
- ** Or, the freeblock is off the end of the page
- */
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ }
+ sz = pPage->xCellSize(pPage, &data[pc]);
+ testcase( pc+sz==usableSize );
+ if( pc+sz>usableSize ){
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ }
+ }
+ if( !pPage->leaf ) iCellLast++;
+ }
+
+ /* Compute the total free space on the page
+ ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
+ ** start of the first freeblock on the page, or is zero if there are no
+ ** freeblocks. */
+ pc = get2byte(&data[hdr+1]);
+ nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */
+ if( pc>0 ){
+ u32 next, size;
+ if( pcpgno);
+ }
+ while( 1 ){
+ if( pc>iCellLast ){
+ /* Freeblock off the end of the page */
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
next = get2byte(&data[pc]);
size = get2byte(&data[pc+2]);
- if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){
- /* Free blocks must be in ascending order. And the last byte of
- ** the free-block must lie on the database page. */
- return SQLITE_CORRUPT_BKPT;
- }
nFree = nFree + size;
+ if( next<=pc+size+3 ) break;
pc = next;
}
-
- /* At this point, nFree contains the sum of the offset to the start
- ** of the cell-content area plus the number of free bytes within
- ** the cell-content area. If this is greater than the usable-size
- ** of the page, then the page must be corrupted. This check also
- ** serves to verify that the offset to the start of the cell-content
- ** area, according to the page header, lies within the page.
- */
- if( nFree>usableSize ){
- return SQLITE_CORRUPT_BKPT;
+ if( next>0 ){
+ /* Freeblock not in ascending order */
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ }
+ if( pc+size>(unsigned int)usableSize ){
+ /* Last freeblock extends past page end */
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
- pPage->nFree = (u16)(nFree - iCellFirst);
- pPage->isInit = 1;
}
+
+ /* At this point, nFree contains the sum of the offset to the start
+ ** of the cell-content area plus the number of free bytes within
+ ** the cell-content area. If this is greater than the usable-size
+ ** of the page, then the page must be corrupted. This check also
+ ** serves to verify that the offset to the start of the cell-content
+ ** area, according to the page header, lies within the page.
+ */
+ if( nFree>usableSize ){
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ }
+ pPage->nFree = (u16)(nFree - iCellFirst);
+ pPage->isInit = 1;
return SQLITE_OK;
}
@@ -63198,7 +64768,7 @@ static void zeroPage(MemPage *pPage, int flags){
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( sqlite3_mutex_held(pBt->mutex) );
- if( pBt->btsFlags & BTS_SECURE_DELETE ){
+ if( pBt->btsFlags & BTS_FAST_SECURE ){
memset(&data[hdr], 0, pBt->usableSize - hdr);
}
data[hdr] = (char)flags;
@@ -63343,7 +64913,7 @@ static int getAndInitPage(
/* If obtaining a child page for a cursor, we must verify that the page is
** compatible with the root page. */
if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PGNO(pgno);
releasePage(*ppPage);
goto getAndInitPage_error;
}
@@ -63605,7 +65175,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
goto btree_open_out;
}
rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
- EXTRA_SIZE, flags, vfsFlags, pageReinit);
+ sizeof(MemPage), flags, vfsFlags, pageReinit);
if( rc==SQLITE_OK ){
sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap);
rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
@@ -63621,8 +65191,10 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
pBt->pCursor = 0;
pBt->pPage1 = 0;
if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY;
-#ifdef SQLITE_SECURE_DELETE
+#if defined(SQLITE_SECURE_DELETE)
pBt->btsFlags |= BTS_SECURE_DELETE;
+#elif defined(SQLITE_FAST_SECURE_DELETE)
+ pBt->btsFlags |= BTS_OVERWRITE;
#endif
/* EVIDENCE-OF: R-51873-39618 The page size for a database file is
** determined by the 2-byte integer located at an offset of 16 bytes from
@@ -63718,12 +65290,14 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
btree_open_out:
if( rc!=SQLITE_OK ){
if( pBt && pBt->pPager ){
- sqlite3PagerClose(pBt->pPager);
+ sqlite3PagerClose(pBt->pPager, 0);
}
sqlite3_free(pBt);
sqlite3_free(p);
*ppBtree = 0;
}else{
+ sqlite3_file *pFile;
+
/* If the B-Tree was successfully opened, set the pager-cache size to the
** default value. Except, when opening on an existing shared pager-cache,
** do not change the pager-cache size.
@@ -63731,6 +65305,11 @@ btree_open_out:
if( sqlite3BtreeSchema(p, 0, 0)==0 ){
sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
}
+
+ pFile = sqlite3PagerFile(pBt->pPager);
+ if( pFile->pMethods ){
+ sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db);
+ }
}
if( mutexOpen ){
assert( sqlite3_mutex_held(mutexOpen) );
@@ -63860,7 +65439,7 @@ SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){
** Clean out and delete the BtShared object.
*/
assert( !pBt->pCursor );
- sqlite3PagerClose(pBt->pPager);
+ sqlite3PagerClose(pBt->pPager, p->db);
if( pBt->xFreeSchema && pBt->pSchema ){
pBt->xFreeSchema(pBt->pSchema);
}
@@ -64063,19 +65642,34 @@ SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
}
/*
-** Set the BTS_SECURE_DELETE flag if newFlag is 0 or 1. If newFlag is -1,
-** then make no changes. Always return the value of the BTS_SECURE_DELETE
-** setting after the change.
+** Change the values for the BTS_SECURE_DELETE and BTS_OVERWRITE flags:
+**
+** newFlag==0 Both BTS_SECURE_DELETE and BTS_OVERWRITE are cleared
+** newFlag==1 BTS_SECURE_DELETE set and BTS_OVERWRITE is cleared
+** newFlag==2 BTS_SECURE_DELETE cleared and BTS_OVERWRITE is set
+** newFlag==(-1) No changes
+**
+** This routine acts as a query if newFlag is less than zero
+**
+** With BTS_OVERWRITE set, deleted content is overwritten by zeros, but
+** freelist leaf pages are not written back to the database. Thus in-page
+** deleted content is cleared, but freelist deleted content is not.
+**
+** With BTS_SECURE_DELETE, operation is like BTS_OVERWRITE with the addition
+** that freelist leaf pages are written back into the database, increasing
+** the amount of disk I/O.
*/
SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
int b;
if( p==0 ) return 0;
sqlite3BtreeEnter(p);
+ assert( BTS_OVERWRITE==BTS_SECURE_DELETE*2 );
+ assert( BTS_FAST_SECURE==(BTS_OVERWRITE|BTS_SECURE_DELETE) );
if( newFlag>=0 ){
- p->pBt->btsFlags &= ~BTS_SECURE_DELETE;
- if( newFlag ) p->pBt->btsFlags |= BTS_SECURE_DELETE;
- }
- b = (p->pBt->btsFlags & BTS_SECURE_DELETE)!=0;
+ p->pBt->btsFlags &= ~BTS_FAST_SECURE;
+ p->pBt->btsFlags |= BTS_SECURE_DELETE*newFlag;
+ }
+ b = (p->pBt->btsFlags & BTS_FAST_SECURE)/BTS_SECURE_DELETE;
sqlite3BtreeLeave(p);
return b;
}
@@ -64126,6 +65720,31 @@ SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *p){
#endif
}
+/*
+** If the user has not set the safety-level for this database connection
+** using "PRAGMA synchronous", and if the safety-level is not already
+** set to the value passed to this function as the second parameter,
+** set it so.
+*/
+#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS
+static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){
+ sqlite3 *db;
+ Db *pDb;
+ if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){
+ while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; }
+ if( pDb->bSyncSet==0
+ && pDb->safety_level!=safety_level
+ && pDb!=&db->aDb[1]
+ ){
+ pDb->safety_level = safety_level;
+ sqlite3PagerSetFlags(pBt->pPager,
+ pDb->safety_level | (db->flags & PAGER_FLAGS_MASK));
+ }
+ }
+}
+#else
+# define setDefaultSyncFlag(pBt,safety_level)
+#endif
/*
** Get a reference to pPage1 of the database file. This will
@@ -64199,26 +65818,15 @@ static int lockBtree(BtShared *pBt){
if( rc!=SQLITE_OK ){
goto page1_init_failed;
}else{
-#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS
- sqlite3 *db;
- Db *pDb;
- if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){
- while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; }
- if( pDb->bSyncSet==0
- && pDb->safety_level==SQLITE_DEFAULT_SYNCHRONOUS+1
- ){
- pDb->safety_level = SQLITE_DEFAULT_WAL_SYNCHRONOUS+1;
- sqlite3PagerSetFlags(pBt->pPager,
- pDb->safety_level | (db->flags & PAGER_FLAGS_MASK));
- }
- }
-#endif
+ setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1);
if( isOpen==0 ){
releasePage(pPage1);
return SQLITE_OK;
}
}
rc = SQLITE_NOTADB;
+ }else{
+ setDefaultSyncFlag(pBt, SQLITE_DEFAULT_SYNCHRONOUS+1);
}
#endif
@@ -64267,7 +65875,7 @@ static int lockBtree(BtShared *pBt){
pageSize-usableSize);
return rc;
}
- if( (pBt->db->flags & SQLITE_RecoveryMode)==0 && nPage>nPageFile ){
+ if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){
rc = SQLITE_CORRUPT_BKPT;
goto page1_init_failed;
}
@@ -64607,14 +66215,11 @@ static int setChildPtrmaps(MemPage *pPage){
int nCell; /* Number of cells in page pPage */
int rc; /* Return code */
BtShared *pBt = pPage->pBt;
- u8 isInitOrig = pPage->isInit;
Pgno pgno = pPage->pgno;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- rc = btreeInitPage(pPage);
- if( rc!=SQLITE_OK ){
- goto set_child_ptrmaps_out;
- }
+ rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage);
+ if( rc!=SQLITE_OK ) return rc;
nCell = pPage->nCell;
for(i=0; iisInit = isInitOrig;
return rc;
}
@@ -64658,16 +66261,15 @@ 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_PGNO(pPage->pgno);
}
put4byte(pPage->aData, iTo);
}else{
- u8 isInitOrig = pPage->isInit;
int i;
int nCell;
int rc;
- rc = btreeInitPage(pPage);
+ rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage);
if( rc ) return rc;
nCell = pPage->nCell;
@@ -64676,12 +66278,14 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
if( eType==PTRMAP_OVERFLOW1 ){
CellInfo info;
pPage->xParseCell(pPage, pCell, &info);
- if( info.nLocalaData+pPage->maskPage
- && iFrom==get4byte(pCell+info.nSize-4)
- ){
- put4byte(pCell+info.nSize-4, iTo);
- break;
+ if( info.nLocal pPage->aData+pPage->pBt->usableSize ){
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ }
+ if( iFrom==get4byte(pCell+info.nSize-4) ){
+ put4byte(pCell+info.nSize-4, iTo);
+ break;
+ }
}
}else{
if( get4byte(pCell)==iFrom ){
@@ -64694,12 +66298,10 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
if( i==nCell ){
if( eType!=PTRMAP_BTREE ||
get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
}
-
- pPage->isInit = isInitOrig;
}
return SQLITE_OK;
}
@@ -65358,7 +66960,12 @@ SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) );
sqlite3BtreeEnter(p);
- rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
+ if( op==SAVEPOINT_ROLLBACK ){
+ rc = saveAllCursors(pBt, 0, 0);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
+ }
if( rc==SQLITE_OK ){
if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){
pBt->nPage = 0;
@@ -65568,7 +67175,7 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
CellInfo info;
int iPage = pCur->iPage;
memset(&info, 0, sizeof(info));
- btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info);
+ btreeParseCell(pCur->apPage[iPage], pCur->ix, &info);
assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 );
}
#else
@@ -65578,7 +67185,7 @@ static SQLITE_NOINLINE void getCellInfo(BtCursor *pCur){
if( pCur->info.nSize==0 ){
int iPage = pCur->iPage;
pCur->curFlags |= BTCF_ValidNKey;
- btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);
+ btreeParseCell(pCur->apPage[iPage],pCur->ix,&pCur->info);
}else{
assertCellInfo(pCur);
}
@@ -65594,6 +67201,10 @@ SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){
return pCur && pCur->eState==CURSOR_VALID;
}
#endif /* NDEBUG */
+SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor *pCur){
+ assert( pCur!=0 );
+ return pCur->eState==CURSOR_VALID;
+}
/*
** Return the value of the integer key or "rowid" for a table btree.
@@ -65740,7 +67351,6 @@ static int copyPayload(
**
** 0: The operation is a read. Populate the overflow cache.
** 1: The operation is a write. Populate the overflow cache.
-** 2: The operation is a read. Do not populate the overflow cache.
**
** A total of "amt" bytes are read or written beginning at "offset".
** Data is read to or from the buffer pBuf.
@@ -65748,13 +67358,13 @@ static int copyPayload(
** The content being read or written might appear on the main page
** or be scattered out on multiple overflow pages.
**
-** If the current cursor entry uses one or more overflow pages and the
-** eOp argument is not 2, this function may allocate space for and lazily
-** populates the overflow page-list cache array (BtCursor.aOverflow).
+** If the current cursor entry uses one or more overflow pages
+** this function may allocate space for and lazily populate
+** the overflow page-list cache array (BtCursor.aOverflow).
** Subsequent calls use this cache to make seeking to the supplied offset
** more efficient.
**
-** Once an overflow page-list cache has been allocated, it may be
+** Once an overflow page-list cache has been allocated, it must be
** invalidated if some other cursor writes to the same table, or if
** the cursor is moved to a different row. Additionally, in auto-vacuum
** mode, the following events may invalidate an overflow page-list cache.
@@ -65776,21 +67386,17 @@ static int accessPayload(
MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
- unsigned char * const pBufStart = pBuf;
- int bEnd; /* True if reading to end of data */
+ unsigned char * const pBufStart = pBuf; /* Start of original out buffer */
#endif
assert( pPage );
+ assert( eOp==0 || eOp==1 );
assert( pCur->eState==CURSOR_VALID );
- assert( pCur->aiIdx[pCur->iPage]nCell );
+ assert( pCur->ixnCell );
assert( cursorHoldsMutex(pCur) );
- assert( eOp!=2 || offset==0 ); /* Always start from beginning for eOp==2 */
getCellInfo(pCur);
aPayload = pCur->info.pPayload;
-#ifdef SQLITE_DIRECT_OVERFLOW_READ
- bEnd = offset+amt==pCur->info.nPayload;
-#endif
assert( offset+amt <= pCur->info.nPayload );
assert( aPayload > pPage->aData );
@@ -65800,7 +67406,7 @@ static int accessPayload(
** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
** but is recast into its current form to avoid integer overflow problems
*/
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
/* Check if data must be read/written to/from the btree page itself. */
@@ -65809,7 +67415,7 @@ static int accessPayload(
if( a+offset>pCur->info.nLocal ){
a = pCur->info.nLocal - offset;
}
- rc = copyPayload(&aPayload[offset], pBuf, a, (eOp & 0x01), pPage->pDbPage);
+ rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
offset = 0;
pBuf += a;
amt -= a;
@@ -65825,53 +67431,46 @@ static int accessPayload(
nextPage = get4byte(&aPayload[pCur->info.nLocal]);
/* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
- ** Except, do not allocate aOverflow[] for eOp==2.
**
** The aOverflow[] array is sized at one entry for each overflow page
** in the overflow chain. The page number of the first overflow page is
** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array
** means "not yet known" (the cache is lazily populated).
*/
- if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
+ if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
if( nOvfl>pCur->nOvflAlloc ){
Pgno *aNew = (Pgno*)sqlite3Realloc(
pCur->aOverflow, nOvfl*2*sizeof(Pgno)
);
if( aNew==0 ){
- rc = SQLITE_NOMEM_BKPT;
+ return SQLITE_NOMEM_BKPT;
}else{
pCur->nOvflAlloc = nOvfl*2;
pCur->aOverflow = aNew;
}
}
- if( rc==SQLITE_OK ){
- memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
- pCur->curFlags |= BTCF_ValidOvfl;
+ memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
+ pCur->curFlags |= BTCF_ValidOvfl;
+ }else{
+ /* If the overflow page-list cache has been allocated and the
+ ** entry for the first required overflow page is valid, skip
+ ** directly to it.
+ */
+ if( pCur->aOverflow[offset/ovflSize] ){
+ iIdx = (offset/ovflSize);
+ nextPage = pCur->aOverflow[iIdx];
+ offset = (offset%ovflSize);
}
}
- /* If the overflow page-list cache has been allocated and the
- ** entry for the first required overflow page is valid, skip
- ** directly to it.
- */
- if( (pCur->curFlags & BTCF_ValidOvfl)!=0
- && pCur->aOverflow[offset/ovflSize]
- ){
- iIdx = (offset/ovflSize);
- nextPage = pCur->aOverflow[iIdx];
- offset = (offset%ovflSize);
- }
-
- for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){
-
+ assert( rc==SQLITE_OK && amt>0 );
+ while( nextPage ){
/* If required, populate the overflow page-list cache. */
- if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){
- assert( pCur->aOverflow[iIdx]==0
- || pCur->aOverflow[iIdx]==nextPage
- || CORRUPT_DB );
- pCur->aOverflow[iIdx] = nextPage;
- }
+ assert( pCur->aOverflow[iIdx]==0
+ || pCur->aOverflow[iIdx]==nextPage
+ || CORRUPT_DB );
+ pCur->aOverflow[iIdx] = nextPage;
if( offset>=ovflSize ){
/* The only reason to read this page is to obtain the page
@@ -65879,11 +67478,7 @@ static int accessPayload(
** data is not required. So first try to lookup the overflow
** page-list cache, if any, then fall back to the getOverflowPage()
** function.
- **
- ** Note that the aOverflow[] array must be allocated because eOp!=2
- ** here. If eOp==2, then offset==0 and this branch is never taken.
*/
- assert( eOp!=2 );
assert( pCur->curFlags & BTCF_ValidOvfl );
assert( pCur->pBtree->db==pBt->db );
if( pCur->aOverflow[iIdx+1] ){
@@ -65897,7 +67492,7 @@ static int accessPayload(
** range of data that is being read (eOp==0) or written (eOp!=0).
*/
#ifdef SQLITE_DIRECT_OVERFLOW_READ
- sqlite3_file *fd;
+ sqlite3_file *fd; /* File from which to do direct overflow read */
#endif
int a = amt;
if( a + offset > ovflSize ){
@@ -65909,27 +67504,25 @@ static int accessPayload(
**
** 1) this is a read operation, and
** 2) data is required from the start of this overflow page, and
- ** 3) the database is file-backed, and
- ** 4) there is no open write-transaction, and
- ** 5) the database is not a WAL database,
- ** 6) all data from the page is being read.
- ** 7) at least 4 bytes have already been read into the output buffer
+ ** 3) there is no open write-transaction, and
+ ** 4) the database is file-backed, and
+ ** 5) the page is not in the WAL file
+ ** 6) at least 4 bytes have already been read into the output buffer
**
** then data can be read directly from the database file into the
** output buffer, bypassing the page-cache altogether. This speeds
** up loading large records that span many overflow pages.
*/
- if( (eOp&0x01)==0 /* (1) */
+ if( eOp==0 /* (1) */
&& offset==0 /* (2) */
- && (bEnd || a==ovflSize) /* (6) */
- && pBt->inTransaction==TRANS_READ /* (4) */
- && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
- && 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */
- && &pBuf[-4]>=pBufStart /* (7) */
+ && pBt->inTransaction==TRANS_READ /* (3) */
+ && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */
+ && 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */
+ && &pBuf[-4]>=pBufStart /* (6) */
){
u8 aSave[4];
u8 *aWrite = &pBuf[-4];
- assert( aWrite>=pBufStart ); /* hence (7) */
+ assert( aWrite>=pBufStart ); /* due to (6) */
memcpy(aSave, aWrite, 4);
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
nextPage = get4byte(aWrite);
@@ -65940,76 +67533,86 @@ static int accessPayload(
{
DbPage *pDbPage;
rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage,
- ((eOp&0x01)==0 ? PAGER_GET_READONLY : 0)
+ (eOp==0 ? PAGER_GET_READONLY : 0)
);
if( rc==SQLITE_OK ){
aPayload = sqlite3PagerGetData(pDbPage);
nextPage = get4byte(aPayload);
- rc = copyPayload(&aPayload[offset+4], pBuf, a, (eOp&0x01), pDbPage);
+ rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
sqlite3PagerUnref(pDbPage);
offset = 0;
}
}
amt -= a;
+ if( amt==0 ) return rc;
pBuf += a;
}
+ if( rc ) break;
+ iIdx++;
}
}
if( rc==SQLITE_OK && amt>0 ){
- return SQLITE_CORRUPT_BKPT;
+ /* Overflow chain ends prematurely */
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
return rc;
}
/*
-** Read part of the key associated with cursor pCur. Exactly
-** "amt" bytes will be transferred into pBuf[]. The transfer
+** Read part of the payload for the row at which that cursor pCur is currently
+** pointing. "amt" bytes will be transferred into pBuf[]. The transfer
** begins at "offset".
**
-** The caller must ensure that pCur is pointing to a valid row
-** in the table.
+** pCur can be pointing to either a table or an index b-tree.
+** If pointing to a table btree, then the content section is read. If
+** pCur is pointing to an index b-tree then the key section is read.
+**
+** For sqlite3BtreePayload(), the caller must ensure that pCur is pointing
+** to a valid row in the table. For sqlite3BtreePayloadChecked(), the
+** cursor might be invalid or might need to be restored before being read.
**
** 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.
*/
-SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
+SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
- assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell );
+ assert( pCur->ixapPage[pCur->iPage]->nCell );
return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
}
/*
-** Read part of the data associated with cursor pCur. Exactly
-** "amt" bytes will be transfered into pBuf[]. The transfer
-** begins at "offset".
-**
-** Return SQLITE_OK on success or an error code if anything goes
-** wrong. An error is returned if "offset+amt" is larger than
-** the available payload.
+** This variant of sqlite3BtreePayload() works even if the cursor has not
+** in the CURSOR_VALID state. It is only used by the sqlite3_blob_read()
+** interface.
*/
-SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
- int rc;
-
#ifndef SQLITE_OMIT_INCRBLOB
+static SQLITE_NOINLINE int accessPayloadChecked(
+ BtCursor *pCur,
+ u32 offset,
+ u32 amt,
+ void *pBuf
+){
+ int rc;
if ( pCur->eState==CURSOR_INVALID ){
return SQLITE_ABORT;
}
-#endif
-
assert( cursorOwnsBtShared(pCur) );
- rc = restoreCursorPosition(pCur);
- if( rc==SQLITE_OK ){
- assert( pCur->eState==CURSOR_VALID );
- assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
- assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell );
- rc = accessPayload(pCur, offset, amt, pBuf, 0);
- }
- return rc;
+ rc = btreeRestoreCursorPosition(pCur);
+ return rc ? rc : accessPayload(pCur, offset, amt, pBuf, 0);
}
+SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
+ if( pCur->eState==CURSOR_VALID ){
+ assert( cursorOwnsBtShared(pCur) );
+ return accessPayload(pCur, offset, amt, pBuf, 0);
+ }else{
+ return accessPayloadChecked(pCur, offset, amt, pBuf);
+ }
+}
+#endif /* SQLITE_OMIT_INCRBLOB */
/*
** Return a pointer to payload information from the entry that the
@@ -66039,7 +67642,7 @@ static const void *fetchPayload(
assert( pCur->eState==CURSOR_VALID );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorOwnsBtShared(pCur) );
- assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell );
+ assert( pCur->ixapPage[pCur->iPage]->nCell );
assert( pCur->info.nSize>0 );
assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB );
assert( pCur->info.pPayloadapPage[pCur->iPage]->aDataEnd ||CORRUPT_DB);
@@ -66090,13 +67693,13 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
}
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
- pCur->iPage++;
- pCur->aiIdx[pCur->iPage] = 0;
+ pCur->aiIdx[pCur->iPage++] = pCur->ix;
+ pCur->ix = 0;
return getAndInitPage(pBt, newPgno, &pCur->apPage[pCur->iPage],
pCur, pCur->curPagerFlags);
}
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
/*
** Page pParent is an internal (non-leaf) tree page. This function
** asserts that page number iChild is the left-child if the iIdx'th
@@ -66139,6 +67742,7 @@ static void moveToParent(BtCursor *pCur){
testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
+ pCur->ix = pCur->aiIdx[pCur->iPage-1];
releasePageNotNull(pCur->apPage[pCur->iPage--]);
}
@@ -66180,9 +67784,12 @@ static int moveToRoot(BtCursor *pCur){
}
if( pCur->iPage>=0 ){
- while( pCur->iPage ){
- assert( pCur->apPage[pCur->iPage]!=0 );
- releasePageNotNull(pCur->apPage[pCur->iPage--]);
+ if( pCur->iPage ){
+ do{
+ assert( pCur->apPage[pCur->iPage]!=0 );
+ releasePageNotNull(pCur->apPage[pCur->iPage--]);
+ }while( pCur->iPage);
+ goto skip_init;
}
}else if( pCur->pgnoRoot==0 ){
pCur->eState = CURSOR_INVALID;
@@ -66193,7 +67800,7 @@ static int moveToRoot(BtCursor *pCur){
0, pCur->curPagerFlags);
if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID;
- return rc;
+ return rc;
}
pCur->iPage = 0;
pCur->curIntKey = pCur->apPage[0]->intKey;
@@ -66213,13 +67820,15 @@ static int moveToRoot(BtCursor *pCur){
** (or the freelist). */
assert( pRoot->intKey==1 || pRoot->intKey==0 );
if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno);
}
- pCur->aiIdx[0] = 0;
+skip_init:
+ pCur->ix = 0;
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
+ pRoot = pCur->apPage[0];
if( pRoot->nCell>0 ){
pCur->eState = CURSOR_VALID;
}else if( !pRoot->leaf ){
@@ -66249,8 +67858,8 @@ static int moveToLeftmost(BtCursor *pCur){
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
- assert( pCur->aiIdx[pCur->iPage]nCell );
- pgno = get4byte(findCell(pPage, pCur->aiIdx[pCur->iPage]));
+ assert( pCur->ixnCell );
+ pgno = get4byte(findCell(pPage, pCur->ix));
rc = moveToChild(pCur, pgno);
}
return rc;
@@ -66275,11 +67884,11 @@ static int moveToRightmost(BtCursor *pCur){
assert( pCur->eState==CURSOR_VALID );
while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
- pCur->aiIdx[pCur->iPage] = pPage->nCell;
+ pCur->ix = pPage->nCell;
rc = moveToChild(pCur, pgno);
if( rc ) return rc;
}
- pCur->aiIdx[pCur->iPage] = pPage->nCell-1;
+ pCur->ix = pPage->nCell-1;
assert( pCur->info.nSize==0 );
assert( (pCur->curFlags & BTCF_ValidNKey)==0 );
return SQLITE_OK;
@@ -66327,7 +67936,7 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
for(ii=0; iiiPage; ii++){
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
}
- assert( pCur->aiIdx[pCur->iPage]==pCur->apPage[pCur->iPage]->nCell-1 );
+ assert( pCur->ix==pCur->apPage[pCur->iPage]->nCell-1 );
assert( pCur->apPage[pCur->iPage]->leaf );
#endif
return SQLITE_OK;
@@ -66408,9 +68017,29 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
*pRes = 0;
return SQLITE_OK;
}
- if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKeyinfo.nKeycurFlags & BTCF_AtLast)!=0 ){
+ *pRes = -1;
+ return SQLITE_OK;
+ }
+ /* If the requested key is one more than the previous key, then
+ ** try to get there using sqlite3BtreeNext() rather than a full
+ ** binary search. This is an optimization only. The correct answer
+ ** is still obtained without this case, only a little more slowely */
+ if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
+ *pRes = 0;
+ rc = sqlite3BtreeNext(pCur, 0);
+ if( rc==SQLITE_OK ){
+ getCellInfo(pCur);
+ if( pCur->info.nKey==intKey ){
+ return SQLITE_OK;
+ }
+ }else if( rc==SQLITE_DONE ){
+ rc = SQLITE_OK;
+ }else{
+ return rc;
+ }
+ }
}
}
@@ -66457,14 +68086,16 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
upr = pPage->nCell-1;
assert( biasRight==0 || biasRight==1 );
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
- pCur->aiIdx[pCur->iPage] = (u16)idx;
+ pCur->ix = (u16)idx;
if( xRecordCompare==0 ){
for(;;){
i64 nCellKey;
pCell = findCellPastPtr(pPage, idx);
if( pPage->intKeyLeaf ){
while( 0x80 <= *(pCell++) ){
- if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
+ if( pCell>=pPage->aDataEnd ){
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ }
}
}
getVarint(pCell, (u64*)&nCellKey);
@@ -66476,16 +68107,16 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
if( lwr>upr ){ c = +1; break; }
}else{
assert( nCellKey==intKey );
- pCur->curFlags |= BTCF_ValidNKey;
- pCur->info.nKey = nCellKey;
- pCur->aiIdx[pCur->iPage] = (u16)idx;
+ pCur->ix = (u16)idx;
if( !pPage->leaf ){
lwr = idx;
goto moveto_next_layer;
}else{
+ pCur->curFlags |= BTCF_ValidNKey;
+ pCur->info.nKey = nCellKey;
+ pCur->info.nSize = 0;
*pRes = 0;
- rc = SQLITE_OK;
- goto moveto_finish;
+ return SQLITE_OK;
}
}
assert( lwr+upr>=0 );
@@ -66537,7 +68168,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
testcase( nCell==2 ); /* Minimum legal index key size */
if( nCell<2 ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PGNO(pPage->pgno);
goto moveto_finish;
}
pCellKey = sqlite3Malloc( nCell+18 );
@@ -66545,8 +68176,9 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
rc = SQLITE_NOMEM_BKPT;
goto moveto_finish;
}
- pCur->aiIdx[pCur->iPage] = (u16)idx;
- rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
+ pCur->ix = (u16)idx;
+ rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
+ pCur->curFlags &= ~BTCF_ValidOvfl;
if( rc ){
sqlite3_free(pCellKey);
goto moveto_finish;
@@ -66566,7 +68198,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
assert( c==0 );
*pRes = 0;
rc = SQLITE_OK;
- pCur->aiIdx[pCur->iPage] = (u16)idx;
+ pCur->ix = (u16)idx;
if( pIdxKey->errCode ) rc = SQLITE_CORRUPT;
goto moveto_finish;
}
@@ -66578,8 +68210,8 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( pPage->isInit );
if( pPage->leaf ){
- assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell );
- pCur->aiIdx[pCur->iPage] = (u16)idx;
+ assert( pCur->ixapPage[pCur->iPage]->nCell );
+ pCur->ix = (u16)idx;
*pRes = c;
rc = SQLITE_OK;
goto moveto_finish;
@@ -66590,13 +68222,13 @@ moveto_next_layer:
}else{
chldPg = get4byte(findCell(pPage, lwr));
}
- pCur->aiIdx[pCur->iPage] = (u16)lwr;
+ pCur->ix = (u16)lwr;
rc = moveToChild(pCur, chldPg);
if( rc ) break;
}
moveto_finish:
pCur->info.nSize = 0;
- pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
+ assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
return rc;
}
@@ -66617,10 +68249,36 @@ SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){
}
/*
-** Advance the cursor to the next entry in the database. If
-** successful then set *pRes=0. If the cursor
-** was already pointing to the last entry in the database before
-** this routine was called, then set *pRes=1.
+** Return an estimate for the number of rows in the table that pCur is
+** pointing to. Return a negative number if no estimate is currently
+** available.
+*/
+SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
+ i64 n;
+ u8 i;
+
+ assert( cursorOwnsBtShared(pCur) );
+ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+
+ /* Currently this interface is only called by the OP_IfSmaller
+ ** opcode, and it that case the cursor will always be valid and
+ ** will always point to a leaf node. */
+ if( NEVER(pCur->eState!=CURSOR_VALID) ) return -1;
+ if( NEVER(pCur->apPage[pCur->iPage]->leaf==0) ) return -1;
+
+ for(n=1, i=0; i<=pCur->iPage; i++){
+ n *= pCur->apPage[i]->nCell;
+ }
+ return n;
+}
+
+/*
+** Advance the cursor to the next entry in the database.
+** Return value:
+**
+** SQLITE_OK success
+** SQLITE_DONE cursor is already pointing at the last element
+** otherwise some kind of error occurred
**
** The main entry point is sqlite3BtreeNext(). That routine is optimized
** for the common case of merely incrementing the cell counter BtCursor.aiIdx
@@ -66628,23 +68286,19 @@ SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){
** routine is called when it is necessary to move to a different page or
** to restore the cursor.
**
-** The calling function will set *pRes to 0 or 1. The initial *pRes value
-** will be 1 if the cursor being stepped corresponds to an SQL index and
-** if this routine could have been skipped if that SQL index had been
-** a unique index. Otherwise the caller will have set *pRes to zero.
-** Zero is the common case. The btree implementation is free to use the
-** initial *pRes value as a hint to improve performance, but the current
-** SQLite btree implementation does not. (Note that the comdb2 btree
-** implementation does use this hint, however.)
+** If bit 0x01 of the F argument in sqlite3BtreeNext(C,F) is 1, then the
+** cursor corresponds to an SQL index and this routine could have been
+** skipped if the SQL index had been a unique index. The F argument
+** is a hint to the implement. SQLite btree implementation does not use
+** this hint, but COMDB2 does.
*/
-static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
+static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
int rc;
int idx;
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
- assert( *pRes==0 );
if( pCur->eState!=CURSOR_VALID ){
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
rc = restoreCursorPosition(pCur);
@@ -66652,8 +68306,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
return rc;
}
if( CURSOR_INVALID==pCur->eState ){
- *pRes = 1;
- return SQLITE_OK;
+ return SQLITE_DONE;
}
if( pCur->skipNext ){
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
@@ -66667,7 +68320,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
}
pPage = pCur->apPage[pCur->iPage];
- idx = ++pCur->aiIdx[pCur->iPage];
+ idx = ++pCur->ix;
assert( pPage->isInit );
/* If the database file is corrupt, it is possible for the value of idx
@@ -66685,15 +68338,14 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
}
do{
if( pCur->iPage==0 ){
- *pRes = 1;
pCur->eState = CURSOR_INVALID;
- return SQLITE_OK;
+ return SQLITE_DONE;
}
moveToParent(pCur);
pPage = pCur->apPage[pCur->iPage];
- }while( pCur->aiIdx[pCur->iPage]>=pPage->nCell );
+ }while( pCur->ix>=pPage->nCell );
if( pPage->intKey ){
- return sqlite3BtreeNext(pCur, pRes);
+ return sqlite3BtreeNext(pCur, 0);
}else{
return SQLITE_OK;
}
@@ -66704,20 +68356,19 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
return moveToLeftmost(pCur);
}
}
-SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
+SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int flags){
MemPage *pPage;
+ UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
assert( cursorOwnsBtShared(pCur) );
- assert( pRes!=0 );
- assert( *pRes==0 || *pRes==1 );
+ assert( flags==0 || flags==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
- *pRes = 0;
- if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur, pRes);
+ if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur);
pPage = pCur->apPage[pCur->iPage];
- if( (++pCur->aiIdx[pCur->iPage])>=pPage->nCell ){
- pCur->aiIdx[pCur->iPage]--;
- return btreeNext(pCur, pRes);
+ if( (++pCur->ix)>=pPage->nCell ){
+ pCur->ix--;
+ return btreeNext(pCur);
}
if( pPage->leaf ){
return SQLITE_OK;
@@ -66727,10 +68378,12 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
}
/*
-** Step the cursor to the back to the previous entry in the database. If
-** successful then set *pRes=0. If the cursor
-** was already pointing to the first entry in the database before
-** this routine was called, then set *pRes=1.
+** Step the cursor to the back to the previous entry in the database.
+** Return values:
+**
+** SQLITE_OK success
+** SQLITE_DONE the cursor is already on the first element of the table
+** otherwise some kind of error occurred
**
** The main entry point is sqlite3BtreePrevious(). That routine is optimized
** for the common case of merely decrementing the cell counter BtCursor.aiIdx
@@ -66738,22 +68391,17 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
** helper routine is called when it is necessary to move to a different page
** or to restore the cursor.
**
-** The calling function will set *pRes to 0 or 1. The initial *pRes value
-** will be 1 if the cursor being stepped corresponds to an SQL index and
-** if this routine could have been skipped if that SQL index had been
-** a unique index. Otherwise the caller will have set *pRes to zero.
-** Zero is the common case. The btree implementation is free to use the
-** initial *pRes value as a hint to improve performance, but the current
-** SQLite btree implementation does not. (Note that the comdb2 btree
-** implementation does use this hint, however.)
+** If bit 0x01 of the F argument to sqlite3BtreePrevious(C,F) is 1, then
+** the cursor corresponds to an SQL index and this routine could have been
+** skipped if the SQL index had been a unique index. The F argument is a
+** hint to the implement. The native SQLite btree implementation does not
+** use this hint, but COMDB2 does.
*/
-static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
+static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
int rc;
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
- assert( pRes!=0 );
- assert( *pRes==0 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
assert( pCur->info.nSize==0 );
@@ -66763,8 +68411,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
return rc;
}
if( CURSOR_INVALID==pCur->eState ){
- *pRes = 1;
- return SQLITE_OK;
+ return SQLITE_DONE;
}
if( pCur->skipNext ){
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
@@ -66780,47 +68427,45 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
pPage = pCur->apPage[pCur->iPage];
assert( pPage->isInit );
if( !pPage->leaf ){
- int idx = pCur->aiIdx[pCur->iPage];
+ int idx = pCur->ix;
rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
if( rc ) return rc;
rc = moveToRightmost(pCur);
}else{
- while( pCur->aiIdx[pCur->iPage]==0 ){
+ while( pCur->ix==0 ){
if( pCur->iPage==0 ){
pCur->eState = CURSOR_INVALID;
- *pRes = 1;
- return SQLITE_OK;
+ return SQLITE_DONE;
}
moveToParent(pCur);
}
assert( pCur->info.nSize==0 );
- assert( (pCur->curFlags & (BTCF_ValidNKey|BTCF_ValidOvfl))==0 );
+ assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 );
- pCur->aiIdx[pCur->iPage]--;
+ pCur->ix--;
pPage = pCur->apPage[pCur->iPage];
if( pPage->intKey && !pPage->leaf ){
- rc = sqlite3BtreePrevious(pCur, pRes);
+ rc = sqlite3BtreePrevious(pCur, 0);
}else{
rc = SQLITE_OK;
}
}
return rc;
}
-SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
+SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int flags){
assert( cursorOwnsBtShared(pCur) );
- assert( pRes!=0 );
- assert( *pRes==0 || *pRes==1 );
+ assert( flags==0 || flags==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
- *pRes = 0;
+ UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
pCur->info.nSize = 0;
if( pCur->eState!=CURSOR_VALID
- || pCur->aiIdx[pCur->iPage]==0
+ || pCur->ix==0
|| pCur->apPage[pCur->iPage]->leaf==0
){
- return btreePrevious(pCur, pRes);
+ return btreePrevious(pCur);
}
- pCur->aiIdx[pCur->iPage]--;
+ pCur->ix--;
return SQLITE_OK;
}
@@ -66926,7 +68571,7 @@ static int allocateBtreePage(
}
testcase( iTrunk==mxPage );
if( iTrunk>mxPage || nSearch++ > n ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PGNO(pPrevTrunk ? pPrevTrunk->pgno : 1);
}else{
rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0);
}
@@ -66955,7 +68600,7 @@ static int allocateBtreePage(
TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
}else if( k>(u32)(pBt->usableSize/4 - 2) ){
/* Value of k is out of range. Database corruption */
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
#ifndef SQLITE_OMIT_AUTOVACUUM
}else if( searchList
@@ -66989,7 +68634,7 @@ static int allocateBtreePage(
MemPage *pNewTrunk;
Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
if( iNewTrunk>mxPage ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
}
testcase( iNewTrunk==mxPage );
@@ -67054,7 +68699,7 @@ static int allocateBtreePage(
iPage = get4byte(&aData[8+closest*4]);
testcase( iPage==mxPage );
if( iPage>mxPage ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
}
testcase( iPage==mxPage );
@@ -67310,30 +68955,29 @@ static void freePage(MemPage *pPage, int *pRC){
static int clearCell(
MemPage *pPage, /* The page that contains the Cell */
unsigned char *pCell, /* First byte of the Cell */
- u16 *pnSize /* Write the size of the Cell here */
+ CellInfo *pInfo /* Size information about the cell */
){
BtShared *pBt = pPage->pBt;
- CellInfo info;
Pgno ovflPgno;
int rc;
int nOvfl;
u32 ovflPageSize;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- pPage->xParseCell(pPage, pCell, &info);
- *pnSize = info.nSize;
- if( info.nLocal==info.nPayload ){
+ pPage->xParseCell(pPage, pCell, pInfo);
+ if( pInfo->nLocal==pInfo->nPayload ){
return SQLITE_OK; /* No overflow pages. Return without doing anything */
}
- if( pCell+info.nSize-1 > pPage->aData+pPage->maskPage ){
- return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */
+ if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){
+ /* Cell extends past end of page */
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
- ovflPgno = get4byte(pCell + info.nSize - 4);
+ ovflPgno = get4byte(pCell + pInfo->nSize - 4);
assert( pBt->usableSize > 4 );
ovflPageSize = pBt->usableSize - 4;
- nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
+ nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize;
assert( nOvfl>0 ||
- (CORRUPT_DB && (info.nPayload + ovflPageSize)nPayload + ovflPageSize)xParseCell(pPage, pCell, &info);
@@ -67573,7 +69217,6 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */
if( *pRC ) return;
-
assert( idx>=0 && idxnCell );
assert( CORRUPT_DB || sz==cellSize(pPage, idx) );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
@@ -67657,7 +69300,10 @@ static void insertCell(
put4byte(pCell, iChild);
}
j = pPage->nOverflow++;
- assert( j<(int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])) );
+ /* Comparison against ArraySize-1 since we hold back one extra slot
+ ** as a contingency. In other words, never need more than 3 overflow
+ ** slots but 4 are allocated, just to be safe. */
+ assert( j < ArraySize(pPage->apOvfl)-1 );
pPage->apOvfl[j] = pCell;
pPage->aiOvfl[j] = (u16)i;
@@ -68397,7 +70043,7 @@ static int balance_nonroot(
nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
if( (i--)==0 ) break;
- if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){
+ if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
apDiv[i] = pParent->apOvfl[0];
pgno = get4byte(apDiv[i]);
szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
@@ -68419,7 +70065,7 @@ static int balance_nonroot(
** In this case, temporarily copy the cell into the aOvflSpace[]
** buffer. It will be copied out again as soon as the aSpace[] buffer
** is allocated. */
- if( pBt->btsFlags & BTS_SECURE_DELETE ){
+ if( pBt->btsFlags & BTS_FAST_SECURE ){
int iOff;
iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
@@ -68589,7 +70235,6 @@ static int balance_nonroot(
for(i=0; inFree;
- if( szNew[i]<0 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; }
for(j=0; jnOverflow; j++){
szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
}
@@ -68987,7 +70632,7 @@ static int balance_nonroot(
** free space needs to be up front.
*/
assert( nNew==1 || CORRUPT_DB );
- rc = defragmentPage(apNew[0]);
+ rc = defragmentPage(apNew[0], -1);
testcase( rc!=SQLITE_OK );
assert( apNew[0]->nFree ==
(get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
@@ -69143,8 +70788,8 @@ static int balance(BtCursor *pCur){
rc = balance_deeper(pPage, &pCur->apPage[1]);
if( rc==SQLITE_OK ){
pCur->iPage = 1;
+ pCur->ix = 0;
pCur->aiIdx[0] = 0;
- pCur->aiIdx[1] = 0;
assert( pCur->apPage[1]->nOverflow );
}
}else{
@@ -69251,22 +70896,24 @@ static int balance(BtCursor *pCur){
** pX.pData,nData,nZero fields must be zero.
**
** If the seekResult parameter is non-zero, then a successful call to
-** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already
-** been performed. seekResult is the search result returned (a negative
-** number if pCur points at an entry that is smaller than (pKey, nKey), or
-** a positive value if pCur points at an entry that is larger than
-** (pKey, nKey)).
+** MovetoUnpacked() to seek cursor pCur to (pKey,nKey) has already
+** been performed. In other words, if seekResult!=0 then the cursor
+** is currently pointing to a cell that will be adjacent to the cell
+** to be inserted. If seekResult<0 then pCur points to a cell that is
+** smaller then (pKey,nKey). If seekResult>0 then pCur points to a cell
+** that is larger than (pKey,nKey).
**
-** If the seekResult parameter is non-zero, then the caller guarantees that
-** cursor pCur is pointing at the existing copy of a row that is to be
-** overwritten. If the seekResult parameter is 0, then cursor pCur may
-** point to any entry or to no entry at all and so this function has to seek
-** the cursor before the new key can be inserted.
+** If seekResult==0, that means pCur is pointing at some unknown location.
+** In that case, this routine must seek the cursor to the correct insertion
+** point for (pKey,nKey) before doing the insertion. For index btrees,
+** if pX->nMem is non-zero, then pX->aMem contains pointers to the unpacked
+** key values and pX->aMem can be used instead of pX->pKey to avoid having
+** to decode the key.
*/
SQLITE_PRIVATE int sqlite3BtreeInsert(
BtCursor *pCur, /* Insert data into the table of this cursor */
const BtreePayload *pX, /* Content of the row to be inserted */
- int appendBias, /* True if this is likely an append */
+ int flags, /* True if this is likely an append */
int seekResult /* Result of prior MovetoUnpacked() call */
){
int rc;
@@ -69279,6 +70926,8 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
unsigned char *oldCell;
unsigned char *newCell = 0;
+ assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND))==flags );
+
if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK );
return pCur->skipNext;
@@ -69317,20 +70966,37 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
assert( pX->pKey==0 );
/* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced */
- invalidateIncrblobCursors(p, pX->nKey, 0);
+ invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
+
+ /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
+ ** to a row with the same key as the new entry being inserted. */
+ assert( (flags & BTREE_SAVEPOSITION)==0 ||
+ ((pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey) );
/* If the cursor is currently on the last row and we are appending a
** new row onto the end, set the "loc" to avoid an unnecessary
** btreeMoveto() call */
- if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey>0
- && pCur->info.nKey==pX->nKey-1 ){
- loc = -1;
+ if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){
+ loc = 0;
}else if( loc==0 ){
- rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, appendBias, &loc);
+ rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);
if( rc ) return rc;
}
- }else if( loc==0 ){
- rc = btreeMoveto(pCur, pX->pKey, pX->nKey, appendBias, &loc);
+ }else if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){
+ if( pX->nMem ){
+ UnpackedRecord r;
+ r.pKeyInfo = pCur->pKeyInfo;
+ r.aMem = pX->aMem;
+ r.nField = pX->nMem;
+ r.default_rc = 0;
+ r.errCode = 0;
+ r.r1 = 0;
+ r.r2 = 0;
+ r.eqSeen = 0;
+ rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
+ }else{
+ rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
+ }
if( rc ) return rc;
}
assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
@@ -69349,9 +71015,9 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
if( rc ) goto end_insert;
assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) );
- idx = pCur->aiIdx[pCur->iPage];
+ idx = pCur->ix;
if( loc==0 ){
- u16 szOld;
+ CellInfo info;
assert( idxnCell );
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ){
@@ -69361,12 +71027,30 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
}
- rc = clearCell(pPage, oldCell, &szOld);
- dropCell(pPage, idx, szOld, &rc);
+ rc = clearCell(pPage, oldCell, &info);
+ if( info.nSize==szNew && info.nLocal==info.nPayload
+ && (!ISAUTOVACUUM || szNewminLocal)
+ ){
+ /* Overwrite the old cell with the new if they are the same size.
+ ** We could also try to do this if the old cell is smaller, then add
+ ** the leftover space to the free list. But experiments show that
+ ** doing that is no faster then skipping this optimization and just
+ ** calling dropCell() and insertCell().
+ **
+ ** This optimization cannot be used on an autovacuum database if the
+ ** new entry uses overflow pages, as the insertCell() call below is
+ ** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */
+ assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */
+ if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
+ memcpy(oldCell, newCell, szNew);
+ return SQLITE_OK;
+ }
+ dropCell(pPage, idx, info.nSize, &rc);
if( rc ) goto end_insert;
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
- idx = ++pCur->aiIdx[pCur->iPage];
+ idx = ++pCur->ix;
+ pCur->curFlags &= ~BTCF_ValidNKey;
}else{
assert( pPage->leaf );
}
@@ -69406,6 +71090,20 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
** from trying to save the current position of the cursor. */
pCur->apPage[pCur->iPage]->nOverflow = 0;
pCur->eState = CURSOR_INVALID;
+ if( (flags & BTREE_SAVEPOSITION) && rc==SQLITE_OK ){
+ rc = moveToRoot(pCur);
+ if( pCur->pKeyInfo ){
+ assert( pCur->pKey==0 );
+ pCur->pKey = sqlite3Malloc( pX->nKey );
+ if( pCur->pKey==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ memcpy(pCur->pKey, pX->pKey, pX->nKey);
+ }
+ }
+ pCur->eState = CURSOR_REQUIRESEEK;
+ pCur->nKey = pX->nKey;
+ }
}
assert( pCur->apPage[pCur->iPage]->nOverflow==0 );
@@ -69438,7 +71136,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
unsigned char *pCell; /* Pointer to cell to delete */
int iCellIdx; /* Index of cell to delete */
int iCellDepth; /* Depth of node containing pCell */
- u16 szCell; /* Size of the cell being deleted */
+ CellInfo info; /* Size of the cell being deleted */
int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */
u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */
@@ -69448,12 +71146,12 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( pCur->curFlags & BTCF_WriteFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
- assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell );
+ assert( pCur->ixapPage[pCur->iPage]->nCell );
assert( pCur->eState==CURSOR_VALID );
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
iCellDepth = pCur->iPage;
- iCellIdx = pCur->aiIdx[iCellDepth];
+ iCellIdx = pCur->ix;
pPage = pCur->apPage[iCellDepth];
pCell = findCell(pPage, iCellIdx);
@@ -69487,8 +71185,8 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** sub-tree headed by the child page of the cell being deleted. This makes
** balancing the tree following the delete operation easier. */
if( !pPage->leaf ){
- int notUsed = 0;
- rc = sqlite3BtreePrevious(pCur, ¬Used);
+ rc = sqlite3BtreePrevious(pCur, 0);
+ assert( rc!=SQLITE_DONE );
if( rc ) return rc;
}
@@ -69502,7 +71200,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
/* If this is a delete operation to remove a row from a table b-tree,
** invalidate any incrblob cursors open on the row being deleted. */
if( pCur->pKeyInfo==0 ){
- invalidateIncrblobCursors(p, pCur->info.nKey, 0);
+ invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
}
/* Make the page containing the entry to be deleted writable. Then free any
@@ -69510,8 +71208,8 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** itself from within the page. */
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
- rc = clearCell(pPage, pCell, &szCell);
- dropCell(pPage, iCellIdx, szCell, &rc);
+ rc = clearCell(pPage, pCell, &info);
+ dropCell(pPage, iCellIdx, info.nSize, &rc);
if( rc ) return rc;
/* If the cell deleted was not located on a leaf page, then the cursor
@@ -69570,7 +71268,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
pCur->eState = CURSOR_SKIPNEXT;
if( iCellIdx>=pPage->nCell ){
pCur->skipNext = -1;
- pCur->aiIdx[iCellDepth] = pPage->nCell-1;
+ pCur->ix = pPage->nCell-1;
}else{
pCur->skipNext = 1;
}
@@ -69761,7 +71459,7 @@ static int clearDatabasePage(
unsigned char *pCell;
int i;
int hdr;
- u16 szCell;
+ CellInfo info;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pgno>btreePagecount(pBt) ){
@@ -69781,7 +71479,7 @@ static int clearDatabasePage(
rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
- rc = clearCell(pPage, pCell, &szCell);
+ rc = clearCell(pPage, pCell, &info);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
@@ -69829,7 +71527,7 @@ SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
/* Invalidate all incrblob cursors open on table iTable (assuming iTable
** is the root of a table b-tree - if it is not, the following call is
** a no-op). */
- invalidateIncrblobCursors(p, 0, 1);
+ invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
}
sqlite3BtreeLeave(p);
@@ -69872,27 +71570,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
assert( sqlite3BtreeHoldsMutex(p) );
assert( p->inTrans==TRANS_WRITE );
-
- /* It is illegal to drop a table if any cursors are open on the
- ** database. This is because in auto-vacuum mode the backend may
- ** need to move another root-page to fill a gap left by the deleted
- ** root page. If an open cursor was using this page a problem would
- ** occur.
- **
- ** This error is caught long before control reaches this point.
- */
- if( NEVER(pBt->pCursor) ){
- sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db);
- return SQLITE_LOCKED_SHAREDCACHE;
- }
-
- /*
- ** It is illegal to drop the sqlite_master table on page 1. But again,
- ** this error is caught long before reaching this point.
- */
- if( NEVER(iTable<2) ){
- return SQLITE_CORRUPT_BKPT;
- }
+ assert( iTable>=2 );
rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
if( rc ) return rc;
@@ -70103,16 +71781,16 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
return moveToRoot(pCur);
}
moveToParent(pCur);
- }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell );
+ }while ( pCur->ix>=pCur->apPage[pCur->iPage]->nCell );
- pCur->aiIdx[pCur->iPage]++;
+ pCur->ix++;
pPage = pCur->apPage[pCur->iPage];
}
/* Descend to the child node of the cell that the cursor currently
** points at. This is the right-child if (iIdx==pPage->nCell).
*/
- iIdx = pCur->aiIdx[pCur->iPage];
+ iIdx = pCur->ix;
if( iIdx==pPage->nCell ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
}else{
@@ -70497,6 +72175,7 @@ static int checkTreePage(
checkAppendMsg(pCheck, "Rowid %lld out of order", info.nKey);
}
maxKey = info.nKey;
+ keyCanBeEqual = 0; /* Only the first key on the page may ==maxKey */
}
/* Check the content overflow list */
@@ -70800,7 +72479,7 @@ SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *
if( pBt->inTransaction!=TRANS_NONE ){
rc = SQLITE_LOCKED;
}else{
- rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt);
+ rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt);
}
sqlite3BtreeLeave(p);
}
@@ -71869,7 +73548,7 @@ copy_finished:
*/
SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
/* If MEM_Dyn is set then Mem.xDel!=0.
- ** Mem.xDel is might not be initialized if MEM_Dyn is clear.
+ ** Mem.xDel might not be initialized if MEM_Dyn is clear.
*/
assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
@@ -71882,6 +73561,35 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
/* Cannot be both MEM_Int and MEM_Real at the same time */
assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) );
+ if( p->flags & MEM_Null ){
+ /* Cannot be both MEM_Null and some other type */
+ assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob
+ |MEM_RowSet|MEM_Frame|MEM_Agg|MEM_Zero))==0 );
+
+ /* If MEM_Null is set, then either the value is a pure NULL (the usual
+ ** case) or it is a pointer set using sqlite3_bind_pointer() or
+ ** sqlite3_result_pointer(). If a pointer, then MEM_Term must also be
+ ** set.
+ */
+ if( (p->flags & (MEM_Term|MEM_Subtype))==(MEM_Term|MEM_Subtype) ){
+ /* This is a pointer type. There may be a flag to indicate what to
+ ** do with the pointer. */
+ assert( ((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
+ ((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
+ ((p->flags&MEM_Static)!=0 ? 1 : 0) <= 1 );
+
+ /* No other bits set */
+ assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype
+ |MEM_Dyn|MEM_Ephem|MEM_Static))==0 );
+ }else{
+ /* A pure NULL might have other flags, such as MEM_Static, MEM_Dyn,
+ ** MEM_Ephem, MEM_Cleared, or MEM_Subtype */
+ }
+ }else{
+ /* The MEM_Cleared bit is only allowed on NULLs */
+ assert( (p->flags & MEM_Cleared)==0 );
+ }
+
/* The szMalloc field holds the correct memory allocation size */
assert( p->szMalloc==0
|| p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) );
@@ -71967,26 +73675,24 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPre
assert( pMem->szMalloc==0
|| pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
- if( pMem->szMallocszMalloc>0 && pMem->z==pMem->zMalloc ){
- pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
- bPreserve = 0;
- }else{
- if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc);
- pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
- }
- if( pMem->zMalloc==0 ){
- sqlite3VdbeMemSetNull(pMem);
- pMem->z = 0;
- pMem->szMalloc = 0;
- return SQLITE_NOMEM_BKPT;
- }else{
- pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
- }
+ if( n<32 ) n = 32;
+ if( bPreserve && pMem->szMalloc>0 && pMem->z==pMem->zMalloc ){
+ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
+ bPreserve = 0;
+ }else{
+ if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
+ pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
+ }
+ if( pMem->zMalloc==0 ){
+ sqlite3VdbeMemSetNull(pMem);
+ pMem->z = 0;
+ pMem->szMalloc = 0;
+ return SQLITE_NOMEM_BKPT;
+ }else{
+ pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
}
- if( bPreserve && pMem->z && pMem->z!=pMem->zMalloc ){
+ if( bPreserve && pMem->z && ALWAYS(pMem->z!=pMem->zMalloc) ){
memcpy(pMem->zMalloc, pMem->z, pMem->n);
}
if( (pMem->flags&MEM_Dyn)!=0 ){
@@ -72183,7 +73889,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
ctx.pFunc = pFunc;
pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
assert( (pMem->flags & MEM_Dyn)==0 );
- if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc);
+ if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
memcpy(pMem, &t, sizeof(t));
rc = ctx.isError;
}
@@ -72234,7 +73940,7 @@ static SQLITE_NOINLINE void vdbeMemClear(Mem *p){
vdbeMemClearExternAndSetNull(p);
}
if( p->szMalloc ){
- sqlite3DbFree(p->db, p->zMalloc);
+ sqlite3DbFreeNN(p->db, p->zMalloc);
p->szMalloc = 0;
}
p->z = 0;
@@ -72262,7 +73968,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
** If the double is out of range of a 64-bit signed integer then
** return the closest available 64-bit signed integer.
*/
-static i64 doubleToInt64(double r){
+static SQLITE_NOINLINE i64 doubleToInt64(double r){
#ifdef SQLITE_OMIT_FLOATING_POINT
/* When floating-point is omitted, double and int64 are the same thing */
return r;
@@ -72298,6 +74004,11 @@ static i64 doubleToInt64(double r){
**
** If pMem represents a string value, its encoding might be changed.
*/
+static SQLITE_NOINLINE i64 memIntValue(Mem *pMem){
+ i64 value = 0;
+ sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
+ return value;
+}
SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){
int flags;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
@@ -72308,10 +74019,8 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){
}else if( flags & MEM_Real ){
return doubleToInt64(pMem->u.r);
}else if( flags & (MEM_Str|MEM_Blob) ){
- i64 value = 0;
assert( pMem->z || pMem->n==0 );
- sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
- return value;
+ return memIntValue(pMem);
}else{
return 0;
}
@@ -72323,6 +74032,12 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){
** value. If it is a string or blob, try to convert it to a double.
** If it is a NULL, return 0.0.
*/
+static SQLITE_NOINLINE double memRealValue(Mem *pMem){
+ /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
+ double val = (double)0;
+ sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
+ return val;
+}
SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
@@ -72331,10 +74046,7 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){
}else if( pMem->flags & MEM_Int ){
return (double)pMem->u.i;
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
- /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
- double val = (double)0;
- sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
- return val;
+ return memRealValue(pMem);
}else{
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
return (double)0;
@@ -72539,6 +74251,27 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
}
}
+/* A no-op destructor */
+static void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); }
+
+/*
+** Set the value stored in *pMem should already be a NULL.
+** Also store a pointer to go with it.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(
+ Mem *pMem,
+ void *pPtr,
+ const char *zPType,
+ void (*xDestructor)(void*)
+){
+ assert( pMem->flags==MEM_Null );
+ pMem->u.zPType = zPType ? zPType : "";
+ pMem->z = pPtr;
+ pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term;
+ pMem->eSubtype = 'p';
+ pMem->xDel = xDestructor ? xDestructor : sqlite3NoopDestructor;
+}
+
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Delete any previous value and set the value stored in *pMem to val,
@@ -72776,10 +74509,9 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
/*
** Move data out of a btree key or data field and into a Mem structure.
-** The data or key is taken from the entry that pCur is currently pointing
+** The data is payload from the entry that pCur is currently pointing
** to. offset and amt determine what portion of the data or key to retrieve.
-** key is true to get the key or false to get data. The result is written
-** into the pMem element.
+** The result is written into the pMem element.
**
** The pMem object must have been initialized. This routine will use
** pMem->zMalloc to hold the content from the btree, if possible. New
@@ -72794,17 +74526,12 @@ static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
u32 offset, /* Offset from the start of data to return bytes from. */
u32 amt, /* Number of bytes to return. */
- int key, /* If true, retrieve from the btree key, not data. */
Mem *pMem /* OUT: Return data in this Mem structure. */
){
int rc;
pMem->flags = MEM_Null;
if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){
- if( key ){
- rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
- }else{
- rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
- }
+ rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
if( rc==SQLITE_OK ){
pMem->z[amt] = 0;
pMem->z[amt+1] = 0;
@@ -72820,7 +74547,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
u32 offset, /* Offset from the start of data to return bytes from. */
u32 amt, /* Number of bytes to return. */
- int key, /* If true, retrieve from the btree key, not data. */
Mem *pMem /* OUT: Return data in this Mem structure. */
){
char *zData; /* Data from the btree layer */
@@ -72841,7 +74567,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
pMem->flags = MEM_Blob|MEM_Ephem;
pMem->n = (int)amt;
}else{
- rc = vdbeMemFromBtreeResize(pCur, offset, amt, key, pMem);
+ rc = vdbeMemFromBtreeResize(pCur, offset, amt, pMem);
}
return rc;
@@ -72859,6 +74585,7 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){
assert( (pVal->flags & MEM_RowSet)==0 );
assert( (pVal->flags & (MEM_Null))==0 );
if( pVal->flags & (MEM_Blob|MEM_Str) ){
+ if( ExpandBlob(pVal) ) return 0;
pVal->flags |= MEM_Str;
if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){
sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);
@@ -72965,7 +74692,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
pRec->aMem[i].db = db;
}
}else{
- sqlite3DbFree(db, pRec);
+ sqlite3DbFreeNN(db, pRec);
pRec = 0;
}
}
@@ -73077,7 +74804,7 @@ static int valueFromFunction(
for(i=0; ipLeft,enc,affinity,&pVal)
+ if( SQLITE_OK==valueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal,pCtx)
&& pVal!=0
){
sqlite3VdbeMemNumerify(pVal);
@@ -73182,6 +74909,7 @@ static int valueFromExpr(
}else if( op==TK_NULL ){
pVal = valueNew(db, pCtx);
if( pVal==0 ) goto no_mem;
+ sqlite3VdbeMemNumerify(pVal);
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
else if( op==TK_BLOB ){
@@ -73275,7 +75003,7 @@ static void recordFunc(
putVarint32(&aRet[1], iSerial);
sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
- sqlite3DbFree(db, aRet);
+ sqlite3DbFreeNN(db, aRet);
}
}
@@ -73321,14 +75049,13 @@ static int stat4ValueFromExpr(
/* Skip over any TK_COLLATE nodes */
pExpr = sqlite3ExprSkipCollate(pExpr);
+ assert( pExpr==0 || pExpr->op!=TK_REGISTER || pExpr->op2!=TK_VARIABLE );
if( !pExpr ){
pVal = valueNew(db, pAlloc);
if( pVal ){
sqlite3VdbeMemSetNull((Mem*)pVal);
}
- }else if( pExpr->op==TK_VARIABLE
- || NEVER(pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
- ){
+ }else if( pExpr->op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){
Vdbe *v;
int iBindVar = pExpr->iColumn;
sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar);
@@ -73336,9 +75063,7 @@ static int stat4ValueFromExpr(
pVal = valueNew(db, pAlloc);
if( pVal ){
rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]);
- if( rc==SQLITE_OK ){
- sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
- }
+ sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
pVal->db = pParse->db;
}
}
@@ -73502,7 +75227,7 @@ SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
sqlite3VdbeMemRelease(&aMem[i]);
}
sqlite3KeyInfoUnref(pRec->pKeyInfo);
- sqlite3DbFree(db, pRec);
+ sqlite3DbFreeNN(db, pRec);
}
}
#endif /* ifdef SQLITE_ENABLE_STAT4 */
@@ -73526,7 +75251,7 @@ SQLITE_PRIVATE void sqlite3ValueSetStr(
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value *v){
if( !v ) return;
sqlite3VdbeMemRelease((Mem *)v);
- sqlite3DbFree(((Mem*)v)->db, v);
+ sqlite3DbFreeNN(((Mem*)v)->db, v);
}
/*
@@ -73612,15 +75337,14 @@ SQLITE_PRIVATE void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){
/*
** Remember the SQL string for a prepared statement.
*/
-SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){
- assert( isPrepareV2==1 || isPrepareV2==0 );
+SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlags){
if( p==0 ) return;
-#if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG)
- if( !isPrepareV2 ) return;
-#endif
+ p->prepFlags = prepFlags;
+ if( (prepFlags & SQLITE_PREPARE_SAVESQL)==0 ){
+ p->expmask = 0;
+ }
assert( p->zSql==0 );
p->zSql = sqlite3DbStrNDup(p->db, z, n);
- p->isPrepareV2 = (u8)isPrepareV2;
}
/*
@@ -73642,7 +75366,10 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
zTmp = pA->zSql;
pA->zSql = pB->zSql;
pB->zSql = zTmp;
- pB->isPrepareV2 = pA->isPrepareV2;
+ pB->expmask = pA->expmask;
+ pB->prepFlags = pA->prepFlags;
+ memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter));
+ pB->aCounter[SQLITE_STMTSTATUS_REPREPARE]++;
}
/*
@@ -73673,6 +75400,12 @@ static int growOpArray(Vdbe *v, int nOp){
UNUSED_PARAMETER(nOp);
#endif
+ /* Ensure that the size of a VDBE does not grow too large */
+ if( nNew > p->db->aLimit[SQLITE_LIMIT_VDBE_OP] ){
+ sqlite3OomFault(p->db);
+ return SQLITE_NOMEM;
+ }
+
assert( nOp<=(1024/sizeof(Op)) );
assert( nNew>=(p->nOpAlloc+nOp) );
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
@@ -73792,6 +75525,9 @@ SQLITE_PRIVATE int sqlite3VdbeLoadString(Vdbe *p, int iDest, const char *zStr){
** "s" character in zTypes[], the register is a string if the argument is
** not NULL, or OP_Null if the value is a null pointer. For each "i" character
** in zTypes[], the register is initialized to an integer.
+**
+** If the input string does not end with "X" then an OP_ResultRow instruction
+** is generated for the values inserted.
*/
SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe *p, int iDest, const char *zTypes, ...){
va_list ap;
@@ -73801,12 +75537,15 @@ SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe *p, int iDest, const char *zTypes,
for(i=0; (c = zTypes[i])!=0; i++){
if( c=='s' ){
const char *z = va_arg(ap, const char*);
- sqlite3VdbeAddOp4(p, z==0 ? OP_Null : OP_String8, 0, iDest++, 0, z, 0);
+ sqlite3VdbeAddOp4(p, z==0 ? OP_Null : OP_String8, 0, iDest+i, 0, z, 0);
+ }else if( c=='i' ){
+ sqlite3VdbeAddOp2(p, OP_Integer, va_arg(ap, int), iDest+i);
}else{
- assert( c=='i' );
- sqlite3VdbeAddOp2(p, OP_Integer, va_arg(ap, int), iDest++);
+ goto skip_op_resultrow;
}
}
+ sqlite3VdbeAddOp2(p, OP_ResultRow, iDest, i);
+skip_op_resultrow:
va_end(ap);
}
@@ -73871,7 +75610,11 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(
int p4 /* The P4 operand as an integer */
){
int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
- sqlite3VdbeChangeP4(p, addr, SQLITE_INT_TO_PTR(p4), P4_INT32);
+ if( p->db->mallocFailed==0 ){
+ VdbeOp *pOp = &p->aOp[addr];
+ pOp->p4type = P4_INT32;
+ pOp->p4.i = p4;
+ }
return addr;
}
@@ -74202,6 +75945,22 @@ SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N){
}
#endif
+/*
+** Verify that the VM passed as the only argument does not contain
+** an OP_ResultRow opcode. Fail an assert() if it does. This is used
+** by code in pragma.c to ensure that the implementation of certain
+** pragmas comports with the flags specified in the mkpragmatab.tcl
+** script.
+*/
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
+SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p){
+ int i;
+ for(i=0; inOp; i++){
+ assert( p->aOp[i].opcode!=OP_ResultRow );
+ }
+}
+#endif
+
/*
** This function returns a pointer to the array of opcodes associated with
** the Vdbe passed as the first argument. It is the callers responsibility
@@ -74321,7 +76080,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
sqlite3VdbeGetOp(p,addr)->p3 = val;
}
-SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){
+SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
assert( p->nOp>0 || p->db->mallocFailed );
if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5;
}
@@ -74341,7 +76100,7 @@ SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
*/
static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
if( (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){
- sqlite3DbFree(db, pDef);
+ sqlite3DbFreeNN(db, pDef);
}
}
@@ -74352,11 +76111,11 @@ static void vdbeFreeOpArray(sqlite3 *, Op *, int);
*/
static SQLITE_NOINLINE void freeP4Mem(sqlite3 *db, Mem *p){
if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
- sqlite3DbFree(db, p);
+ sqlite3DbFreeNN(db, p);
}
static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){
freeEphemeralFunction(db, p->pFunc);
- sqlite3DbFree(db, p);
+ sqlite3DbFreeNN(db, p);
}
static void freeP4(sqlite3 *db, int p4type, void *p4){
assert( db );
@@ -74382,10 +76141,6 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
break;
}
#endif
- case P4_MPRINTF: {
- if( db->pnBytesFreed==0 ) sqlite3_free(p4);
- break;
- }
case P4_FUNCDEF: {
freeEphemeralFunction(db, (FuncDef*)p4);
break;
@@ -74413,14 +76168,14 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
if( aOp ){
Op *pOp;
- for(pOp=aOp; pOp<&aOp[nOp]; pOp++){
- if( pOp->p4type ) freeP4(db, pOp->p4type, pOp->p4.p);
+ for(pOp=&aOp[nOp-1]; pOp>=aOp; pOp--){
+ if( pOp->p4type <= P4_FREE_IF_LE ) freeP4(db, pOp->p4type, pOp->p4.p);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
sqlite3DbFree(db, pOp->zComment);
#endif
}
+ sqlite3DbFreeNN(db, aOp);
}
- sqlite3DbFree(db, aOp);
}
/*
@@ -74530,16 +76285,42 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
}
}
+/*
+** Change the P4 operand of the most recently coded instruction
+** to the value defined by the arguments. This is a high-speed
+** version of sqlite3VdbeChangeP4().
+**
+** The P4 operand must not have been previously defined. And the new
+** P4 must not be P4_INT32. Use sqlite3VdbeChangeP4() in either of
+** those cases.
+*/
+SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe *p, void *pP4, int n){
+ VdbeOp *pOp;
+ assert( n!=P4_INT32 && n!=P4_VTAB );
+ assert( n<=0 );
+ if( p->db->mallocFailed ){
+ freeP4(p->db, n, pP4);
+ }else{
+ assert( pP4!=0 );
+ assert( p->nOp>0 );
+ pOp = &p->aOp[p->nOp-1];
+ assert( pOp->p4type==P4_NOTUSED );
+ pOp->p4type = n;
+ pOp->p4.p = pP4;
+ }
+}
+
/*
** Set the P4 on the most recently added opcode to the KeyInfo for the
** index given.
*/
SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){
Vdbe *v = pParse->pVdbe;
+ KeyInfo *pKeyInfo;
assert( v!=0 );
assert( pIdx!=0 );
- sqlite3VdbeChangeP4(v, -1, (char*)sqlite3KeyInfoOfIndex(pParse, pIdx),
- P4_KEYINFO);
+ pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pIdx);
+ if( pKeyInfo ) sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO);
}
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
@@ -74829,7 +76610,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg);
break;
}
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
case P4_FUNCCTX: {
FuncDef *pDef = pOp->p4.pCtx->pFunc;
sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg);
@@ -75067,7 +76848,7 @@ static void releaseMemArray(Mem *p, int N){
if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
sqlite3VdbeMemRelease(p);
}else if( p->szMalloc ){
- sqlite3DbFree(db, p->zMalloc);
+ sqlite3DbFreeNN(db, p->zMalloc);
p->szMalloc = 0;
}
@@ -75507,10 +77288,8 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
x.nFree = x.nNeeded;
}while( !db->mallocFailed );
- p->nzVar = pParse->nzVar;
- p->azVar = pParse->azVar;
- pParse->nzVar = 0;
- pParse->azVar = 0;
+ p->pVList = pParse->pVList;
+ pParse->pVList = 0;
p->explain = pParse->explain;
if( db->mallocFailed ){
p->nVar = 0;
@@ -75538,15 +77317,15 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
if( pCx==0 ){
return;
}
- assert( pCx->pBt==0 || pCx->eCurType==CURTYPE_BTREE );
+ assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE );
switch( pCx->eCurType ){
case CURTYPE_SORTER: {
sqlite3VdbeSorterClose(p->db, pCx);
break;
}
case CURTYPE_BTREE: {
- if( pCx->pBt ){
- sqlite3BtreeClose(pCx->pBt);
+ if( pCx->isEphemeral ){
+ if( pCx->pBtx ) sqlite3BtreeClose(pCx->pBtx);
/* The pCx->pCursor will be close automatically, if it exists, by
** the call above. */
}else{
@@ -75670,17 +77449,18 @@ static void Cleanup(Vdbe *p){
** be called on an SQL statement before sqlite3_step().
*/
SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
- Mem *pColName;
int n;
sqlite3 *db = p->db;
- releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
- sqlite3DbFree(db, p->aColName);
+ if( p->nResColumn ){
+ releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
+ sqlite3DbFree(db, p->aColName);
+ }
n = nResColumn*COLNAME_N;
p->nResColumn = (u16)nResColumn;
- p->aColName = pColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
+ p->aColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
if( p->aColName==0 ) return;
- initMemArray(p->aColName, n, p->db, MEM_Null);
+ initMemArray(p->aColName, n, db, MEM_Null);
}
/*
@@ -76015,60 +77795,59 @@ static void checkActiveVdbeCnt(sqlite3 *db){
** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
** Otherwise SQLITE_OK.
*/
-SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
+static SQLITE_NOINLINE int vdbeCloseStatement(Vdbe *p, int eOp){
sqlite3 *const db = p->db;
int rc = SQLITE_OK;
+ int i;
+ const int iSavepoint = p->iStatement-1;
- /* If p->iStatement is greater than zero, then this Vdbe opened a
- ** statement transaction that should be closed here. The only exception
- ** is that an IO error may have occurred, causing an emergency rollback.
- ** In this case (db->nStatement==0), and there is nothing to do.
- */
- if( db->nStatement && p->iStatement ){
- int i;
- const int iSavepoint = p->iStatement-1;
+ assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE);
+ assert( db->nStatement>0 );
+ assert( p->iStatement==(db->nStatement+db->nSavepoint) );
- assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE);
- assert( db->nStatement>0 );
- assert( p->iStatement==(db->nStatement+db->nSavepoint) );
-
- for(i=0; inDb; i++){
- int rc2 = SQLITE_OK;
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- if( eOp==SAVEPOINT_ROLLBACK ){
- rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint);
- }
- if( rc2==SQLITE_OK ){
- rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint);
- }
- if( rc==SQLITE_OK ){
- rc = rc2;
- }
- }
- }
- db->nStatement--;
- p->iStatement = 0;
-
- if( rc==SQLITE_OK ){
+ for(i=0; inDb; i++){
+ int rc2 = SQLITE_OK;
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt ){
if( eOp==SAVEPOINT_ROLLBACK ){
- rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
+ rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint);
+ }
+ if( rc2==SQLITE_OK ){
+ rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint);
}
if( rc==SQLITE_OK ){
- rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
+ rc = rc2;
}
}
+ }
+ db->nStatement--;
+ p->iStatement = 0;
- /* If the statement transaction is being rolled back, also restore the
- ** database handles deferred constraint counter to the value it had when
- ** the statement transaction was opened. */
+ if( rc==SQLITE_OK ){
if( eOp==SAVEPOINT_ROLLBACK ){
- db->nDeferredCons = p->nStmtDefCons;
- db->nDeferredImmCons = p->nStmtDefImmCons;
+ rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
}
+ if( rc==SQLITE_OK ){
+ rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
+ }
+ }
+
+ /* If the statement transaction is being rolled back, also restore the
+ ** database handles deferred constraint counter to the value it had when
+ ** the statement transaction was opened. */
+ if( eOp==SAVEPOINT_ROLLBACK ){
+ db->nDeferredCons = p->nStmtDefCons;
+ db->nDeferredImmCons = p->nStmtDefImmCons;
}
return rc;
}
+SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
+ if( p->db->nStatement && p->iStatement ){
+ return vdbeCloseStatement(p, eOp);
+ }
+ return SQLITE_OK;
+}
+
/*
** This function is called when a transaction opened by the database
@@ -76128,13 +77907,13 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
** one, or the complete transaction if there is no statement transaction.
*/
+ if( p->magic!=VDBE_MAGIC_RUN ){
+ return SQLITE_OK;
+ }
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM_BKPT;
}
closeAllCursors(p);
- if( p->magic!=VDBE_MAGIC_RUN ){
- return SQLITE_OK;
- }
checkActiveVdbeCnt(db);
/* No commit or rollback needed if the program never started or if the
@@ -76331,10 +78110,10 @@ SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){
sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
sqlite3EndBenignMalloc();
db->bBenignMalloc--;
- db->errCode = rc;
- }else{
- sqlite3Error(db, rc);
+ }else if( db->pErr ){
+ sqlite3ValueSetNull(db->pErr);
}
+ db->errCode = rc;
return rc;
}
@@ -76441,7 +78220,6 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
}
}
#endif
- p->iCurrentTime = 0;
p->magic = VDBE_MAGIC_RESET;
return p->rc & db->errMask;
}
@@ -76480,16 +78258,18 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3 *db, AuxData **pp, int iOp,
while( *pp ){
AuxData *pAux = *pp;
if( (iOp<0)
- || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & MASKBIT32(pAux->iArg))))
+ || (pAux->iAuxOp==iOp
+ && pAux->iAuxArg>=0
+ && (pAux->iAuxArg>31 || !(mask & MASKBIT32(pAux->iAuxArg))))
){
- testcase( pAux->iArg==31 );
- if( pAux->xDelete ){
- pAux->xDelete(pAux->pAux);
+ testcase( pAux->iAuxArg==31 );
+ if( pAux->xDeleteAux ){
+ pAux->xDeleteAux(pAux->pAux);
}
- *pp = pAux->pNext;
+ *pp = pAux->pNextAux;
sqlite3DbFree(db, pAux);
}else{
- pp= &pAux->pNext;
+ pp= &pAux->pNextAux;
}
}
}
@@ -76504,7 +78284,6 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3 *db, AuxData **pp, int iOp,
*/
SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
SubProgram *pSub, *pNext;
- int i;
assert( p->db==0 || p->db==db );
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
for(pSub=p->pProgram; pSub; pSub=pNext){
@@ -76514,18 +78293,20 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
}
if( p->magic!=VDBE_MAGIC_INIT ){
releaseMemArray(p->aVar, p->nVar);
- for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
- sqlite3DbFree(db, p->azVar);
+ sqlite3DbFree(db, p->pVList);
sqlite3DbFree(db, p->pFree);
}
vdbeFreeOpArray(db, p->aOp, p->nOp);
sqlite3DbFree(db, p->aColName);
sqlite3DbFree(db, p->zSql);
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- for(i=0; inScan; i++){
- sqlite3DbFree(db, p->aScan[i].zName);
+ {
+ int i;
+ for(i=0; inScan; i++){
+ sqlite3DbFree(db, p->aScan[i].zName);
+ }
+ sqlite3DbFree(db, p->aScan);
}
- sqlite3DbFree(db, p->aScan);
#endif
}
@@ -76550,7 +78331,7 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
}
p->magic = VDBE_MAGIC_DEAD;
p->db = 0;
- sqlite3DbFree(db, p);
+ sqlite3DbFreeNN(db, p);
}
/*
@@ -77026,30 +78807,13 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
** If an OOM error occurs, NULL is returned.
*/
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
- KeyInfo *pKeyInfo, /* Description of the record */
- char *pSpace, /* Unaligned space available */
- int szSpace, /* Size of pSpace[] in bytes */
- char **ppFree /* OUT: Caller should free this pointer */
+ KeyInfo *pKeyInfo /* Description of the record */
){
UnpackedRecord *p; /* Unpacked record to return */
- int nOff; /* Increment pSpace by nOff to align it */
int nByte; /* Number of bytes required for *p */
-
- /* We want to shift the pointer pSpace up such that it is 8-byte aligned.
- ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
- ** it by. If pSpace is already 8-byte aligned, nOff should be zero.
- */
- nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
- if( nByte>szSpace+nOff ){
- p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
- *ppFree = (char *)p;
- if( !p ) return 0;
- }else{
- p = (UnpackedRecord*)&pSpace[nOff];
- *ppFree = 0;
- }
-
+ p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
+ if( !p ) return 0;
p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
assert( pKeyInfo->aSortOrder!=0 );
p->pKeyInfo = pKeyInfo;
@@ -77097,7 +78861,7 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
p->nField = u;
}
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
/*
** This function compares two index or table record keys in the same way
** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(),
@@ -77202,7 +78966,7 @@ debugCompareEnd:
}
#endif
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
/*
** Count the number of fields (a.k.a. columns) in the record given by
** pKey,nKey. The verify that this count is less than or equal to the
@@ -77257,7 +79021,6 @@ static int vdbeCompareMemString(
}else{
int rc;
const void *v1, *v2;
- int n1, n2;
Mem c1;
Mem c2;
sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null);
@@ -77265,11 +79028,13 @@ static int vdbeCompareMemString(
sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
- n1 = v1==0 ? 0 : c1.n;
v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
- n2 = v2==0 ? 0 : c2.n;
- rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
- if( (v1==0 || v2==0) && prcErr ) *prcErr = SQLITE_NOMEM_BKPT;
+ if( (v1==0 || v2==0) ){
+ if( prcErr ) *prcErr = SQLITE_NOMEM_BKPT;
+ rc = 0;
+ }else{
+ rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2);
+ }
sqlite3VdbeMemRelease(&c1);
sqlite3VdbeMemRelease(&c2);
return rc;
@@ -77923,7 +79688,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
/* Read in the complete content of the index entry */
sqlite3VdbeMemInit(&m, db, 0);
- rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m);
+ rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
if( rc ){
return rc;
}
@@ -78003,7 +79768,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
return SQLITE_CORRUPT_BKPT;
}
sqlite3VdbeMemInit(&m, db, 0);
- rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m);
+ rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
if( rc ){
return rc;
}
@@ -78054,6 +79819,13 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){
return v->db;
}
+/*
+** Return the SQLITE_PREPARE flags for a Vdbe.
+*/
+SQLITE_PRIVATE u8 sqlite3VdbePrepareFlags(Vdbe *v){
+ return v->prepFlags;
+}
+
/*
** Return a pointer to an sqlite3_value structure containing the value bound
** parameter iVar of VM v. Except, if the value is an SQL NULL, return
@@ -78066,6 +79838,7 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff
assert( iVar>0 );
if( v ){
Mem *pMem = &v->aVar[iVar-1];
+ assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
if( 0==(pMem->flags & MEM_Null) ){
sqlite3_value *pRet = sqlite3ValueNew(v->db);
if( pRet ){
@@ -78085,13 +79858,36 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff
*/
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
assert( iVar>0 );
- if( iVar>32 ){
- v->expmask = 0xffffffff;
+ assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
+ if( iVar>=32 ){
+ v->expmask |= 0x80000000;
}else{
v->expmask |= ((u32)1 << (iVar-1));
}
}
+/*
+** Cause a function to throw an error if it was call from OP_PureFunc
+** rather than OP_Function.
+**
+** OP_PureFunc means that the function must be deterministic, and should
+** throw an error if it is given inputs that would make it non-deterministic.
+** This routine is invoked by date/time functions that use non-deterministic
+** features such as 'now'.
+*/
+SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context *pCtx){
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ if( pCtx->pVdbe==0 ) return 1;
+#endif
+ if( pCtx->pVdbe->aOp[pCtx->iOp].opcode==OP_PureFunc ){
+ sqlite3_result_error(pCtx,
+ "non-deterministic function in index expression or CHECK constraint",
+ -1);
+ return 0;
+ }
+ return 1;
+}
+
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
@@ -78119,14 +79915,14 @@ SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
** This function is used to free UnpackedRecord structures allocated by
** the vdbeUnpackRecord() function found in vdbeapi.c.
*/
-static void vdbeFreeUnpacked(sqlite3 *db, UnpackedRecord *p){
+static void vdbeFreeUnpacked(sqlite3 *db, int nField, UnpackedRecord *p){
if( p ){
int i;
- for(i=0; inField; i++){
+ for(i=0; iaMem[i];
if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem);
}
- sqlite3DbFree(db, p);
+ sqlite3DbFreeNN(db, p);
}
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -78155,10 +79951,15 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
assert( db->pPreUpdate==0 );
memset(&preupdate, 0, sizeof(PreUpdate));
- if( op==SQLITE_UPDATE ){
- iKey2 = v->aMem[iReg].u.i;
+ if( HasRowid(pTab)==0 ){
+ iKey1 = iKey2 = 0;
+ preupdate.pPk = sqlite3PrimaryKeyIndex(pTab);
}else{
- iKey2 = iKey1;
+ if( op==SQLITE_UPDATE ){
+ iKey2 = v->aMem[iReg].u.i;
+ }else{
+ iKey2 = iKey1;
+ }
}
assert( pCsr->nField==pTab->nCol
@@ -78181,14 +79982,14 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
db->pPreUpdate = 0;
sqlite3DbFree(db, preupdate.aRecord);
- vdbeFreeUnpacked(db, preupdate.pUnpacked);
- vdbeFreeUnpacked(db, preupdate.pNewUnpacked);
+ vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pUnpacked);
+ vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pNewUnpacked);
if( preupdate.aNew ){
int i;
for(i=0; inField; i++){
sqlite3VdbeMemRelease(&preupdate.aNew[i]);
}
- sqlite3DbFree(db, preupdate.aNew);
+ sqlite3DbFreeNN(db, preupdate.aNew);
}
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -78351,7 +80152,8 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
sqlite3VdbeMemRelease(&p->aVar[i]);
p->aVar[i].flags = MEM_Null;
}
- if( p->isPrepareV2 && p->expmask ){
+ assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 );
+ if( p->expmask ){
p->expired = 1;
}
sqlite3_mutex_leave(mutex);
@@ -78395,6 +80197,19 @@ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value *pVal){
Mem *pMem = (Mem*)pVal;
return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0);
}
+SQLITE_API void *sqlite3_value_pointer(sqlite3_value *pVal, const char *zPType){
+ Mem *p = (Mem*)pVal;
+ if( (p->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) ==
+ (MEM_Null|MEM_Term|MEM_Subtype)
+ && zPType!=0
+ && p->eSubtype=='p'
+ && strcmp(p->u.zPType, zPType)==0
+ ){
+ return (void*)p->z;
+ }else{
+ return 0;
+ }
+}
SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8);
}
@@ -78573,6 +80388,18 @@ SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetNull(pCtx->pOut);
}
+SQLITE_API void sqlite3_result_pointer(
+ sqlite3_context *pCtx,
+ void *pPtr,
+ const char *zPType,
+ void (*xDestructor)(void*)
+){
+ Mem *pOut = pCtx->pOut;
+ assert( sqlite3_mutex_held(pOut->db->mutex) );
+ sqlite3VdbeMemRelease(pOut);
+ pOut->flags = MEM_Null;
+ sqlite3VdbeMemSetPointer(pOut, pPtr, zPType, xDestructor);
+}
SQLITE_API void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){
Mem *pOut = pCtx->pOut;
assert( sqlite3_mutex_held(pOut->db->mutex) );
@@ -78829,8 +80656,11 @@ end_of_step:
|| (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE
);
assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp );
- if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
- /* If this statement was prepared using sqlite3_prepare_v2(), and an
+ if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
+ && rc!=SQLITE_ROW
+ && rc!=SQLITE_DONE
+ ){
+ /* If this statement was prepared using saved SQL and an
** error has occurred, then return the error code in p->rc to the
** caller. Set the error code in the database handle to the same value.
*/
@@ -79000,6 +80830,12 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
/*
** Return the auxiliary data pointer, if any, for the iArg'th argument to
** the user-function defined by pCtx.
+**
+** The left-most argument is 0.
+**
+** Undocumented behavior: If iArg is negative then access a cache of
+** auxiliary data pointers that is available to all functions within a
+** single prepared statement. The iArg values must match.
*/
SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
AuxData *pAuxData;
@@ -79010,17 +80846,24 @@ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
#else
assert( pCtx->pVdbe!=0 );
#endif
- for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
- if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
+ for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNextAux){
+ if( pAuxData->iAuxArg==iArg && (pAuxData->iAuxOp==pCtx->iOp || iArg<0) ){
+ return pAuxData->pAux;
+ }
}
-
- return (pAuxData ? pAuxData->pAux : 0);
+ return 0;
}
/*
** Set the auxiliary data pointer and delete function, for the iArg'th
** argument to the user-function defined by pCtx. Any previous value is
** deleted by calling the delete function specified when it was set.
+**
+** The left-most argument is 0.
+**
+** Undocumented behavior: If iArg is negative then make the data available
+** to all functions within the current prepared statement using iArg as an
+** access code.
*/
SQLITE_API void sqlite3_set_auxdata(
sqlite3_context *pCtx,
@@ -79032,33 +80875,34 @@ SQLITE_API void sqlite3_set_auxdata(
Vdbe *pVdbe = pCtx->pVdbe;
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- if( iArg<0 ) goto failed;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( pVdbe==0 ) goto failed;
#else
assert( pVdbe!=0 );
#endif
- for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
- if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
+ for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNextAux){
+ if( pAuxData->iAuxArg==iArg && (pAuxData->iAuxOp==pCtx->iOp || iArg<0) ){
+ break;
+ }
}
if( pAuxData==0 ){
pAuxData = sqlite3DbMallocZero(pVdbe->db, sizeof(AuxData));
if( !pAuxData ) goto failed;
- pAuxData->iOp = pCtx->iOp;
- pAuxData->iArg = iArg;
- pAuxData->pNext = pVdbe->pAuxData;
+ pAuxData->iAuxOp = pCtx->iOp;
+ pAuxData->iAuxArg = iArg;
+ pAuxData->pNextAux = pVdbe->pAuxData;
pVdbe->pAuxData = pAuxData;
if( pCtx->fErrorOrAux==0 ){
pCtx->isError = 0;
pCtx->fErrorOrAux = 1;
}
- }else if( pAuxData->xDelete ){
- pAuxData->xDelete(pAuxData->pAux);
+ }else if( pAuxData->xDeleteAux ){
+ pAuxData->xDeleteAux(pAuxData->pAux);
}
pAuxData->pAux = pAux;
- pAuxData->xDelete = xDelete;
+ pAuxData->xDeleteAux = xDelete;
return;
failed:
@@ -79455,9 +81299,8 @@ static int vdbeUnbind(Vdbe *p, int i){
** as if there had been a schema change, on the first sqlite3_step() call
** following any change to the bindings of that parameter.
*/
- if( p->isPrepareV2 &&
- ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff)
- ){
+ assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 );
+ if( p->expmask!=0 && (p->expmask & (i>=31 ? 0x80000000 : (u32)1<expired = 1;
}
return SQLITE_OK;
@@ -79486,8 +81329,10 @@ static int bindText(
if( rc==SQLITE_OK && encoding!=0 ){
rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
}
- sqlite3Error(p->db, rc);
- rc = sqlite3ApiExit(p->db, rc);
+ if( rc ){
+ sqlite3Error(p->db, rc);
+ rc = sqlite3ApiExit(p->db, rc);
+ }
}
sqlite3_mutex_leave(p->db->mutex);
}else if( xDel!=SQLITE_STATIC && xDel!=SQLITE_TRANSIENT ){
@@ -79558,6 +81403,24 @@ SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
}
return rc;
}
+SQLITE_API int sqlite3_bind_pointer(
+ sqlite3_stmt *pStmt,
+ int i,
+ void *pPtr,
+ const char *zPTtype,
+ void (*xDestructor)(void*)
+){
+ int rc;
+ Vdbe *p = (Vdbe*)pStmt;
+ rc = vdbeUnbind(p, i);
+ if( rc==SQLITE_OK ){
+ sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
+ sqlite3_mutex_leave(p->db->mutex);
+ }else if( xDestructor ){
+ xDestructor(pPtr);
+ }
+ return rc;
+}
SQLITE_API int sqlite3_bind_text(
sqlite3_stmt *pStmt,
int i,
@@ -79667,10 +81530,8 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
*/
SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
Vdbe *p = (Vdbe*)pStmt;
- if( p==0 || i<1 || i>p->nzVar ){
- return 0;
- }
- return p->azVar[i-1];
+ if( p==0 ) return 0;
+ return sqlite3VListNumToName(p->pVList, i);
}
/*
@@ -79679,19 +81540,8 @@ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
** return 0.
*/
SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
- int i;
- if( p==0 ){
- return 0;
- }
- if( zName ){
- for(i=0; inzVar; i++){
- const char *z = p->azVar[i];
- if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){
- return i+1;
- }
- }
- }
- return 0;
+ if( p==0 || zName==0 ) return 0;
+ return sqlite3VListNameToNum(p->pVList, zName, nName);
}
SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName));
@@ -79733,10 +81583,12 @@ SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *
if( pFrom->nVar!=pTo->nVar ){
return SQLITE_ERROR;
}
- if( pTo->isPrepareV2 && pTo->expmask ){
+ assert( (pTo->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || pTo->expmask==0 );
+ if( pTo->expmask ){
pTo->expired = 1;
}
- if( pFrom->isPrepareV2 && pFrom->expmask ){
+ assert( (pFrom->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || pFrom->expmask==0 );
+ if( pFrom->expmask ){
pFrom->expired = 1;
}
return sqlite3TransferBindings(pFromStmt, pToStmt);
@@ -79805,8 +81657,19 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
return 0;
}
#endif
- v = pVdbe->aCounter[op];
- if( resetFlag ) pVdbe->aCounter[op] = 0;
+ if( op==SQLITE_STMTSTATUS_MEMUSED ){
+ sqlite3 *db = pVdbe->db;
+ sqlite3_mutex_enter(db->mutex);
+ v = 0;
+ db->pnBytesFreed = (int*)&v;
+ sqlite3VdbeClearObject(db, pVdbe);
+ sqlite3DbFree(db, pVdbe);
+ db->pnBytesFreed = 0;
+ sqlite3_mutex_leave(db->mutex);
+ }else{
+ v = pVdbe->aCounter[op];
+ if( resetFlag ) pVdbe->aCounter[op] = 0;
+ }
return (int)v;
}
@@ -79854,10 +81717,9 @@ static UnpackedRecord *vdbeUnpackRecord(
int nKey,
const void *pKey
){
- char *dummy; /* Dummy argument for AllocUnpackedRecord() */
UnpackedRecord *pRet; /* Return value */
- pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo, 0, 0, &dummy);
+ pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pRet ){
memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1));
sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet);
@@ -79871,6 +81733,7 @@ static UnpackedRecord *vdbeUnpackRecord(
*/
SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
PreUpdate *p = db->pPreUpdate;
+ Mem *pMem;
int rc = SQLITE_OK;
/* Test that this call is being made from within an SQLITE_DELETE or
@@ -79879,6 +81742,9 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
rc = SQLITE_MISUSE_BKPT;
goto preupdate_old_out;
}
+ if( p->pPk ){
+ iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
+ }
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
goto preupdate_old_out;
@@ -79892,7 +81758,7 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
aRec = sqlite3DbMallocRaw(db, nRec);
if( !aRec ) goto preupdate_old_out;
- rc = sqlite3BtreeData(p->pCsr->uc.pCursor, 0, nRec, aRec);
+ rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
if( rc==SQLITE_OK ){
p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
if( !p->pUnpacked ) rc = SQLITE_NOMEM;
@@ -79904,17 +81770,14 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
p->aRecord = aRec;
}
- if( iIdx>=p->pUnpacked->nField ){
+ pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
+ if( iIdx==p->pTab->iPKey ){
+ sqlite3VdbeMemSetInt64(pMem, p->iKey1);
+ }else if( iIdx>=p->pUnpacked->nField ){
*ppValue = (sqlite3_value *)columnNullValue();
- }else{
- Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
- *ppValue = &p->pUnpacked->aMem[iIdx];
- if( iIdx==p->pTab->iPKey ){
- sqlite3VdbeMemSetInt64(pMem, p->iKey1);
- }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
- if( pMem->flags & MEM_Int ){
- sqlite3VdbeMemRealify(pMem);
- }
+ }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
+ if( pMem->flags & MEM_Int ){
+ sqlite3VdbeMemRealify(pMem);
}
}
@@ -79967,6 +81830,9 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
rc = SQLITE_MISUSE_BKPT;
goto preupdate_new_out;
}
+ if( p->pPk && p->op!=SQLITE_UPDATE ){
+ iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
+ }
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
goto preupdate_new_out;
@@ -79987,13 +81853,11 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
}
p->pNewUnpacked = pUnpack;
}
- if( iIdx>=pUnpack->nField ){
+ pMem = &pUnpack->aMem[iIdx];
+ if( iIdx==p->pTab->iPKey ){
+ sqlite3VdbeMemSetInt64(pMem, p->iKey2);
+ }else if( iIdx>=pUnpack->nField ){
pMem = (sqlite3_value *)columnNullValue();
- }else{
- pMem = &pUnpack->aMem[iIdx];
- if( iIdx==p->pTab->iPKey ){
- sqlite3VdbeMemSetInt64(pMem, p->iKey2);
- }
}
}else{
/* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required
@@ -80409,7 +82273,7 @@ SQLITE_API int sqlite3_found_count = 0;
** Test a register to see if it exceeds the current maximum blob size.
** If it does, record the new maximum blob size.
*/
-#if defined(SQLITE_TEST) && !defined(SQLITE_OMIT_BUILTIN_TEST)
+#if defined(SQLITE_TEST) && !defined(SQLITE_UNTESTABLE)
# define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P)
#else
# define UPDATE_MAX_BLOBSIZE(P)
@@ -80519,7 +82383,7 @@ static VdbeCursor *allocateCursor(
}
if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){
p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
- memset(pCx, 0, sizeof(VdbeCursor));
+ memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
pCx->eCurType = eCurType;
pCx->iDb = iDb;
pCx->nField = nField;
@@ -80701,9 +82565,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
}else{
c = 's';
}
-
- sqlite3_snprintf(100, zCsr, "%c", c);
- zCsr += sqlite3Strlen30(zCsr);
+ *(zCsr++) = c;
sqlite3_snprintf(100, zCsr, "%d[", pMem->n);
zCsr += sqlite3Strlen30(zCsr);
for(i=0; i<16 && in; i++){
@@ -80715,9 +82577,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
if( z<32 || z>126 ) *zCsr++ = '.';
else *zCsr++ = z;
}
-
- sqlite3_snprintf(100, zCsr, "]%s", encnames[pMem->enc]);
- zCsr += sqlite3Strlen30(zCsr);
+ *(zCsr++) = ']';
if( f & MEM_Zero ){
sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
zCsr += sqlite3Strlen30(zCsr);
@@ -80788,6 +82648,7 @@ static void registerTrace(int iReg, Mem *p){
printf("REG[%d] = ", iReg);
memTracePrint(p);
printf("\n");
+ sqlite3VdbeCheckMemInvariants(p);
}
#endif
@@ -80963,15 +82824,13 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
int iCompare = 0; /* Result of last comparison */
unsigned nVmStep = 0; /* Number of virtual machine steps */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */
+ unsigned nProgressLimit; /* Invoke xProgress() when nVmStep reaches this */
#endif
Mem *aMem = p->aMem; /* Copy of p->aMem */
Mem *pIn1 = 0; /* 1st input operand */
Mem *pIn2 = 0; /* 2nd input operand */
Mem *pIn3 = 0; /* 3rd input operand */
Mem *pOut = 0; /* Output operand */
- int *aPermute = 0; /* Permutation of columns for OP_Compare */
- i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */
#ifdef VDBE_PROFILE
u64 start; /* CPU clock count at start of opcode */
#endif
@@ -80986,7 +82845,6 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
}
assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
assert( p->bIsReader || p->readOnly!=0 );
- p->rc = SQLITE_OK;
p->iCurrentTime = 0;
assert( p->explain==0 );
p->pResultSet = 0;
@@ -80998,6 +82856,8 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
assert( 0 < db->nProgressOps );
nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
+ }else{
+ nProgressLimit = 0xffffffff;
}
#endif
#ifdef SQLITE_DEBUG
@@ -81157,7 +83017,7 @@ jump_to_p2_and_check_for_interrupt:
pOp = &aOp[pOp->p2 - 1];
/* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
- ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon
+ ** OP_VNext, or OP_SorterNext) all jump here upon
** completion. Check to see if sqlite3_interrupt() has been called
** or if the progress callback needs to be invoked.
**
@@ -81175,7 +83035,7 @@ check_for_interrupt:
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
- if( db->xProgress!=0 && nVmStep>=nProgressLimit ){
+ if( nVmStep>=nProgressLimit && db->xProgress!=0 ){
assert( db->nProgressOps!=0 );
nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
if( db->xProgress(db->pProgressArg) ){
@@ -81347,7 +83207,6 @@ case OP_Halt: {
p->nFrame--;
sqlite3VdbeSetChanges(db, p->nChange);
pcx = sqlite3VdbeFrameRestore(pFrame);
- lastRowid = db->lastRowid;
if( pOp->p2==OE_Ignore ){
/* Instruction pcx is the OP_Program that invoked the sub-program
** currently being halted. If the p2 instruction of this OP_Halt
@@ -81364,7 +83223,7 @@ case OP_Halt: {
p->rc = pOp->p1;
p->errorAction = (u8)pOp->p2;
p->pc = pcx;
- assert( pOp->p5>=0 && pOp->p5<=4 );
+ assert( pOp->p5<=4 );
if( p->rc ){
if( pOp->p5 ){
static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
@@ -81546,7 +83405,7 @@ case OP_Null: { /* out2 */
case OP_SoftNull: {
assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
pOut = &aMem[pOp->p1];
- pOut->flags = (pOut->flags|MEM_Null)&~MEM_Undefined;
+ pOut->flags = (pOut->flags&~(MEM_Undefined|MEM_AffMask))|MEM_Null;
break;
}
@@ -81577,12 +83436,12 @@ case OP_Variable: { /* out2 */
Mem *pVar; /* Value being transferred */
assert( pOp->p1>0 && pOp->p1<=p->nVar );
- assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] );
+ assert( pOp->p4.z==0 || pOp->p4.z==sqlite3VListNumToName(p->pVList,pOp->p1) );
pVar = &p->aVar[pOp->p1 - 1];
if( sqlite3VdbeMemTooBig(pVar) ){
goto too_big;
}
- pOut = out2Prerelease(p, pOp);
+ pOut = &aMem[pOp->p2];
sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
UPDATE_MAX_BLOBSIZE(pOut);
break;
@@ -81718,7 +83577,7 @@ case OP_ResultRow: {
/* Run the progress counter just before returning.
*/
if( db->xProgress!=0
- && nVmStep>=nProgressLimit
+ && nVmStep>=nProgressLimit
&& db->xProgress(db->pProgressArg)!=0
){
rc = SQLITE_INTERRUPT;
@@ -81889,7 +83748,6 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
type2 = numericType(pIn2);
pOut = &aMem[pOp->p3];
flags = pIn1->flags | pIn2->flags;
- if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
if( (type1 & type2 & MEM_Int)!=0 ){
iA = pIn1->u.i;
iB = pIn2->u.i;
@@ -81913,6 +83771,8 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
}
pOut->u.i = iB;
MemSetTypeFlag(pOut, MEM_Int);
+ }else if( (flags & MEM_Null)!=0 ){
+ goto arithmetic_result_is_null;
}else{
bIntint = 0;
fp_math:
@@ -81960,7 +83820,7 @@ arithmetic_result_is_null:
/* Opcode: CollSeq P1 * * P4
**
-** P4 is a pointer to a CollSeq struct. If the next call to a user function
+** P4 is a pointer to a CollSeq object. If the next call to a user function
** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will
** be returned. This is used by the built-in min(), max() and nullif()
** functions.
@@ -81981,119 +83841,6 @@ case OP_CollSeq: {
break;
}
-/* Opcode: Function0 P1 P2 P3 P4 P5
-** Synopsis: r[P3]=func(r[P2@P5])
-**
-** Invoke a user function (P4 is a pointer to a FuncDef object that
-** defines the function) with P5 arguments taken from register P2 and
-** successors. The result of the function is stored in register P3.
-** Register P3 must not be one of the function inputs.
-**
-** P1 is a 32-bit bitmask indicating whether or not each argument to the
-** function was determined to be constant at compile time. If the first
-** argument was constant then bit 0 of P1 is set. This is used to determine
-** whether meta data associated with a user function argument using the
-** sqlite3_set_auxdata() API may be safely retained until the next
-** invocation of this opcode.
-**
-** See also: Function, AggStep, AggFinal
-*/
-/* Opcode: Function P1 P2 P3 P4 P5
-** Synopsis: r[P3]=func(r[P2@P5])
-**
-** Invoke a user function (P4 is a pointer to an sqlite3_context object that
-** contains a pointer to the function to be run) with P5 arguments taken
-** from register P2 and successors. The result of the function is stored
-** in register P3. Register P3 must not be one of the function inputs.
-**
-** P1 is a 32-bit bitmask indicating whether or not each argument to the
-** function was determined to be constant at compile time. If the first
-** argument was constant then bit 0 of P1 is set. This is used to determine
-** whether meta data associated with a user function argument using the
-** sqlite3_set_auxdata() API may be safely retained until the next
-** invocation of this opcode.
-**
-** SQL functions are initially coded as OP_Function0 with P4 pointing
-** to a FuncDef object. But on first evaluation, the P4 operand is
-** automatically converted into an sqlite3_context object and the operation
-** changed to this OP_Function opcode. In this way, the initialization of
-** the sqlite3_context object occurs only once, rather than once for each
-** evaluation of the function.
-**
-** See also: Function0, AggStep, AggFinal
-*/
-case OP_Function0: {
- int n;
- sqlite3_context *pCtx;
-
- assert( pOp->p4type==P4_FUNCDEF );
- n = pOp->p5;
- assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
- assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
- assert( pOp->p3p2 || pOp->p3>=pOp->p2+n );
- pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
- if( pCtx==0 ) goto no_mem;
- pCtx->pOut = 0;
- pCtx->pFunc = pOp->p4.pFunc;
- pCtx->iOp = (int)(pOp - aOp);
- pCtx->pVdbe = p;
- pCtx->argc = n;
- pOp->p4type = P4_FUNCCTX;
- pOp->p4.pCtx = pCtx;
- pOp->opcode = OP_Function;
- /* Fall through into OP_Function */
-}
-case OP_Function: {
- int i;
- sqlite3_context *pCtx;
-
- assert( pOp->p4type==P4_FUNCCTX );
- pCtx = pOp->p4.pCtx;
-
- /* If this function is inside of a trigger, the register array in aMem[]
- ** might change from one evaluation to the next. The next block of code
- ** checks to see if the register array has changed, and if so it
- ** reinitializes the relavant parts of the sqlite3_context object */
- pOut = &aMem[pOp->p3];
- if( pCtx->pOut != pOut ){
- pCtx->pOut = pOut;
- for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
- }
-
- memAboutToChange(p, pCtx->pOut);
-#ifdef SQLITE_DEBUG
- for(i=0; iargc; i++){
- assert( memIsValid(pCtx->argv[i]) );
- REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
- }
-#endif
- MemSetTypeFlag(pCtx->pOut, MEM_Null);
- pCtx->fErrorOrAux = 0;
- db->lastRowid = lastRowid;
- (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
- lastRowid = db->lastRowid; /* Remember rowid changes made by xSFunc */
-
- /* If the function returned an error, throw an exception */
- if( pCtx->fErrorOrAux ){
- if( pCtx->isError ){
- sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut));
- rc = pCtx->isError;
- }
- sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
- if( rc ) goto abort_due_to_error;
- }
-
- /* Copy the result of the function into register P3 */
- if( pOut->flags & (MEM_Str|MEM_Blob) ){
- sqlite3VdbeChangeEncoding(pCtx->pOut, encoding);
- if( sqlite3VdbeMemTooBig(pCtx->pOut) ) goto too_big;
- }
-
- REGISTER_TRACE(pOp->p3, pCtx->pOut);
- UPDATE_MAX_BLOBSIZE(pCtx->pOut);
- break;
-}
-
/* Opcode: BitAnd P1 P2 P3 * *
** Synopsis: r[P3]=r[P1]&r[P2]
**
@@ -82243,11 +83990,11 @@ case OP_RealAffinity: { /* in1 */
** Force the value in register P1 to be the type defined by P2.
**
**
-** - TEXT
-**
- BLOB
-**
- NUMERIC
-**
- INTEGER
-**
- REAL
+**
- P2=='A' → BLOB
+**
- P2=='B' → TEXT
+**
- P2=='C' → NUMERIC
+**
- P2=='D' → INTEGER
+**
- P2=='E' → REAL
**
**
** A NULL value is not changed by this routine. It remains NULL.
@@ -82390,8 +84137,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
assert( (flags1 & MEM_Cleared)==0 );
assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
- if( (flags1&MEM_Null)!=0
- && (flags3&MEM_Null)!=0
+ if( (flags1&flags3&MEM_Null)!=0
&& (flags3&MEM_Cleared)==0
){
res = 0; /* Operands are equal */
@@ -82528,8 +84274,8 @@ case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
/* Opcode: Permutation * * * P4 *
**
-** Set the permutation used by the OP_Compare operator to be the array
-** of integers in P4.
+** Set the permutation used by the OP_Compare operator in the next
+** instruction. The permutation is stored in the P4 operand.
**
** The permutation is only valid until the next OP_Compare that has
** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
@@ -82541,7 +84287,8 @@ case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
case OP_Permutation: {
assert( pOp->p4type==P4_INTARRAY );
assert( pOp->p4.ai );
- aPermute = pOp->p4.ai + 1;
+ assert( pOp[1].opcode==OP_Compare );
+ assert( pOp[1].p5 & OPFLAG_PERMUTE );
break;
}
@@ -82574,15 +84321,24 @@ case OP_Compare: {
int idx;
CollSeq *pColl; /* Collating sequence to use on this term */
int bRev; /* True for DESCENDING sort order */
+ int *aPermute; /* The permutation */
- if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
+ if( (pOp->p5 & OPFLAG_PERMUTE)==0 ){
+ aPermute = 0;
+ }else{
+ assert( pOp>aOp );
+ assert( pOp[-1].opcode==OP_Permutation );
+ assert( pOp[-1].p4type==P4_INTARRAY );
+ aPermute = pOp[-1].p4.ai + 1;
+ assert( aPermute!=0 );
+ }
n = pOp->p3;
pKeyInfo = pOp->p4.pKeyInfo;
assert( n>0 );
assert( pKeyInfo!=0 );
p1 = pOp->p1;
p2 = pOp->p2;
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
if( aPermute ){
int k, mx = 0;
for(k=0; kmx ) mx = aPermute[k];
@@ -82608,7 +84364,6 @@ case OP_Compare: {
break;
}
}
- aPermute = 0;
break;
}
@@ -82721,19 +84476,39 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
/* Opcode: Once P1 P2 * * *
**
-** If the P1 value is equal to the P1 value on the OP_Init opcode at
-** instruction 0, then jump to P2. If the two P1 values differ, then
-** set the P1 value on this opcode to equal the P1 value on the OP_Init
-** and fall through.
+** Fall through to the next instruction the first time this opcode is
+** encountered on each invocation of the byte-code program. Jump to P2
+** on the second and all subsequent encounters during the same invocation.
+**
+** Top-level programs determine first invocation by comparing the P1
+** operand against the P1 operand on the OP_Init opcode at the beginning
+** of the program. If the P1 values differ, then fall through and make
+** the P1 of this opcode equal to the P1 of OP_Init. If P1 values are
+** the same then take the jump.
+**
+** For subprograms, there is a bitmask in the VdbeFrame that determines
+** whether or not the jump should be taken. The bitmask is necessary
+** because the self-altering code trick does not work for recursive
+** triggers.
*/
case OP_Once: { /* jump */
+ u32 iAddr; /* Address of this instruction */
assert( p->aOp[0].opcode==OP_Init );
- VdbeBranchTaken(p->aOp[0].p1==pOp->p1, 2);
- if( p->aOp[0].p1==pOp->p1 ){
- goto jump_to_p2;
+ if( p->pFrame ){
+ iAddr = (int)(pOp - p->aOp);
+ if( (p->pFrame->aOnce[iAddr/8] & (1<<(iAddr & 7)))!=0 ){
+ VdbeBranchTaken(1, 2);
+ goto jump_to_p2;
+ }
+ p->pFrame->aOnce[iAddr/8] |= 1<<(iAddr & 7);
}else{
- pOp->p1 = p->aOp[0].p1;
+ if( p->aOp[0].p1==pOp->p1 ){
+ VdbeBranchTaken(1, 2);
+ goto jump_to_p2;
+ }
}
+ VdbeBranchTaken(0, 2);
+ pOp->p1 = p->aOp[0].p1;
break;
}
@@ -82798,6 +84573,24 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
break;
}
+/* Opcode: IfNullRow P1 P2 P3 * *
+** Synopsis: if P1.nullRow then r[P3]=NULL, goto P2
+**
+** Check the cursor P1 to see if it is currently pointing at a NULL row.
+** If it is, then set register P3 to NULL and jump immediately to P2.
+** If P1 is not on a NULL row, then fall through without making any
+** changes.
+*/
+case OP_IfNullRow: { /* jump */
+ assert( pOp->p1>=0 && pOp->p1nCursor );
+ assert( p->apCsr[pOp->p1]!=0 );
+ if( p->apCsr[pOp->p1]->nullRow ){
+ sqlite3VdbeMemSetNull(aMem + pOp->p3);
+ goto jump_to_p2;
+ }
+ break;
+}
+
/* Opcode: Column P1 P2 P3 P4 P5
** Synopsis: r[P3]=PX
**
@@ -82809,7 +84602,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
**
** The value extracted is stored in register P3.
**
-** If the column contains fewer than P2 fields, then extract a NULL. Or,
+** If the record contains fewer than P2 fields, then extract a NULL. Or,
** if the P4 argument is a P4_MEM use the value of the P4 argument as
** the result.
**
@@ -82818,7 +84611,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
** The first OP_Column against a pseudo-table after the value of the content
** register has changed should have this bit set.
**
-** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 when
+** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then
** the result is guaranteed to only be used as the argument of a length()
** or typeof() function, respectively. The loading of large blobs can be
** skipped for length() and all content loading can be skipped for typeof().
@@ -82844,7 +84637,9 @@ case OP_Column: {
pC = p->apCsr[pOp->p1];
p2 = pOp->p2;
- /* If the cursor cache is stale, bring it up-to-date */
+ /* If the cursor cache is stale (meaning it is not currently point at
+ ** the correct row) then bring it up-to-date by doing the necessary
+ ** B-Tree seek. */
rc = sqlite3VdbeCursorMoveto(&pC, &p2);
if( rc ) goto abort_due_to_error;
@@ -82858,7 +84653,6 @@ case OP_Column: {
assert( pC->eCurType!=CURTYPE_VTAB );
assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
assert( pC->eCurType!=CURTYPE_SORTER );
- pCrsr = pC->uc.pCursor;
if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/
if( pC->nullRow ){
@@ -82874,6 +84668,7 @@ case OP_Column: {
goto op_column_out;
}
}else{
+ pCrsr = pC->uc.pCursor;
assert( pC->eCurType==CURTYPE_BTREE );
assert( pCrsr );
assert( sqlite3BtreeCursorIsValid(pCrsr) );
@@ -82937,7 +84732,7 @@ case OP_Column: {
/* Make sure zData points to enough of the record to cover the header. */
if( pC->aRow==0 ){
memset(&sMem, 0, sizeof(sMem));
- rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], !pC->isTable, &sMem);
+ rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, 0, aOffset[0], &sMem);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
zData = (u8*)sMem.z;
}else{
@@ -83046,12 +84841,16 @@ case OP_Column: {
** 2. the length(X) function if X is a blob, and
** 3. if the content length is zero.
** So we might as well use bogus content rather than reading
- ** content from disk. */
- static u8 aZero[8]; /* This is the bogus content */
+ ** content from disk.
+ **
+ ** Although sqlite3VdbeSerialGet() may read at most 8 bytes from the
+ ** buffer passed to it, debugging function VdbeMemPrettyPrint() may
+ ** read up to 16. So 16 bytes of bogus content is supplied.
+ */
+ static u8 aZero[16]; /* This is the bogus content */
sqlite3VdbeSerialGet(aZero, t, pDest);
}else{
- rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable,
- pDest);
+ rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest);
pDest->flags &= ~MEM_Ephem;
@@ -83069,24 +84868,24 @@ op_column_out:
**
** Apply affinities to a range of P2 registers starting with P1.
**
-** P4 is a string that is P2 characters long. The nth character of the
-** string indicates the column affinity that should be used for the nth
+** P4 is a string that is P2 characters long. The N-th character of the
+** string indicates the column affinity that should be used for the N-th
** memory cell in the range.
*/
case OP_Affinity: {
const char *zAffinity; /* The affinity to be applied */
- char cAff; /* A single character of affinity */
zAffinity = pOp->p4.z;
assert( zAffinity!=0 );
+ assert( pOp->p2>0 );
assert( zAffinity[pOp->p2]==0 );
pIn1 = &aMem[pOp->p1];
- while( (cAff = *(zAffinity++))!=0 ){
+ do{
assert( pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)] );
assert( memIsValid(pIn1) );
- applyAffinity(pIn1, cAff, encoding);
+ applyAffinity(pIn1, *(zAffinity++), encoding);
pIn1++;
- }
+ }while( zAffinity[0] );
break;
}
@@ -83097,8 +84896,8 @@ case OP_Affinity: {
** use as a data record in a database table or as a key
** in an index. The OP_Column opcode can decode the record later.
**
-** P4 may be a string that is P2 characters long. The nth character of the
-** string indicates the column affinity that should be used for the nth
+** P4 may be a string that is P2 characters long. The N-th character of the
+** string indicates the column affinity that should be used for the N-th
** field of the index key.
**
** The mapping from character to affinity is given by the SQLITE_AFF_
@@ -83166,6 +84965,20 @@ case OP_MakeRecord: {
}while( zAffinity[0] );
}
+#ifdef SQLITE_ENABLE_NULL_TRIM
+ /* NULLs can be safely trimmed from the end of the record, as long as
+ ** as the schema format is 2 or more and none of the omitted columns
+ ** have a non-NULL default value. Also, the record must be left with
+ ** at least one field. If P5>0 then it will be one more than the
+ ** index of the right-most column with a non-NULL default value */
+ if( pOp->p5 ){
+ while( (pLast->flags & MEM_Null)!=0 && nField>pOp->p5 ){
+ pLast--;
+ nField--;
+ }
+ }
+#endif
+
/* Loop through the elements that will make up the record to figure
** out how much space is required for the new record.
*/
@@ -83243,7 +85056,6 @@ case OP_MakeRecord: {
pOut->u.nZero = nZero;
pOut->flags |= MEM_Zero;
}
- pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */
REGISTER_TRACE(pOp->p3, pOut);
UPDATE_MAX_BLOBSIZE(pOut);
break;
@@ -83873,6 +85685,37 @@ open_cursor_set_hints:
break;
}
+/* Opcode: OpenDup P1 P2 * * *
+**
+** Open a new cursor P1 that points to the same ephemeral table as
+** cursor P2. The P2 cursor must have been opened by a prior OP_OpenEphemeral
+** opcode. Only ephemeral cursors may be duplicated.
+**
+** Duplicate ephemeral cursors are used for self-joins of materialized views.
+*/
+case OP_OpenDup: {
+ VdbeCursor *pOrig; /* The original cursor to be duplicated */
+ VdbeCursor *pCx; /* The new cursor */
+
+ pOrig = p->apCsr[pOp->p2];
+ assert( pOrig->pBtx!=0 ); /* Only ephemeral cursors can be duplicated */
+
+ pCx = allocateCursor(p, pOp->p1, pOrig->nField, -1, CURTYPE_BTREE);
+ if( pCx==0 ) goto no_mem;
+ pCx->nullRow = 1;
+ pCx->isEphemeral = 1;
+ pCx->pKeyInfo = pOrig->pKeyInfo;
+ pCx->isTable = pOrig->isTable;
+ rc = sqlite3BtreeCursor(pOrig->pBtx, MASTER_ROOT, BTREE_WRCSR,
+ pCx->pKeyInfo, pCx->uc.pCursor);
+ /* The sqlite3BtreeCursor() routine can only fail for the first cursor
+ ** opened for a database. Since there is already an open cursor when this
+ ** opcode is run, the sqlite3BtreeCursor() cannot fail */
+ assert( rc==SQLITE_OK );
+ break;
+}
+
+
/* Opcode: OpenEphemeral P1 P2 * P4 P5
** Synopsis: nColumn=P2
**
@@ -83916,10 +85759,10 @@ case OP_OpenEphemeral: {
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->isEphemeral = 1;
- rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt,
+ rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx,
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
+ rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1);
}
if( rc==SQLITE_OK ){
/* If a transient index is required, create it by calling
@@ -83927,21 +85770,20 @@ case OP_OpenEphemeral: {
** opening it. If a transient table is required, just use the
** automatically created table with root-page 1 (an BLOB_INTKEY table).
*/
- if( (pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
+ if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
int pgno;
assert( pOp->p4type==P4_KEYINFO );
- rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
+ rc = sqlite3BtreeCreateTable(pCx->pBtx, &pgno, BTREE_BLOBKEY | pOp->p5);
if( rc==SQLITE_OK ){
assert( pgno==MASTER_ROOT+1 );
assert( pKeyInfo->db==db );
assert( pKeyInfo->enc==ENC(db) );
- pCx->pKeyInfo = pKeyInfo;
- rc = sqlite3BtreeCursor(pCx->pBt, pgno, BTREE_WRCSR,
+ rc = sqlite3BtreeCursor(pCx->pBtx, pgno, BTREE_WRCSR,
pKeyInfo, pCx->uc.pCursor);
}
pCx->isTable = 0;
}else{
- rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, BTREE_WRCSR,
+ rc = sqlite3BtreeCursor(pCx->pBtx, MASTER_ROOT, BTREE_WRCSR,
0, pCx->uc.pCursor);
pCx->isTable = 1;
}
@@ -84173,7 +86015,8 @@ case OP_SeekGT: { /* jump, in3 */
if( pC->isTable ){
/* The BTREE_SEEK_EQ flag is only set on index cursors */
- assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0 );
+ assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0
+ || CORRUPT_DB );
/* The input value in P3 might be of any type: integer, real, string,
** blob, or NULL. But it needs to be an integer before we can do
@@ -84278,8 +86121,15 @@ case OP_SeekGT: { /* jump, in3 */
if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT );
if( res<0 || (res==0 && oc==OP_SeekGT) ){
res = 0;
- rc = sqlite3BtreeNext(pC->uc.pCursor, &res);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_DONE ){
+ rc = SQLITE_OK;
+ res = 1;
+ }else{
+ goto abort_due_to_error;
+ }
+ }
}else{
res = 0;
}
@@ -84287,8 +86137,15 @@ case OP_SeekGT: { /* jump, in3 */
assert( oc==OP_SeekLT || oc==OP_SeekLE );
if( res>0 || (res==0 && oc==OP_SeekLT) ){
res = 0;
- rc = sqlite3BtreePrevious(pC->uc.pCursor, &res);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ rc = sqlite3BtreePrevious(pC->uc.pCursor, 0);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_DONE ){
+ rc = SQLITE_OK;
+ res = 1;
+ }else{
+ goto abort_due_to_error;
+ }
+ }
}else{
/* res might be negative because the table is empty. Check to
** see if this is the case.
@@ -84375,10 +86232,9 @@ case OP_Found: { /* jump, in3 */
int ii;
VdbeCursor *pC;
int res;
- char *pFree;
+ UnpackedRecord *pFree;
UnpackedRecord *pIdxKey;
UnpackedRecord r;
- char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7];
#ifdef SQLITE_TEST
if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++;
@@ -84395,7 +86251,6 @@ case OP_Found: { /* jump, in3 */
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
assert( pC->isTable==0 );
- pFree = 0;
if( pOp->p4.i>0 ){
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p4.i;
@@ -84408,13 +86263,14 @@ case OP_Found: { /* jump, in3 */
}
#endif
pIdxKey = &r;
+ pFree = 0;
}else{
- pIdxKey = sqlite3VdbeAllocUnpackedRecord(
- pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree
- );
- if( pIdxKey==0 ) goto no_mem;
assert( pIn3->flags & MEM_Blob );
- (void)ExpandBlob(pIn3);
+ rc = ExpandBlob(pIn3);
+ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
+ if( rc ) goto no_mem;
+ pFree = pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
+ if( pIdxKey==0 ) goto no_mem;
sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
}
pIdxKey->default_rc = 0;
@@ -84431,7 +86287,7 @@ case OP_Found: { /* jump, in3 */
}
}
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res);
- sqlite3DbFree(db, pFree);
+ if( pFree ) sqlite3DbFreeNN(db, pFree);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
@@ -84658,7 +86514,7 @@ case OP_NewRowid: { /* out2 */
sqlite3VdbeMemIntegerify(pMem);
assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
- rc = SQLITE_FULL; /* IMP: R-12275-61338 */
+ rc = SQLITE_FULL; /* IMP: R-17817-00630 */
goto abort_due_to_error;
}
if( vu.i+1 ){
@@ -84710,15 +86566,10 @@ case OP_NewRowid: { /* out2 */
** then rowid is stored for subsequent return by the
** sqlite3_last_insert_rowid() function (otherwise it is unmodified).
**
-** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of
-** the last seek operation (OP_NotExists or OP_SeekRowid) was a success,
-** then this
-** operation will not attempt to find the appropriate row before doing
-** the insert but will instead overwrite the row that the cursor is
-** currently pointing to. Presumably, the prior OP_NotExists or
-** OP_SeekRowid opcode
-** has already positioned the cursor correctly. This is an optimization
-** that boosts performance by avoiding redundant seeks.
+** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might
+** run faster by avoiding an unnecessary seek on cursor P1. However,
+** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior
+** seeks on the cursor or if the most recent seek used a key equal to P3.
**
** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an
** UPDATE operation. Otherwise (if the flag is clear) then this opcode
@@ -84763,7 +86614,7 @@ case OP_InsertInt: {
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
- assert( pC->isTable );
+ assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
REGISTER_TRACE(pOp->p2, pData);
@@ -84779,14 +86630,13 @@ case OP_InsertInt: {
}
if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
- assert( pC->isTable );
assert( pC->iDb>=0 );
zDb = db->aDb[pC->iDb].zDbSName;
pTab = pOp->p4.pTab;
- assert( HasRowid(pTab) );
+ assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
}else{
- pTab = 0; /* Not needed. Silence a comiler warning. */
+ pTab = 0; /* Not needed. Silence a compiler warning. */
zDb = 0; /* Not needed. Silence a compiler warning. */
}
@@ -84798,10 +86648,11 @@ case OP_InsertInt: {
){
sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey, pOp->p2);
}
+ if( pOp->p5 & OPFLAG_ISNOOP ) break;
#endif
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
- if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = x.nKey;
+ if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey;
if( pData->flags & MEM_Null ){
x.pData = 0;
x.nData = 0;
@@ -84818,7 +86669,7 @@ case OP_InsertInt: {
}
x.pKey = 0;
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
- (pOp->p5 & OPFLAG_APPEND)!=0, seekResult
+ (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), seekResult
);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
@@ -84910,8 +86761,11 @@ case OP_Delete: {
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/* Invoke the pre-update-hook if required. */
- if( db->xPreUpdateCallback && pOp->p4.pTab && HasRowid(pTab) ){
- assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) );
+ if( db->xPreUpdateCallback && pOp->p4.pTab ){
+ assert( !(opflags & OPFLAG_ISUPDATE)
+ || HasRowid(pTab)==0
+ || (aMem[pOp->p3].flags & MEM_Int)
+ );
sqlite3VdbePreUpdateHook(p, pC,
(opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE,
zDb, pTab, pC->movetoTarget,
@@ -84942,6 +86796,7 @@ case OP_Delete: {
rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5);
pC->cacheStatus = CACHE_STALE;
+ pC->seekResult = 0;
if( rc ) goto abort_due_to_error;
/* Invoke the update-hook if required. */
@@ -85028,50 +86883,51 @@ case OP_SorterData: {
break;
}
-/* Opcode: RowData P1 P2 * * *
+/* Opcode: RowData P1 P2 P3 * *
** Synopsis: r[P2]=data
**
-** Write into register P2 the complete row data for cursor P1.
+** Write into register P2 the complete row content for the row at
+** which cursor P1 is currently pointing.
** There is no interpretation of the data.
** It is just copied onto the P2 register exactly as
** it is found in the database file.
**
-** If the P1 cursor must be pointing to a valid row (not a NULL row)
-** of a real table, not a pseudo-table.
-*/
-/* Opcode: RowKey P1 P2 * * *
-** Synopsis: r[P2]=key
-**
-** Write into register P2 the complete row key for cursor P1.
-** There is no interpretation of the data.
-** The key is copied onto the P2 register exactly as
-** it is found in the database file.
+** If cursor P1 is an index, then the content is the key of the row.
+** If cursor P2 is a table, then the content extracted is the data.
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
** of a real table, not a pseudo-table.
+**
+** If P3!=0 then this opcode is allowed to make an ephermeral pointer
+** into the database page. That means that the content of the output
+** register will be invalidated as soon as the cursor moves - including
+** moves caused by other cursors that "save" the the current cursors
+** position in order that they can write to the same table. If P3==0
+** then a copy of the data is made into memory. P3!=0 is faster, but
+** P3==0 is safer.
+**
+** If P3!=0 then the content of the P2 register is unsuitable for use
+** in OP_Result and any OP_Result will invalidate the P2 register content.
+** The P2 register content is invalidated by opcodes like OP_Function or
+** by any use of another cursor pointing to the same table.
*/
-case OP_RowKey:
case OP_RowData: {
VdbeCursor *pC;
BtCursor *pCrsr;
u32 n;
- pOut = &aMem[pOp->p2];
- memAboutToChange(p, pOut);
+ pOut = out2Prerelease(p, pOp);
- /* Note that RowKey and RowData are really exactly the same instruction */
assert( pOp->p1>=0 && pOp->p1nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( isSorter(pC)==0 );
- assert( pC->isTable || pOp->opcode!=OP_RowData );
- assert( pC->isTable==0 || pOp->opcode==OP_RowData );
assert( pC->nullRow==0 );
assert( pC->uc.pCursor!=0 );
pCrsr = pC->uc.pCursor;
- /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
+ /* The OP_RowData opcodes always follow OP_NotExists or
** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions
** that might invalidate the cursor.
** If this where not the case, on of the following assert()s
@@ -85091,18 +86947,9 @@ case OP_RowData: {
goto too_big;
}
testcase( n==0 );
- if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){
- goto no_mem;
- }
- pOut->n = n;
- MemSetTypeFlag(pOut, MEM_Blob);
- if( pC->isTable==0 ){
- rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z);
- }else{
- rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z);
- }
+ rc = sqlite3VdbeMemFromBtree(pCrsr, 0, n, pOut);
if( rc ) goto abort_due_to_error;
- pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
+ if( !pOp->p3 ) Deephemeralize(pOut);
UPDATE_MAX_BLOBSIZE(pOut);
REGISTER_TRACE(pOp->p2, pOut);
break;
@@ -85191,6 +87038,13 @@ case OP_NullRow: {
** This opcode leaves the cursor configured to move in reverse order,
** from the end toward the beginning. In other words, the cursor is
** configured to use Prev, not Next.
+**
+** If P3 is -1, then the cursor is positioned at the end of the btree
+** for the purpose of appending a new entry onto the btree. In that
+** case P2 must be 0. It is assumed that the cursor is used only for
+** appending and so if the cursor is valid, then the cursor must already
+** be pointing at the end of the btree and so no changes are made to
+** the cursor.
*/
case OP_Last: { /* jump */
VdbeCursor *pC;
@@ -85204,23 +87058,63 @@ case OP_Last: { /* jump */
pCrsr = pC->uc.pCursor;
res = 0;
assert( pCrsr!=0 );
- rc = sqlite3BtreeLast(pCrsr, &res);
- pC->nullRow = (u8)res;
- pC->deferredMoveto = 0;
- pC->cacheStatus = CACHE_STALE;
pC->seekResult = pOp->p3;
#ifdef SQLITE_DEBUG
pC->seekOp = OP_Last;
#endif
- if( rc ) goto abort_due_to_error;
- if( pOp->p2>0 ){
- VdbeBranchTaken(res!=0,2);
- if( res ) goto jump_to_p2;
+ if( pOp->p3==0 || !sqlite3BtreeCursorIsValidNN(pCrsr) ){
+ rc = sqlite3BtreeLast(pCrsr, &res);
+ pC->nullRow = (u8)res;
+ pC->deferredMoveto = 0;
+ pC->cacheStatus = CACHE_STALE;
+ if( rc ) goto abort_due_to_error;
+ if( pOp->p2>0 ){
+ VdbeBranchTaken(res!=0,2);
+ if( res ) goto jump_to_p2;
+ }
+ }else{
+ assert( pOp->p2==0 );
}
break;
}
+/* Opcode: IfSmaller P1 P2 P3 * *
+**
+** Estimate the number of rows in the table P1. Jump to P2 if that
+** estimate is less than approximately 2**(0.1*P3).
+*/
+case OP_IfSmaller: { /* jump */
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int res;
+ i64 sz;
+ assert( pOp->p1>=0 && pOp->p1nCursor );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ pCrsr = pC->uc.pCursor;
+ assert( pCrsr );
+ rc = sqlite3BtreeFirst(pCrsr, &res);
+ if( rc ) goto abort_due_to_error;
+ if( res==0 ){
+ sz = sqlite3BtreeRowCountEst(pCrsr);
+ if( ALWAYS(sz>=0) && sqlite3LogEst((u64)sz)p3 ) res = 1;
+ }
+ VdbeBranchTaken(res!=0,2);
+ if( res ) goto jump_to_p2;
+ break;
+}
+
+
+/* Opcode: SorterSort P1 P2 * * *
+**
+** After all records have been inserted into the Sorter object
+** identified by P1, invoke this opcode to actually do the sorting.
+** Jump to P2 if there are no records to be sorted.
+**
+** This opcode is an alias for OP_Sort and OP_Rewind that is used
+** for Sorter objects.
+*/
/* Opcode: Sort P1 P2 * * *
**
** This opcode does exactly the same thing as OP_Rewind except that
@@ -85348,14 +87242,19 @@ case OP_Rewind: { /* jump */
** This opcode works just like Prev except that if cursor P1 is not
** open it behaves a no-op.
*/
+/* Opcode: SorterNext P1 P2 * * P5
+**
+** This opcode works just like OP_Next except that P1 must be a
+** sorter object for which the OP_SorterSort opcode has been
+** invoked. This opcode advances the cursor to the next sorted
+** record, or jumps to P2 if there are no more sorted records.
+*/
case OP_SorterNext: { /* jump */
VdbeCursor *pC;
- int res;
pC = p->apCsr[pOp->p1];
assert( isSorter(pC) );
- res = 0;
- rc = sqlite3VdbeSorterNext(db, pC, &res);
+ rc = sqlite3VdbeSorterNext(db, pC);
goto next_tail;
case OP_PrevIfOpen: /* jump */
case OP_NextIfOpen: /* jump */
@@ -85366,12 +87265,9 @@ case OP_Next: /* jump */
assert( pOp->p1>=0 && pOp->p1nCursor );
assert( pOp->p5aCounter) );
pC = p->apCsr[pOp->p1];
- res = pOp->p3;
assert( pC!=0 );
assert( pC->deferredMoveto==0 );
assert( pC->eCurType==CURTYPE_BTREE );
- assert( res==0 || (res==1 && pC->isTable==0) );
- testcase( res==1 );
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
@@ -85386,45 +87282,59 @@ case OP_Next: /* jump */
|| pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
|| pC->seekOp==OP_Last );
- rc = pOp->p4.xAdvance(pC->uc.pCursor, &res);
+ rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3);
next_tail:
pC->cacheStatus = CACHE_STALE;
- VdbeBranchTaken(res==0,2);
- if( rc ) goto abort_due_to_error;
- if( res==0 ){
+ VdbeBranchTaken(rc==SQLITE_OK,2);
+ if( rc==SQLITE_OK ){
pC->nullRow = 0;
p->aCounter[pOp->p5]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
goto jump_to_p2_and_check_for_interrupt;
- }else{
- pC->nullRow = 1;
}
+ if( rc!=SQLITE_DONE ) goto abort_due_to_error;
+ rc = SQLITE_OK;
+ pC->nullRow = 1;
goto check_for_interrupt;
}
-/* Opcode: IdxInsert P1 P2 P3 * P5
+/* Opcode: IdxInsert P1 P2 P3 P4 P5
** Synopsis: key=r[P2]
**
** Register P2 holds an SQL index key made using the
** MakeRecord instructions. This opcode writes that key
** into the index P1. Data for the entry is nil.
**
-** P3 is a flag that provides a hint to the b-tree layer that this
-** insert is likely to be an append.
+** If P4 is not zero, then it is the number of values in the unpacked
+** key of reg(P2). In that case, P3 is the index of the first register
+** for the unpacked key. The availability of the unpacked key can sometimes
+** be an optimization.
+**
+** If P5 has the OPFLAG_APPEND bit set, that is a hint to the b-tree layer
+** that this insert is likely to be an append.
**
** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is
** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear,
** then the change counter is unchanged.
**
-** If P5 has the OPFLAG_USESEEKRESULT bit set, then the cursor must have
-** just done a seek to the spot where the new entry is to be inserted.
-** This flag avoids doing an extra seek.
+** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might
+** run faster by avoiding an unnecessary seek on cursor P1. However,
+** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior
+** seeks on the cursor or if the most recent seek used a key equivalent
+** to P2.
**
** This instruction only works for indices. The equivalent instruction
** for tables is OP_Insert.
*/
+/* Opcode: SorterInsert P1 P2 * * *
+** Synopsis: key=r[P2]
+**
+** Register P2 holds an SQL index key made using the
+** MakeRecord instructions. This opcode writes that key
+** into the sorter P1. Data for the entry is nil.
+*/
case OP_SorterInsert: /* in2 */
case OP_IdxInsert: { /* in2 */
VdbeCursor *pC;
@@ -85446,7 +87356,10 @@ case OP_IdxInsert: { /* in2 */
}else{
x.nKey = pIn2->n;
x.pKey = pIn2->z;
- rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, pOp->p3,
+ x.aMem = aMem + pOp->p3;
+ x.nMem = (u16)pOp->p4.i;
+ rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
+ (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)),
((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
);
assert( pC->deferredMoveto==0 );
@@ -85490,11 +87403,12 @@ case OP_IdxDelete: {
}
assert( pC->deferredMoveto==0 );
pC->cacheStatus = CACHE_STALE;
+ pC->seekResult = 0;
break;
}
-/* Opcode: Seek P1 * P3 P4 *
-** Synopsis: Move P3 to P1.rowid
+/* Opcode: DeferredSeek P1 * P3 P4 *
+** Synopsis: Move P3 to P1.rowid if needed
**
** P1 is an open index cursor and P3 is a cursor on the corresponding
** table. This opcode does a deferred seek of the P3 table cursor
@@ -85521,11 +87435,11 @@ case OP_IdxDelete: {
**
** See also: Rowid, MakeRecord.
*/
-case OP_Seek:
-case OP_IdxRowid: { /* out2 */
- VdbeCursor *pC; /* The P1 index cursor */
- VdbeCursor *pTabCur; /* The P2 table cursor (OP_Seek only) */
- i64 rowid; /* Rowid that P1 current points to */
+case OP_DeferredSeek:
+case OP_IdxRowid: { /* out2 */
+ VdbeCursor *pC; /* The P1 index cursor */
+ VdbeCursor *pTabCur; /* The P2 table cursor (OP_DeferredSeek only) */
+ i64 rowid; /* Rowid that P1 current points to */
assert( pOp->p1>=0 && pOp->p1nCursor );
pC = p->apCsr[pOp->p1];
@@ -85551,7 +87465,7 @@ case OP_IdxRowid: { /* out2 */
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- if( pOp->opcode==OP_Seek ){
+ if( pOp->opcode==OP_DeferredSeek ){
assert( pOp->p3>=0 && pOp->p3nCursor );
pTabCur = p->apCsr[pOp->p3];
assert( pTabCur!=0 );
@@ -85567,7 +87481,6 @@ case OP_IdxRowid: { /* out2 */
}else{
pOut = out2Prerelease(p, pOp);
pOut->u.i = rowid;
- pOut->flags = MEM_Int;
}
}else{
assert( pOp->opcode==OP_IdxRowid );
@@ -85679,10 +87592,17 @@ case OP_IdxGE: { /* jump */
** might be moved into the newly deleted root page in order to keep all
** root pages contiguous at the beginning of the database. The former
** value of the root page that moved - its value before the move occurred -
-** is stored in register P2. If no page
-** movement was required (because the table being dropped was already
-** the last one in the database) then a zero is stored in register P2.
-** If AUTOVACUUM is disabled then a zero is stored in register P2.
+** is stored in register P2. If no page movement was required (because the
+** table being dropped was already the last one in the database) then a
+** zero is stored in register P2. If AUTOVACUUM is disabled then a zero
+** is stored in register P2.
+**
+** This opcode throws an error if there are any active reader VMs when
+** it is invoked. This is done to avoid the difficulty associated with
+** updating existing cursors when a root page is moved in an AUTOVACUUM
+** database. This error is thrown even if the database is not an AUTOVACUUM
+** db in order to avoid introducing an incompatibility between autovacuum
+** and non-autovacuum modes.
**
** See also: Clear
*/
@@ -85831,6 +87751,18 @@ case OP_CreateTable: { /* out2 */
break;
}
+/* Opcode: SqlExec * * * P4 *
+**
+** Run the SQL statement or statements specified in the P4 string.
+*/
+case OP_SqlExec: {
+ db->nSqlExec++;
+ rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0);
+ db->nSqlExec--;
+ if( rc ) goto abort_due_to_error;
+ break;
+}
+
/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
@@ -85859,7 +87791,7 @@ case OP_ParseSchema: {
assert( iDb>=0 && iDbnDb );
assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
/* Used to be a conditional */ {
- zMaster = SCHEMA_TABLE(iDb);
+ zMaster = MASTER_NAME;
initData.db = db;
initData.iDb = pOp->p1;
initData.pzErrMsg = &p->zErrMsg;
@@ -85875,7 +87807,7 @@ case OP_ParseSchema: {
assert( !db->mallocFailed );
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
if( rc==SQLITE_OK ) rc = initData.rc;
- sqlite3DbFree(db, zSql);
+ sqlite3DbFreeNN(db, zSql);
db->init.busy = 0;
}
}
@@ -85951,7 +87883,7 @@ case OP_DropTrigger: {
** register P1 the text of an error message describing any problems.
** If no problems are found, store a NULL in register P1.
**
-** The register P3 contains the maximum number of allowed errors.
+** The register P3 contains one less than the maximum number of allowed errors.
** At most reg(P3) errors will be reported.
** In other words, the analysis stops as soon as reg(P1) errors are
** seen. Reg(P1) is updated with the number of errors remaining.
@@ -85984,14 +87916,14 @@ case OP_IntegrityCk: {
assert( pOp->p5nDb );
assert( DbMaskTest(p->btreeMask, pOp->p5) );
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
- (int)pnErr->u.i, &nErr);
- pnErr->u.i -= nErr;
+ (int)pnErr->u.i+1, &nErr);
sqlite3VdbeMemSetNull(pIn1);
if( nErr==0 ){
assert( z==0 );
}else if( z==0 ){
goto no_mem;
}else{
+ pnErr->u.i -= nErr-1;
sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
}
UPDATE_MAX_BLOBSIZE(pIn1);
@@ -86003,7 +87935,7 @@ case OP_IntegrityCk: {
/* Opcode: RowSetAdd P1 P2 * * *
** Synopsis: rowset(P1)=r[P2]
**
-** Insert the integer value held by register P2 into a boolean index
+** Insert the integer value held by register P2 into a RowSet object
** held in register P1.
**
** An assertion fails if P2 is not an integer.
@@ -86023,8 +87955,9 @@ case OP_RowSetAdd: { /* in1, in2 */
/* Opcode: RowSetRead P1 P2 P3 * *
** Synopsis: r[P3]=rowset(P1)
**
-** Extract the smallest value from boolean index P1 and put that value into
-** register P3. Or, if boolean index P1 is initially empty, leave P3
+** Extract the smallest value from the RowSet object in P1
+** and put that value into register P3.
+** Or, if RowSet object P1 is initially empty, leave P3
** unchanged and jump to instruction P2.
*/
case OP_RowSetRead: { /* jump, in1, out3 */
@@ -86055,15 +87988,14 @@ case OP_RowSetRead: { /* jump, in1, out3 */
** integer in P3 into the RowSet and continue on to the
** next opcode.
**
-** The RowSet object is optimized for the case where successive sets
-** of integers, where each set contains no duplicates. Each set
-** of values is identified by a unique P4 value. The first set
-** must have P4==0, the final set P4=-1. P4 must be either -1 or
-** non-negative. For non-negative values of P4 only the lower 4
-** bits are significant.
+** The RowSet object is optimized for the case where sets of integers
+** are inserted in distinct phases, which each set contains no duplicates.
+** Each set is identified by a unique P4 value. The first set
+** must have P4==0, the final set must have P4==-1, and for all other sets
+** must have P4>0.
**
** This allows optimizations: (a) when P4==0 there is no need to test
-** the rowset object for P3, as it is guaranteed not to contain it,
+** the RowSet object for P3, as it is guaranteed not to contain it,
** (b) when P4==-1 there is no need to insert the value, as it will
** never be tested for, and (c) when a value that is part of set X is
** inserted, there is no need to search to see if the same value was
@@ -86170,7 +88102,8 @@ case OP_Program: { /* jump */
if( pProgram->nCsr==0 ) nMem++;
nByte = ROUND8(sizeof(VdbeFrame))
+ nMem * sizeof(Mem)
- + pProgram->nCsr * sizeof(VdbeCursor *);
+ + pProgram->nCsr * sizeof(VdbeCursor*)
+ + (pProgram->nOp + 7)/8;
pFrame = sqlite3DbMallocZero(db, nByte);
if( !pFrame ){
goto no_mem;
@@ -86209,7 +88142,7 @@ case OP_Program: { /* jump */
p->nFrame++;
pFrame->pParent = p->pFrame;
- pFrame->lastRowid = lastRowid;
+ pFrame->lastRowid = db->lastRowid;
pFrame->nChange = p->nChange;
pFrame->nDbChange = p->db->nChange;
assert( pFrame->pAuxData==0 );
@@ -86221,6 +88154,8 @@ case OP_Program: { /* jump */
p->nMem = pFrame->nChildMem;
p->nCursor = (u16)pFrame->nChildCsr;
p->apCsr = (VdbeCursor **)&aMem[p->nMem];
+ pFrame->aOnce = (u8*)&p->apCsr[pProgram->nCsr];
+ memset(pFrame->aOnce, 0, (pProgram->nOp + 7)/8);
p->aOp = aOp = pProgram->aOp;
p->nOp = pProgram->nOp;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
@@ -86370,29 +88305,42 @@ case OP_IfPos: { /* jump, in1 */
** Otherwise, r[P2] is set to the sum of r[P1] and r[P3].
*/
case OP_OffsetLimit: { /* in1, out2, in3 */
+ i64 x;
pIn1 = &aMem[pOp->p1];
pIn3 = &aMem[pOp->p3];
pOut = out2Prerelease(p, pOp);
assert( pIn1->flags & MEM_Int );
assert( pIn3->flags & MEM_Int );
- pOut->u.i = pIn1->u.i<=0 ? -1 : pIn1->u.i+(pIn3->u.i>0?pIn3->u.i:0);
+ x = pIn1->u.i;
+ if( x<=0 || sqlite3AddInt64(&x, pIn3->u.i>0?pIn3->u.i:0) ){
+ /* If the LIMIT is less than or equal to zero, loop forever. This
+ ** is documented. But also, if the LIMIT+OFFSET exceeds 2^63 then
+ ** also loop forever. This is undocumented. In fact, one could argue
+ ** that the loop should terminate. But assuming 1 billion iterations
+ ** per second (far exceeding the capabilities of any current hardware)
+ ** it would take nearly 300 years to actually reach the limit. So
+ ** looping forever is a reasonable approximation. */
+ pOut->u.i = -1;
+ }else{
+ pOut->u.i = x;
+ }
break;
}
-/* Opcode: IfNotZero P1 P2 P3 * *
-** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2
+/* Opcode: IfNotZero P1 P2 * * *
+** Synopsis: if r[P1]!=0 then r[P1]--, goto P2
**
** Register P1 must contain an integer. If the content of register P1 is
-** initially nonzero, then subtract P3 from the value in register P1 and
-** jump to P2. If register P1 is initially zero, leave it unchanged
-** and fall through.
+** initially greater than zero, then decrement the value in register P1.
+** If it is non-zero (negative or positive) and then also jump to P2.
+** If register P1 is initially zero, leave it unchanged and fall through.
*/
case OP_IfNotZero: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int );
VdbeBranchTaken(pIn1->u.i<0, 2);
if( pIn1->u.i ){
- pIn1->u.i -= pOp->p3;
+ if( pIn1->u.i>0 ) pIn1->u.i--;
goto jump_to_p2;
}
break;
@@ -86401,13 +88349,13 @@ case OP_IfNotZero: { /* jump, in1 */
/* Opcode: DecrJumpZero P1 P2 * * *
** Synopsis: if (--r[P1])==0 goto P2
**
-** Register P1 must hold an integer. Decrement the value in register P1
-** then jump to P2 if the new value is exactly zero.
+** Register P1 must hold an integer. Decrement the value in P1
+** and jump to P2 if the new value is exactly zero.
*/
case OP_DecrJumpZero: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int );
- pIn1->u.i--;
+ if( pIn1->u.i>SMALLEST_INT64 ) pIn1->u.i--;
VdbeBranchTaken(pIn1->u.i==0, 2);
if( pIn1->u.i==0 ) goto jump_to_p2;
break;
@@ -86653,7 +88601,7 @@ case OP_JournalMode: { /* out2 */
** file. An EXCLUSIVE lock may still be held on the database file
** after a successful return.
*/
- rc = sqlite3PagerCloseWal(pPager);
+ rc = sqlite3PagerCloseWal(pPager, db);
if( rc==SQLITE_OK ){
sqlite3PagerSetJournalMode(pPager, eNew);
}
@@ -86763,7 +88711,7 @@ case OP_Expire: {
*/
case OP_TableLock: {
u8 isWriteLock = (u8)pOp->p3;
- if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
+ if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommit) ){
int p1 = pOp->p1;
assert( p1>=0 && p1nDb );
assert( DbMaskTest(p->btreeMask, p1) );
@@ -87137,7 +89085,7 @@ case OP_VUpdate: {
sqlite3VtabImportErrmsg(p, pVtab);
if( rc==SQLITE_OK && pOp->p1 ){
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
- db->lastRowid = lastRowid = rowid;
+ db->lastRowid = rowid;
}
if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
if( pOp->p5==OE_Ignore ){
@@ -87192,6 +89140,121 @@ case OP_MaxPgcnt: { /* out2 */
}
#endif
+/* Opcode: Function0 P1 P2 P3 P4 P5
+** Synopsis: r[P3]=func(r[P2@P5])
+**
+** Invoke a user function (P4 is a pointer to a FuncDef object that
+** defines the function) with P5 arguments taken from register P2 and
+** successors. The result of the function is stored in register P3.
+** Register P3 must not be one of the function inputs.
+**
+** P1 is a 32-bit bitmask indicating whether or not each argument to the
+** function was determined to be constant at compile time. If the first
+** argument was constant then bit 0 of P1 is set. This is used to determine
+** whether meta data associated with a user function argument using the
+** sqlite3_set_auxdata() API may be safely retained until the next
+** invocation of this opcode.
+**
+** See also: Function, AggStep, AggFinal
+*/
+/* Opcode: Function P1 P2 P3 P4 P5
+** Synopsis: r[P3]=func(r[P2@P5])
+**
+** Invoke a user function (P4 is a pointer to an sqlite3_context object that
+** contains a pointer to the function to be run) with P5 arguments taken
+** from register P2 and successors. The result of the function is stored
+** in register P3. Register P3 must not be one of the function inputs.
+**
+** P1 is a 32-bit bitmask indicating whether or not each argument to the
+** function was determined to be constant at compile time. If the first
+** argument was constant then bit 0 of P1 is set. This is used to determine
+** whether meta data associated with a user function argument using the
+** sqlite3_set_auxdata() API may be safely retained until the next
+** invocation of this opcode.
+**
+** SQL functions are initially coded as OP_Function0 with P4 pointing
+** to a FuncDef object. But on first evaluation, the P4 operand is
+** automatically converted into an sqlite3_context object and the operation
+** changed to this OP_Function opcode. In this way, the initialization of
+** the sqlite3_context object occurs only once, rather than once for each
+** evaluation of the function.
+**
+** See also: Function0, AggStep, AggFinal
+*/
+case OP_PureFunc0:
+case OP_Function0: {
+ int n;
+ sqlite3_context *pCtx;
+
+ assert( pOp->p4type==P4_FUNCDEF );
+ n = pOp->p5;
+ assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
+ assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
+ assert( pOp->p3p2 || pOp->p3>=pOp->p2+n );
+ pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
+ if( pCtx==0 ) goto no_mem;
+ pCtx->pOut = 0;
+ pCtx->pFunc = pOp->p4.pFunc;
+ pCtx->iOp = (int)(pOp - aOp);
+ pCtx->pVdbe = p;
+ pCtx->argc = n;
+ pOp->p4type = P4_FUNCCTX;
+ pOp->p4.pCtx = pCtx;
+ assert( OP_PureFunc == OP_PureFunc0+2 );
+ assert( OP_Function == OP_Function0+2 );
+ pOp->opcode += 2;
+ /* Fall through into OP_Function */
+}
+case OP_PureFunc:
+case OP_Function: {
+ int i;
+ sqlite3_context *pCtx;
+
+ assert( pOp->p4type==P4_FUNCCTX );
+ pCtx = pOp->p4.pCtx;
+
+ /* If this function is inside of a trigger, the register array in aMem[]
+ ** might change from one evaluation to the next. The next block of code
+ ** checks to see if the register array has changed, and if so it
+ ** reinitializes the relavant parts of the sqlite3_context object */
+ pOut = &aMem[pOp->p3];
+ if( pCtx->pOut != pOut ){
+ pCtx->pOut = pOut;
+ for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
+ }
+
+ memAboutToChange(p, pOut);
+#ifdef SQLITE_DEBUG
+ for(i=0; iargc; i++){
+ assert( memIsValid(pCtx->argv[i]) );
+ REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
+ }
+#endif
+ MemSetTypeFlag(pOut, MEM_Null);
+ pCtx->fErrorOrAux = 0;
+ (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
+
+ /* If the function returned an error, throw an exception */
+ if( pCtx->fErrorOrAux ){
+ if( pCtx->isError ){
+ sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut));
+ rc = pCtx->isError;
+ }
+ sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
+ if( rc ) goto abort_due_to_error;
+ }
+
+ /* Copy the result of the function into register P3 */
+ if( pOut->flags & (MEM_Str|MEM_Blob) ){
+ sqlite3VdbeChangeEncoding(pOut, encoding);
+ if( sqlite3VdbeMemTooBig(pOut) ) goto too_big;
+ }
+
+ REGISTER_TRACE(pOp->p3, pOut);
+ UPDATE_MAX_BLOBSIZE(pOut);
+ break;
+}
+
/* Opcode: Init P1 P2 * P4 *
** Synopsis: Start at P2
@@ -87237,7 +89300,11 @@ case OP_Init: { /* jump */
sqlite3_free(z);
}else
#endif
- {
+ if( db->nVdbeExec>1 ){
+ char *z = sqlite3MPrintf(db, "-- %s", zTrace);
+ (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, z);
+ sqlite3DbFree(db, z);
+ }else{
(void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace);
}
}
@@ -87267,6 +89334,7 @@ case OP_Init: { /* jump */
pOp->p1 = 0;
}
pOp->p1++;
+ p->aCounter[SQLITE_STMTSTATUS_RUN]++;
goto jump_to_p2;
}
@@ -87373,7 +89441,6 @@ abort_due_to_error:
** release the mutexes on btrees that were acquired at the
** top. */
vdbe_return:
- db->lastRowid = lastRowid;
testcase( nVmStep>0 );
p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
sqlite3VdbeLeave(p);
@@ -87437,10 +89504,9 @@ abort_due_to_interrupt:
*/
typedef struct Incrblob Incrblob;
struct Incrblob {
- int flags; /* Copy of "flags" passed to sqlite3_blob_open() */
int nByte; /* Size of open blob, in bytes */
int iOffset; /* Byte offset of blob in cursor data */
- int iCol; /* Table column this handle is open on */
+ u16 iCol; /* Table column this handle is open on */
BtCursor *pCsr; /* Cursor pointing at blob row */
sqlite3_stmt *pStmt; /* Statement holding cursor open */
sqlite3 *db; /* The associated database */
@@ -87471,17 +89537,27 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
char *zErr = 0; /* Error message */
Vdbe *v = (Vdbe *)p->pStmt;
- /* Set the value of the SQL statements only variable to integer iRow.
- ** This is done directly instead of using sqlite3_bind_int64() to avoid
- ** triggering asserts related to mutexes.
+ /* Set the value of register r[1] in the SQL statement to integer iRow.
+ ** This is done directly as a performance optimization
*/
- assert( v->aVar[0].flags&MEM_Int );
- v->aVar[0].u.i = iRow;
+ v->aMem[1].flags = MEM_Int;
+ v->aMem[1].u.i = iRow;
- rc = sqlite3_step(p->pStmt);
+ /* If the statement has been run before (and is paused at the OP_ResultRow)
+ ** then back it up to the point where it does the OP_SeekRowid. This could
+ ** have been down with an extra OP_Goto, but simply setting the program
+ ** counter is faster. */
+ if( v->pc>3 ){
+ v->pc = 3;
+ rc = sqlite3VdbeExec(v);
+ }else{
+ rc = sqlite3_step(p->pStmt);
+ }
if( rc==SQLITE_ROW ){
VdbeCursor *pC = v->apCsr[0];
- u32 type = pC->aType[p->iCol];
+ u32 type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0;
+ testcase( pC->nHdrParsed==p->iCol );
+ testcase( pC->nHdrParsed==p->iCol+1 );
if( type<12 ){
zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
type==0?"null": type==7?"real": "integer"
@@ -87526,7 +89602,7 @@ SQLITE_API int sqlite3_blob_open(
const char *zTable, /* The table containing the blob */
const char *zColumn, /* The column containing the blob */
sqlite_int64 iRow, /* The row containing the glob */
- int flags, /* True -> read/write access, false -> read-only */
+ int wrFlag, /* True -> read/write access, false -> read-only */
sqlite3_blob **ppBlob /* Handle for accessing the blob returned here */
){
int nAttempt = 0;
@@ -87548,7 +89624,7 @@ SQLITE_API int sqlite3_blob_open(
return SQLITE_MISUSE_BKPT;
}
#endif
- flags = !!flags; /* flags = (flags ? 1 : 0); */
+ wrFlag = !!wrFlag; /* wrFlag = (wrFlag ? 1 : 0); */
sqlite3_mutex_enter(db->mutex);
@@ -87608,9 +89684,8 @@ SQLITE_API int sqlite3_blob_open(
/* If the value is being opened for writing, check that the
** column is not indexed, and that it is not part of a foreign key.
- ** It is against the rules to open a column to which either of these
- ** descriptions applies for writing. */
- if( flags ){
+ */
+ if( wrFlag ){
const char *zFault = 0;
Index *pIdx;
#ifndef SQLITE_OMIT_FOREIGN_KEY
@@ -87671,19 +89746,17 @@ SQLITE_API int sqlite3_blob_open(
static const VdbeOpList openBlob[] = {
{OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */
{OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */
- {OP_Variable, 1, 1, 0}, /* 2: Move ?1 into reg[1] */
- {OP_NotExists, 0, 7, 1}, /* 3: Seek the cursor */
- {OP_Column, 0, 0, 1}, /* 4 */
- {OP_ResultRow, 1, 0, 0}, /* 5 */
- {OP_Goto, 0, 2, 0}, /* 6 */
- {OP_Close, 0, 0, 0}, /* 7 */
- {OP_Halt, 0, 0, 0}, /* 8 */
+ /* blobSeekToRow() will initialize r[1] to the desired rowid */
+ {OP_NotExists, 0, 5, 1}, /* 2: Seek the cursor to rowid=r[1] */
+ {OP_Column, 0, 0, 1}, /* 3 */
+ {OP_ResultRow, 1, 0, 0}, /* 4 */
+ {OP_Halt, 0, 0, 0}, /* 5 */
};
Vdbe *v = (Vdbe *)pBlob->pStmt;
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
VdbeOp *aOp;
- sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags,
+ sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag,
pTab->pSchema->schema_cookie,
pTab->pSchema->iGeneration);
sqlite3VdbeChangeP5(v, 1);
@@ -87700,7 +89773,7 @@ SQLITE_API int sqlite3_blob_open(
#else
aOp[0].p1 = iDb;
aOp[0].p2 = pTab->tnum;
- aOp[0].p3 = flags;
+ aOp[0].p3 = wrFlag;
sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
}
if( db->mallocFailed==0 ){
@@ -87708,7 +89781,7 @@ SQLITE_API int sqlite3_blob_open(
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
** parameter of the other to pTab->tnum. */
- if( flags ) aOp[1].opcode = OP_OpenWrite;
+ if( wrFlag ) aOp[1].opcode = OP_OpenWrite;
aOp[1].p2 = pTab->tnum;
aOp[1].p3 = iDb;
@@ -87721,23 +89794,21 @@ SQLITE_API int sqlite3_blob_open(
*/
aOp[1].p4type = P4_INT32;
aOp[1].p4.i = pTab->nCol+1;
- aOp[4].p2 = pTab->nCol;
+ aOp[3].p2 = pTab->nCol;
- pParse->nVar = 1;
+ pParse->nVar = 0;
pParse->nMem = 1;
pParse->nTab = 1;
sqlite3VdbeMakeReady(v, pParse);
}
}
- pBlob->flags = flags;
pBlob->iCol = iCol;
pBlob->db = db;
sqlite3BtreeLeaveAll(db);
if( db->mallocFailed ){
goto blob_open_out;
}
- sqlite3_bind_int64(pBlob->pStmt, 1, iRow);
rc = blobSeekToRow(pBlob, iRow, &zErr);
} while( (++nAttempt)0 && s1<7) || s1==8 || s1==9 );
assert( (s2>0 && s2<7) || s2==8 || s2==9 );
- if( s1>7 && s2>7 ){
+ if( s1==s2 ){
+ /* The two values have the same sign. Compare using memcmp(). */
+ static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8, 0, 0, 0 };
+ const u8 n = aLen[s1];
+ int i;
+ res = 0;
+ for(i=0; i7 && s2>7 ){
res = s1 - s2;
}else{
- if( s1==s2 ){
- if( (*v1 ^ *v2) & 0x80 ){
- /* The two values have different signs */
- res = (*v1 & 0x80) ? -1 : +1;
- }else{
- /* The two values have the same sign. Compare using memcmp(). */
- static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8 };
- int i;
- res = 0;
- for(i=0; i7 ){
+ res = +1;
+ }else if( s1>7 ){
+ res = -1;
}else{
- if( s2>7 ){
- res = +1;
- }else if( s1>7 ){
- res = -1;
- }else{
- res = s1 - s2;
- }
- assert( res!=0 );
+ res = s1 - s2;
+ }
+ assert( res!=0 );
- if( res>0 ){
- if( *v1 & 0x80 ) res = -1;
- }else{
- if( *v2 & 0x80 ) res = +1;
- }
+ if( res>0 ){
+ if( *v1 & 0x80 ) res = -1;
+ }else{
+ if( *v2 & 0x80 ) res = +1;
}
}
@@ -88881,7 +90951,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
}
#endif
- assert( pCsr->pKeyInfo && pCsr->pBt==0 );
+ assert( pCsr->pKeyInfo && pCsr->pBtx==0 );
assert( pCsr->eCurType==CURTYPE_SORTER );
szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nField-1)*sizeof(CollSeq*);
sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask);
@@ -89249,12 +91319,8 @@ static int vdbeSorterOpenTempFile(
*/
static int vdbeSortAllocUnpacked(SortSubtask *pTask){
if( pTask->pUnpacked==0 ){
- char *pFree;
- pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(
- pTask->pSorter->pKeyInfo, 0, 0, &pFree
- );
- assert( pTask->pUnpacked==(UnpackedRecord*)pFree );
- if( pFree==0 ) return SQLITE_NOMEM_BKPT;
+ pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pTask->pSorter->pKeyInfo);
+ if( pTask->pUnpacked==0 ) return SQLITE_NOMEM_BKPT;
pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField;
pTask->pUnpacked->errCode = 0;
}
@@ -90539,9 +92605,13 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *pCsr, int *pbEof){
}
/*
-** Advance to the next element in the sorter.
+** Advance to the next element in the sorter. Return value:
+**
+** SQLITE_OK success
+** SQLITE_DONE end of data
+** otherwise some kind of error.
*/
-SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
+SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr){
VdbeSorter *pSorter;
int rc; /* Return code */
@@ -90555,21 +92625,22 @@ SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, in
#if SQLITE_MAX_WORKER_THREADS>0
if( pSorter->bUseThreads ){
rc = vdbePmaReaderNext(pSorter->pReader);
- *pbEof = (pSorter->pReader->pFd==0);
+ if( rc==SQLITE_OK && pSorter->pReader->pFd==0 ) rc = SQLITE_DONE;
}else
#endif
/*if( !pSorter->bUseThreads )*/ {
+ int res = 0;
assert( pSorter->pMerger!=0 );
assert( pSorter->pMerger->pTask==(&pSorter->aTask[0]) );
- rc = vdbeMergeEngineStep(pSorter->pMerger, pbEof);
+ rc = vdbeMergeEngineStep(pSorter->pMerger, &res);
+ if( rc==SQLITE_OK && res ) rc = SQLITE_DONE;
}
}else{
SorterRecord *pFree = pSorter->list.pList;
pSorter->list.pList = pFree->u.pNext;
pFree->u.pNext = 0;
if( pSorter->list.aMemory==0 ) vdbeSorterRecordFree(db, pFree);
- *pbEof = !pSorter->list.pList;
- rc = SQLITE_OK;
+ rc = pSorter->list.pList ? SQLITE_OK : SQLITE_DONE;
}
return rc;
}
@@ -90655,9 +92726,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
r2 = pSorter->pUnpacked;
pKeyInfo = pCsr->pKeyInfo;
if( r2==0 ){
- char *p;
- r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo,0,0,&p);
- assert( pSorter->pUnpacked==(UnpackedRecord*)p );
+ r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( r2==0 ) return SQLITE_NOMEM_BKPT;
r2->nField = nKeyCol;
}
@@ -91128,11 +93197,11 @@ SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){
**
** WRC_Continue Continue descending down the tree.
**
-** WRC_Prune Do not descend into child nodes. But allow
+** WRC_Prune Do not descend into child nodes, but allow
** the walk to continue with sibling nodes.
**
** WRC_Abort Do no more callbacks. Unwind the stack and
-** return the top-level walk call.
+** return from the top-level walk call.
**
** The return value from this routine is WRC_Abort to abandon the tree walk
** and WRC_Continue to continue.
@@ -91142,15 +93211,17 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
testcase( ExprHasProperty(pExpr, EP_Reduced) );
rc = pWalker->xExprCallback(pWalker, pExpr);
- if( rc || ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
- return rc & WRC_Abort;
- }
- if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
- if( pExpr->pRight && walkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
- }else if( pExpr->x.pList ){
- if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
+ if( rc ) return rc & WRC_Abort;
+ if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
+ if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
+ assert( pExpr->x.pList==0 || pExpr->pRight==0 );
+ if( pExpr->pRight ){
+ if( walkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
+ }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
+ }else if( pExpr->x.pList ){
+ if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
+ }
}
return WRC_Continue;
}
@@ -91205,7 +93276,7 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
pSrc = p->pSrc;
if( ALWAYS(pSrc) ){
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){
+ if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
return WRC_Abort;
}
if( pItem->fg.isTabFunc
@@ -91225,8 +93296,9 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
**
** If it is not NULL, the xSelectCallback() callback is invoked before
** the walk of the expressions and FROM clause. The xSelectCallback2()
-** method, if it is not NULL, is invoked following the walk of the
-** expressions and FROM clause.
+** method is invoked following the walk of the expressions and FROM clause,
+** but only if both xSelectCallback and xSelectCallback2 are both non-NULL
+** and if the expressions and FROM clause both return WRC_Continue;
**
** Return WRC_Continue under normal conditions. Return WRC_Abort if
** there is an abort request.
@@ -91236,29 +93308,22 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
*/
SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
int rc;
- if( p==0 || (pWalker->xSelectCallback==0 && pWalker->xSelectCallback2==0) ){
- return WRC_Continue;
- }
- rc = WRC_Continue;
- pWalker->walkerDepth++;
- while( p ){
- if( pWalker->xSelectCallback ){
- rc = pWalker->xSelectCallback(pWalker, p);
- if( rc ) break;
- }
+ if( p==0 ) return WRC_Continue;
+ if( pWalker->xSelectCallback==0 ) return WRC_Continue;
+ do{
+ rc = pWalker->xSelectCallback(pWalker, p);
+ if( rc ) return rc & WRC_Abort;
if( sqlite3WalkSelectExpr(pWalker, p)
|| sqlite3WalkSelectFrom(pWalker, p)
){
- pWalker->walkerDepth--;
return WRC_Abort;
}
if( pWalker->xSelectCallback2 ){
pWalker->xSelectCallback2(pWalker, p);
}
p = p->pPrior;
- }
- pWalker->walkerDepth--;
- return rc & WRC_Abort;
+ }while( p!=0 );
+ return WRC_Continue;
}
/************** End of walker.c **********************************************/
@@ -91280,8 +93345,6 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
** table and column.
*/
/* #include "sqliteInt.h" */
-/* #include */
-/* #include */
/*
** Walk the expression tree pExpr and increase the aggregate function
@@ -91496,7 +93559,8 @@ static int lookupName(
}
/* Start at the inner-most context and move outward until a match is found */
- while( pNC && cnt==0 ){
+ assert( pNC && cnt==0 );
+ do{
ExprList *pEList;
SrcList *pSrcList = pNC->pSrcList;
@@ -91681,11 +93745,11 @@ static int lookupName(
/* Advance to the next name context. The loop will exit when either
** we have a match (cnt>0) or when we run out of name contexts.
*/
- if( cnt==0 ){
- pNC = pNC->pNext;
- nSubquery++;
- }
- }
+ if( cnt ) break;
+ pNC = pNC->pNext;
+ nSubquery++;
+ }while( pNC );
+
/*
** If X and Y are NULL (in other words if only the column name Z is
@@ -91744,6 +93808,7 @@ static int lookupName(
sqlite3ExprDelete(db, pExpr->pRight);
pExpr->pRight = 0;
pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN);
+ ExprSetProperty(pExpr, EP_Leaf);
lookupname_end:
if( cnt==1 ){
assert( pNC!=0 );
@@ -91782,7 +93847,6 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr
testcase( iCol==BMS-1 );
pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
}
- ExprSetProperty(p, EP_Resolved);
}
return p;
}
@@ -91842,8 +93906,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pParse = pNC->pParse;
assert( pParse==pWalker->pParse );
- if( ExprHasProperty(pExpr, EP_Resolved) ) return WRC_Prune;
- ExprSetProperty(pExpr, EP_Resolved);
#ifndef NDEBUG
if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
SrcList *pSrcList = pNC->pSrcList;
@@ -91875,33 +93937,38 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
&& !defined(SQLITE_OMIT_SUBQUERY) */
- /* A lone identifier is the name of a column.
- */
- case TK_ID: {
- return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr);
- }
-
- /* A table name and column name: ID.ID
+ /* A column name: ID
+ ** Or table name and column name: ID.ID
** Or a database, table and column: ID.ID.ID
+ **
+ ** The TK_ID and TK_OUT cases are combined so that there will only
+ ** be one call to lookupName(). Then the compiler will in-line
+ ** lookupName() for a size reduction and performance increase.
*/
+ case TK_ID:
case TK_DOT: {
const char *zColumn;
const char *zTable;
const char *zDb;
Expr *pRight;
- /* if( pSrcList==0 ) break; */
- notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
- pRight = pExpr->pRight;
- if( pRight->op==TK_ID ){
+ if( pExpr->op==TK_ID ){
zDb = 0;
- zTable = pExpr->pLeft->u.zToken;
- zColumn = pRight->u.zToken;
+ zTable = 0;
+ zColumn = pExpr->u.zToken;
}else{
- assert( pRight->op==TK_DOT );
- zDb = pExpr->pLeft->u.zToken;
- zTable = pRight->pLeft->u.zToken;
- zColumn = pRight->pRight->u.zToken;
+ notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
+ pRight = pExpr->pRight;
+ if( pRight->op==TK_ID ){
+ zDb = 0;
+ zTable = pExpr->pLeft->u.zToken;
+ zColumn = pRight->u.zToken;
+ }else{
+ assert( pRight->op==TK_DOT );
+ zDb = pExpr->pLeft->u.zToken;
+ zTable = pRight->pLeft->u.zToken;
+ zColumn = pRight->pRight->u.zToken;
+ }
}
return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
}
@@ -92171,7 +94238,7 @@ static int resolveOrderByTermToExprList(
** result-set entry.
*/
for(i=0; inExpr; i++){
- if( sqlite3ExprCompare(pEList->a[i].pExpr, pE, -1)<2 ){
+ if( sqlite3ExprCompare(0, pEList->a[i].pExpr, pE, -1)<2 ){
return i+1;
}
}
@@ -92405,7 +94472,7 @@ static int resolveOrderGroupBy(
return 1;
}
for(j=0; jpEList->nExpr; j++){
- if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
+ if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
pItem->u.x.iOrderByCol = j+1;
}
}
@@ -92691,37 +94758,29 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames(
u16 savedHasAgg;
Walker w;
- if( pExpr==0 ) return 0;
-#if SQLITE_MAX_EXPR_DEPTH>0
- {
- Parse *pParse = pNC->pParse;
- if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){
- return 1;
- }
- pParse->nHeight += pExpr->nHeight;
- }
-#endif
+ if( pExpr==0 ) return SQLITE_OK;
savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg);
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg);
w.pParse = pNC->pParse;
w.xExprCallback = resolveExprStep;
w.xSelectCallback = resolveSelectStep;
w.xSelectCallback2 = 0;
- w.walkerDepth = 0;
- w.eCode = 0;
w.u.pNC = pNC;
+#if SQLITE_MAX_EXPR_DEPTH>0
+ w.pParse->nHeight += pExpr->nHeight;
+ if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
+ return SQLITE_ERROR;
+ }
+#endif
sqlite3WalkExpr(&w, pExpr);
#if SQLITE_MAX_EXPR_DEPTH>0
- pNC->pParse->nHeight -= pExpr->nHeight;
+ w.pParse->nHeight -= pExpr->nHeight;
#endif
- if( pNC->nErr>0 || w.pParse->nErr>0 ){
- ExprSetProperty(pExpr, EP_Error);
- }
if( pNC->ncFlags & NC_HasAgg ){
ExprSetProperty(pExpr, EP_Agg);
}
pNC->ncFlags |= savedHasAgg;
- return ExprHasProperty(pExpr, EP_Error);
+ return pNC->nErr>0 || w.pParse->nErr>0;
}
/*
@@ -92762,9 +94821,9 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
Walker w;
assert( p!=0 );
- memset(&w, 0, sizeof(w));
w.xExprCallback = resolveExprStep;
w.xSelectCallback = resolveSelectStep;
+ w.xSelectCallback2 = 0;
w.pParse = pParse;
w.u.pNC = pOuterNC;
sqlite3WalkSelect(&w, p);
@@ -92867,7 +94926,7 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
return sqlite3AffinityType(pExpr->u.zToken, 0);
}
#endif
- if( op==TK_AGG_COLUMN || op==TK_COLUMN ){
+ if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){
return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
}
if( op==TK_SELECT_COLUMN ){
@@ -93040,7 +95099,7 @@ static char comparisonAffinity(Expr *pExpr){
aff = sqlite3CompareAffinity(pExpr->pRight, aff);
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
- }else if( NEVER(aff==0) ){
+ }else if( aff==0 ){
aff = SQLITE_AFF_BLOB;
}
return aff;
@@ -93161,7 +95220,6 @@ SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr){
}
}
-#ifndef SQLITE_OMIT_SUBQUERY
/*
** Return a pointer to a subexpression of pVector that is the i-th
** column of the vector (numbered starting with 0). The caller must
@@ -93189,9 +95247,7 @@ SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){
}
return pVector;
}
-#endif /* !defined(SQLITE_OMIT_SUBQUERY) */
-#ifndef SQLITE_OMIT_SUBQUERY
/*
** Compute and return a new Expr object which when passed to
** sqlite3ExprCode() will generate all necessary code to compute
@@ -93223,9 +95279,10 @@ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(
assert( pVector->flags & EP_xIsSelect );
/* The TK_SELECT_COLUMN Expr node:
**
- ** pLeft: pVector containing TK_SELECT
+ ** pLeft: pVector containing TK_SELECT. Not deleted.
** pRight: not used. But recursively deleted.
** iColumn: Index of a column in pVector
+ ** iTable: 0 or the number of columns on the LHS of an assignment
** pLeft->iTable: First in an array of register holding result, or 0
** if the result is not yet computed.
**
@@ -93236,7 +95293,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(
** with the same pLeft pointer to the pVector, but only one of them
** will own the pVector.
*/
- pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0, 0);
+ pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0);
if( pRet ){
pRet->iColumn = iField;
pRet->pLeft = pVector;
@@ -93248,7 +95305,6 @@ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(
}
return pRet;
}
-#endif /* !define(SQLITE_OMIT_SUBQUERY) */
/*
** If expression pExpr is of type TK_SELECT, generate code to evaluate
@@ -93336,7 +95392,10 @@ static void codeVectorCompare(
u8 opx = op;
int addrDone = sqlite3VdbeMakeLabel(v);
- assert( nLeft==sqlite3ExprVectorSize(pRight) );
+ if( nLeft!=sqlite3ExprVectorSize(pRight) ){
+ sqlite3ErrorMsg(pParse, "row value misused");
+ return;
+ }
assert( pExpr->op==TK_EQ || pExpr->op==TK_NE
|| pExpr->op==TK_IS || pExpr->op==TK_ISNOT
|| pExpr->op==TK_LT || pExpr->op==TK_GT
@@ -93553,7 +95612,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAlloc(
pNew->iAgg = -1;
if( pToken ){
if( nExtra==0 ){
- pNew->flags |= EP_IntValue;
+ pNew->flags |= EP_IntValue|EP_Leaf;
pNew->u.iValue = iValue;
}else{
pNew->u.zToken = (char*)&pNew[1];
@@ -93628,15 +95687,19 @@ SQLITE_PRIVATE Expr *sqlite3PExpr(
Parse *pParse, /* Parsing context */
int op, /* Expression opcode */
Expr *pLeft, /* Left operand */
- Expr *pRight, /* Right operand */
- const Token *pToken /* Argument token */
+ Expr *pRight /* Right operand */
){
Expr *p;
if( op==TK_AND && pParse->nErr==0 ){
/* Take advantage of short-circuit false optimization for AND */
p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
}else{
- p = sqlite3ExprAlloc(pParse->db, op & TKFLG_MASK, pToken, 1);
+ p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr));
+ if( p ){
+ memset(p, 0, sizeof(Expr));
+ p->op = op & TKFLG_MASK;
+ p->iAgg = -1;
+ }
sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
}
if( p ) {
@@ -93739,7 +95802,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *
** variable number.
**
** Wildcards of the form "?nnn" are assigned the number "nnn". We make
-** sure "nnn" is not too be to avoid a denial of service attack when
+** sure "nnn" is not too big to avoid a denial of service attack when
** the SQL statement comes from an external source.
**
** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number
@@ -93750,25 +95813,31 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *
SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
sqlite3 *db = pParse->db;
const char *z;
+ ynVar x;
if( pExpr==0 ) return;
assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
z = pExpr->u.zToken;
assert( z!=0 );
assert( z[0]!=0 );
- assert( n==sqlite3Strlen30(z) );
+ assert( n==(u32)sqlite3Strlen30(z) );
if( z[1]==0 ){
/* Wildcard of the form "?". Assign the next variable number */
assert( z[0]=='?' );
- pExpr->iColumn = (ynVar)(++pParse->nVar);
+ x = (ynVar)(++pParse->nVar);
}else{
- ynVar x;
+ int doAdd = 0;
if( z[0]=='?' ){
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
** use it as the variable number */
i64 i;
- int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
- x = (ynVar)i;
+ int bOk;
+ if( n==2 ){ /*OPTIMIZATION-IF-TRUE*/
+ i = z[1]-'0'; /* The common case of ?N for a single digit N */
+ bOk = 1;
+ }else{
+ bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
+ }
testcase( i==0 );
testcase( i==1 );
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
@@ -93778,40 +95847,30 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
return;
}
- if( i>pParse->nVar ){
- pParse->nVar = (int)i;
+ x = (ynVar)i;
+ if( x>pParse->nVar ){
+ pParse->nVar = (int)x;
+ doAdd = 1;
+ }else if( sqlite3VListNumToName(pParse->pVList, x)==0 ){
+ doAdd = 1;
}
}else{
/* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
** number as the prior appearance of the same name, or if the name
** has never appeared before, reuse the same variable number
*/
- ynVar i;
- for(i=x=0; inzVar; i++){
- if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){
- x = (ynVar)i+1;
- break;
- }
+ x = (ynVar)sqlite3VListNameToNum(pParse->pVList, z, n);
+ if( x==0 ){
+ x = (ynVar)(++pParse->nVar);
+ doAdd = 1;
}
- if( x==0 ) x = (ynVar)(++pParse->nVar);
}
- pExpr->iColumn = x;
- if( x>pParse->nzVar ){
- char **a;
- a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
- if( a==0 ){
- assert( db->mallocFailed ); /* Error reported through mallocFailed */
- return;
- }
- pParse->azVar = a;
- memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
- pParse->nzVar = x;
+ if( doAdd ){
+ pParse->pVList = sqlite3VListAdd(db, pParse->pVList, z, n, x);
}
- if( pParse->azVar[x-1]==0 ){
- pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
- }
- }
- if( pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
+ }
+ pExpr->iColumn = x;
+ if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
sqlite3ErrorMsg(pParse, "too many SQL variables");
}
}
@@ -93834,8 +95893,9 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
/* The Expr.x union is never used at the same time as Expr.pRight */
assert( p->x.pList==0 || p->pRight==0 );
if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
- sqlite3ExprDelete(db, p->pRight);
- if( ExprHasProperty(p, EP_xIsSelect) ){
+ if( p->pRight ){
+ sqlite3ExprDeleteNN(db, p->pRight);
+ }else if( ExprHasProperty(p, EP_xIsSelect) ){
sqlite3SelectDelete(db, p->x.pSelect);
}else{
sqlite3ExprListDelete(db, p->x.pList);
@@ -93843,7 +95903,7 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
}
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
if( !ExprHasProperty(p, EP_Static) ){
- sqlite3DbFree(db, p);
+ sqlite3DbFreeNN(db, p);
}
}
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
@@ -93900,7 +95960,7 @@ static int dupedExprStructSize(Expr *p, int flags){
assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
assert( EXPR_FULLSIZE<=0xfff );
assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
- if( 0==flags ){
+ if( 0==flags || p->op==TK_SELECT_COLUMN ){
nSize = EXPR_FULLSIZE;
}else{
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
@@ -94043,6 +96103,8 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
+ assert( p->iColumn==0 || p->pRight==0 );
+ assert( p->pRight==0 || p->pRight==p->pLeft );
}else{
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
}
@@ -94105,21 +96167,35 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags)
ExprList *pNew;
struct ExprList_item *pItem, *pOldItem;
int i;
+ Expr *pPriorSelectCol = 0;
assert( db!=0 );
if( p==0 ) return 0;
- pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
+ pNew = sqlite3DbMallocRawNN(db,
+ sizeof(*pNew)+sizeof(pNew->a[0])*(p->nExpr-1) );
if( pNew==0 ) return 0;
- pNew->nExpr = i = p->nExpr;
- if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; inExpr; i+=i){}
- pNew->a = pItem = sqlite3DbMallocRawNN(db, i*sizeof(p->a[0]) );
- if( pItem==0 ){
- sqlite3DbFree(db, pNew);
- return 0;
- }
+ pNew->nAlloc = pNew->nExpr = p->nExpr;
+ pItem = pNew->a;
pOldItem = p->a;
for(i=0; inExpr; i++, pItem++, pOldItem++){
Expr *pOldExpr = pOldItem->pExpr;
+ Expr *pNewExpr;
pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
+ if( pOldExpr
+ && pOldExpr->op==TK_SELECT_COLUMN
+ && (pNewExpr = pItem->pExpr)!=0
+ ){
+ assert( pNewExpr->iColumn==0 || i>0 );
+ if( pNewExpr->iColumn==0 ){
+ assert( pOldExpr->pLeft==pOldExpr->pRight );
+ pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
+ }else{
+ assert( i>0 );
+ assert( pItem[-1].pExpr!=0 );
+ assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 );
+ assert( pPriorSelectCol==pItem[-1].pExpr->pLeft );
+ pNewExpr->pLeft = pPriorSelectCol;
+ }
+ }
pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
pItem->sortOrder = pOldItem->sortOrder;
@@ -94170,7 +96246,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
}
pTab = pNewItem->pTab = pOldItem->pTab;
if( pTab ){
- pTab->nRef++;
+ pTab->nTabRef++;
}
pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags);
@@ -94189,7 +96265,7 @@ SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
pNew->nId = p->nId;
pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) );
if( pNew->a==0 ){
- sqlite3DbFree(db, pNew);
+ sqlite3DbFreeNN(db, pNew);
return 0;
}
/* Note that because the size of the allocation for p->a[] is not
@@ -94203,33 +96279,41 @@ SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
}
return pNew;
}
-SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
- Select *pNew, *pPrior;
+SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
+ Select *pRet = 0;
+ Select *pNext = 0;
+ Select **pp = &pRet;
+ Select *p;
+
assert( db!=0 );
- if( p==0 ) return 0;
- pNew = sqlite3DbMallocRawNN(db, sizeof(*p) );
- if( pNew==0 ) return 0;
- pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
- pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
- pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
- pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
- pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags);
- pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags);
- pNew->op = p->op;
- pNew->pPrior = pPrior = sqlite3SelectDup(db, p->pPrior, flags);
- if( pPrior ) pPrior->pNext = pNew;
- pNew->pNext = 0;
- pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
- pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
- pNew->iLimit = 0;
- pNew->iOffset = 0;
- pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
- pNew->addrOpenEphm[0] = -1;
- pNew->addrOpenEphm[1] = -1;
- pNew->nSelectRow = p->nSelectRow;
- pNew->pWith = withDup(db, p->pWith);
- sqlite3SelectSetName(pNew, p->zSelName);
- return pNew;
+ for(p=pDup; p; p=p->pPrior){
+ Select *pNew = sqlite3DbMallocRawNN(db, sizeof(*p) );
+ if( pNew==0 ) break;
+ pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
+ pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
+ pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
+ pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
+ pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags);
+ pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags);
+ pNew->op = p->op;
+ pNew->pNext = pNext;
+ pNew->pPrior = 0;
+ pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
+ pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
+ pNew->iLimit = 0;
+ pNew->iOffset = 0;
+ pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
+ pNew->addrOpenEphm[0] = -1;
+ pNew->addrOpenEphm[1] = -1;
+ pNew->nSelectRow = p->nSelectRow;
+ pNew->pWith = withDup(db, p->pWith);
+ sqlite3SelectSetName(pNew, p->zSelName);
+ *pp = pNew;
+ pp = &pNew->pPrior;
+ pNext = pNew;
+ }
+
+ return pRet;
}
#else
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
@@ -94252,6 +96336,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(
ExprList *pList, /* List to which to append. Might be NULL */
Expr *pExpr /* Expression to be appended. Might be NULL */
){
+ struct ExprList_item *pItem;
sqlite3 *db = pParse->db;
assert( db!=0 );
if( pList==0 ){
@@ -94260,23 +96345,22 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(
goto no_mem;
}
pList->nExpr = 0;
- pList->a = sqlite3DbMallocRawNN(db, sizeof(pList->a[0]));
- if( pList->a==0 ) goto no_mem;
- }else if( (pList->nExpr & (pList->nExpr-1))==0 ){
- struct ExprList_item *a;
- assert( pList->nExpr>0 );
- a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0]));
- if( a==0 ){
+ pList->nAlloc = 1;
+ }else if( pList->nExpr==pList->nAlloc ){
+ ExprList *pNew;
+ pNew = sqlite3DbRealloc(db, pList,
+ sizeof(*pList)+(2*pList->nAlloc - 1)*sizeof(pList->a[0]));
+ if( pNew==0 ){
goto no_mem;
}
- pList->a = a;
- }
- assert( pList->a!=0 );
- if( 1 ){
- struct ExprList_item *pItem = &pList->a[pList->nExpr++];
- memset(pItem, 0, sizeof(*pItem));
- pItem->pExpr = pExpr;
+ pList = pNew;
+ pList->nAlloc *= 2;
}
+ pItem = &pList->a[pList->nExpr++];
+ assert( offsetof(struct ExprList_item,zName)==sizeof(pItem->pExpr) );
+ assert( offsetof(struct ExprList_item,pExpr)==0 );
+ memset(&pItem->zName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zName));
+ pItem->pExpr = pExpr;
return pList;
no_mem:
@@ -94294,7 +96378,7 @@ no_mem:
** Or: (a,b,c) = (SELECT x,y,z FROM ....)
**
** For each term of the vector assignment, append new entries to the
-** expression list pList. In the case of a subquery on the LHS, append
+** expression list pList. In the case of a subquery on the RHS, append
** TK_SELECT_COLUMN expressions.
*/
SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(
@@ -94311,13 +96395,19 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(
** exit prior to this routine being invoked */
if( NEVER(pColumns==0) ) goto vector_append_error;
if( pExpr==0 ) goto vector_append_error;
- n = sqlite3ExprVectorSize(pExpr);
- if( pColumns->nId!=n ){
+
+ /* If the RHS is a vector, then we can immediately check to see that
+ ** the size of the RHS and LHS match. But if the RHS is a SELECT,
+ ** wildcards ("*") in the result set of the SELECT must be expanded before
+ ** we can do the size check, so defer the size check until code generation.
+ */
+ if( pExpr->op!=TK_SELECT && pColumns->nId!=(n=sqlite3ExprVectorSize(pExpr)) ){
sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
pColumns->nId, n);
goto vector_append_error;
}
- for(i=0; inId; i++){
Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
if( pList ){
@@ -94326,12 +96416,20 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(
pColumns->a[i].zName = 0;
}
}
- if( pExpr->op==TK_SELECT ){
- if( pList && pList->a[iFirst].pExpr ){
- assert( pList->a[iFirst].pExpr->op==TK_SELECT_COLUMN );
- pList->a[iFirst].pExpr->pRight = pExpr;
- pExpr = 0;
- }
+
+ if( !db->mallocFailed && pExpr->op==TK_SELECT && ALWAYS(pList!=0) ){
+ Expr *pFirst = pList->a[iFirst].pExpr;
+ assert( pFirst!=0 );
+ assert( pFirst->op==TK_SELECT_COLUMN );
+
+ /* Store the SELECT statement in pRight so it will be deleted when
+ ** sqlite3ExprListDelete() is called */
+ pFirst->pRight = pExpr;
+ pExpr = 0;
+
+ /* Remember the size of the LHS in iTable so that we can check that
+ ** the RHS and LHS sizes match during code generation. */
+ pFirst->iTable = pColumns->nId;
}
vector_append_error:
@@ -94425,16 +96523,16 @@ SQLITE_PRIVATE void sqlite3ExprListCheckLength(
** Delete an entire expression list.
*/
static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){
- int i;
- struct ExprList_item *pItem;
- assert( pList->a!=0 || pList->nExpr==0 );
- for(pItem=pList->a, i=0; inExpr; i++, pItem++){
+ int i = pList->nExpr;
+ struct ExprList_item *pItem = pList->a;
+ assert( pList->nExpr>0 );
+ do{
sqlite3ExprDelete(db, pItem->pExpr);
sqlite3DbFree(db, pItem->zName);
sqlite3DbFree(db, pItem->zSpan);
- }
- sqlite3DbFree(db, pList->a);
- sqlite3DbFree(db, pList);
+ pItem++;
+ }while( --i>0 );
+ sqlite3DbFreeNN(db, pList);
}
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
if( pList ) exprListDeleteNN(db, pList);
@@ -94513,10 +96611,12 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_AGG_COLUMN );
if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){
return WRC_Continue;
- }else{
- pWalker->eCode = 0;
- return WRC_Abort;
}
+ /* Fall through */
+ case TK_IF_NULL_ROW:
+ testcase( pExpr->op==TK_IF_NULL_ROW );
+ pWalker->eCode = 0;
+ return WRC_Abort;
case TK_VARIABLE:
if( pWalker->eCode==5 ){
/* Silently convert bound parameters that appear inside of CREATE
@@ -94543,10 +96643,12 @@ static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
}
static int exprIsConst(Expr *p, int initFlag, int iCur){
Walker w;
- memset(&w, 0, sizeof(w));
w.eCode = initFlag;
w.xExprCallback = exprNodeIsConstant;
w.xSelectCallback = selectNodeIsConstant;
+#ifdef SQLITE_DEBUG
+ w.xSelectCallback2 = sqlite3SelectWalkAssert2;
+#endif
w.u.iCur = iCur;
sqlite3WalkExpr(&w, p);
return w.eCode;
@@ -94584,6 +96686,65 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){
return exprIsConst(p, 3, iCur);
}
+
+/*
+** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
+*/
+static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
+ ExprList *pGroupBy = pWalker->u.pGroupBy;
+ int i;
+
+ /* Check if pExpr is identical to any GROUP BY term. If so, consider
+ ** it constant. */
+ for(i=0; inExpr; i++){
+ Expr *p = pGroupBy->a[i].pExpr;
+ if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){
+ CollSeq *pColl = sqlite3ExprCollSeq(pWalker->pParse, p);
+ if( pColl==0 || sqlite3_stricmp("BINARY", pColl->zName)==0 ){
+ return WRC_Prune;
+ }
+ }
+ }
+
+ /* Check if pExpr is a sub-select. If so, consider it variable. */
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ pWalker->eCode = 0;
+ return WRC_Abort;
+ }
+
+ return exprNodeIsConstant(pWalker, pExpr);
+}
+
+/*
+** Walk the expression tree passed as the first argument. Return non-zero
+** if the expression consists entirely of constants or copies of terms
+** in pGroupBy that sort with the BINARY collation sequence.
+**
+** This routine is used to determine if a term of the HAVING clause can
+** be promoted into the WHERE clause. In order for such a promotion to work,
+** the value of the HAVING clause term must be the same for all members of
+** a "group". The requirement that the GROUP BY term must be BINARY
+** assumes that no other collating sequence will have a finer-grained
+** grouping than binary. In other words (A=B COLLATE binary) implies
+** A=B in every other collating sequence. The requirement that the
+** GROUP BY be BINARY is stricter than necessary. It would also work
+** to promote HAVING clauses that use the same alternative collating
+** sequence as the GROUP BY term, but that is much harder to check,
+** alternative collating sequences are uncommon, and this is only an
+** optimization, so we take the easy way out and simply require the
+** GROUP BY to use the BINARY collating sequence.
+*/
+SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
+ Walker w;
+ w.eCode = 1;
+ w.xExprCallback = exprNodeIsConstantOrGroupBy;
+ w.xSelectCallback = 0;
+ w.u.pGroupBy = pGroupBy;
+ w.pParse = pParse;
+ sqlite3WalkExpr(&w, p);
+ return w.eCode;
+}
+
/*
** Walk an expression tree. Return non-zero if the expression is constant
** or a function call with constant arguments. Return and 0 if there
@@ -94605,10 +96766,12 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
*/
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){
Walker w;
- memset(&w, 0, sizeof(w));
w.eCode = 1;
w.xExprCallback = sqlite3ExprWalkNoop;
w.xSelectCallback = selectNodeIsConstant;
+#ifdef SQLITE_DEBUG
+ w.xSelectCallback2 = sqlite3SelectWalkAssert2;
+#endif
sqlite3WalkExpr(&w, p);
return w.eCode==0;
}
@@ -94622,6 +96785,7 @@ SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){
*/
SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){
int rc = 0;
+ if( p==0 ) return 0; /* Can only happen following on OOM */
/* If an expression is an integer literal that fits in a signed 32-bit
** integer, then the EP_IntValue flag will have already been set */
@@ -95129,7 +97293,7 @@ static char *exprINAffinity(Parse *pParse, Expr *pExpr){
char *zRet;
assert( pExpr->op==TK_IN );
- zRet = sqlite3DbMallocZero(pParse->db, nVal+1);
+ zRet = sqlite3DbMallocRaw(pParse->db, nVal+1);
if( zRet ){
int i;
for(i=0; iflags & EP_xIsSelect ){
+ sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1);
+ }else
+#endif
+ {
+ sqlite3ErrorMsg(pParse, "row value misused");
+ }
+}
+
/*
** Generate code for scalar subqueries used as a subquery expression, EXISTS,
** or IN operators. Examples:
@@ -95272,7 +97458,6 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
int i;
sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
dest.zAffSdst = exprINAffinity(pParse, pExpr);
- assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
pSelect->iLimit = 0;
testcase( pSelect->selFlags & SF_Distinct );
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
@@ -95347,7 +97532,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
}else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
sqlite3ExprCacheAffinityChange(pParse, r3, 1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1);
}
}
}
@@ -95442,11 +97627,7 @@ SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){
return 1;
}
}else if( nVector!=1 ){
- if( (pIn->pLeft->flags & EP_xIsSelect) ){
- sqlite3SubselectError(pParse, nVector, 1);
- }else{
- sqlite3ErrorMsg(pParse, "row value misused");
- }
+ sqlite3VectorErrorMsg(pParse, pIn->pLeft);
return 1;
}
return 0;
@@ -95751,22 +97932,22 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
const char *z = pExpr->u.zToken;
assert( z!=0 );
c = sqlite3DecOrHexToI64(z, &value);
- if( c==0 || (c==2 && negFlag) ){
- if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
- sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64);
- }else{
+ if( c==1 || (c==2 && !negFlag) || (negFlag && value==SMALLEST_INT64)){
#ifdef SQLITE_OMIT_FLOATING_POINT
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
#else
#ifndef SQLITE_OMIT_HEX_INTEGER
if( sqlite3_strnicmp(z,"0x",2)==0 ){
- sqlite3ErrorMsg(pParse, "hex literal too big: %s", z);
+ sqlite3ErrorMsg(pParse, "hex literal too big: %s%s", negFlag?"-":"",z);
}else
#endif
{
codeReal(v, z, negFlag, iMem);
}
#endif
+ }else{
+ if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
+ sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64);
}
}
}
@@ -95925,8 +98106,9 @@ SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(
if( iTabCol==XN_EXPR ){
assert( pIdx->aColExpr );
assert( pIdx->aColExpr->nExpr>iIdxCol );
- pParse->iSelfTab = iTabCur;
+ pParse->iSelfTab = iTabCur + 1;
sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut);
+ pParse->iSelfTab = 0;
}else{
sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur,
iTabCol, regOut);
@@ -95943,6 +98125,10 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
int iCol, /* Index of the column to extract */
int regOut /* Extract the value into this register */
){
+ if( pTab==0 ){
+ sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
+ return;
+ }
if( iCol<0 || iCol==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
}else{
@@ -96016,7 +98202,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg(
SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){
int i;
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("CLEAR\n");
}
@@ -96099,7 +98285,11 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){
}else{
*piFreeable = 0;
if( p->op==TK_SELECT ){
+#if SQLITE_OMIT_SUBQUERY
+ iResult = 0;
+#else
iResult = sqlite3CodeSubselect(pParse, p, 0, 0);
+#endif
}else{
int i;
iResult = pParse->nMem+1;
@@ -96162,13 +98352,13 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
case TK_COLUMN: {
int iTab = pExpr->iTable;
if( iTab<0 ){
- if( pParse->ckBase>0 ){
+ if( pParse->iSelfTab<0 ){
/* Generating CHECK constraints or inserting into partial index */
- return pExpr->iColumn + pParse->ckBase;
+ return pExpr->iColumn - pParse->iSelfTab;
}else{
/* Coding an expression that is part of an index where column names
** in the index refer to the table to which the index belongs */
- iTab = pParse->iSelfTab;
+ iTab = pParse->iSelfTab - 1;
}
}
return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
@@ -96217,9 +98407,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
assert( pExpr->u.zToken[0]!=0 );
sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
if( pExpr->u.zToken[1]!=0 ){
- assert( pExpr->u.zToken[0]=='?'
- || strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 );
- sqlite3VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC);
+ const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn);
+ assert( pExpr->u.zToken[0]=='?' || strcmp(pExpr->u.zToken, z)==0 );
+ pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */
+ sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC);
}
return target;
}
@@ -96369,6 +98560,11 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
u8 enc = ENC(db); /* The text encoding used by this database */
CollSeq *pColl = 0; /* A collating sequence */
+ if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
+ /* SQL functions can be expensive. So try to move constant functions
+ ** out of the inner loop, even if that means an extra OP_Copy. */
+ return sqlite3ExprCodeAtInit(pParse, pExpr, -1);
+ }
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
@@ -96417,6 +98613,22 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
return sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
}
+#ifdef SQLITE_DEBUG
+ /* The AFFINITY() function evaluates to a string that describes
+ ** the type affinity of the argument. This is used for testing of
+ ** the SQLite type logic.
+ */
+ if( pDef->funcFlags & SQLITE_FUNC_AFFINITY ){
+ const char *azAff[] = { "blob", "text", "numeric", "integer", "real" };
+ char aff;
+ assert( nFarg==1 );
+ aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
+ sqlite3VdbeLoadString(v, target,
+ aff ? azAff[aff-SQLITE_AFF_BLOB] : "none");
+ return target;
+ }
+#endif
+
for(i=0; ia[i].pExpr) ){
testcase( i==31 );
@@ -96483,8 +98695,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
- sqlite3VdbeAddOp4(v, OP_Function0, constMask, r1, target,
- (char*)pDef, P4_FUNCDEF);
+ sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0,
+ constMask, r1, target, (char*)pDef, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nFarg);
if( nFarg && constMask==0 ){
sqlite3ReleaseTempRange(pParse, r1, nFarg);
@@ -96505,9 +98717,17 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
break;
}
case TK_SELECT_COLUMN: {
+ int n;
if( pExpr->pLeft->iTable==0 ){
pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0);
}
+ assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
+ if( pExpr->iTable
+ && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
+ ){
+ sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
+ pExpr->iTable, n);
+ }
return pExpr->pLeft->iTable + pExpr->iColumn;
}
case TK_IN: {
@@ -96606,6 +98826,17 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
break;
}
+ case TK_IF_NULL_ROW: {
+ int addrINR;
+ addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable);
+ sqlite3ExprCachePush(pParse);
+ inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
+ sqlite3ExprCachePop(pParse);
+ sqlite3VdbeJumpHere(v, addrINR);
+ sqlite3VdbeChangeP3(v, addrINR, inReg);
+ break;
+ }
+
/*
** Form A:
** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
@@ -96725,24 +98956,40 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
/*
** Factor out the code of the given expression to initialization time.
+**
+** If regDest>=0 then the result is always stored in that register and the
+** result is not reusable. If regDest<0 then this routine is free to
+** store the value whereever it wants. The register where the expression
+** is stored is returned. When regDest<0, two identical expressions will
+** code to the same register.
*/
-SQLITE_PRIVATE void sqlite3ExprCodeAtInit(
+SQLITE_PRIVATE int sqlite3ExprCodeAtInit(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* The expression to code when the VDBE initializes */
- int regDest, /* Store the value in this register */
- u8 reusable /* True if this expression is reusable */
+ int regDest /* Store the value in this register */
){
ExprList *p;
assert( ConstFactorOk(pParse) );
p = pParse->pConstExpr;
+ if( regDest<0 && p ){
+ struct ExprList_item *pItem;
+ int i;
+ for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
+ if( pItem->reusable && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 ){
+ return pItem->u.iConstExprReg;
+ }
+ }
+ }
pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
p = sqlite3ExprListAppend(pParse, p, pExpr);
if( p ){
struct ExprList_item *pItem = &p->a[p->nExpr-1];
+ pItem->reusable = regDest<0;
+ if( regDest<0 ) regDest = ++pParse->nMem;
pItem->u.iConstExprReg = regDest;
- pItem->reusable = reusable;
}
pParse->pConstExpr = p;
+ return regDest;
}
/*
@@ -96765,19 +99012,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
&& pExpr->op!=TK_REGISTER
&& sqlite3ExprIsConstantNotJoin(pExpr)
){
- ExprList *p = pParse->pConstExpr;
- int i;
*pReg = 0;
- if( p ){
- struct ExprList_item *pItem;
- for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
- if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){
- return pItem->u.iConstExprReg;
- }
- }
- }
- r2 = ++pParse->nMem;
- sqlite3ExprCodeAtInit(pParse, pExpr, r2, 1);
+ r2 = sqlite3ExprCodeAtInit(pParse, pExpr, -1);
}else{
int r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
@@ -96831,7 +99067,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){
*/
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){
- sqlite3ExprCodeAtInit(pParse, pExpr, target, 0);
+ sqlite3ExprCodeAtInit(pParse, pExpr, target);
}else{
sqlite3ExprCode(pParse, pExpr, target);
}
@@ -96895,10 +99131,15 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList(
if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
for(pItem=pList->a, i=0; ipExpr;
- if( (flags & SQLITE_ECEL_REF)!=0 && (j = pList->a[i].u.x.iOrderByCol)>0 ){
- sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
+ if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){
+ if( flags & SQLITE_ECEL_OMITREF ){
+ i--;
+ n--;
+ }else{
+ sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
+ }
}else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){
- sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0);
+ sqlite3ExprCodeAtInit(pParse, pExpr, target+i);
}else{
int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
if( inReg!=target+i ){
@@ -96971,6 +99212,11 @@ static void exprCodeBetween(
if( xJump ){
xJump(pParse, &exprAnd, dest, jumpIfNull);
}else{
+ /* Mark the expression is being from the ON or USING clause of a join
+ ** so that the sqlite3ExprCodeTarget() routine will not attempt to move
+ ** it into the Parse.pConstExpr list. We should use a new bit for this,
+ ** for clarity, but we are out of bits in the Expr.flags field so we
+ ** have to reuse the EP_FromJoin bit. Bummer. */
exprX.flags |= EP_FromJoin;
sqlite3ExprCodeTarget(pParse, &exprAnd, dest);
}
@@ -97284,6 +99530,41 @@ SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,i
sqlite3ExprDelete(db, pCopy);
}
+/*
+** Expression pVar is guaranteed to be an SQL variable. pExpr may be any
+** type of expression.
+**
+** If pExpr is a simple SQL value - an integer, real, string, blob
+** or NULL value - then the VDBE currently being prepared is configured
+** to re-prepare each time a new value is bound to variable pVar.
+**
+** Additionally, if pExpr is a simple SQL value and the value is the
+** same as that currently bound to variable pVar, non-zero is returned.
+** Otherwise, if the values are not the same or if pExpr is not a simple
+** SQL value, zero is returned.
+*/
+static int exprCompareVariable(Parse *pParse, Expr *pVar, Expr *pExpr){
+ int res = 0;
+ int iVar;
+ sqlite3_value *pL, *pR = 0;
+
+ sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR);
+ if( pR ){
+ iVar = pVar->iColumn;
+ sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
+ pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB);
+ if( pL ){
+ if( sqlite3_value_type(pL)==SQLITE_TEXT ){
+ sqlite3_value_text(pL); /* Make sure the encoding is UTF-8 */
+ }
+ res = 0==sqlite3MemCompare(pL, pR, 0);
+ }
+ sqlite3ValueFree(pR);
+ sqlite3ValueFree(pL);
+ }
+
+ return res;
+}
/*
** Do a deep comparison of two expression trees. Return 0 if the two
@@ -97306,12 +99587,22 @@ SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,i
** this routine is used, it does not hurt to get an extra 2 - that
** just might result in some slightly slower code. But returning
** an incorrect 0 or 1 could lead to a malfunction.
+**
+** If pParse is not NULL then TK_VARIABLE terms in pA with bindings in
+** pParse->pReprepare can be matched against literals in pB. The
+** pParse->pVdbe->expmask bitmask is updated for each variable referenced.
+** If pParse is NULL (the normal case) then any TK_VARIABLE term in
+** Argument pParse should normally be NULL. If it is not NULL and pA or
+** pB causes a return value of 2.
*/
-SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
+SQLITE_PRIVATE int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
u32 combinedFlags;
if( pA==0 || pB==0 ){
return pB==pA ? 0 : 2;
}
+ if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){
+ return 0;
+ }
combinedFlags = pA->flags | pB->flags;
if( combinedFlags & EP_IntValue ){
if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
@@ -97320,10 +99611,10 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
return 2;
}
if( pA->op!=pB->op ){
- if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){
+ if( pA->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA->pLeft,pB,iTab)<2 ){
return 1;
}
- if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft, iTab)<2 ){
+ if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){
return 1;
}
return 2;
@@ -97338,8 +99629,8 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
if( combinedFlags & EP_xIsSelect ) return 2;
- if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
- if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
+ if( sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
+ if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){
if( pA->iColumn!=pB->iColumn ) return 2;
@@ -97374,11 +99665,22 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
Expr *pExprA = pA->a[i].pExpr;
Expr *pExprB = pB->a[i].pExpr;
if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1;
- if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1;
+ if( sqlite3ExprCompare(0, pExprA, pExprB, iTab) ) return 1;
}
return 0;
}
+/*
+** Like sqlite3ExprCompare() except COLLATE operators at the top-level
+** are ignored.
+*/
+SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){
+ return sqlite3ExprCompare(0,
+ sqlite3ExprSkipCollate(pA),
+ sqlite3ExprSkipCollate(pB),
+ iTab);
+}
+
/*
** Return true if we can prove the pE2 will always be true if pE1 is
** true. Return false if we cannot complete the proof or if pE2 might
@@ -97395,25 +99697,29 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
** Expr.iTable<0 then assume a table number given by iTab.
**
+** If pParse is not NULL, then the values of bound variables in pE1 are
+** compared against literal values in pE2 and pParse->pVdbe->expmask is
+** modified to record which bound variables are referenced. If pParse
+** is NULL, then false will be returned if pE1 contains any bound variables.
+**
** When in doubt, return false. Returning true might give a performance
** improvement. Returning false might cause a performance reduction, but
** it will always give the correct answer and is hence always safe.
*/
-SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){
- if( sqlite3ExprCompare(pE1, pE2, iTab)==0 ){
+SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){
+ if( sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){
return 1;
}
if( pE2->op==TK_OR
- && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab)
- || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) )
+ && (sqlite3ExprImpliesExpr(pParse, pE1, pE2->pLeft, iTab)
+ || sqlite3ExprImpliesExpr(pParse, pE1, pE2->pRight, iTab) )
){
return 1;
}
- if( pE2->op==TK_NOTNULL
- && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0
- && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS)
- ){
- return 1;
+ if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){
+ Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft);
+ testcase( pX!=pE1->pLeft );
+ if( sqlite3ExprCompare(pParse, pX, pE2->pLeft, iTab)==0 ) return 1;
}
return 0;
}
@@ -97521,8 +99827,8 @@ SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
Walker w;
struct SrcCount cnt;
assert( pExpr->op==TK_AGG_FUNCTION );
- memset(&w, 0, sizeof(w));
w.xExprCallback = exprSrcCount;
+ w.xSelectCallback = 0;
w.u.pSrcCount = &cnt;
cnt.pSrc = pSrcList;
cnt.nThis = 0;
@@ -97654,7 +99960,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; inFunc; i++, pItem++){
- if( sqlite3ExprCompare(pItem->pExpr, pExpr, -1)==0 ){
+ if( sqlite3ExprCompare(0, pItem->pExpr, pExpr, -1)==0 ){
break;
}
}
@@ -97694,10 +100000,14 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
return WRC_Continue;
}
static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
- UNUSED_PARAMETER(pWalker);
UNUSED_PARAMETER(pSelect);
+ pWalker->walkerDepth++;
return WRC_Continue;
}
+static void analyzeAggregatesInSelectEnd(Walker *pWalker, Select *pSelect){
+ UNUSED_PARAMETER(pSelect);
+ pWalker->walkerDepth--;
+}
/*
** Analyze the pExpr expression looking for aggregate functions and
@@ -97710,9 +100020,10 @@ static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
*/
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
Walker w;
- memset(&w, 0, sizeof(w));
w.xExprCallback = analyzeAggregate;
w.xSelectCallback = analyzeAggregatesInSelect;
+ w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
+ w.walkerDepth = 0;
w.u.pNC = pNC;
assert( pNC->pSrcList!=0 );
sqlite3WalkExpr(&w, pExpr);
@@ -97813,8 +100124,8 @@ SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse *pParse){
SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int iLast){
int i;
if( pParse->nRangeReg>0
- && pParse->iRangeReg+pParse->nRangeRegiRangeReg>=iFirst
+ && pParse->iRangeReg+pParse->nRangeReg > iFirst
+ && pParse->iRangeReg <= iLast
){
return 0;
}
@@ -98206,7 +100517,7 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
** Or, if zName is not a system table, zero is returned.
*/
static int isSystemTable(Parse *pParse, const char *zName){
- if( sqlite3Strlen30(zName)>6 && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
+ if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "table %s may not be altered", zName);
return 1;
}
@@ -98335,7 +100646,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
sqlite3NestedParse(pParse,
"UPDATE \"%w\".%s SET "
"sql = sqlite_rename_parent(sql, %Q, %Q) "
- "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere);
+ "WHERE %s;", zDb, MASTER_NAME, zTabName, zName, zWhere);
sqlite3DbFree(db, zWhere);
}
}
@@ -98359,7 +100670,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
"ELSE name END "
"WHERE tbl_name=%Q COLLATE nocase AND "
"(type='table' OR type='index' OR type='trigger');",
- zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
+ zDb, MASTER_NAME, zName, zName, zName,
#ifndef SQLITE_OMIT_TRIGGER
zName,
#endif
@@ -98520,7 +100831,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
"UPDATE \"%w\".%s SET "
"sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
"WHERE type = 'table' AND name = %Q",
- zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
+ zDb, MASTER_NAME, pNew->addColOffset, zCol, pNew->addColOffset+1,
zTab
);
sqlite3DbFree(db, zCol);
@@ -98604,7 +100915,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table));
if( !pNew ) goto exit_begin_add_column;
pParse->pNewTable = pNew;
- pNew->nRef = 1;
+ pNew->nTabRef = 1;
pNew->nCol = pTab->nCol;
assert( pNew->nCol>0 );
nAlloc = (((pNew->nCol-1)/8)*8)+8;
@@ -98624,7 +100935,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
}
pNew->pSchema = db->aDb[iDb].pSchema;
pNew->addColOffset = pTab->addColOffset;
- pNew->nRef = 1;
+ pNew->nTabRef = 1;
/* Begin a transaction and increment the schema cookie. */
sqlite3BeginWriteOperation(pParse, 0, iDb);
@@ -98932,6 +101243,7 @@ struct Stat4Accum {
Stat4Sample *aBest; /* Array of nCol best samples */
int iMin; /* Index in a[] of entry with minimum score */
int nSample; /* Current number of samples */
+ int nMaxEqZero; /* Max leading 0 in anEq[] for any a[] entry */
int iGet; /* Index of current sample accessed by stat_get() */
Stat4Sample *a; /* Array of mxSample Stat4Sample objects */
sqlite3 *db; /* Database connection, for malloc() */
@@ -99196,6 +101508,13 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
assert( IsStat4 || nEqZero==0 );
#ifdef SQLITE_ENABLE_STAT4
+ /* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0
+ ** values in the anEq[] array of any sample in Stat4Accum.a[]. In
+ ** other words, if nMaxEqZero is n, then it is guaranteed that there
+ ** are no samples with Stat4Sample.anEq[m]==0 for (m>=n). */
+ if( nEqZero>p->nMaxEqZero ){
+ p->nMaxEqZero = nEqZero;
+ }
if( pNew->isPSample==0 ){
Stat4Sample *pUpgrade = 0;
assert( pNew->anEq[pNew->iCol]>0 );
@@ -99293,12 +101612,22 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){
}
}
- /* Update the anEq[] fields of any samples already collected. */
+ /* Check that no sample contains an anEq[] entry with an index of
+ ** p->nMaxEqZero or greater set to zero. */
for(i=p->nSample-1; i>=0; i--){
int j;
- for(j=iChng; jnCol; j++){
- if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j];
+ for(j=p->nMaxEqZero; jnCol; j++) assert( p->a[i].anEq[j]>0 );
+ }
+
+ /* Update the anEq[] fields of any samples already collected. */
+ if( iChngnMaxEqZero ){
+ for(i=p->nSample-1; i>=0; i--){
+ int j;
+ for(j=iChng; jnCol; j++){
+ if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j];
+ }
}
+ p->nMaxEqZero = iChng;
}
#endif
@@ -99439,6 +101768,12 @@ static const FuncDef statPushFuncdef = {
** The content to returned is determined by the parameter J
** which is one of the STAT_GET_xxxx values defined above.
**
+** The stat_get(P,J) function is not available to generic SQL. It is
+** inserted as part of a manually constructed bytecode program. (See
+** the callStatGet() routine below.) It is guaranteed that the P
+** parameter will always be a poiner to a Stat4Accum object, never a
+** NULL.
+**
** If neither STAT3 nor STAT4 are enabled, then J is always
** STAT_GET_STAT1 and is hence omitted and this routine becomes
** a one-parameter function, stat_get(P), that always returns the
@@ -99822,7 +102157,7 @@ static void analyzeOneTable(
regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
for(j=0; jnKeyCol; j++){
k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
- assert( k>=0 && knCol );
+ assert( k>=0 && knColumn );
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
}
@@ -100006,27 +102341,14 @@ SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
if( i==1 ) continue; /* Do not analyze the TEMP database */
analyzeDatabase(pParse, i);
}
- }else if( pName2->n==0 ){
- /* Form 2: Analyze the database or table named */
- iDb = sqlite3FindDb(db, pName1);
- if( iDb>=0 ){
- analyzeDatabase(pParse, iDb);
- }else{
- z = sqlite3NameFromToken(db, pName1);
- if( z ){
- if( (pIdx = sqlite3FindIndex(db, z, 0))!=0 ){
- analyzeTable(pParse, pIdx->pTable, pIdx);
- }else if( (pTab = sqlite3LocateTable(pParse, 0, z, 0))!=0 ){
- analyzeTable(pParse, pTab, 0);
- }
- sqlite3DbFree(db, z);
- }
- }
+ }else if( pName2->n==0 && (iDb = sqlite3FindDb(db, pName1))>=0 ){
+ /* Analyze the schema named as the argument */
+ analyzeDatabase(pParse, iDb);
}else{
- /* Form 3: Analyze the fully qualified table name */
+ /* Form 3: Analyze the table or index named as an argument */
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
if( iDb>=0 ){
- zDb = db->aDb[iDb].zDbSName;
+ zDb = pName2->n ? db->aDb[iDb].zDbSName : 0;
z = sqlite3NameFromToken(db, pTableName);
if( z ){
if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){
@@ -100036,10 +102358,11 @@ SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
}
sqlite3DbFree(db, z);
}
- }
+ }
+ }
+ if( db->nSqlExec==0 && (v = sqlite3GetVdbe(pParse))!=0 ){
+ sqlite3VdbeAddOp0(v, OP_Expire);
}
- v = sqlite3GetVdbe(pParse);
- if( v ) sqlite3VdbeAddOp0(v, OP_Expire);
}
/*
@@ -100168,7 +102491,11 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
#endif
pIndex->bUnordered = 0;
decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex);
- if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
+ pIndex->hasStat1 = 1;
+ if( pIndex->pPartIdxWhere==0 ){
+ pTable->nRowLogEst = pIndex->aiRowLogEst[0];
+ pTable->tabFlags |= TF_HasStat1;
+ }
}else{
Index fakeIdx;
fakeIdx.szIdxRow = pTable->szTabRow;
@@ -100177,6 +102504,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
#endif
decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx);
pTable->szTabRow = fakeIdx.szIdxRow;
+ pTable->tabFlags |= TF_HasStat1;
}
return 0;
@@ -100257,7 +102585,7 @@ static void initAvgEq(Index *pIdx){
}
}
- if( nDist100>nSum100 ){
+ if( nDist100>nSum100 && sumEqp, sqlite3_column_blob(pStmt, 4), pSample->n);
+ if( pSample->n ){
+ memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n);
+ }
pIdx->nSample++;
}
rc = sqlite3_finalize(pStmt);
@@ -100469,15 +102799,20 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
HashElem *i;
char *zSql;
int rc = SQLITE_OK;
+ Schema *pSchema = db->aDb[iDb].pSchema;
assert( iDb>=0 && iDbnDb );
assert( db->aDb[iDb].pBt!=0 );
/* Clear any prior statistics */
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
+ for(i=sqliteHashFirst(&pSchema->tblHash); i; i=sqliteHashNext(i)){
+ Table *pTab = sqliteHashData(i);
+ pTab->tabFlags &= ~TF_HasStat1;
+ }
+ for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
- pIdx->aiRowLogEst[0] = 0;
+ pIdx->hasStat1 = 0;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
sqlite3DeleteIndexSamples(db, pIdx);
pIdx->aSample = 0;
@@ -100500,9 +102835,9 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
/* Set appropriate defaults on all indexes not in the sqlite_stat1 table */
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
+ for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
- if( pIdx->aiRowLogEst[0]==0 ) sqlite3DefaultRowEst(pIdx);
+ if( !pIdx->hasStat1 ) sqlite3DefaultRowEst(pIdx);
}
/* Load the statistics from the sqlite_stat4 table. */
@@ -100512,7 +102847,7 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
rc = loadStat4(db, sInfo.zDatabase);
db->lookaside.bDisable--;
}
- for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
+ for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
sqlite3_free(pIdx->aiRowEst);
pIdx->aiRowEst = 0;
@@ -100601,7 +102936,8 @@ static void attachFunc(
char *zPath = 0;
char *zErr = 0;
unsigned int flags;
- Db *aNew;
+ Db *aNew; /* New array of Db pointers */
+ Db *pNew; /* Db object for the newly attached database */
char *zErrDyn = 0;
sqlite3_vfs *pVfs;
@@ -100649,8 +102985,8 @@ static void attachFunc(
if( aNew==0 ) return;
}
db->aDb = aNew;
- aNew = &db->aDb[db->nDb];
- memset(aNew, 0, sizeof(*aNew));
+ pNew = &db->aDb[db->nDb];
+ memset(pNew, 0, sizeof(*pNew));
/* Open the database file. If the btree is successfully opened, use
** it to obtain the database schema. At this point the schema may
@@ -100666,36 +103002,37 @@ static void attachFunc(
}
assert( pVfs );
flags |= SQLITE_OPEN_MAIN_DB;
- rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
+ rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
sqlite3_free( zPath );
db->nDb++;
+ db->skipBtreeMutex = 0;
if( rc==SQLITE_CONSTRAINT ){
rc = SQLITE_ERROR;
zErrDyn = sqlite3MPrintf(db, "database is already attached");
}else if( rc==SQLITE_OK ){
Pager *pPager;
- aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);
- if( !aNew->pSchema ){
+ pNew->pSchema = sqlite3SchemaGet(db, pNew->pBt);
+ if( !pNew->pSchema ){
rc = SQLITE_NOMEM_BKPT;
- }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
+ }else if( pNew->pSchema->file_format && pNew->pSchema->enc!=ENC(db) ){
zErrDyn = sqlite3MPrintf(db,
"attached databases must use the same text encoding as main database");
rc = SQLITE_ERROR;
}
- sqlite3BtreeEnter(aNew->pBt);
- pPager = sqlite3BtreePager(aNew->pBt);
+ sqlite3BtreeEnter(pNew->pBt);
+ pPager = sqlite3BtreePager(pNew->pBt);
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
- sqlite3BtreeSecureDelete(aNew->pBt,
+ sqlite3BtreeSecureDelete(pNew->pBt,
sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
- sqlite3BtreeSetPagerFlags(aNew->pBt,
+ sqlite3BtreeSetPagerFlags(pNew->pBt,
PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK));
#endif
- sqlite3BtreeLeave(aNew->pBt);
+ sqlite3BtreeLeave(pNew->pBt);
}
- aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
- aNew->zDbSName = sqlite3DbStrDup(db, zName);
- if( rc==SQLITE_OK && aNew->zDbSName==0 ){
+ pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
+ pNew->zDbSName = sqlite3DbStrDup(db, zName);
+ if( rc==SQLITE_OK && pNew->zDbSName==0 ){
rc = SQLITE_NOMEM_BKPT;
}
@@ -101333,6 +103670,18 @@ SQLITE_PRIVATE int sqlite3AuthCheck(
if( db->xAuth==0 ){
return SQLITE_OK;
}
+
+ /* EVIDENCE-OF: R-43249-19882 The third through sixth parameters to the
+ ** callback are either NULL pointers or zero-terminated strings that
+ ** contain additional details about the action to be authorized.
+ **
+ ** The following testcase() macros show that any of the 3rd through 6th
+ ** parameters can be either NULL or a string. */
+ testcase( zArg1==0 );
+ testcase( zArg2==0 );
+ testcase( zArg3==0 );
+ testcase( pParse->zAuthContext==0 );
+
rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext
#ifdef SQLITE_USER_AUTHENTICATION
,db->auth.zAuthUser
@@ -101411,10 +103760,10 @@ SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext *pContext){
** codeTableLocks() functions.
*/
struct TableLock {
- int iDb; /* The database containing the table to be locked */
- int iTab; /* The root page of the table to be locked */
- u8 isWriteLock; /* True for write lock. False for a read lock */
- const char *zName; /* Name of the table */
+ int iDb; /* The database containing the table to be locked */
+ int iTab; /* The root page of the table to be locked */
+ u8 isWriteLock; /* True for write lock. False for a read lock */
+ const char *zLockName; /* Name of the table */
};
/*
@@ -101440,6 +103789,8 @@ SQLITE_PRIVATE void sqlite3TableLock(
TableLock *p;
assert( iDb>=0 );
+ if( iDb==1 ) return;
+ if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
for(i=0; inTableLock; i++){
p = &pToplevel->aTableLock[i];
if( p->iDb==iDb && p->iTab==iTab ){
@@ -101456,7 +103807,7 @@ SQLITE_PRIVATE void sqlite3TableLock(
p->iDb = iDb;
p->iTab = iTab;
p->isWriteLock = isWriteLock;
- p->zName = zName;
+ p->zLockName = zName;
}else{
pToplevel->nTableLock = 0;
sqlite3OomFault(pToplevel->db);
@@ -101478,7 +103829,7 @@ static void codeTableLocks(Parse *pParse){
TableLock *p = &pParse->aTableLock[i];
int p1 = p->iDb;
sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock,
- p->zName, P4_STATIC);
+ p->zLockName, P4_STATIC);
}
}
#else
@@ -101687,15 +104038,22 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const cha
return 0;
}
#endif
- for(i=OMIT_TEMPDB; inDb; i++){
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
- assert( sqlite3SchemaMutexHeld(db, j, 0) );
- p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
- if( p ) break;
+ while(1){
+ for(i=OMIT_TEMPDB; inDb; i++){
+ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
+ if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
+ assert( sqlite3SchemaMutexHeld(db, j, 0) );
+ p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
+ if( p ) return p;
+ }
}
+ /* Not found. If the name we were looking for was temp.sqlite_master
+ ** then change the name to sqlite_temp_master and try again. */
+ if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break;
+ if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
+ zName = TEMP_MASTER_NAME;
}
- return p;
+ return 0;
}
/*
@@ -101731,6 +104089,9 @@ SQLITE_PRIVATE Table *sqlite3LocateTable(
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName);
+ if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
+ pMod = sqlite3PragmaVtabRegister(pParse->db, zName);
+ }
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
return pMod->pEpoTab;
}
@@ -102013,7 +104374,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
/* Do not delete the table until the reference count reaches zero. */
if( !pTable ) return;
- if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return;
+ if( ((!db || db->pnBytesFreed==0) && (--pTable->nTabRef)>0) ) return;
deleteTable(db, pTable);
}
@@ -102067,7 +104428,7 @@ SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
*/
SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){
Vdbe *v = sqlite3GetVdbe(p);
- sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
+ sqlite3TableLock(p, iDb, MASTER_ROOT, 1, MASTER_NAME);
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
if( p->nTab==0 ){
p->nTab = 1;
@@ -102085,7 +104446,10 @@ SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *db, const char *zName){
if( zName ){
Db *pDb;
for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
- if( 0==sqlite3StrICmp(pDb->zDbSName, zName) ) break;
+ if( 0==sqlite3_stricmp(pDb->zDbSName, zName) ) break;
+ /* "main" is always an acceptable alias for the primary database
+ ** even if it has been renamed using SQLITE_DBCONFIG_MAINDBNAME. */
+ if( i==0 && 0==sqlite3_stricmp("main", zName) ) break;
}
}
return i;
@@ -102304,8 +104668,12 @@ SQLITE_PRIVATE void sqlite3StartTable(
pTable->zName = zName;
pTable->iPKey = -1;
pTable->pSchema = db->aDb[iDb].pSchema;
- pTable->nRef = 1;
+ pTable->nTabRef = 1;
+#ifdef SQLITE_DEFAULT_ROWEST
+ pTable->nRowLogEst = sqlite3LogEst(SQLITE_DEFAULT_ROWEST);
+#else
pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
+#endif
assert( pParse->pNewTable==0 );
pParse->pNewTable = pTable;
@@ -102481,6 +104849,7 @@ SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){
p = pParse->pNewTable;
if( p==0 || NEVER(p->nCol<1) ) return;
p->aCol[p->nCol-1].notNull = (u8)onError;
+ p->tabFlags |= TF_HasNotNull;
}
/*
@@ -103099,15 +105468,6 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
}else{
pPk = sqlite3PrimaryKeyIndex(pTab);
- /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
- ** table entry. This is only required if currently generating VDBE
- ** code for a CREATE TABLE (not when parsing one as part of reading
- ** a database schema). */
- if( v ){
- assert( db->init.busy==0 );
- sqlite3VdbeChangeOpcode(v, pPk->tnum, OP_Goto);
- }
-
/*
** Remove all redundant columns from the PRIMARY KEY. For example, change
** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later
@@ -103127,6 +105487,15 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
if( !db->init.imposterTable ) pPk->uniqNotNull = 1;
nPk = pPk->nKeyCol;
+ /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
+ ** table entry. This is only required if currently generating VDBE
+ ** code for a CREATE TABLE (not when parsing one as part of reading
+ ** a database schema). */
+ if( v && pPk->tnum>0 ){
+ assert( db->init.busy==0 );
+ sqlite3VdbeChangeOpcode(v, pPk->tnum, OP_Goto);
+ }
+
/* The root page of the PRIMARY KEY is the table root page */
pPk->tnum = pTab->tnum;
@@ -103370,7 +105739,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
"UPDATE %Q.%s "
"SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "
"WHERE rowid=#%d",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
+ db->aDb[iDb].zDbSName, MASTER_NAME,
zType,
p->zName,
p->zName,
@@ -103707,7 +106076,7 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){
*/
sqlite3NestedParse(pParse,
"UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
- pParse->db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), iTable, r1, r1);
+ pParse->db->aDb[iDb].zDbSName, MASTER_NAME, iTable, r1, r1);
#endif
sqlite3ReleaseTempReg(pParse, r1);
}
@@ -103850,7 +106219,7 @@ SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, in
*/
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
- pDb->zDbSName, SCHEMA_TABLE(iDb), pTab->zName);
+ pDb->zDbSName, MASTER_NAME, pTab->zName);
if( !isView && !IsVirtual(pTab) ){
destroyTable(pParse, pTab);
}
@@ -104197,7 +106566,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
}
sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1);
- sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
@@ -104742,7 +107111,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
*/
sqlite3NestedParse(pParse,
"INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
+ db->aDb[iDb].zDbSName, MASTER_NAME,
pIndex->zName,
pTab->zName,
iMem,
@@ -104820,6 +107189,9 @@ SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){
int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
int i;
+ /* Indexes with default row estimates should not have stat1 data */
+ assert( !pIdx->hasStat1 );
+
/* Set the first entry (number of rows in the index) to the estimated
** number of rows in the table, or half the number of rows in the table
** for a partial index. But do not let the estimate drop below 10. */
@@ -104894,7 +107266,7 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists
sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pIndex->zName
+ db->aDb[iDb].zDbSName, MASTER_NAME, pIndex->zName
);
sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
sqlite3ChangeCookie(pParse, iDb);
@@ -104985,7 +107357,7 @@ SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
sqlite3DbFree(db, pList->a[i].zName);
}
sqlite3DbFree(db, pList->a);
- sqlite3DbFree(db, pList);
+ sqlite3DbFreeNN(db, pList);
}
/*
@@ -105037,7 +107409,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
/* Allocate additional space if needed */
if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
SrcList *pNew;
- int nAlloc = pSrc->nSrc+nExtra;
+ int nAlloc = pSrc->nSrc*2+nExtra;
int nGot;
pNew = sqlite3DbRealloc(db, pSrc,
sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
@@ -105115,9 +107487,12 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) );
if( pList==0 ) return 0;
pList->nAlloc = 1;
- pList->nSrc = 0;
+ pList->nSrc = 1;
+ memset(&pList->a[0], 0, sizeof(pList->a[0]));
+ pList->a[0].iCursor = -1;
+ }else{
+ pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
}
- pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
if( db->mallocFailed ){
sqlite3SrcListDelete(db, pList);
return 0;
@@ -105127,12 +107502,12 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
pDatabase = 0;
}
if( pDatabase ){
- Token *pTemp = pDatabase;
- pDatabase = pTable;
- pTable = pTemp;
+ pItem->zName = sqlite3NameFromToken(db, pDatabase);
+ pItem->zDatabase = sqlite3NameFromToken(db, pTable);
+ }else{
+ pItem->zName = sqlite3NameFromToken(db, pTable);
+ pItem->zDatabase = 0;
}
- pItem->zName = sqlite3NameFromToken(db, pTable);
- pItem->zDatabase = sqlite3NameFromToken(db, pDatabase);
return pList;
}
@@ -105172,7 +107547,7 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
sqlite3ExprDelete(db, pItem->pOn);
sqlite3IdListDelete(db, pItem->pUsing);
}
- sqlite3DbFree(db, pList);
+ sqlite3DbFreeNN(db, pList);
}
/*
@@ -105321,36 +107696,25 @@ SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){
}
/*
-** Generate VDBE code for a COMMIT statement.
+** Generate VDBE code for a COMMIT or ROLLBACK statement.
+** Code for ROLLBACK is generated if eType==TK_ROLLBACK. Otherwise
+** code is generated for a COMMIT.
*/
-SQLITE_PRIVATE void sqlite3CommitTransaction(Parse *pParse){
+SQLITE_PRIVATE void sqlite3EndTransaction(Parse *pParse, int eType){
Vdbe *v;
+ int isRollback;
assert( pParse!=0 );
assert( pParse->db!=0 );
- if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ){
+ assert( eType==TK_COMMIT || eType==TK_END || eType==TK_ROLLBACK );
+ isRollback = eType==TK_ROLLBACK;
+ if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION,
+ isRollback ? "ROLLBACK" : "COMMIT", 0, 0) ){
return;
}
v = sqlite3GetVdbe(pParse);
if( v ){
- sqlite3VdbeAddOp1(v, OP_AutoCommit, 1);
- }
-}
-
-/*
-** Generate VDBE code for a ROLLBACK statement.
-*/
-SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse *pParse){
- Vdbe *v;
-
- assert( pParse!=0 );
- assert( pParse->db!=0 );
- if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ){
- return;
- }
- v = sqlite3GetVdbe(pParse);
- if( v ){
- sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 1);
+ sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, isRollback);
}
}
@@ -105540,7 +107904,9 @@ SQLITE_PRIVATE void sqlite3UniqueConstraint(
assert( pIdx->aiColumn[j]>=0 );
zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2);
- sqlite3XPrintf(&errMsg, "%s.%s", pTab->zName, zCol);
+ sqlite3StrAccumAppendAll(&errMsg, pTab->zName);
+ sqlite3StrAccumAppend(&errMsg, ".", 1);
+ sqlite3StrAccumAppendAll(&errMsg, zCol);
}
}
zErr = sqlite3StrAccumFinish(&errMsg);
@@ -105929,7 +108295,7 @@ SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
** from the main database is substituted, if one is available.
*/
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
- if( pColl ){
+ if( pColl && pColl->xCmp==0 ){
const char *zName = pColl->zName;
sqlite3 *db = pParse->db;
CollSeq *p = sqlite3GetCollSeq(pParse, ENC(db), pColl, zName);
@@ -105965,8 +108331,8 @@ static CollSeq *findCollSeqEntry(
pColl = sqlite3HashFind(&db->aCollSeq, zName);
if( 0==pColl && create ){
- int nName = sqlite3Strlen30(zName);
- pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1);
+ int nName = sqlite3Strlen30(zName) + 1;
+ pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName);
if( pColl ){
CollSeq *pDel = 0;
pColl[0].zName = (char*)&pColl[3];
@@ -105976,7 +108342,6 @@ static CollSeq *findCollSeqEntry(
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, pColl);
/* If a malloc() failure occurred in sqlite3HashInsert(), it will
@@ -106116,7 +108481,8 @@ SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(
FuncDef *pOther;
const char *zName = aDef[i].zName;
int nName = sqlite3Strlen30(zName);
- int h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ;
+ int h = (zName[0] + nName) % SQLITE_FUNC_HASH_SZ;
+ assert( zName[0]>='a' && zName[0]<='z' );
pOther = functionSearch(h, zName);
if( pOther ){
assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );
@@ -106332,7 +108698,7 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
sqlite3DeleteTable(pParse->db, pItem->pTab);
pItem->pTab = pTab;
if( pTab ){
- pTab->nRef++;
+ pTab->nTabRef++;
}
if( sqlite3IndexedByLookup(pParse, pItem) ){
pTab = 0;
@@ -106460,7 +108826,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
** );
*/
- pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
+ pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0);
if( pSelectRowid == 0 ) goto limit_where_cleanup;
pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid);
if( pEList == 0 ) goto limit_where_cleanup;
@@ -106479,8 +108845,8 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
if( pSelect == 0 ) return 0;
/* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
- pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
- pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0) : 0;
+ pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0);
+ pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0) : 0;
sqlite3PExprAddSelect(pParse, pInClause, pSelect);
return pInClause;
@@ -106646,7 +109012,14 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
/* Special case: A DELETE without a WHERE clause deletes everything.
** It is easier just to erase the whole table. Prior to version 3.6.5,
** this optimization caused the row change count (the value returned by
- ** API function sqlite3_count_changes) to be set incorrectly. */
+ ** API function sqlite3_count_changes) to be set incorrectly.
+ **
+ ** The "rcauth==SQLITE_OK" terms is the
+ ** IMPLEMENTATION-OF: R-17228-37124 If the action code is SQLITE_DELETE and
+ ** the callback returns SQLITE_IGNORE then the DELETE operation proceeds but
+ ** the truncate optimization is disabled and all rows are deleted
+ ** individually.
+ */
if( rcauth==SQLITE_OK
&& pWhere==0
&& !bComplex
@@ -106745,10 +109118,10 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
nKey = 0; /* Zero tells OP_Found to use a composite key */
sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
sqlite3IndexAffinityStr(pParse->db, pPk), nPk);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk);
}else{
/* Add the rowid of the row to be deleted to the RowSet */
- nKey = 1; /* OP_Seek always uses a single rowid */
+ nKey = 1; /* OP_DeferredSeek always uses a single rowid */
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
}
}
@@ -106791,7 +109164,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
}
}else if( pPk ){
addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey);
+ sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey);
assert( nKey==0 ); /* OP_Found will use a composite key */
}else{
addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey);
@@ -106815,12 +109188,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
#endif
{
int count = (pParse->nested==0); /* True to count changes */
- int iIdxNoSeek = -1;
- if( bComplex==0 && aiCurOnePass[1]!=iDataCur ){
- iIdxNoSeek = aiCurOnePass[1];
- }
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
- iKey, nKey, count, OE_Default, eOnePass, iIdxNoSeek);
+ iKey, nKey, count, OE_Default, eOnePass, aiCurOnePass[1]);
}
/* End of the loop over all rowids/primary-keys. */
@@ -106834,14 +109203,6 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
sqlite3VdbeGoto(v, addrLoop);
sqlite3VdbeJumpHere(v, addrLoop);
}
-
- /* Close the cursors open on the table and its indexes. */
- if( !isView && !IsVirtual(pTab) ){
- if( !pPk ) sqlite3VdbeAddOp1(v, OP_Close, iDataCur);
- for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
- sqlite3VdbeAddOp1(v, OP_Close, iIdxCur + i);
- }
- }
} /* End non-truncate path */
/* Update the sqlite_sequence table by storing the content of the
@@ -106908,15 +109269,17 @@ delete_from_cleanup:
**
** If eMode is ONEPASS_MULTI, then this call is being made as part
** of a ONEPASS delete that affects multiple rows. In this case, if
-** iIdxNoSeek is a valid cursor number (>=0), then its position should
-** be preserved following the delete operation. Or, if iIdxNoSeek is not
-** a valid cursor number, the position of iDataCur should be preserved
-** instead.
+** iIdxNoSeek is a valid cursor number (>=0) and is not the same as
+** iDataCur, then its position should be preserved following the delete
+** operation. Or, if iIdxNoSeek is not a valid cursor number, the
+** position of iDataCur should be preserved instead.
**
** iIdxNoSeek:
-** If iIdxNoSeek is a valid cursor number (>=0), then it identifies an
-** index cursor (from within array of cursors starting at iIdxCur) that
-** already points to the index entry to be deleted.
+** If iIdxNoSeek is a valid cursor number (>=0) not equal to iDataCur,
+** then it identifies an index cursor (from within array of cursors
+** starting at iIdxCur) that already points to the index entry to be deleted.
+** Except, this optimization is disabled if there are BEFORE triggers since
+** the trigger body might have moved the cursor.
*/
SQLITE_PRIVATE void sqlite3GenerateRowDelete(
Parse *pParse, /* Parsing context */
@@ -106987,13 +109350,18 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
/* If any BEFORE triggers were coded, then seek the cursor to the
** row to be deleted again. It may be that the BEFORE triggers moved
- ** the cursor or of already deleted the row that the cursor was
+ ** the cursor or already deleted the row that the cursor was
** pointing to.
+ **
+ ** Also disable the iIdxNoSeek optimization since the BEFORE trigger
+ ** may have moved that cursor.
*/
if( addrStart=0 );
+ iIdxNoSeek = -1;
}
/* Do FK processing. This call checks that any FK constraints that
@@ -107016,11 +109384,13 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
u8 p5 = 0;
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
- sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE);
+ if( pParse->nested==0 ){
+ sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
+ }
if( eMode!=ONEPASS_OFF ){
sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE);
}
- if( iIdxNoSeek>=0 ){
+ if( iIdxNoSeek>=0 && iIdxNoSeek!=iDataCur ){
sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek);
}
if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION;
@@ -107144,10 +109514,11 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
if( piPartIdxLabel ){
if( pIdx->pPartIdxWhere ){
*piPartIdxLabel = sqlite3VdbeMakeLabel(v);
- pParse->iSelfTab = iDataCur;
+ pParse->iSelfTab = iDataCur + 1;
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
SQLITE_JUMPIFNULL);
+ pParse->iSelfTab = 0;
}else{
*piPartIdxLabel = 0;
}
@@ -107174,6 +109545,10 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
}
if( regOut ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
+ if( pIdx->pTable->pSelect ){
+ const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx);
+ sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
+ }
}
sqlite3ReleaseTempRange(pParse, regBase, nCol);
return regBase;
@@ -107271,16 +109646,20 @@ static void typeofFunc(
int NotUsed,
sqlite3_value **argv
){
- const char *z = 0;
+ static const char *azType[] = { "integer", "real", "text", "blob", "null" };
+ int i = sqlite3_value_type(argv[0]) - 1;
UNUSED_PARAMETER(NotUsed);
- switch( sqlite3_value_type(argv[0]) ){
- case SQLITE_INTEGER: z = "integer"; break;
- case SQLITE_TEXT: z = "text"; break;
- case SQLITE_FLOAT: z = "real"; break;
- case SQLITE_BLOB: z = "blob"; break;
- default: z = "null"; break;
- }
- sqlite3_result_text(context, z, -1, SQLITE_STATIC);
+ assert( i>=0 && i0 ){
+ if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
+ zHaystack = sqlite3_value_blob(argv[0]);
+ zNeedle = sqlite3_value_blob(argv[1]);
+ isText = 0;
+ }else{
+ zHaystack = sqlite3_value_text(argv[0]);
+ zNeedle = sqlite3_value_text(argv[1]);
+ isText = 1;
+ }
+ if( zNeedle==0 || (nHaystack && zHaystack==0) ) return;
+ while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
+ N++;
+ do{
+ nHaystack--;
+ zHaystack++;
+ }while( isText && (zHaystack[0]&0xc0)==0x80 );
+ }
+ if( nNeedle>nHaystack ) N = 0;
}
- while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
- N++;
- do{
- nHaystack--;
- zHaystack++;
- }while( isText && (zHaystack[0]&0xc0)==0x80 );
- }
- if( nNeedle>nHaystack ) N = 0;
sqlite3_result_int(context, N);
}
@@ -107793,9 +110173,19 @@ static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 };
static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
/*
-** Compare two UTF-8 strings for equality where the first string can
-** potentially be a "glob" or "like" expression. Return true (1) if they
-** are the same and false (0) if they are different.
+** Possible error returns from patternMatch()
+*/
+#define SQLITE_MATCH 0
+#define SQLITE_NOMATCH 1
+#define SQLITE_NOWILDCARDMATCH 2
+
+/*
+** Compare two UTF-8 strings for equality where the first string is
+** a GLOB or LIKE expression. Return values:
+**
+** SQLITE_MATCH: Match
+** SQLITE_NOMATCH: No match
+** SQLITE_NOWILDCARDMATCH: No match in spite of having * or % wildcards.
**
** Globbing rules:
**
@@ -107846,30 +110236,31 @@ static int patternCompare(
** single character of the input string for each "?" skipped */
while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){
if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
- return 0;
+ return SQLITE_NOWILDCARDMATCH;
}
}
if( c==0 ){
- return 1; /* "*" at the end of the pattern matches */
+ return SQLITE_MATCH; /* "*" at the end of the pattern matches */
}else if( c==matchOther ){
if( pInfo->matchSet==0 ){
c = sqlite3Utf8Read(&zPattern);
- if( c==0 ) return 0;
+ if( c==0 ) return SQLITE_NOWILDCARDMATCH;
}else{
/* "[...]" immediately follows the "*". We have to do a slow
** recursive search in this case, but it is an unusual case. */
assert( matchOther<0x80 ); /* '[' is a single-byte character */
- while( *zString
- && patternCompare(&zPattern[-1],zString,pInfo,matchOther)==0 ){
+ while( *zString ){
+ int bMatch = patternCompare(&zPattern[-1],zString,pInfo,matchOther);
+ if( bMatch!=SQLITE_NOMATCH ) return bMatch;
SQLITE_SKIP_UTF8(zString);
}
- return *zString!=0;
+ return SQLITE_NOWILDCARDMATCH;
}
}
/* At this point variable c contains the first character of the
** pattern string past the "*". Search in the input string for the
- ** first matching character and recursively contine the match from
+ ** first matching character and recursively continue the match from
** that point.
**
** For a case-insensitive search, set variable cx to be the same as
@@ -107878,6 +110269,7 @@ static int patternCompare(
*/
if( c<=0x80 ){
u32 cx;
+ int bMatch;
if( noCase ){
cx = sqlite3Toupper(c);
c = sqlite3Tolower(c);
@@ -107886,27 +110278,30 @@ static int patternCompare(
}
while( (c2 = *(zString++))!=0 ){
if( c2!=c && c2!=cx ) continue;
- if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1;
+ bMatch = patternCompare(zPattern,zString,pInfo,matchOther);
+ if( bMatch!=SQLITE_NOMATCH ) return bMatch;
}
}else{
+ int bMatch;
while( (c2 = Utf8Read(zString))!=0 ){
if( c2!=c ) continue;
- if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1;
+ bMatch = patternCompare(zPattern,zString,pInfo,matchOther);
+ if( bMatch!=SQLITE_NOMATCH ) return bMatch;
}
}
- return 0;
+ return SQLITE_NOWILDCARDMATCH;
}
if( c==matchOther ){
if( pInfo->matchSet==0 ){
c = sqlite3Utf8Read(&zPattern);
- if( c==0 ) return 0;
+ if( c==0 ) return SQLITE_NOMATCH;
zEscaped = zPattern;
}else{
u32 prior_c = 0;
int seen = 0;
int invert = 0;
c = sqlite3Utf8Read(&zString);
- if( c==0 ) return 0;
+ if( c==0 ) return SQLITE_NOMATCH;
c2 = sqlite3Utf8Read(&zPattern);
if( c2=='^' ){
invert = 1;
@@ -107930,7 +110325,7 @@ static int patternCompare(
c2 = sqlite3Utf8Read(&zPattern);
}
if( c2==0 || (seen ^ invert)==0 ){
- return 0;
+ return SQLITE_NOMATCH;
}
continue;
}
@@ -107941,23 +110336,25 @@ static int patternCompare(
continue;
}
if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue;
- return 0;
+ return SQLITE_NOMATCH;
}
- return *zString==0;
+ return *zString==0 ? SQLITE_MATCH : SQLITE_NOMATCH;
}
/*
-** The sqlite3_strglob() interface.
+** The sqlite3_strglob() interface. Return 0 on a match (like strcmp()) and
+** non-zero if there is no match.
*/
SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){
- return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[')==0;
+ return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[');
}
/*
-** The sqlite3_strlike() interface.
+** The sqlite3_strlike() interface. Return 0 on a match and non-zero for
+** a miss - like strcmp().
*/
SQLITE_API int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){
- return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc)==0;
+ return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc);
}
/*
@@ -108038,7 +110435,7 @@ static void likeFunc(
#ifdef SQLITE_TEST
sqlite3_like_count++;
#endif
- sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
+ sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH);
}
}
@@ -108809,7 +111206,7 @@ static void groupConcatStep(
zSep = ",";
nSep = 1;
}
- if( nSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep);
+ if( zSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep);
}
zVal = (char*)sqlite3_value_text(argv[0]);
nVal = sqlite3_value_bytes(argv[0]);
@@ -108964,6 +111361,9 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
+#ifdef SQLITE_DEBUG
+ FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY),
+#endif
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
FUNCTION(rtrim, 1, 2, 0, trimFunc ),
@@ -109286,7 +111686,7 @@ SQLITE_PRIVATE int sqlite3FkLocateIndex(
}
for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) ){
+ if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) && pIdx->pPartIdxWhere==0 ){
/* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
** of columns. If each indexed column corresponds to a foreign key
** column of pFKey, then this index is a winner. */
@@ -109645,7 +112045,7 @@ static void fkScanChildren(
assert( iCol>=0 );
zCol = pFKey->pFrom->aCol[iCol].zName;
pRight = sqlite3Expr(db, TK_ID, zCol);
- pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0);
+ pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
pWhere = sqlite3ExprAnd(db, pWhere, pEq);
}
@@ -109667,7 +112067,7 @@ static void fkScanChildren(
if( HasRowid(pTab) ){
pLeft = exprTableRegister(pParse, pTab, regData, -1);
pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, -1);
- pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0);
+ pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight);
}else{
Expr *pEq, *pAll = 0;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
@@ -109677,10 +112077,10 @@ static void fkScanChildren(
assert( iCol>=0 );
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol);
- pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0);
+ pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
pAll = sqlite3ExprAnd(db, pAll, pEq);
}
- pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0, 0);
+ pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0);
}
pWhere = sqlite3ExprAnd(db, pWhere, pNe);
}
@@ -109694,10 +112094,12 @@ static void fkScanChildren(
/* Create VDBE to loop through the entries in pSrc that match the WHERE
** clause. For each row found, increment either the deferred or immediate
** foreign key constraint counter. */
- pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
- sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
- if( pWInfo ){
- sqlite3WhereEnd(pWInfo);
+ if( pParse->nErr==0 ){
+ pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
+ sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
+ if( pWInfo ){
+ sqlite3WhereEnd(pWInfo);
+ }
}
/* Clean up the WHERE clause constructed above. */
@@ -110068,7 +112470,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
struct SrcList_item *pItem = pSrc->a;
pItem->pTab = pFKey->pFrom;
pItem->zName = pFKey->pFrom->zName;
- pItem->pTab->nRef++;
+ pItem->pTab->nTabRef++;
pItem->iCursor = pParse->nTab++;
if( regNew!=0 ){
@@ -110148,8 +112550,16 @@ SQLITE_PRIVATE u32 sqlite3FkOldmask(
** UPDATE statement modifies the rowid fields of the table.
**
** If any foreign key processing will be required, this function returns
-** true. If there is no foreign key related processing, this function
-** returns false.
+** non-zero. If there is no foreign key related processing, this function
+** returns zero.
+**
+** For an UPDATE, this function returns 2 if:
+**
+** * There are any FKs for which pTab is the child and the parent table, or
+** * the UPDATE modifies one or more parent keys for which the action is
+** not "NO ACTION" (i.e. is CASCADE, SET DEFAULT or SET NULL).
+**
+** Or, assuming some other foreign key processing is required, 1.
*/
SQLITE_PRIVATE int sqlite3FkRequired(
Parse *pParse, /* Parse context */
@@ -110157,12 +112567,13 @@ SQLITE_PRIVATE int sqlite3FkRequired(
int *aChange, /* Non-NULL for UPDATE operations */
int chngRowid /* True for UPDATE that affects rowid */
){
+ int eRet = 0;
if( pParse->db->flags&SQLITE_ForeignKeys ){
if( !aChange ){
/* A DELETE operation. Foreign key processing is required if the
** table in question is either the child or parent table for any
** foreign key constraint. */
- return (sqlite3FkReferences(pTab) || pTab->pFKey);
+ eRet = (sqlite3FkReferences(pTab) || pTab->pFKey);
}else{
/* This is an UPDATE. Foreign key processing is only required if the
** operation modifies one or more child or parent key columns. */
@@ -110170,16 +112581,22 @@ SQLITE_PRIVATE int sqlite3FkRequired(
/* Check if any child key columns are being modified. */
for(p=pTab->pFKey; p; p=p->pNextFrom){
- if( fkChildIsModified(pTab, p, aChange, chngRowid) ) return 1;
+ if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) return 2;
+ if( fkChildIsModified(pTab, p, aChange, chngRowid) ){
+ eRet = 1;
+ }
}
/* Check if any parent key columns are being modified. */
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
- if( fkParentIsModified(pTab, p, aChange, chngRowid) ) return 1;
+ if( fkParentIsModified(pTab, p, aChange, chngRowid) ){
+ if( p->aAction[1]!=OE_None ) return 2;
+ eRet = 1;
+ }
}
}
}
- return 0;
+ return eRet;
}
/*
@@ -110266,10 +112683,9 @@ static Trigger *fkActionTrigger(
pEq = sqlite3PExpr(pParse, TK_EQ,
sqlite3PExpr(pParse, TK_DOT,
sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
- sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)
- , 0),
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)),
sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0)
- , 0);
+ );
pWhere = sqlite3ExprAnd(db, pWhere, pEq);
/* For ON UPDATE, construct the next term of the WHEN clause.
@@ -110281,13 +112697,11 @@ static Trigger *fkActionTrigger(
pEq = sqlite3PExpr(pParse, TK_IS,
sqlite3PExpr(pParse, TK_DOT,
sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
- sqlite3ExprAlloc(db, TK_ID, &tToCol, 0),
- 0),
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)),
sqlite3PExpr(pParse, TK_DOT,
sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
- sqlite3ExprAlloc(db, TK_ID, &tToCol, 0),
- 0),
- 0);
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0))
+ );
pWhen = sqlite3ExprAnd(db, pWhen, pEq);
}
@@ -110296,8 +112710,7 @@ static Trigger *fkActionTrigger(
if( action==OE_Cascade ){
pNew = sqlite3PExpr(pParse, TK_DOT,
sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
- sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)
- , 0);
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0));
}else if( action==OE_SetDflt ){
Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt;
if( pDflt ){
@@ -110353,7 +112766,7 @@ static Trigger *fkActionTrigger(
pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE);
pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
if( pWhen ){
- pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0, 0);
+ pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0);
pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
}
}
@@ -110957,7 +113370,7 @@ SQLITE_PRIVATE void sqlite3Insert(
sqlite3 *db; /* The main database structure */
Table *pTab; /* The table to insert into. aka TABLE */
char *zTab; /* Name of the table into which we are inserting */
- int i, j, idx; /* Loop counters */
+ int i, j; /* Loop counters */
Vdbe *v; /* Generate code into this virtual machine */
Index *pIdx; /* For looping over indices of the table */
int nColumn; /* Number of columns in the data */
@@ -110993,10 +113406,10 @@ SQLITE_PRIVATE void sqlite3Insert(
#endif
db = pParse->db;
- memset(&dest, 0, sizeof(dest));
if( pParse->nErr || db->mallocFailed ){
goto insert_cleanup;
}
+ dest.iSDParm = 0; /* Suppress a harmless compiler warning */
/* If the Select object is really just a simple VALUES() list with a
** single row (the common case) then keep that one row of values
@@ -111264,8 +113677,10 @@ SQLITE_PRIVATE void sqlite3Insert(
if( aRegIdx==0 ){
goto insert_cleanup;
}
- for(i=0; ipIndex; ipNext, i++){
+ assert( pIdx );
aRegIdx[i] = ++pParse->nMem;
+ pParse->nMem += pIdx->nColumn;
}
}
@@ -111467,12 +113882,26 @@ SQLITE_PRIVATE void sqlite3Insert(
#endif
{
int isReplace; /* Set to true if constraints may cause a replace */
+ int bUseSeek; /* True to use OPFLAG_SEEKRESULT */
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0
);
sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
+
+ /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE
+ ** constraints or (b) there are no triggers and this table is not a
+ ** parent table in a foreign key constraint. It is safe to set the
+ ** flag in the second case as if any REPLACE constraint is hit, an
+ ** OP_Delete or OP_IdxDelete instruction will be executed on each
+ ** cursor that is disturbed. And these instructions both clear the
+ ** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT
+ ** functionality. */
+ bUseSeek = (isReplace==0 || (pTrigger==0 &&
+ ((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0)
+ ));
sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
- regIns, aRegIdx, 0, appendFlag, isReplace==0);
+ regIns, aRegIdx, 0, appendFlag, bUseSeek
+ );
}
}
@@ -111501,14 +113930,6 @@ SQLITE_PRIVATE void sqlite3Insert(
sqlite3VdbeJumpHere(v, addrInsTop);
}
- if( !IsVirtual(pTab) && !isView ){
- /* Close all tables opened */
- if( iDataCurpIndex; pIdx; pIdx=pIdx->pNext, idx++){
- sqlite3VdbeAddOp1(v, OP_Close, idx+iIdxCur);
- }
- }
-
insert_end:
/* Update the sqlite_sequence table by storing the content of the
** maximum rowid counter values recorded while inserting into
@@ -111715,7 +114136,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
int ipkBottom = 0; /* Bottom of the rowid change constraint check */
u8 isUpdate; /* True if this is an UPDATE operation */
u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */
- int regRowid = -1; /* Register holding ROWID value */
isUpdate = regOldData!=0;
db = pParse->db;
@@ -111770,8 +114190,9 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
case OE_Fail: {
char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
pTab->aCol[i].zName);
- sqlite3VdbeAddOp4(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError,
- regNewData+1+i, zMsg, P4_DYNAMIC);
+ sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError,
+ regNewData+1+i);
+ sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
VdbeCoverage(v);
break;
@@ -111797,7 +114218,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
#ifndef SQLITE_OMIT_CHECK
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
ExprList *pCheck = pTab->pCheck;
- pParse->ckBase = regNewData+1;
+ pParse->iSelfTab = -(regNewData+1);
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
for(i=0; inExpr; i++){
int allOk;
@@ -111817,6 +114238,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
sqlite3VdbeResolveLabel(v, allOk);
}
+ pParse->iSelfTab = 0;
}
#endif /* !defined(SQLITE_OMIT_CHECK) */
@@ -111835,7 +114257,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
if( isUpdate ){
- /* pkChng!=0 does not mean that the rowid has change, only that
+ /* pkChng!=0 does not mean that the rowid has changed, only that
** it might have changed. Skip the conflict logic below if the rowid
** is unchanged. */
sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData);
@@ -111913,7 +114335,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** OP_Insert replace the existing entry than it is to delete the
** existing entry and then insert a new one. */
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP);
- sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE);
+ sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
if( pTab->pIndex ){
@@ -111961,29 +114383,27 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
/* Skip partial indices for which the WHERE clause is not true */
if( pIdx->pPartIdxWhere ){
sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]);
- pParse->ckBase = regNewData+1;
+ pParse->iSelfTab = -(regNewData+1);
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, addrUniqueOk,
SQLITE_JUMPIFNULL);
- pParse->ckBase = 0;
+ pParse->iSelfTab = 0;
}
/* Create a record for this index entry as it should appear after
** the insert or update. Store that record in the aRegIdx[ix] register
*/
- regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn);
+ regIdx = aRegIdx[ix]+1;
for(i=0; inColumn; i++){
int iField = pIdx->aiColumn[i];
int x;
if( iField==XN_EXPR ){
- pParse->ckBase = regNewData+1;
+ pParse->iSelfTab = -(regNewData+1);
sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
- pParse->ckBase = 0;
+ pParse->iSelfTab = 0;
VdbeComment((v, "%s column %d", pIdx->zName, i));
}else{
if( iField==XN_ROWID || iField==pTab->iPKey ){
- if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */
x = regNewData;
- regRowid = pIdx->pPartIdxWhere ? -1 : regIdx+i;
}else{
x = iField + regNewData + 1;
}
@@ -111993,7 +114413,9 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
VdbeComment((v, "for %s", pIdx->zName));
- sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn);
+#ifdef SQLITE_ENABLE_NULL_TRIM
+ if( pIdx->idxType==2 ) sqlite3SetMakeRecordP5(v, pIdx->pTable);
+#endif
/* In an UPDATE operation, if this index is the PRIMARY KEY index
** of a WITHOUT ROWID table and there has been no change the
@@ -112007,7 +114429,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
/* Find out what action to take in case there is a uniqueness conflict */
onError = pIdx->onError;
if( onError==OE_None ){
- sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
sqlite3VdbeResolveLabel(v, addrUniqueOk);
continue; /* pIdx is not a UNIQUE index */
}
@@ -112016,7 +114437,26 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}else if( onError==OE_Default ){
onError = OE_Abort;
}
-
+
+ /* Collision detection may be omitted if all of the following are true:
+ ** (1) The conflict resolution algorithm is REPLACE
+ ** (2) The table is a WITHOUT ROWID table
+ ** (3) There are no secondary indexes on the table
+ ** (4) No delete triggers need to be fired if there is a conflict
+ ** (5) No FK constraint counters need to be updated if a conflict occurs.
+ */
+ if( (ix==0 && pIdx->pNext==0) /* Condition 3 */
+ && pPk==pIdx /* Condition 2 */
+ && onError==OE_Replace /* Condition 1 */
+ && ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */
+ 0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0))
+ && ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */
+ (0==pTab->pFKey && 0==sqlite3FkReferences(pTab)))
+ ){
+ sqlite3VdbeResolveLabel(v, addrUniqueOk);
+ continue;
+ }
+
/* Check to see if the new index entry will be unique */
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
@@ -112100,13 +114540,12 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
regR, nPkField, 0, OE_Replace,
- (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), -1);
+ (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
seenReplace = 1;
break;
}
}
sqlite3VdbeResolveLabel(v, addrUniqueOk);
- sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
}
if( ipkTop ){
@@ -112118,6 +114557,28 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace));
}
+#ifdef SQLITE_ENABLE_NULL_TRIM
+/*
+** Change the P5 operand on the last opcode (which should be an OP_MakeRecord)
+** to be the number of columns in table pTab that must not be NULL-trimmed.
+**
+** Or if no columns of pTab may be NULL-trimmed, leave P5 at zero.
+*/
+SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){
+ u16 i;
+
+ /* Records with omitted columns are only allowed for schema format
+ ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */
+ if( pTab->pSchema->file_format<2 ) return;
+
+ for(i=pTab->nCol-1; i>0; i--){
+ if( pTab->aCol[i].pDflt!=0 ) break;
+ if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break;
+ }
+ sqlite3VdbeChangeP5(v, i+1);
+}
+#endif
+
/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite3GenerateConstraintChecks.
@@ -112134,7 +114595,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
int iIdxCur, /* First index cursor */
int regNewData, /* Range of content */
int *aRegIdx, /* Register used by each index. 0 for unused indices */
- int isUpdate, /* True for UPDATE, False for INSERT */
+ int update_flags, /* True for UPDATE, False for INSERT */
int appendBias, /* True if this is likely to be an append */
int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
){
@@ -112146,6 +114607,11 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
int i; /* Loop counter */
u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */
+ assert( update_flags==0
+ || update_flags==OPFLAG_ISUPDATE
+ || update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION)
+ );
+
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
@@ -112156,26 +114622,39 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
}
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]);
- pik_flags = 0;
- if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT;
+ pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
assert( pParse->nested==0 );
pik_flags |= OPFLAG_NCHANGE;
+ pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ if( update_flags==0 ){
+ sqlite3VdbeAddOp4(v, OP_InsertInt,
+ iIdxCur+i, aRegIdx[i], 0, (char*)pTab, P4_TABLE
+ );
+ sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
+ }
+#endif
}
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
+ aRegIdx[i]+1,
+ pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn);
sqlite3VdbeChangeP5(v, pik_flags);
}
if( !HasRowid(pTab) ) return;
regData = regNewData + 1;
regRec = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
- if( !bAffinityDone ) sqlite3TableAffinity(v, pTab, 0);
- sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
+ sqlite3SetMakeRecordP5(v, pTab);
+ if( !bAffinityDone ){
+ sqlite3TableAffinity(v, pTab, 0);
+ sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
+ }
if( pParse->nested ){
pik_flags = 0;
}else{
pik_flags = OPFLAG_NCHANGE;
- pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID);
+ pik_flags |= (update_flags?update_flags:OPFLAG_LASTROWID);
}
if( appendBias ){
pik_flags |= OPFLAG_APPEND;
@@ -112185,7 +114664,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
}
sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData);
if( !pParse->nested ){
- sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE);
+ sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
}
sqlite3VdbeChangeP5(v, pik_flags);
}
@@ -112305,7 +114784,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
}
if( pSrc->aiColumn[i]==XN_EXPR ){
assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 );
- if( sqlite3ExprCompare(pSrc->aColExpr->a[i].pExpr,
+ if( sqlite3ExprCompare(0, pSrc->aColExpr->a[i].pExpr,
pDest->aColExpr->a[i].pExpr, -1)!=0 ){
return 0; /* Different expressions in the index */
}
@@ -112317,7 +114796,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
return 0; /* Different collating sequences */
}
}
- if( sqlite3ExprCompare(pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){
+ if( sqlite3ExprCompare(0, pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){
return 0; /* Different WHERE clauses */
}
@@ -112386,7 +114865,7 @@ static int xferOptimization(
return 0; /* tab1 must not have triggers */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pDest->tabFlags & TF_Virtual ){
+ if( IsVirtual(pDest) ){
return 0; /* tab1 must not be a virtual table */
}
#endif
@@ -112448,7 +114927,7 @@ static int xferOptimization(
return 0; /* source and destination must both be WITHOUT ROWID or not */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pSrc->tabFlags & TF_Virtual ){
+ if( IsVirtual(pSrc) ){
return 0; /* tab2 must not be a virtual table */
}
#endif
@@ -112568,6 +115047,7 @@ static int xferOptimization(
sqlite3VdbeJumpHere(v, addr1);
}
if( HasRowid(pSrc) ){
+ u8 insFlags;
sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
if( pDest->iPKey>=0 ){
@@ -112583,10 +115063,17 @@ static int xferOptimization(
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
assert( (pDest->tabFlags & TF_Autoincrement)==0 );
}
- sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
+ if( db->flags & SQLITE_Vacuum ){
+ sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1);
+ insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|
+ OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
+ }else{
+ insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND;
+ }
sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid,
(char*)pDest, P4_TABLE);
- sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
+ sqlite3VdbeChangeP5(v, insFlags);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
@@ -112608,7 +115095,7 @@ static int xferOptimization(
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
VdbeComment((v, "%s", pDestIdx->zName));
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
if( db->flags & SQLITE_Vacuum ){
/* This INSERT command is part of a VACUUM operation, which guarantees
** that the destination table is empty. If all indexed columns use
@@ -112626,8 +115113,6 @@ static int xferOptimization(
** sorted order. */
for(i=0; inColumn; i++){
const char *zColl = pSrcIdx->azColl[i];
- assert( sqlite3_stricmp(sqlite3StrBINARY, zColl)!=0
- || sqlite3StrBINARY==zColl );
if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
}
if( i==pSrcIdx->nColumn ){
@@ -112638,8 +115123,8 @@ static int xferOptimization(
if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){
idxInsFlags |= OPFLAG_NCHANGE;
}
- sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
- sqlite3VdbeChangeP5(v, idxInsFlags);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
+ sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
@@ -112737,7 +115222,7 @@ SQLITE_API int sqlite3_exec(
(SQLITE_DONE==rc && !callbackIsInit
&& db->flags&SQLITE_NullCallback)) ){
if( !callbackIsInit ){
- azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1);
+ azCols = sqlite3DbMallocRaw(db, (2*nCol+1)*sizeof(const char*));
if( azCols==0 ){
goto exec_out;
}
@@ -112758,6 +115243,7 @@ SQLITE_API int sqlite3_exec(
goto exec_out;
}
}
+ azVals[i] = 0;
}
if( xCallback(pArg, nCol, azVals, azCols) ){
/* EVIDENCE-OF: R-38229-40159 If the callback function to
@@ -112790,11 +115276,8 @@ exec_out:
rc = sqlite3ApiExit(db, rc);
if( rc!=SQLITE_OK && pzErrMsg ){
- int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db));
- *pzErrMsg = sqlite3Malloc(nErrMsg);
- if( *pzErrMsg ){
- memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg);
- }else{
+ *pzErrMsg = sqlite3DbStrDup(0, sqlite3_errmsg(db));
+ if( *pzErrMsg==0 ){
rc = SQLITE_NOMEM_BKPT;
sqlite3Error(db, SQLITE_NOMEM);
}
@@ -113113,6 +115596,16 @@ struct sqlite3_api_routines {
/* Version 3.14.0 and later */
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
char *(*expanded_sql)(sqlite3_stmt*);
+ /* Version 3.18.0 and later */
+ void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
+ /* Version 3.20.0 and later */
+ int (*prepare_v3)(sqlite3*,const char*,int,unsigned int,
+ sqlite3_stmt**,const char**);
+ int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
+ sqlite3_stmt**,const void**);
+ int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
+ void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
+ void *(*value_pointer)(sqlite3_value*,const char*);
};
/*
@@ -113371,6 +115864,14 @@ typedef int (*sqlite3_loadext_entry)(
/* Version 3.14.0 and later */
#define sqlite3_trace_v2 sqlite3_api->trace_v2
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
+/* Version 3.18.0 and later */
+#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
+/* Version 3.20.0 and later */
+#define sqlite3_prepare_v3 sqlite3_api->prepare_v3
+#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3
+#define sqlite3_bind_pointer sqlite3_api->bind_pointer
+#define sqlite3_result_pointer sqlite3_api->result_pointer
+#define sqlite3_value_pointer sqlite3_api->value_pointer
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -113393,7 +115894,6 @@ typedef int (*sqlite3_loadext_entry)(
/************** End of sqlite3ext.h ******************************************/
/************** Continuing where we left off in loadext.c ********************/
/* #include "sqliteInt.h" */
-/* #include */
#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
@@ -113427,6 +115927,7 @@ typedef int (*sqlite3_loadext_entry)(
# define sqlite3_open16 0
# define sqlite3_prepare16 0
# define sqlite3_prepare16_v2 0
+# define sqlite3_prepare16_v3 0
# define sqlite3_result_error16 0
# define sqlite3_result_text16 0
# define sqlite3_result_text16be 0
@@ -113797,7 +116298,15 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_system_errno,
/* Version 3.14.0 and later */
sqlite3_trace_v2,
- sqlite3_expanded_sql
+ sqlite3_expanded_sql,
+ /* Version 3.18.0 and later */
+ sqlite3_set_last_insert_rowid,
+ /* Version 3.20.0 and later */
+ sqlite3_prepare_v3,
+ sqlite3_prepare16_v3,
+ sqlite3_bind_pointer,
+ sqlite3_result_pointer,
+ sqlite3_value_pointer
};
/*
@@ -114202,6 +116711,8 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit
** that script and rerun it.
*/
+
+/* The various pragma types */
#define PragTyp_HEADER_VALUE 0
#define PragTyp_AUTO_VACUUM 1
#define PragTyp_FLAG 2
@@ -114217,450 +116728,633 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
#define PragTyp_ENCODING 12
#define PragTyp_FOREIGN_KEY_CHECK 13
#define PragTyp_FOREIGN_KEY_LIST 14
-#define PragTyp_INCREMENTAL_VACUUM 15
-#define PragTyp_INDEX_INFO 16
-#define PragTyp_INDEX_LIST 17
-#define PragTyp_INTEGRITY_CHECK 18
-#define PragTyp_JOURNAL_MODE 19
-#define PragTyp_JOURNAL_SIZE_LIMIT 20
-#define PragTyp_LOCK_PROXY_FILE 21
-#define PragTyp_LOCKING_MODE 22
-#define PragTyp_PAGE_COUNT 23
-#define PragTyp_MMAP_SIZE 24
-#define PragTyp_PAGE_SIZE 25
-#define PragTyp_SECURE_DELETE 26
-#define PragTyp_SHRINK_MEMORY 27
-#define PragTyp_SOFT_HEAP_LIMIT 28
-#define PragTyp_STATS 29
-#define PragTyp_SYNCHRONOUS 30
-#define PragTyp_TABLE_INFO 31
-#define PragTyp_TEMP_STORE 32
-#define PragTyp_TEMP_STORE_DIRECTORY 33
-#define PragTyp_THREADS 34
-#define PragTyp_WAL_AUTOCHECKPOINT 35
-#define PragTyp_WAL_CHECKPOINT 36
-#define PragTyp_ACTIVATE_EXTENSIONS 37
-#define PragTyp_HEXKEY 38
-#define PragTyp_KEY 39
-#define PragTyp_REKEY 40
-#define PragTyp_LOCK_STATUS 41
-#define PragTyp_PARSER_TRACE 42
-#define PragFlag_NeedSchema 0x01
-#define PragFlag_ReadOnly 0x02
-static const struct sPragmaNames {
- const char *const zName; /* Name of pragma */
- u8 ePragTyp; /* PragTyp_XXX value */
- u8 mPragFlag; /* Zero or more PragFlag_XXX values */
- u32 iArg; /* Extra argument */
-} aPragmaNames[] = {
+#define PragTyp_FUNCTION_LIST 15
+#define PragTyp_INCREMENTAL_VACUUM 16
+#define PragTyp_INDEX_INFO 17
+#define PragTyp_INDEX_LIST 18
+#define PragTyp_INTEGRITY_CHECK 19
+#define PragTyp_JOURNAL_MODE 20
+#define PragTyp_JOURNAL_SIZE_LIMIT 21
+#define PragTyp_LOCK_PROXY_FILE 22
+#define PragTyp_LOCKING_MODE 23
+#define PragTyp_PAGE_COUNT 24
+#define PragTyp_MMAP_SIZE 25
+#define PragTyp_MODULE_LIST 26
+#define PragTyp_OPTIMIZE 27
+#define PragTyp_PAGE_SIZE 28
+#define PragTyp_PRAGMA_LIST 29
+#define PragTyp_SECURE_DELETE 30
+#define PragTyp_SHRINK_MEMORY 31
+#define PragTyp_SOFT_HEAP_LIMIT 32
+#define PragTyp_SYNCHRONOUS 33
+#define PragTyp_TABLE_INFO 34
+#define PragTyp_TEMP_STORE 35
+#define PragTyp_TEMP_STORE_DIRECTORY 36
+#define PragTyp_THREADS 37
+#define PragTyp_WAL_AUTOCHECKPOINT 38
+#define PragTyp_WAL_CHECKPOINT 39
+#define PragTyp_ACTIVATE_EXTENSIONS 40
+#define PragTyp_HEXKEY 41
+#define PragTyp_KEY 42
+#define PragTyp_REKEY 43
+#define PragTyp_LOCK_STATUS 44
+#define PragTyp_PARSER_TRACE 45
+#define PragTyp_STATS 46
+
+/* Property flags associated with various pragma. */
+#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
+#define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */
+#define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */
+#define PragFlg_ReadOnly 0x08 /* Read-only HEADER_VALUE */
+#define PragFlg_Result0 0x10 /* Acts as query when no argument */
+#define PragFlg_Result1 0x20 /* Acts as query when has one argument */
+#define PragFlg_SchemaOpt 0x40 /* Schema restricts name search if present */
+#define PragFlg_SchemaReq 0x80 /* Schema required - "main" is default */
+
+/* Names of columns for pragmas that return multi-column result
+** or that return single-column results where the name of the
+** result column is different from the name of the pragma
+*/
+static const char *const pragCName[] = {
+ /* 0 */ "cache_size", /* Used by: default_cache_size */
+ /* 1 */ "cid", /* Used by: table_info */
+ /* 2 */ "name",
+ /* 3 */ "type",
+ /* 4 */ "notnull",
+ /* 5 */ "dflt_value",
+ /* 6 */ "pk",
+ /* 7 */ "tbl", /* Used by: stats */
+ /* 8 */ "idx",
+ /* 9 */ "wdth",
+ /* 10 */ "hght",
+ /* 11 */ "flgs",
+ /* 12 */ "seqno", /* Used by: index_info */
+ /* 13 */ "cid",
+ /* 14 */ "name",
+ /* 15 */ "seqno", /* Used by: index_xinfo */
+ /* 16 */ "cid",
+ /* 17 */ "name",
+ /* 18 */ "desc",
+ /* 19 */ "coll",
+ /* 20 */ "key",
+ /* 21 */ "seq", /* Used by: index_list */
+ /* 22 */ "name",
+ /* 23 */ "unique",
+ /* 24 */ "origin",
+ /* 25 */ "partial",
+ /* 26 */ "seq", /* Used by: database_list */
+ /* 27 */ "name",
+ /* 28 */ "file",
+ /* 29 */ "name", /* Used by: function_list */
+ /* 30 */ "builtin",
+ /* 31 */ "name", /* Used by: module_list pragma_list */
+ /* 32 */ "seq", /* Used by: collation_list */
+ /* 33 */ "name",
+ /* 34 */ "id", /* Used by: foreign_key_list */
+ /* 35 */ "seq",
+ /* 36 */ "table",
+ /* 37 */ "from",
+ /* 38 */ "to",
+ /* 39 */ "on_update",
+ /* 40 */ "on_delete",
+ /* 41 */ "match",
+ /* 42 */ "table", /* Used by: foreign_key_check */
+ /* 43 */ "rowid",
+ /* 44 */ "parent",
+ /* 45 */ "fkid",
+ /* 46 */ "busy", /* Used by: wal_checkpoint */
+ /* 47 */ "log",
+ /* 48 */ "checkpointed",
+ /* 49 */ "timeout", /* Used by: busy_timeout */
+ /* 50 */ "database", /* Used by: lock_status */
+ /* 51 */ "status",
+};
+
+/* Definitions of all built-in pragmas */
+typedef struct PragmaName {
+ const char *const zName; /* Name of pragma */
+ u8 ePragTyp; /* PragTyp_XXX value */
+ u8 mPragFlg; /* Zero or more PragFlg_XXX values */
+ u8 iPragCName; /* Start of column names in pragCName[] */
+ u8 nPragCName; /* Num of col names. 0 means use pragma name */
+ u32 iArg; /* Extra argument */
+} PragmaName;
+static const PragmaName aPragmaName[] = {
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
- { /* zName: */ "activate_extensions",
- /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "activate_extensions",
+ /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
+ /* ePragFlg: */ 0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
- { /* zName: */ "application_id",
- /* ePragTyp: */ PragTyp_HEADER_VALUE,
- /* ePragFlag: */ 0,
- /* iArg: */ BTREE_APPLICATION_ID },
+ {/* zName: */ "application_id",
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
+ /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ BTREE_APPLICATION_ID },
#endif
#if !defined(SQLITE_OMIT_AUTOVACUUM)
- { /* zName: */ "auto_vacuum",
- /* ePragTyp: */ PragTyp_AUTO_VACUUM,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
+ {/* zName: */ "auto_vacuum",
+ /* ePragTyp: */ PragTyp_AUTO_VACUUM,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
- { /* zName: */ "automatic_index",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_AutoIndex },
+ {/* zName: */ "automatic_index",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_AutoIndex },
#endif
#endif
- { /* zName: */ "busy_timeout",
- /* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "busy_timeout",
+ /* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
+ /* ePragFlg: */ PragFlg_Result0,
+ /* ColNames: */ 49, 1,
+ /* iArg: */ 0 },
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- { /* zName: */ "cache_size",
- /* ePragTyp: */ PragTyp_CACHE_SIZE,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
+ {/* zName: */ "cache_size",
+ /* ePragTyp: */ PragTyp_CACHE_SIZE,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- { /* zName: */ "cache_spill",
- /* ePragTyp: */ PragTyp_CACHE_SPILL,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "cache_spill",
+ /* ePragTyp: */ PragTyp_CACHE_SPILL,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
- { /* zName: */ "case_sensitive_like",
- /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
- { /* zName: */ "cell_size_check",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_CellSizeCk },
+ {/* zName: */ "case_sensitive_like",
+ /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE,
+ /* ePragFlg: */ PragFlg_NoColumns,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
+ {/* zName: */ "cell_size_check",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_CellSizeCk },
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- { /* zName: */ "checkpoint_fullfsync",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_CkptFullFSync },
+ {/* zName: */ "checkpoint_fullfsync",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_CkptFullFSync },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
- { /* zName: */ "collation_list",
- /* ePragTyp: */ PragTyp_COLLATION_LIST,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "collation_list",
+ /* ePragTyp: */ PragTyp_COLLATION_LIST,
+ /* ePragFlg: */ PragFlg_Result0,
+ /* ColNames: */ 32, 2,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
- { /* zName: */ "compile_options",
- /* ePragTyp: */ PragTyp_COMPILE_OPTIONS,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "compile_options",
+ /* ePragTyp: */ PragTyp_COMPILE_OPTIONS,
+ /* ePragFlg: */ PragFlg_Result0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- { /* zName: */ "count_changes",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_CountRows },
+ {/* zName: */ "count_changes",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_CountRows },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
- { /* zName: */ "data_store_directory",
- /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "data_store_directory",
+ /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY,
+ /* ePragFlg: */ PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
- { /* zName: */ "data_version",
- /* ePragTyp: */ PragTyp_HEADER_VALUE,
- /* ePragFlag: */ PragFlag_ReadOnly,
- /* iArg: */ BTREE_DATA_VERSION },
+ {/* zName: */ "data_version",
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
+ /* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ BTREE_DATA_VERSION },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
- { /* zName: */ "database_list",
- /* ePragTyp: */ PragTyp_DATABASE_LIST,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
+ {/* zName: */ "database_list",
+ /* ePragTyp: */ PragTyp_DATABASE_LIST,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
+ /* ColNames: */ 26, 3,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
- { /* zName: */ "default_cache_size",
- /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
+ {/* zName: */ "default_cache_size",
+ /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 1,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
- { /* zName: */ "defer_foreign_keys",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_DeferFKs },
+ {/* zName: */ "defer_foreign_keys",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_DeferFKs },
#endif
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- { /* zName: */ "empty_result_callbacks",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_NullCallback },
+ {/* zName: */ "empty_result_callbacks",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_NullCallback },
#endif
#if !defined(SQLITE_OMIT_UTF16)
- { /* zName: */ "encoding",
- /* ePragTyp: */ PragTyp_ENCODING,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "encoding",
+ /* ePragTyp: */ PragTyp_ENCODING,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
- { /* zName: */ "foreign_key_check",
- /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
+ {/* zName: */ "foreign_key_check",
+ /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
+ /* ColNames: */ 42, 4,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
- { /* zName: */ "foreign_key_list",
- /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
+ {/* zName: */ "foreign_key_list",
+ /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
+ /* ColNames: */ 34, 8,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
- { /* zName: */ "foreign_keys",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_ForeignKeys },
+ {/* zName: */ "foreign_keys",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_ForeignKeys },
#endif
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
- { /* zName: */ "freelist_count",
- /* ePragTyp: */ PragTyp_HEADER_VALUE,
- /* ePragFlag: */ PragFlag_ReadOnly,
- /* iArg: */ BTREE_FREE_PAGE_COUNT },
+ {/* zName: */ "freelist_count",
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
+ /* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ BTREE_FREE_PAGE_COUNT },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- { /* zName: */ "full_column_names",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_FullColNames },
- { /* zName: */ "fullfsync",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_FullFSync },
+ {/* zName: */ "full_column_names",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_FullColNames },
+ {/* zName: */ "fullfsync",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_FullFSync },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+#if defined(SQLITE_INTROSPECTION_PRAGMAS)
+ {/* zName: */ "function_list",
+ /* ePragTyp: */ PragTyp_FUNCTION_LIST,
+ /* ePragFlg: */ PragFlg_Result0,
+ /* ColNames: */ 29, 2,
+ /* iArg: */ 0 },
+#endif
#endif
#if defined(SQLITE_HAS_CODEC)
- { /* zName: */ "hexkey",
- /* ePragTyp: */ PragTyp_HEXKEY,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
- { /* zName: */ "hexrekey",
- /* ePragTyp: */ PragTyp_HEXKEY,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "hexkey",
+ /* ePragTyp: */ PragTyp_HEXKEY,
+ /* ePragFlg: */ 0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
+ {/* zName: */ "hexrekey",
+ /* ePragTyp: */ PragTyp_HEXKEY,
+ /* ePragFlg: */ 0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if !defined(SQLITE_OMIT_CHECK)
- { /* zName: */ "ignore_check_constraints",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_IgnoreChecks },
+ {/* zName: */ "ignore_check_constraints",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_IgnoreChecks },
#endif
#endif
#if !defined(SQLITE_OMIT_AUTOVACUUM)
- { /* zName: */ "incremental_vacuum",
- /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
+ {/* zName: */ "incremental_vacuum",
+ /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_NoColumns,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
- { /* zName: */ "index_info",
- /* ePragTyp: */ PragTyp_INDEX_INFO,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
- { /* zName: */ "index_list",
- /* ePragTyp: */ PragTyp_INDEX_LIST,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
- { /* zName: */ "index_xinfo",
- /* ePragTyp: */ PragTyp_INDEX_INFO,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 1 },
+ {/* zName: */ "index_info",
+ /* ePragTyp: */ PragTyp_INDEX_INFO,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
+ /* ColNames: */ 12, 3,
+ /* iArg: */ 0 },
+ {/* zName: */ "index_list",
+ /* ePragTyp: */ PragTyp_INDEX_LIST,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
+ /* ColNames: */ 21, 5,
+ /* iArg: */ 0 },
+ {/* zName: */ "index_xinfo",
+ /* ePragTyp: */ PragTyp_INDEX_INFO,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
+ /* ColNames: */ 15, 6,
+ /* iArg: */ 1 },
#endif
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
- { /* zName: */ "integrity_check",
- /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
+ {/* zName: */ "integrity_check",
+ /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- { /* zName: */ "journal_mode",
- /* ePragTyp: */ PragTyp_JOURNAL_MODE,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
- { /* zName: */ "journal_size_limit",
- /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "journal_mode",
+ /* ePragTyp: */ PragTyp_JOURNAL_MODE,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
+ {/* zName: */ "journal_size_limit",
+ /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if defined(SQLITE_HAS_CODEC)
- { /* zName: */ "key",
- /* ePragTyp: */ PragTyp_KEY,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "key",
+ /* ePragTyp: */ PragTyp_KEY,
+ /* ePragFlg: */ 0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- { /* zName: */ "legacy_file_format",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_LegacyFileFmt },
+ {/* zName: */ "legacy_file_format",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_LegacyFileFmt },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
- { /* zName: */ "lock_proxy_file",
- /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "lock_proxy_file",
+ /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE,
+ /* ePragFlg: */ PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- { /* zName: */ "lock_status",
- /* ePragTyp: */ PragTyp_LOCK_STATUS,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "lock_status",
+ /* ePragTyp: */ PragTyp_LOCK_STATUS,
+ /* ePragFlg: */ PragFlg_Result0,
+ /* ColNames: */ 50, 2,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- { /* zName: */ "locking_mode",
- /* ePragTyp: */ PragTyp_LOCKING_MODE,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
- { /* zName: */ "max_page_count",
- /* ePragTyp: */ PragTyp_PAGE_COUNT,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
- { /* zName: */ "mmap_size",
- /* ePragTyp: */ PragTyp_MMAP_SIZE,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
- { /* zName: */ "page_count",
- /* ePragTyp: */ PragTyp_PAGE_COUNT,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
- { /* zName: */ "page_size",
- /* ePragTyp: */ PragTyp_PAGE_SIZE,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "locking_mode",
+ /* ePragTyp: */ PragTyp_LOCKING_MODE,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
+ {/* zName: */ "max_page_count",
+ /* ePragTyp: */ PragTyp_PAGE_COUNT,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
+ {/* zName: */ "mmap_size",
+ /* ePragTyp: */ PragTyp_MMAP_SIZE,
+ /* ePragFlg: */ 0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+#if !defined(SQLITE_OMIT_VIRTUALTABLE)
+#if defined(SQLITE_INTROSPECTION_PRAGMAS)
+ {/* zName: */ "module_list",
+ /* ePragTyp: */ PragTyp_MODULE_LIST,
+ /* ePragFlg: */ PragFlg_Result0,
+ /* ColNames: */ 31, 1,
+ /* iArg: */ 0 },
+#endif
+#endif
+#endif
+ {/* zName: */ "optimize",
+ /* ePragTyp: */ PragTyp_OPTIMIZE,
+ /* ePragFlg: */ PragFlg_Result1|PragFlg_NeedSchema,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+ {/* zName: */ "page_count",
+ /* ePragTyp: */ PragTyp_PAGE_COUNT,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
+ {/* zName: */ "page_size",
+ /* ePragTyp: */ PragTyp_PAGE_SIZE,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE)
- { /* zName: */ "parser_trace",
- /* ePragTyp: */ PragTyp_PARSER_TRACE,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "parser_trace",
+ /* ePragTyp: */ PragTyp_PARSER_TRACE,
+ /* ePragFlg: */ 0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
+#endif
+#if defined(SQLITE_INTROSPECTION_PRAGMAS)
+ {/* zName: */ "pragma_list",
+ /* ePragTyp: */ PragTyp_PRAGMA_LIST,
+ /* ePragFlg: */ PragFlg_Result0,
+ /* ColNames: */ 31, 1,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- { /* zName: */ "query_only",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_QueryOnly },
+ {/* zName: */ "query_only",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_QueryOnly },
#endif
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
- { /* zName: */ "quick_check",
- /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
+ {/* zName: */ "quick_check",
+ /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- { /* zName: */ "read_uncommitted",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_ReadUncommitted },
- { /* zName: */ "recursive_triggers",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_RecTriggers },
+ {/* zName: */ "read_uncommitted",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_ReadUncommit },
+ {/* zName: */ "recursive_triggers",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_RecTriggers },
#endif
#if defined(SQLITE_HAS_CODEC)
- { /* zName: */ "rekey",
- /* ePragTyp: */ PragTyp_REKEY,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "rekey",
+ /* ePragTyp: */ PragTyp_REKEY,
+ /* ePragFlg: */ 0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- { /* zName: */ "reverse_unordered_selects",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_ReverseOrder },
+ {/* zName: */ "reverse_unordered_selects",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_ReverseOrder },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
- { /* zName: */ "schema_version",
- /* ePragTyp: */ PragTyp_HEADER_VALUE,
- /* ePragFlag: */ 0,
- /* iArg: */ BTREE_SCHEMA_VERSION },
+ {/* zName: */ "schema_version",
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
+ /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ BTREE_SCHEMA_VERSION },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- { /* zName: */ "secure_delete",
- /* ePragTyp: */ PragTyp_SECURE_DELETE,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "secure_delete",
+ /* ePragTyp: */ PragTyp_SECURE_DELETE,
+ /* ePragFlg: */ PragFlg_Result0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- { /* zName: */ "short_column_names",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_ShortColNames },
+ {/* zName: */ "short_column_names",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_ShortColNames },
#endif
- { /* zName: */ "shrink_memory",
- /* ePragTyp: */ PragTyp_SHRINK_MEMORY,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
- { /* zName: */ "soft_heap_limit",
- /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "shrink_memory",
+ /* ePragTyp: */ PragTyp_SHRINK_MEMORY,
+ /* ePragFlg: */ PragFlg_NoColumns,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
+ {/* zName: */ "soft_heap_limit",
+ /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT,
+ /* ePragFlg: */ PragFlg_Result0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if defined(SQLITE_DEBUG)
- { /* zName: */ "sql_trace",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_SqlTrace },
+ {/* zName: */ "sql_trace",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_SqlTrace },
#endif
#endif
-#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
- { /* zName: */ "stats",
- /* ePragTyp: */ PragTyp_STATS,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
+ {/* zName: */ "stats",
+ /* ePragTyp: */ PragTyp_STATS,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
+ /* ColNames: */ 7, 5,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- { /* zName: */ "synchronous",
- /* ePragTyp: */ PragTyp_SYNCHRONOUS,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
+ {/* zName: */ "synchronous",
+ /* ePragTyp: */ PragTyp_SYNCHRONOUS,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
- { /* zName: */ "table_info",
- /* ePragTyp: */ PragTyp_TABLE_INFO,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
+ {/* zName: */ "table_info",
+ /* ePragTyp: */ PragTyp_TABLE_INFO,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
+ /* ColNames: */ 1, 6,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
- { /* zName: */ "temp_store",
- /* ePragTyp: */ PragTyp_TEMP_STORE,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
- { /* zName: */ "temp_store_directory",
- /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "temp_store",
+ /* ePragTyp: */ PragTyp_TEMP_STORE,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
+ {/* zName: */ "temp_store_directory",
+ /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY,
+ /* ePragFlg: */ PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#endif
- { /* zName: */ "threads",
- /* ePragTyp: */ PragTyp_THREADS,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
+ {/* zName: */ "threads",
+ /* ePragTyp: */ PragTyp_THREADS,
+ /* ePragFlg: */ PragFlg_Result0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
- { /* zName: */ "user_version",
- /* ePragTyp: */ PragTyp_HEADER_VALUE,
- /* ePragFlag: */ 0,
- /* iArg: */ BTREE_USER_VERSION },
+ {/* zName: */ "user_version",
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
+ /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ BTREE_USER_VERSION },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if defined(SQLITE_DEBUG)
- { /* zName: */ "vdbe_addoptrace",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_VdbeAddopTrace },
- { /* zName: */ "vdbe_debug",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
- { /* zName: */ "vdbe_eqp",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_VdbeEQP },
- { /* zName: */ "vdbe_listing",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_VdbeListing },
- { /* zName: */ "vdbe_trace",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_VdbeTrace },
+ {/* zName: */ "vdbe_addoptrace",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_VdbeAddopTrace },
+ {/* zName: */ "vdbe_debug",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
+ {/* zName: */ "vdbe_eqp",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_VdbeEQP },
+ {/* zName: */ "vdbe_listing",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_VdbeListing },
+ {/* zName: */ "vdbe_trace",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_VdbeTrace },
#endif
#endif
#if !defined(SQLITE_OMIT_WAL)
- { /* zName: */ "wal_autocheckpoint",
- /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT,
- /* ePragFlag: */ 0,
- /* iArg: */ 0 },
- { /* zName: */ "wal_checkpoint",
- /* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
- /* ePragFlag: */ PragFlag_NeedSchema,
- /* iArg: */ 0 },
+ {/* zName: */ "wal_autocheckpoint",
+ /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT,
+ /* ePragFlg: */ 0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
+ {/* zName: */ "wal_checkpoint",
+ /* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
+ /* ePragFlg: */ PragFlg_NeedSchema,
+ /* ColNames: */ 46, 3,
+ /* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
- { /* zName: */ "writable_schema",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlag: */ 0,
- /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
+ {/* zName: */ "writable_schema",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_WriteSchema },
#endif
};
-/* Number of pragmas: 60 on by default, 73 total. */
+/* Number of pragmas: 60 on by default, 77 total. */
/************** End of pragma.h **********************************************/
/************** Continuing where we left off in pragma.c *********************/
@@ -114798,29 +117492,29 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){
#endif /* SQLITE_PAGER_PRAGMAS */
/*
-** Set the names of the first N columns to the values in azCol[]
+** Set result column names for a pragma.
*/
-static void setAllColumnNames(
- Vdbe *v, /* The query under construction */
- int N, /* Number of columns */
- const char **azCol /* Names of columns */
+static void setPragmaResultColumnNames(
+ Vdbe *v, /* The query under construction */
+ const PragmaName *pPragma /* The pragma */
){
- int i;
- sqlite3VdbeSetNumCols(v, N);
- for(i=0; inPragCName;
+ sqlite3VdbeSetNumCols(v, n==0 ? 1 : n);
+ if( n==0 ){
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, pPragma->zName, SQLITE_STATIC);
+ }else{
+ int i, j;
+ for(i=0, j=pPragma->iPragCName; iupr ? 0 : &aPragmaName[mid];
+}
+
+/*
+** Helper subroutine for PRAGMA integrity_check:
+**
+** Generate code to output a single-column result row with the result
+** held in register regResult. Decrement the result count and halt if
+** the maximum number of result rows have been issued.
+*/
+static int integrityCheckResultRow(Vdbe *v, int regResult){
+ int addr;
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1);
+ addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
+ return addr;
+}
+
/*
** Process a pragma statement.
**
@@ -114940,12 +117668,11 @@ SQLITE_PRIVATE void sqlite3Pragma(
Token *pId; /* Pointer to token */
char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */
int iDb; /* Database index for */
- int lwr, upr, mid = 0; /* Binary search bounds */
int rc; /* return value form SQLITE_FCNTL_PRAGMA */
sqlite3 *db = pParse->db; /* The database connection */
Db *pDb; /* The specific database being pragmaed */
Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */
- const struct sPragmaNames *pPragma;
+ const PragmaName *pPragma; /* The pragma */
/* BEGIN SQLCIPHER */
#ifdef SQLITE_HAS_CODEC
extern int sqlcipher_codec_pragma(sqlite3*, int, Parse *, const char *, const char *);
@@ -115005,7 +117732,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
db->busyHandler.nBusy = 0;
rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
if( rc==SQLITE_OK ){
- returnSingleText(v, "result", aFcntl[0]);
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, aFcntl[0], SQLITE_TRANSIENT);
+ returnSingleText(v, aFcntl[0]);
sqlite3_free(aFcntl[0]);
goto pragma_out;
}
@@ -115030,26 +117759,21 @@ SQLITE_PRIVATE void sqlite3Pragma(
/* END SQLCIPHER */
/* Locate the pragma in the lookup table */
- lwr = 0;
- upr = ArraySize(aPragmaNames)-1;
- while( lwr<=upr ){
- mid = (lwr+upr)/2;
- rc = sqlite3_stricmp(zLeft, aPragmaNames[mid].zName);
- if( rc==0 ) break;
- if( rc<0 ){
- upr = mid - 1;
- }else{
- lwr = mid + 1;
- }
- }
- if( lwr>upr ) goto pragma_out;
- pPragma = &aPragmaNames[mid];
+ pPragma = pragmaLocate(zLeft);
+ if( pPragma==0 ) goto pragma_out;
/* Make sure the database schema is loaded if the pragma requires that */
- if( (pPragma->mPragFlag & PragFlag_NeedSchema)!=0 ){
+ if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
}
+ /* Register the result column names for pragmas that return results */
+ if( (pPragma->mPragFlg & PragFlg_NoColumns)==0
+ && ((pPragma->mPragFlg & PragFlg_NoColumns1)==0 || zRight==0)
+ ){
+ setPragmaResultColumnNames(v, pPragma);
+ }
+
/* Jump to the appropriate pragma handler */
switch( pPragma->ePragTyp ){
@@ -115086,7 +117810,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
VdbeOp *aOp;
sqlite3VdbeUsesBtree(v, iDb);
if( !zRight ){
- setOneColumnName(v, "cache_size");
pParse->nMem += 2;
sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(getCacheSize));
aOp = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize, iLn);
@@ -115121,7 +117844,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
assert( pBt!=0 );
if( !zRight ){
int size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0;
- returnSingleInt(v, "page_size", size);
+ returnSingleInt(v, size);
}else{
/* Malloc may fail when setting the page-size, as there is an internal
** buffer that the pager module resizes using sqlite3_realloc().
@@ -115136,18 +117859,22 @@ SQLITE_PRIVATE void sqlite3Pragma(
/*
** PRAGMA [schema.]secure_delete
- ** PRAGMA [schema.]secure_delete=ON/OFF
+ ** PRAGMA [schema.]secure_delete=ON/OFF/FAST
**
** The first form reports the current setting for the
** secure_delete flag. The second form changes the secure_delete
- ** flag setting and reports thenew value.
+ ** flag setting and reports the new value.
*/
case PragTyp_SECURE_DELETE: {
Btree *pBt = pDb->pBt;
int b = -1;
assert( pBt!=0 );
if( zRight ){
- b = sqlite3GetBoolean(zRight, 0);
+ if( sqlite3_stricmp(zRight, "fast")==0 ){
+ b = 2;
+ }else{
+ b = sqlite3GetBoolean(zRight, 0);
+ }
}
if( pId2->n==0 && b>=0 ){
int ii;
@@ -115156,7 +117883,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
}
b = sqlite3BtreeSecureDelete(pBt, b);
- returnSingleInt(v, "secure_delete", b);
+ returnSingleInt(v, b);
break;
}
@@ -115188,8 +117915,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3AbsInt32(sqlite3Atoi(zRight)));
}
sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1);
- sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
break;
}
@@ -115235,7 +117960,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){
zRet = "exclusive";
}
- returnSingleText(v, "locking_mode", zRet);
+ returnSingleText(v, zRet);
break;
}
@@ -115248,7 +117973,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
int ii; /* Loop counter */
- setOneColumnName(v, "journal_mode");
if( zRight==0 ){
/* If there is no "=MODE" part of the pragma, do a query for the
** current mode */
@@ -115294,7 +118018,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( iLimit<-1 ) iLimit = -1;
}
iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
- returnSingleInt(v, "journal_size_limit", iLimit);
+ returnSingleInt(v, iLimit);
break;
}
@@ -115312,7 +118036,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
Btree *pBt = pDb->pBt;
assert( pBt!=0 );
if( !zRight ){
- returnSingleInt(v, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt));
+ returnSingleInt(v, sqlite3BtreeGetAutoVacuum(pBt));
}else{
int eAuto = getAutoVacuum(zRight);
assert( eAuto>=0 && eAuto<=2 );
@@ -115391,7 +118115,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
case PragTyp_CACHE_SIZE: {
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( !zRight ){
- returnSingleInt(v, "cache_size", pDb->pSchema->cache_size);
+ returnSingleInt(v, pDb->pSchema->cache_size);
}else{
int size = sqlite3Atoi(zRight);
pDb->pSchema->cache_size = size;
@@ -115425,7 +118149,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
case PragTyp_CACHE_SPILL: {
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( !zRight ){
- returnSingleInt(v, "cache_spill",
+ returnSingleInt(v,
(db->flags & SQLITE_CacheSpill)==0 ? 0 :
sqlite3BtreeSetSpillSize(pDb->pBt,0));
}else{
@@ -115479,7 +118203,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
rc = SQLITE_OK;
#endif
if( rc==SQLITE_OK ){
- returnSingleInt(v, "mmap_size", sz);
+ returnSingleInt(v, sz);
}else if( rc!=SQLITE_NOTFOUND ){
pParse->nErr++;
pParse->rc = rc;
@@ -115500,7 +118224,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
*/
case PragTyp_TEMP_STORE: {
if( !zRight ){
- returnSingleInt(v, "temp_store", db->temp_store);
+ returnSingleInt(v, db->temp_store);
}else{
changeTempStorage(pParse, zRight);
}
@@ -115519,7 +118243,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
*/
case PragTyp_TEMP_STORE_DIRECTORY: {
if( !zRight ){
- returnSingleText(v, "temp_store_directory", sqlite3_temp_directory);
+ returnSingleText(v, sqlite3_temp_directory);
}else{
#ifndef SQLITE_OMIT_WSD
if( zRight[0] ){
@@ -115563,7 +118287,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
*/
case PragTyp_DATA_STORE_DIRECTORY: {
if( !zRight ){
- returnSingleText(v, "data_store_directory", sqlite3_data_directory);
+ returnSingleText(v, sqlite3_data_directory);
}else{
#ifndef SQLITE_OMIT_WSD
if( zRight[0] ){
@@ -115602,7 +118326,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3_file *pFile = sqlite3PagerFile(pPager);
sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE,
&proxy_file_path);
- returnSingleText(v, "lock_proxy_file", proxy_file_path);
+ returnSingleText(v, proxy_file_path);
}else{
Pager *pPager = sqlite3BtreePager(pDb->pBt);
sqlite3_file *pFile = sqlite3PagerFile(pPager);
@@ -115634,12 +118358,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
*/
case PragTyp_SYNCHRONOUS: {
if( !zRight ){
- returnSingleInt(v, "synchronous", pDb->safety_level-1);
+ returnSingleInt(v, pDb->safety_level-1);
}else{
if( !db->autoCommit ){
sqlite3ErrorMsg(pParse,
"Safety level may not be changed inside a transaction");
- }else{
+ }else if( iDb!=1 ){
int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK;
if( iLevel==0 ) iLevel = 1;
pDb->safety_level = iLevel;
@@ -115654,7 +118378,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
#ifndef SQLITE_OMIT_FLAG_PRAGMAS
case PragTyp_FLAG: {
if( zRight==0 ){
- returnSingleInt(v, pPragma->zName, (db->flags & pPragma->iArg)!=0 );
+ setPragmaResultColumnNames(v, pPragma);
+ returnSingleInt(v, (db->flags & pPragma->iArg)!=0 );
}else{
int mask = pPragma->iArg; /* Mask of bits to set or clear. */
if( db->autoCommit==0 ){
@@ -115704,16 +118429,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
Table *pTab;
pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb);
if( pTab ){
- static const char *azCol[] = {
- "cid", "name", "type", "notnull", "dflt_value", "pk"
- };
int i, k;
int nHidden = 0;
Column *pCol;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
pParse->nMem = 6;
sqlite3CodeVerifySchema(pParse, iDb);
- setAllColumnNames(v, 6, azCol); assert( 6==ArraySize(azCol) );
sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){
if( IsHiddenColumn(pCol) ){
@@ -115735,47 +118456,43 @@ SQLITE_PRIVATE void sqlite3Pragma(
pCol->notNull ? 1 : 0,
pCol->pDflt ? pCol->pDflt->u.zToken : 0,
k);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
}
}
}
break;
+#ifdef SQLITE_DEBUG
case PragTyp_STATS: {
- static const char *azCol[] = { "table", "index", "width", "height" };
Index *pIdx;
HashElem *i;
- v = sqlite3GetVdbe(pParse);
- pParse->nMem = 4;
+ pParse->nMem = 5;
sqlite3CodeVerifySchema(pParse, iDb);
- setAllColumnNames(v, 4, azCol); assert( 4==ArraySize(azCol) );
for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
Table *pTab = sqliteHashData(i);
- sqlite3VdbeMultiLoad(v, 1, "ssii",
+ sqlite3VdbeMultiLoad(v, 1, "ssiii",
pTab->zName,
0,
pTab->szTabRow,
- pTab->nRowLogEst);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
+ pTab->nRowLogEst,
+ pTab->tabFlags);
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- sqlite3VdbeMultiLoad(v, 2, "sii",
+ sqlite3VdbeMultiLoad(v, 2, "siiiX",
pIdx->zName,
pIdx->szIdxRow,
- pIdx->aiRowLogEst[0]);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
+ pIdx->aiRowLogEst[0],
+ pIdx->hasStat1);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5);
}
}
}
break;
+#endif
case PragTyp_INDEX_INFO: if( zRight ){
Index *pIdx;
Table *pTab;
pIdx = sqlite3FindIndex(db, zRight, zDb);
if( pIdx ){
- static const char *azCol[] = {
- "seqno", "cid", "name", "desc", "coll", "key"
- };
int i;
int mx;
if( pPragma->iArg ){
@@ -115789,14 +118506,13 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
pTab = pIdx->pTable;
sqlite3CodeVerifySchema(pParse, iDb);
- assert( pParse->nMem<=ArraySize(azCol) );
- setAllColumnNames(v, pParse->nMem, azCol);
+ assert( pParse->nMem<=pPragma->nPragCName );
for(i=0; iaiColumn[i];
- sqlite3VdbeMultiLoad(v, 1, "iis", i, cnum,
+ sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum,
cnum<0 ? 0 : pTab->aCol[cnum].zName);
if( pPragma->iArg ){
- sqlite3VdbeMultiLoad(v, 4, "isi",
+ sqlite3VdbeMultiLoad(v, 4, "isiX",
pIdx->aSortOrder[i],
pIdx->azColl[i],
inKeyCol);
@@ -115813,13 +118529,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
int i;
pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab ){
- static const char *azCol[] = {
- "seq", "name", "unique", "origin", "partial"
- };
- v = sqlite3GetVdbe(pParse);
pParse->nMem = 5;
sqlite3CodeVerifySchema(pParse, iDb);
- setAllColumnNames(v, 5, azCol); assert( 5==ArraySize(azCol) );
for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
const char *azOrigin[] = { "c", "u", "pk" };
sqlite3VdbeMultiLoad(v, 1, "isisi",
@@ -115828,17 +118539,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
IsUniqueIndex(pIdx),
azOrigin[pIdx->idxType],
pIdx->pPartIdxWhere!=0);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5);
}
}
}
break;
case PragTyp_DATABASE_LIST: {
- static const char *azCol[] = { "seq", "name", "file" };
int i;
pParse->nMem = 3;
- setAllColumnNames(v, 3, azCol); assert( 3==ArraySize(azCol) );
for(i=0; inDb; i++){
if( db->aDb[i].pBt==0 ) continue;
assert( db->aDb[i].zDbSName!=0 );
@@ -115846,24 +118554,64 @@ SQLITE_PRIVATE void sqlite3Pragma(
i,
db->aDb[i].zDbSName,
sqlite3BtreeGetFilename(db->aDb[i].pBt));
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
}
}
break;
case PragTyp_COLLATION_LIST: {
- static const char *azCol[] = { "seq", "name" };
int i = 0;
HashElem *p;
pParse->nMem = 2;
- setAllColumnNames(v, 2, azCol); assert( 2==ArraySize(azCol) );
for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){
CollSeq *pColl = (CollSeq *)sqliteHashData(p);
sqlite3VdbeMultiLoad(v, 1, "is", i++, pColl->zName);
+ }
+ }
+ break;
+
+#ifdef SQLITE_INTROSPECTION_PRAGMAS
+ case PragTyp_FUNCTION_LIST: {
+ int i;
+ HashElem *j;
+ FuncDef *p;
+ pParse->nMem = 2;
+ for(i=0; iu.pHash ){
+ sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
+ }
+ }
+ for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){
+ p = (FuncDef*)sqliteHashData(j);
+ sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
}
break;
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ case PragTyp_MODULE_LIST: {
+ HashElem *j;
+ pParse->nMem = 1;
+ for(j=sqliteHashFirst(&db->aModule); j; j=sqliteHashNext(j)){
+ Module *pMod = (Module*)sqliteHashData(j);
+ sqlite3VdbeMultiLoad(v, 1, "s", pMod->zName);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ }
+ }
+ break;
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+ case PragTyp_PRAGMA_LIST: {
+ int i;
+ for(i=0; ipFKey;
if( pFK ){
- static const char *azCol[] = {
- "id", "seq", "table", "from", "to", "on_update", "on_delete",
- "match"
- };
int i = 0;
pParse->nMem = 8;
sqlite3CodeVerifySchema(pParse, iDb);
- setAllColumnNames(v, 8, azCol); assert( 8==ArraySize(azCol) );
while(pFK){
int j;
for(j=0; jnCol; j++){
@@ -115895,7 +118637,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
actionName(pFK->aAction[1]), /* ON UPDATE */
actionName(pFK->aAction[0]), /* ON DELETE */
"NONE");
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 8);
}
++i;
pFK = pFK->pNextFrom;
@@ -115923,14 +118664,11 @@ SQLITE_PRIVATE void sqlite3Pragma(
int addrTop; /* Top of a loop checking foreign keys */
int addrOk; /* Jump here if the key is OK */
int *aiCols; /* child to parent column mapping */
- static const char *azCol[] = { "table", "rowid", "parent", "fkid" };
regResult = pParse->nMem+1;
pParse->nMem += 4;
regKey = ++pParse->nMem;
regRow = ++pParse->nMem;
- v = sqlite3GetVdbe(pParse);
- setAllColumnNames(v, 4, azCol); assert( 4==ArraySize(azCol) );
sqlite3CodeVerifySchema(pParse, iDb);
k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
while( k ){
@@ -115977,34 +118715,38 @@ SQLITE_PRIVATE void sqlite3Pragma(
assert( x==0 );
}
addrOk = sqlite3VdbeMakeLabel(v);
- if( pParent && pIdx==0 ){
- int iKey = pFK->aCol[0].iFrom;
- assert( iKey>=0 && iKeynCol );
- if( iKey!=pTab->iPKey ){
- sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
- sqlite3ColumnDefault(v, pTab, iKey, regRow);
- sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v);
- }else{
- sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
- }
- sqlite3VdbeAddOp3(v, OP_SeekRowid, i, 0, regRow); VdbeCoverage(v);
- sqlite3VdbeGoto(v, addrOk);
- sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
- }else{
- for(j=0; jnCol; j++){
- sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
- aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j);
- sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
- }
- if( pParent ){
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
- sqlite3IndexAffinityStr(db,pIdx), pFK->nCol);
- sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
- VdbeCoverage(v);
- }
+
+ /* Generate code to read the child key values into registers
+ ** regRow..regRow+n. If any of the child key values are NULL, this
+ ** row cannot cause an FK violation. Jump directly to addrOk in
+ ** this case. */
+ for(j=0; jnCol; j++){
+ int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom;
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j);
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
}
- sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
- sqlite3VdbeMultiLoad(v, regResult+2, "si", pFK->zTo, i-1);
+
+ /* Generate code to query the parent index for a matching parent
+ ** key. If a match is found, jump to addrOk. */
+ if( pIdx ){
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
+ sqlite3IndexAffinityStr(db,pIdx), pFK->nCol);
+ sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
+ VdbeCoverage(v);
+ }else if( pParent ){
+ int jmp = sqlite3VdbeCurrentAddr(v)+2;
+ sqlite3VdbeAddOp3(v, OP_SeekRowid, i, jmp, regRow); VdbeCoverage(v);
+ sqlite3VdbeGoto(v, addrOk);
+ assert( pFK->nCol==1 );
+ }
+
+ /* Generate code to report an FK violation to the caller. */
+ if( HasRowid(pTab) ){
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regResult+1);
+ }
+ sqlite3VdbeMultiLoad(v, regResult+2, "siX", pFK->zTo, i-1);
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
sqlite3VdbeResolveLabel(v, addrOk);
sqlite3DbFree(db, aiCols);
@@ -116045,9 +118787,17 @@ SQLITE_PRIVATE void sqlite3Pragma(
#endif
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
- /* Pragma "quick_check" is reduced version of
+ /* PRAGMA integrity_check
+ ** PRAGMA integrity_check(N)
+ ** PRAGMA quick_check
+ ** PRAGMA quick_check(N)
+ **
+ ** Verify the integrity of the database.
+ **
+ ** The "quick_check" is reduced version of
** integrity_check designed to detect most database corruption
- ** without most of the overhead of a full integrity-check.
+ ** without the overhead of cross-checking indexes. Quick_check
+ ** is linear time wherease integrity_check is O(NlogN).
*/
case PragTyp_INTEGRITY_CHECK: {
int i, j, addr, mxErr;
@@ -116069,7 +118819,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
/* Initialize the VDBE program */
pParse->nMem = 6;
- setOneColumnName(v, "integrity_check");
/* Set the maximum error count */
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
@@ -116079,7 +118828,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
}
}
- sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */
+ sqlite3VdbeAddOp2(v, OP_Integer, mxErr-1, 1); /* reg[1] holds errors left */
/* Do an integrity check on each database file */
for(i=0; inDb; i++){
@@ -116094,10 +118843,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( iDb>=0 && i!=iDb ) continue;
sqlite3CodeVerifySchema(pParse, i);
- addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */
- VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
- sqlite3VdbeJumpHere(v, addr);
/* Do an integrity check of the B-Tree
**
@@ -116127,6 +118872,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
/* Make sure sufficient number of registers have been allocated */
pParse->nMem = MAX( pParse->nMem, 8+mxIdx );
+ sqlite3ClearTempRegCache(pParse);
/* Do the b-tree integrity checks */
sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY);
@@ -116137,12 +118883,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
P4_DYNAMIC);
sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
+ integrityCheckResultRow(v, 2);
sqlite3VdbeJumpHere(v, addr);
/* Make sure all the indices are constructed correctly.
*/
- for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){
+ for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
Index *pIdx, *pPk;
Index *pPrior = 0;
@@ -116150,12 +118896,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
int iDataCur, iIdxCur;
int r1 = -1;
- if( pTab->pIndex==0 ) continue;
+ if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
+ if( pTab->pCheck==0
+ && (pTab->tabFlags & TF_HasNotNull)==0
+ && (pTab->pIndex==0 || isQuick)
+ ){
+ continue; /* No additional checks needed for this table */
+ }
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
- addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */
- VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
- sqlite3VdbeJumpHere(v, addr);
sqlite3ExprCacheClear(pParse);
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
1, 0, &iDataCur, &iIdxCur);
@@ -116170,24 +118918,46 @@ SQLITE_PRIVATE void sqlite3Pragma(
/* Verify that all NOT NULL columns really are NOT NULL */
for(j=0; jnCol; j++){
char *zErr;
- int jmp2, jmp3;
+ int jmp2;
if( j==pTab->iPKey ) continue;
if( pTab->aCol[j].notNull==0 ) continue;
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
pTab->aCol[j].zName);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
- jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
- sqlite3VdbeAddOp0(v, OP_Halt);
+ integrityCheckResultRow(v, 3);
sqlite3VdbeJumpHere(v, jmp2);
- sqlite3VdbeJumpHere(v, jmp3);
+ }
+ /* Verify CHECK constraints */
+ if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
+ ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0);
+ if( db->mallocFailed==0 ){
+ int addrCkFault = sqlite3VdbeMakeLabel(v);
+ int addrCkOk = sqlite3VdbeMakeLabel(v);
+ char *zErr;
+ int k;
+ pParse->iSelfTab = iDataCur + 1;
+ sqlite3ExprCachePush(pParse);
+ for(k=pCheck->nExpr-1; k>0; k--){
+ sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0);
+ }
+ sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk,
+ SQLITE_JUMPIFNULL);
+ sqlite3VdbeResolveLabel(v, addrCkFault);
+ pParse->iSelfTab = 0;
+ zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s",
+ pTab->zName);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
+ integrityCheckResultRow(v, 3);
+ sqlite3VdbeResolveLabel(v, addrCkOk);
+ sqlite3ExprCachePop(pParse);
+ }
+ sqlite3ExprListDelete(db, pCheck);
}
/* Validate index entries for the current row */
- for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+ for(j=0, pIdx=pTab->pIndex; pIdx && !isQuick; pIdx=pIdx->pNext, j++){
int jmp2, jmp3, jmp4, jmp5;
int ckUniq = sqlite3VdbeMakeLabel(v);
if( pPk==pIdx ) continue;
@@ -116198,16 +118968,13 @@ SQLITE_PRIVATE void sqlite3Pragma(
/* Verify that an index entry exists for the current table row */
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
pIdx->nColumn); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
sqlite3VdbeLoadString(v, 3, "row ");
sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
sqlite3VdbeLoadString(v, 4, " missing from index ");
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
- jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
- sqlite3VdbeAddOp0(v, OP_Halt);
+ jmp4 = integrityCheckResultRow(v, 3);
sqlite3VdbeJumpHere(v, jmp2);
/* For UNIQUE indexes, verify that only one entry exists with the
** current key. The entry is unique if (1) any column is NULL
@@ -116228,7 +118995,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeJumpHere(v, jmp6);
sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
pIdx->nKeyCol); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
sqlite3VdbeGoto(v, jmp5);
sqlite3VdbeResolveLabel(v, uniqOk);
@@ -116239,19 +119005,18 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, loopTop-1);
#ifndef SQLITE_OMIT_BTREECOUNT
- sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
- for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- if( pPk==pIdx ) continue;
- addr = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
- sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
- sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v);
- sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
- sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
- sqlite3VdbeLoadString(v, 3, pIdx->zName);
- sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1);
+ if( !isQuick ){
+ sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+ if( pPk==pIdx ) continue;
+ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
+ addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v);
+ sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
+ sqlite3VdbeLoadString(v, 3, pIdx->zName);
+ sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
+ integrityCheckResultRow(v, 7);
+ sqlite3VdbeJumpHere(v, addr);
+ }
}
#endif /* SQLITE_OMIT_BTREECOUNT */
}
@@ -116260,7 +119025,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList endCode[] = {
{ OP_AddImm, 1, 0, 0}, /* 0 */
- { OP_If, 1, 4, 0}, /* 1 */
+ { OP_IfNotZero, 1, 4, 0}, /* 1 */
{ OP_String8, 0, 3, 0}, /* 2 */
{ OP_ResultRow, 3, 1, 0}, /* 3 */
};
@@ -116268,7 +119033,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
if( aOp ){
- aOp[0].p2 = -mxErr;
+ aOp[0].p2 = 1-mxErr;
aOp[2].p4type = P4_STATIC;
aOp[2].p4.z = "ok";
}
@@ -116321,7 +119086,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
assert( encnames[SQLITE_UTF8].enc==SQLITE_UTF8 );
assert( encnames[SQLITE_UTF16LE].enc==SQLITE_UTF16LE );
assert( encnames[SQLITE_UTF16BE].enc==SQLITE_UTF16BE );
- returnSingleText(v, "encoding", encnames[ENC(pParse->db)].zName);
+ returnSingleText(v, encnames[ENC(pParse->db)].zName);
}else{ /* "PRAGMA encoding = XXX" */
/* Only change the value of sqlite.enc if the database handle is not
** initialized. If the main database exists, the new sqlite.enc value
@@ -116384,7 +119149,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
case PragTyp_HEADER_VALUE: {
int iCookie = pPragma->iArg; /* Which cookie to read or write */
sqlite3VdbeUsesBtree(v, iDb);
- if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){
+ if( zRight && (pPragma->mPragFlg & PragFlg_ReadOnly)==0 ){
/* Write the specified cookie value */
static const VdbeOpList setCookie[] = {
{ OP_Transaction, 0, 1, 0}, /* 0 */
@@ -116412,8 +119177,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
aOp[0].p1 = iDb;
aOp[1].p1 = iDb;
aOp[1].p3 = iCookie;
- sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
sqlite3VdbeReusable(v);
}
}
@@ -116431,7 +119194,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
int i = 0;
const char *zOpt;
pParse->nMem = 1;
- setOneColumnName(v, "compile_option");
while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){
sqlite3VdbeLoadString(v, 1, zOpt);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
@@ -116448,7 +119210,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
** Checkpoint the database.
*/
case PragTyp_WAL_CHECKPOINT: {
- static const char *azCol[] = { "busy", "log", "checkpointed" };
int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
int eMode = SQLITE_CHECKPOINT_PASSIVE;
if( zRight ){
@@ -116460,7 +119221,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
eMode = SQLITE_CHECKPOINT_TRUNCATE;
}
}
- setAllColumnNames(v, 3, azCol); assert( 3==ArraySize(azCol) );
pParse->nMem = 3;
sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
@@ -116479,7 +119239,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( zRight ){
sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight));
}
- returnSingleInt(v, "wal_autocheckpoint",
+ returnSingleInt(v,
db->xWalCallback==sqlite3WalDefaultHook ?
SQLITE_PTR_TO_INT(db->pWalArg) : 0);
}
@@ -116498,6 +119258,119 @@ SQLITE_PRIVATE void sqlite3Pragma(
break;
}
+ /*
+ ** PRAGMA optimize
+ ** PRAGMA optimize(MASK)
+ ** PRAGMA schema.optimize
+ ** PRAGMA schema.optimize(MASK)
+ **
+ ** Attempt to optimize the database. All schemas are optimized in the first
+ ** two forms, and only the specified schema is optimized in the latter two.
+ **
+ ** The details of optimizations performed by this pragma are expected
+ ** to change and improve over time. Applications should anticipate that
+ ** this pragma will perform new optimizations in future releases.
+ **
+ ** The optional argument is a bitmask of optimizations to perform:
+ **
+ ** 0x0001 Debugging mode. Do not actually perform any optimizations
+ ** but instead return one line of text for each optimization
+ ** that would have been done. Off by default.
+ **
+ ** 0x0002 Run ANALYZE on tables that might benefit. On by default.
+ ** See below for additional information.
+ **
+ ** 0x0004 (Not yet implemented) Record usage and performance
+ ** information from the current session in the
+ ** database file so that it will be available to "optimize"
+ ** pragmas run by future database connections.
+ **
+ ** 0x0008 (Not yet implemented) Create indexes that might have
+ ** been helpful to recent queries
+ **
+ ** The default MASK is and always shall be 0xfffe. 0xfffe means perform all
+ ** of the optimizations listed above except Debug Mode, including new
+ ** optimizations that have not yet been invented. If new optimizations are
+ ** ever added that should be off by default, those off-by-default
+ ** optimizations will have bitmasks of 0x10000 or larger.
+ **
+ ** DETERMINATION OF WHEN TO RUN ANALYZE
+ **
+ ** In the current implementation, a table is analyzed if only if all of
+ ** the following are true:
+ **
+ ** (1) MASK bit 0x02 is set.
+ **
+ ** (2) The query planner used sqlite_stat1-style statistics for one or
+ ** more indexes of the table at some point during the lifetime of
+ ** the current connection.
+ **
+ ** (3) One or more indexes of the table are currently unanalyzed OR
+ ** the number of rows in the table has increased by 25 times or more
+ ** since the last time ANALYZE was run.
+ **
+ ** The rules for when tables are analyzed are likely to change in
+ ** future releases.
+ */
+ case PragTyp_OPTIMIZE: {
+ int iDbLast; /* Loop termination point for the schema loop */
+ int iTabCur; /* Cursor for a table whose size needs checking */
+ HashElem *k; /* Loop over tables of a schema */
+ Schema *pSchema; /* The current schema */
+ Table *pTab; /* A table in the schema */
+ Index *pIdx; /* An index of the table */
+ LogEst szThreshold; /* Size threshold above which reanalysis is needd */
+ char *zSubSql; /* SQL statement for the OP_SqlExec opcode */
+ u32 opMask; /* Mask of operations to perform */
+
+ if( zRight ){
+ opMask = (u32)sqlite3Atoi(zRight);
+ if( (opMask & 0x02)==0 ) break;
+ }else{
+ opMask = 0xfffe;
+ }
+ iTabCur = pParse->nTab++;
+ for(iDbLast = zDb?iDb:db->nDb-1; iDb<=iDbLast; iDb++){
+ if( iDb==1 ) continue;
+ sqlite3CodeVerifySchema(pParse, iDb);
+ pSchema = db->aDb[iDb].pSchema;
+ for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
+ pTab = (Table*)sqliteHashData(k);
+
+ /* If table pTab has not been used in a way that would benefit from
+ ** having analysis statistics during the current session, then skip it.
+ ** This also has the effect of skipping virtual tables and views */
+ if( (pTab->tabFlags & TF_StatsUsed)==0 ) continue;
+
+ /* Reanalyze if the table is 25 times larger than the last analysis */
+ szThreshold = pTab->nRowLogEst + 46; assert( sqlite3LogEst(25)==46 );
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( !pIdx->hasStat1 ){
+ szThreshold = 0; /* Always analyze if any index lacks statistics */
+ break;
+ }
+ }
+ if( szThreshold ){
+ sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
+ sqlite3VdbeAddOp3(v, OP_IfSmaller, iTabCur,
+ sqlite3VdbeCurrentAddr(v)+2+(opMask&1), szThreshold);
+ VdbeCoverage(v);
+ }
+ zSubSql = sqlite3MPrintf(db, "ANALYZE \"%w\".\"%w\"",
+ db->aDb[iDb].zDbSName, pTab->zName);
+ if( opMask & 0x01 ){
+ int r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, r1, 0, zSubSql, P4_DYNAMIC);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, r1, 1);
+ }else{
+ sqlite3VdbeAddOp4(v, OP_SqlExec, 0, 0, 0, zSubSql, P4_DYNAMIC);
+ }
+ }
+ }
+ sqlite3VdbeAddOp0(v, OP_Expire);
+ break;
+ }
+
/*
** PRAGMA busy_timeout
** PRAGMA busy_timeout = N
@@ -116512,7 +119385,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( zRight ){
sqlite3_busy_timeout(db, sqlite3Atoi(zRight));
}
- returnSingleInt(v, "timeout", db->busyTimeout);
+ returnSingleInt(v, db->busyTimeout);
break;
}
@@ -116532,7 +119405,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
sqlite3_soft_heap_limit64(N);
}
- returnSingleInt(v, "soft_heap_limit", sqlite3_soft_heap_limit64(-1));
+ returnSingleInt(v, sqlite3_soft_heap_limit64(-1));
break;
}
@@ -116551,8 +119424,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
){
sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff));
}
- returnSingleInt(v, "threads",
- sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1));
+ returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1));
break;
}
@@ -116564,9 +119436,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
static const char *const azLockName[] = {
"unlocked", "shared", "reserved", "pending", "exclusive"
};
- static const char *azCol[] = { "database", "status" };
int i;
- setAllColumnNames(v, 2, azCol); assert( 2==ArraySize(azCol) );
pParse->nMem = 2;
for(i=0; inDb; i++){
Btree *pBt;
@@ -116581,7 +119451,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
zState = azLockName[j];
}
sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zDbSName, zState);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
break;
}
@@ -116632,10 +119501,329 @@ SQLITE_PRIVATE void sqlite3Pragma(
} /* End of the PRAGMA switch */
+ /* The following block is a no-op unless SQLITE_DEBUG is defined. Its only
+ ** purpose is to execute assert() statements to verify that if the
+ ** PragFlg_NoColumns1 flag is set and the caller specified an argument
+ ** to the PRAGMA, the implementation has not added any OP_ResultRow
+ ** instructions to the VM. */
+ if( (pPragma->mPragFlg & PragFlg_NoColumns1) && zRight ){
+ sqlite3VdbeVerifyNoResultRow(v);
+ }
+
pragma_out:
sqlite3DbFree(db, zLeft);
sqlite3DbFree(db, zRight);
}
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*****************************************************************************
+** Implementation of an eponymous virtual table that runs a pragma.
+**
+*/
+typedef struct PragmaVtab PragmaVtab;
+typedef struct PragmaVtabCursor PragmaVtabCursor;
+struct PragmaVtab {
+ sqlite3_vtab base; /* Base class. Must be first */
+ sqlite3 *db; /* The database connection to which it belongs */
+ const PragmaName *pName; /* Name of the pragma */
+ u8 nHidden; /* Number of hidden columns */
+ u8 iHidden; /* Index of the first hidden column */
+};
+struct PragmaVtabCursor {
+ sqlite3_vtab_cursor base; /* Base class. Must be first */
+ sqlite3_stmt *pPragma; /* The pragma statement to run */
+ sqlite_int64 iRowid; /* Current rowid */
+ char *azArg[2]; /* Value of the argument and schema */
+};
+
+/*
+** Pragma virtual table module xConnect method.
+*/
+static int pragmaVtabConnect(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ const PragmaName *pPragma = (const PragmaName*)pAux;
+ PragmaVtab *pTab = 0;
+ int rc;
+ int i, j;
+ char cSep = '(';
+ StrAccum acc;
+ char zBuf[200];
+
+ UNUSED_PARAMETER(argc);
+ UNUSED_PARAMETER(argv);
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
+ sqlite3StrAccumAppendAll(&acc, "CREATE TABLE x");
+ for(i=0, j=pPragma->iPragCName; inPragCName; i++, j++){
+ sqlite3XPrintf(&acc, "%c\"%s\"", cSep, pragCName[j]);
+ cSep = ',';
+ }
+ if( i==0 ){
+ sqlite3XPrintf(&acc, "(\"%s\"", pPragma->zName);
+ cSep = ',';
+ i++;
+ }
+ j = 0;
+ if( pPragma->mPragFlg & PragFlg_Result1 ){
+ sqlite3StrAccumAppendAll(&acc, ",arg HIDDEN");
+ j++;
+ }
+ if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){
+ sqlite3StrAccumAppendAll(&acc, ",schema HIDDEN");
+ j++;
+ }
+ sqlite3StrAccumAppend(&acc, ")", 1);
+ sqlite3StrAccumFinish(&acc);
+ assert( strlen(zBuf) < sizeof(zBuf)-1 );
+ rc = sqlite3_declare_vtab(db, zBuf);
+ if( rc==SQLITE_OK ){
+ pTab = (PragmaVtab*)sqlite3_malloc(sizeof(PragmaVtab));
+ if( pTab==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ memset(pTab, 0, sizeof(PragmaVtab));
+ pTab->pName = pPragma;
+ pTab->db = db;
+ pTab->iHidden = i;
+ pTab->nHidden = j;
+ }
+ }else{
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }
+
+ *ppVtab = (sqlite3_vtab*)pTab;
+ return rc;
+}
+
+/*
+** Pragma virtual table module xDisconnect method.
+*/
+static int pragmaVtabDisconnect(sqlite3_vtab *pVtab){
+ PragmaVtab *pTab = (PragmaVtab*)pVtab;
+ sqlite3_free(pTab);
+ return SQLITE_OK;
+}
+
+/* Figure out the best index to use to search a pragma virtual table.
+**
+** There are not really any index choices. But we want to encourage the
+** query planner to give == constraints on as many hidden parameters as
+** possible, and especially on the first hidden parameter. So return a
+** high cost if hidden parameters are unconstrained.
+*/
+static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
+ PragmaVtab *pTab = (PragmaVtab*)tab;
+ const struct sqlite3_index_constraint *pConstraint;
+ int i, j;
+ int seen[2];
+
+ pIdxInfo->estimatedCost = (double)1;
+ if( pTab->nHidden==0 ){ return SQLITE_OK; }
+ pConstraint = pIdxInfo->aConstraint;
+ seen[0] = 0;
+ seen[1] = 0;
+ for(i=0; inConstraint; i++, pConstraint++){
+ if( pConstraint->usable==0 ) continue;
+ if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
+ if( pConstraint->iColumn < pTab->iHidden ) continue;
+ j = pConstraint->iColumn - pTab->iHidden;
+ assert( j < 2 );
+ seen[j] = i+1;
+ }
+ if( seen[0]==0 ){
+ pIdxInfo->estimatedCost = (double)2147483647;
+ pIdxInfo->estimatedRows = 2147483647;
+ return SQLITE_OK;
+ }
+ j = seen[0]-1;
+ pIdxInfo->aConstraintUsage[j].argvIndex = 1;
+ pIdxInfo->aConstraintUsage[j].omit = 1;
+ if( seen[1]==0 ) return SQLITE_OK;
+ pIdxInfo->estimatedCost = (double)20;
+ pIdxInfo->estimatedRows = 20;
+ j = seen[1]-1;
+ pIdxInfo->aConstraintUsage[j].argvIndex = 2;
+ pIdxInfo->aConstraintUsage[j].omit = 1;
+ return SQLITE_OK;
+}
+
+/* Create a new cursor for the pragma virtual table */
+static int pragmaVtabOpen(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){
+ PragmaVtabCursor *pCsr;
+ pCsr = (PragmaVtabCursor*)sqlite3_malloc(sizeof(*pCsr));
+ if( pCsr==0 ) return SQLITE_NOMEM;
+ memset(pCsr, 0, sizeof(PragmaVtabCursor));
+ pCsr->base.pVtab = pVtab;
+ *ppCursor = &pCsr->base;
+ return SQLITE_OK;
+}
+
+/* Clear all content from pragma virtual table cursor. */
+static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){
+ int i;
+ sqlite3_finalize(pCsr->pPragma);
+ pCsr->pPragma = 0;
+ for(i=0; iazArg); i++){
+ sqlite3_free(pCsr->azArg[i]);
+ pCsr->azArg[i] = 0;
+ }
+}
+
+/* Close a pragma virtual table cursor */
+static int pragmaVtabClose(sqlite3_vtab_cursor *cur){
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)cur;
+ pragmaVtabCursorClear(pCsr);
+ sqlite3_free(pCsr);
+ return SQLITE_OK;
+}
+
+/* Advance the pragma virtual table cursor to the next row */
+static int pragmaVtabNext(sqlite3_vtab_cursor *pVtabCursor){
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
+ int rc = SQLITE_OK;
+
+ /* Increment the xRowid value */
+ pCsr->iRowid++;
+ assert( pCsr->pPragma );
+ if( SQLITE_ROW!=sqlite3_step(pCsr->pPragma) ){
+ rc = sqlite3_finalize(pCsr->pPragma);
+ pCsr->pPragma = 0;
+ pragmaVtabCursorClear(pCsr);
+ }
+ return rc;
+}
+
+/*
+** Pragma virtual table module xFilter method.
+*/
+static int pragmaVtabFilter(
+ sqlite3_vtab_cursor *pVtabCursor,
+ int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv
+){
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
+ PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab);
+ int rc;
+ int i, j;
+ StrAccum acc;
+ char *zSql;
+
+ UNUSED_PARAMETER(idxNum);
+ UNUSED_PARAMETER(idxStr);
+ pragmaVtabCursorClear(pCsr);
+ j = (pTab->pName->mPragFlg & PragFlg_Result1)!=0 ? 0 : 1;
+ for(i=0; iazArg) );
+ assert( pCsr->azArg[j]==0 );
+ if( zText ){
+ pCsr->azArg[j] = sqlite3_mprintf("%s", zText);
+ if( pCsr->azArg[j]==0 ){
+ return SQLITE_NOMEM;
+ }
+ }
+ }
+ sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]);
+ sqlite3StrAccumAppendAll(&acc, "PRAGMA ");
+ if( pCsr->azArg[1] ){
+ sqlite3XPrintf(&acc, "%Q.", pCsr->azArg[1]);
+ }
+ sqlite3StrAccumAppendAll(&acc, pTab->pName->zName);
+ if( pCsr->azArg[0] ){
+ sqlite3XPrintf(&acc, "=%Q", pCsr->azArg[0]);
+ }
+ zSql = sqlite3StrAccumFinish(&acc);
+ if( zSql==0 ) return SQLITE_NOMEM;
+ rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pPragma, 0);
+ sqlite3_free(zSql);
+ if( rc!=SQLITE_OK ){
+ pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
+ return rc;
+ }
+ return pragmaVtabNext(pVtabCursor);
+}
+
+/*
+** Pragma virtual table module xEof method.
+*/
+static int pragmaVtabEof(sqlite3_vtab_cursor *pVtabCursor){
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
+ return (pCsr->pPragma==0);
+}
+
+/* The xColumn method simply returns the corresponding column from
+** the PRAGMA.
+*/
+static int pragmaVtabColumn(
+ sqlite3_vtab_cursor *pVtabCursor,
+ sqlite3_context *ctx,
+ int i
+){
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
+ PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab);
+ if( iiHidden ){
+ sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pPragma, i));
+ }else{
+ sqlite3_result_text(ctx, pCsr->azArg[i-pTab->iHidden],-1,SQLITE_TRANSIENT);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Pragma virtual table module xRowid method.
+*/
+static int pragmaVtabRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *p){
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
+ *p = pCsr->iRowid;
+ return SQLITE_OK;
+}
+
+/* The pragma virtual table object */
+static const sqlite3_module pragmaVtabModule = {
+ 0, /* iVersion */
+ 0, /* xCreate - create a table */
+ pragmaVtabConnect, /* xConnect - connect to an existing table */
+ pragmaVtabBestIndex, /* xBestIndex - Determine search strategy */
+ pragmaVtabDisconnect, /* xDisconnect - Disconnect from a table */
+ 0, /* xDestroy - Drop a table */
+ pragmaVtabOpen, /* xOpen - open a cursor */
+ pragmaVtabClose, /* xClose - close a cursor */
+ pragmaVtabFilter, /* xFilter - configure scan constraints */
+ pragmaVtabNext, /* xNext - advance a cursor */
+ pragmaVtabEof, /* xEof */
+ pragmaVtabColumn, /* xColumn - read data */
+ pragmaVtabRowid, /* xRowid - read data */
+ 0, /* xUpdate - write data */
+ 0, /* xBegin - begin transaction */
+ 0, /* xSync - sync transaction */
+ 0, /* xCommit - commit transaction */
+ 0, /* xRollback - rollback transaction */
+ 0, /* xFindFunction - function overloading */
+ 0, /* xRename - rename the table */
+ 0, /* xSavepoint */
+ 0, /* xRelease */
+ 0 /* xRollbackTo */
+};
+
+/*
+** Check to see if zTabName is really the name of a pragma. If it is,
+** then register an eponymous virtual table for that pragma and return
+** a pointer to the Module object for the new virtual table.
+*/
+SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3 *db, const char *zName){
+ const PragmaName *pName;
+ assert( sqlite3_strnicmp(zName, "pragma_", 7)==0 );
+ pName = pragmaLocate(zName+7);
+ if( pName==0 ) return 0;
+ if( (pName->mPragFlg & (PragFlg_Result0|PragFlg_Result1))==0 ) return 0;
+ assert( sqlite3HashFind(&db->aModule, zName)==0 );
+ return sqlite3VtabCreateModule(db, zName, &pragmaVtabModule, (void*)pName, 0);
+}
+
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
#endif /* SQLITE_OMIT_PRAGMA */
@@ -116668,7 +119856,7 @@ static void corruptSchema(
const char *zExtra /* Error information */
){
sqlite3 *db = pData->db;
- if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){
+ if( !db->mallocFailed && (db->flags & SQLITE_WriteSchema)==0 ){
char *z;
if( zObj==0 ) zObj = "?";
z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
@@ -116955,8 +120143,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
rc = SQLITE_NOMEM_BKPT;
sqlite3ResetAllSchemasOfConnection(db);
}
- if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){
- /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider
+ if( rc==SQLITE_OK || (db->flags&SQLITE_WriteSchema)){
+ /* Black magic: If the SQLITE_WriteSchema flag is set, then consider
** the schema loaded, even if errors occurred. In this situation the
** current sqlite3_prepare() operation will fail, but the following one
** will attempt to compile the supplied statement against whatever subset
@@ -117156,7 +120344,7 @@ static int sqlite3Prepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
- int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */
+ u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
Vdbe *pReprepare, /* VM being reprepared */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
@@ -117173,6 +120361,14 @@ static int sqlite3Prepare(
/* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
assert( sqlite3_mutex_held(db->mutex) );
+ /* For a long-term use prepared statement avoid the use of
+ ** lookaside memory.
+ */
+ if( prepFlags & SQLITE_PREPARE_PERSISTENT ){
+ sParse.disableLookaside++;
+ db->lookaside.bDisable++;
+ }
+
/* Check to verify that it is possible to get a read lock on all
** database schemas. The inability to get a read lock indicates that
** some other database connection is holding a write-lock, which in
@@ -117204,7 +120400,7 @@ static int sqlite3Prepare(
if( rc ){
const char *zDb = db->aDb[i].zDbSName;
sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
- testcase( db->flags & SQLITE_ReadUncommitted );
+ testcase( db->flags & SQLITE_ReadUncommit );
goto end_prepare;
}
}
@@ -117272,8 +120468,7 @@ static int sqlite3Prepare(
#endif
if( db->init.busy==0 ){
- Vdbe *pVdbe = sParse.pVdbe;
- sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag);
+ sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
}
if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
sqlite3VdbeFinalize(sParse.pVdbe);
@@ -117307,7 +120502,7 @@ static int sqlite3LockAndPrepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
- int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */
+ u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
Vdbe *pOld, /* VM being reprepared */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
@@ -117323,10 +120518,10 @@ static int sqlite3LockAndPrepare(
}
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
- rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
+ rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
if( rc==SQLITE_SCHEMA ){
sqlite3_finalize(*ppStmt);
- rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
+ rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
}
sqlite3BtreeLeaveAll(db);
sqlite3_mutex_leave(db->mutex);
@@ -117347,13 +120542,15 @@ SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){
sqlite3_stmt *pNew;
const char *zSql;
sqlite3 *db;
+ u8 prepFlags;
assert( sqlite3_mutex_held(sqlite3VdbeDb(p)->mutex) );
zSql = sqlite3_sql((sqlite3_stmt *)p);
assert( zSql!=0 ); /* Reprepare only called for prepare_v2() statements */
db = sqlite3VdbeDb(p);
assert( sqlite3_mutex_held(db->mutex) );
- rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0);
+ prepFlags = sqlite3VdbePrepareFlags(p);
+ rc = sqlite3LockAndPrepare(db, zSql, -1, prepFlags, p, &pNew, 0);
if( rc ){
if( rc==SQLITE_NOMEM ){
sqlite3OomFault(db);
@@ -117399,8 +120596,36 @@ SQLITE_API int sqlite3_prepare_v2(
const char **pzTail /* OUT: End of parsed string */
){
int rc;
- rc = sqlite3LockAndPrepare(db,zSql,nBytes,1,0,ppStmt,pzTail);
- assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
+ /* EVIDENCE-OF: R-37923-12173 The sqlite3_prepare_v2() interface works
+ ** exactly the same as sqlite3_prepare_v3() with a zero prepFlags
+ ** parameter.
+ **
+ ** Proof in that the 5th parameter to sqlite3LockAndPrepare is 0 */
+ rc = sqlite3LockAndPrepare(db,zSql,nBytes,SQLITE_PREPARE_SAVESQL,0,
+ ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 );
+ return rc;
+}
+SQLITE_API int sqlite3_prepare_v3(
+ sqlite3 *db, /* Database handle. */
+ const char *zSql, /* UTF-8 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const char **pzTail /* OUT: End of parsed string */
+){
+ int rc;
+ /* EVIDENCE-OF: R-56861-42673 sqlite3_prepare_v3() differs from
+ ** sqlite3_prepare_v2() only in having the extra prepFlags parameter,
+ ** which is a bit array consisting of zero or more of the
+ ** SQLITE_PREPARE_* flags.
+ **
+ ** Proof by comparison to the implementation of sqlite3_prepare_v2()
+ ** directly above. */
+ rc = sqlite3LockAndPrepare(db,zSql,nBytes,
+ SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK),
+ 0,ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 );
return rc;
}
@@ -117413,7 +120638,7 @@ static int sqlite3Prepare16(
sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-16 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
- int saveSqlFlag, /* True to save SQL text into the sqlite3_stmt */
+ u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const void **pzTail /* OUT: End of parsed string */
){
@@ -117441,7 +120666,7 @@ static int sqlite3Prepare16(
sqlite3_mutex_enter(db->mutex);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
if( zSql8 ){
- rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8);
+ rc = sqlite3LockAndPrepare(db, zSql8, -1, prepFlags, 0, ppStmt, &zTail8);
}
if( zTail8 && pzTail ){
@@ -117487,7 +120712,22 @@ SQLITE_API int sqlite3_prepare16_v2(
const void **pzTail /* OUT: End of parsed string */
){
int rc;
- rc = sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail);
+ rc = sqlite3Prepare16(db,zSql,nBytes,SQLITE_PREPARE_SAVESQL,ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
+ return rc;
+}
+SQLITE_API int sqlite3_prepare16_v3(
+ sqlite3 *db, /* Database handle. */
+ const void *zSql, /* UTF-16 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const void **pzTail /* OUT: End of parsed string */
+){
+ int rc;
+ rc = sqlite3Prepare16(db,zSql,nBytes,
+ SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK),
+ ppStmt,pzTail);
assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
return rc;
}
@@ -117574,7 +120814,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
sqlite3ExprDelete(db, p->pLimit);
sqlite3ExprDelete(db, p->pOffset);
if( p->pWith ) sqlite3WithDelete(db, p->pWith);
- if( bFree ) sqlite3DbFree(db, p);
+ if( bFree ) sqlite3DbFreeNN(db, p);
p = pPrior;
bFree = 1;
}
@@ -117610,14 +120850,13 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
){
Select *pNew;
Select standin;
- sqlite3 *db = pParse->db;
- pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
+ pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
if( pNew==0 ){
- assert( db->mallocFailed );
+ assert( pParse->db->mallocFailed );
pNew = &standin;
}
if( pEList==0 ){
- pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0));
+ pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(pParse->db,TK_ASTERISK,0));
}
pNew->pEList = pEList;
pNew->op = TK_SELECT;
@@ -117630,7 +120869,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = 0;
- if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc));
+ if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*pSrc));
pNew->pSrc = pSrc;
pNew->pWhere = pWhere;
pNew->pGroupBy = pGroupBy;
@@ -117641,9 +120880,9 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->pLimit = pLimit;
pNew->pOffset = pOffset;
pNew->pWith = 0;
- assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 );
- if( db->mallocFailed ) {
- clearSelect(db, pNew, pNew!=&standin);
+ assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || pParse->db->mallocFailed!=0 );
+ if( pParse->db->mallocFailed ) {
+ clearSelect(pParse->db, pNew, pNew!=&standin);
pNew = 0;
}else{
assert( pNew->pSrc!=0 || pParse->nErr>0 );
@@ -117832,7 +121071,7 @@ static void addWhereTerm(
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft);
pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);
- pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
+ pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2);
if( pEq && isOuterJoin ){
ExprSetProperty(pEq, EP_FromJoin);
assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
@@ -118019,7 +121258,7 @@ static void pushOntoSorter(
int iLimit; /* LIMIT counter */
assert( bSeq==0 || bSeq==1 );
- assert( nData==1 || regData==regOrigData );
+ assert( nData==1 || regData==regOrigData || regOrigData==0 );
if( nPrefixReg ){
assert( nPrefixReg==nExpr+bSeq );
regBase = regData - nExpr - bSeq;
@@ -118031,11 +121270,11 @@ static void pushOntoSorter(
iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
pSort->labelDone = sqlite3VdbeMakeLabel(v);
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
- SQLITE_ECEL_DUP|SQLITE_ECEL_REF);
+ SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0));
if( bSeq ){
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
}
- if( nPrefixReg==0 ){
+ if( nPrefixReg==0 && nData>0 ){
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord);
@@ -118085,7 +121324,8 @@ static void pushOntoSorter(
}else{
op = OP_IdxInsert;
}
- sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
+ sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord,
+ regBase+nOBSat, nBase-nOBSat);
if( iLimit ){
int addr;
int r1 = 0;
@@ -118093,7 +121333,7 @@ static void pushOntoSorter(
** register is initialized with value of LIMIT+OFFSET.) After the sorter
** fills up, delete the least entry in the sorter after each insert.
** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */
- addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v);
+ addr = sqlite3VdbeAddOp1(v, OP_IfNotZero, iLimit); VdbeCoverage(v);
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
if( pSort->bOrderedInnerLoop ){
r1 = ++pParse->nMem;
@@ -118153,7 +121393,8 @@ static void codeDistinct(
r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N);
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, r1);
}
@@ -118164,7 +121405,7 @@ static void codeDistinct(
** If srcTab is negative, then the pEList expressions
** are evaluated in order to get the data for this row. If srcTab is
** zero or more, then data is pulled from srcTab and pEList is used only
-** to get number columns and the datatype for each column.
+** to get the number of columns and the collation sequence for each column.
*/
static void selectInnerLoop(
Parse *pParse, /* The parser context */
@@ -118179,13 +121420,20 @@ static void selectInnerLoop(
){
Vdbe *v = pParse->pVdbe;
int i;
- int hasDistinct; /* True if the DISTINCT keyword is present */
- int regResult; /* Start of memory holding result set */
+ int hasDistinct; /* True if the DISTINCT keyword is present */
int eDest = pDest->eDest; /* How to dispose of results */
int iParm = pDest->iSDParm; /* First argument to disposal method */
int nResultCol; /* Number of result columns */
int nPrefixReg = 0; /* Number of extra registers before regResult */
+ /* Usually, regResult is the first cell in an array of memory cells
+ ** containing the current result row. In this case regOrig is set to the
+ ** same value. However, if the results are being sent to the sorter, the
+ ** values for any expressions that are also part of the sort-key are omitted
+ ** from this array. In this case regOrig is set to zero. */
+ int regResult; /* Start of memory holding current results */
+ int regOrig; /* Start of memory holding full result (or 0) */
+
assert( v );
assert( pEList!=0 );
hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;
@@ -118216,7 +121464,7 @@ static void selectInnerLoop(
pParse->nMem += nResultCol;
}
pDest->nSdst = nResultCol;
- regResult = pDest->iSdst;
+ regOrig = regResult = pDest->iSdst;
if( srcTab>=0 ){
for(i=0; ipOrderBy), set the associated
+ ** iOrderByCol value to one more than the index of the ORDER BY
+ ** expression within the sort-key that pushOntoSorter() will generate.
+ ** This allows the pEList field to be omitted from the sorted record,
+ ** saving space and CPU cycles. */
+ ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF);
+ for(i=pSort->nOBSat; ipOrderBy->nExpr; i++){
+ int j;
+ if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){
+ pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat;
+ }
+ }
+ regOrig = 0;
+ assert( eDest==SRT_Set || eDest==SRT_Mem
+ || eDest==SRT_Coroutine || eDest==SRT_Output );
+ }
+ nResultCol = sqlite3ExprCodeExprList(pParse,pEList,regResult,0,ecelFlags);
}
/* If the DISTINCT keyword was present on the SELECT statement
@@ -118306,7 +121572,7 @@ static void selectInnerLoop(
int r1;
r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
sqlite3ReleaseTempReg(pParse, r1);
break;
}
@@ -118343,7 +121609,7 @@ static void selectInnerLoop(
int addr = sqlite3VdbeCurrentAddr(v) + 4;
sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0);
VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,regResult,nResultCol);
assert( pSort==0 );
}
#endif
@@ -118372,14 +121638,14 @@ static void selectInnerLoop(
** does not matter. But there might be a LIMIT clause, in which
** case the order does matter */
pushOntoSorter(
- pParse, pSort, p, regResult, regResult, nResultCol, nPrefixReg);
+ pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
}else{
int r1 = sqlite3GetTempReg(pParse);
assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
r1, pDest->zAffSdst, nResultCol);
sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
sqlite3ReleaseTempReg(pParse, r1);
}
break;
@@ -118398,11 +121664,12 @@ static void selectInnerLoop(
** memory cells and break out of the scan loop.
*/
case SRT_Mem: {
- assert( nResultCol==pDest->nSdst );
if( pSort ){
+ assert( nResultCol<=pDest->nSdst );
pushOntoSorter(
- pParse, pSort, p, regResult, regResult, nResultCol, nPrefixReg);
+ pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
}else{
+ assert( nResultCol==pDest->nSdst );
assert( regResult==iParm );
/* The LIMIT clause will jump out of the loop for us */
}
@@ -118415,7 +121682,7 @@ static void selectInnerLoop(
testcase( eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
if( pSort ){
- pushOntoSorter(pParse, pSort, p, regResult, regResult, nResultCol,
+ pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol,
nPrefixReg);
}else if( eDest==SRT_Coroutine ){
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
@@ -118465,7 +121732,7 @@ static void selectInnerLoop(
}
sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey);
sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2);
if( addrTest ) sqlite3VdbeJumpHere(v, addrTest);
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempRange(pParse, r2, nKey+2);
@@ -118502,7 +121769,7 @@ static void selectInnerLoop(
** X extra columns.
*/
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
- int nExtra = (N+X)*(sizeof(CollSeq*)+1);
+ int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*);
KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
if( p ){
p->aSortOrder = (u8*)&p->aColl[N+X];
@@ -118525,7 +121792,7 @@ SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo *p){
if( p ){
assert( p->nRef>0 );
p->nRef--;
- if( p->nRef==0 ) sqlite3DbFree(p->db, p);
+ if( p->nRef==0 ) sqlite3DbFreeNN(p->db, p);
}
}
@@ -118700,14 +121967,13 @@ static void generateSortTail(
int iParm = pDest->iSDParm;
int regRow;
int regRowid;
+ int iCol;
int nKey;
int iSortTab; /* Sorter cursor to read from */
int nSortData; /* Trailing values to read from sorter */
int i;
int bSeq; /* True if sorter record includes seq. no. */
-#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
struct ExprList_item *aOutEx = p->pEList->a;
-#endif
assert( addrBreak<0 );
if( pSort->labelBkOut ){
@@ -118745,11 +122011,18 @@ static void generateSortTail(
iSortTab = iTab;
bSeq = 1;
}
- for(i=0; izAffSdst, nColumn);
sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn);
break;
}
case SRT_Mem: {
@@ -118903,13 +122176,10 @@ static const char *columnTypeImpl(
** of the SELECT statement. Return the declaration type and origin
** data for the result-set column of the sub-select.
*/
- if( iCol>=0 && ALWAYS(iColpEList->nExpr) ){
+ if( iCol>=0 && iColpEList->nExpr ){
/* If iCol is less than zero, then the expression requests the
** rowid of the sub-select or view. This expression is legal (see
** test case misc2.2.2) - it always evaluates to NULL.
- **
- ** The ALWAYS() is because iCol>=pS->pEList->nExpr will have been
- ** caught already by name resolution.
*/
NameContext sNC;
Expr *p = pS->pEList->a[iCol].pExpr;
@@ -118994,6 +122264,7 @@ static void generateColumnTypes(
NameContext sNC;
sNC.pSrcList = pTabList;
sNC.pParse = pParse;
+ sNC.pNext = 0;
for(i=0; inExpr; i++){
Expr *p = pEList->a[i].pExpr;
const char *zType;
@@ -119018,20 +122289,49 @@ static void generateColumnTypes(
#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
}
+
/*
-** 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.
+** Compute the column names for a SELECT statement.
+**
+** The only guarantee that SQLite makes about column names is that if the
+** column has an AS clause assigning it a name, that will be the name used.
+** That is the only documented guarantee. However, countless applications
+** developed over the years have made baseless assumptions about column names
+** and will break if those assumptions changes. Hence, use extreme caution
+** when modifying this routine to avoid breaking legacy.
+**
+** See Also: sqlite3ColumnsFromExprList()
+**
+** The PRAGMA short_column_names and PRAGMA full_column_names settings are
+** deprecated. The default setting is short=ON, full=OFF. 99.9% of all
+** applications should operate this way. Nevertheless, we need to support the
+** other modes for legacy:
+**
+** short=OFF, full=OFF: Column name is the text of the expression has it
+** originally appears in the SELECT statement. In
+** other words, the zSpan of the result expression.
+**
+** short=ON, full=OFF: (This is the default setting). If the result
+** refers directly to a table column, then the result
+** column name is just the table column name: COLUMN.
+** Otherwise use zSpan.
+**
+** full=ON, short=ANY: If the result refers directly to a table column,
+** then the result column name with the table name
+** prefix, ex: TABLE.COLUMN. Otherwise use zSpan.
*/
static void generateColumnNames(
Parse *pParse, /* Parser context */
- SrcList *pTabList, /* List of tables */
- ExprList *pEList /* Expressions defining the result set */
+ Select *pSelect /* Generate column names for this SELECT statement */
){
Vdbe *v = pParse->pVdbe;
- int i, j;
+ int i;
+ Table *pTab;
+ SrcList *pTabList;
+ ExprList *pEList;
sqlite3 *db = pParse->db;
- int fullNames, shortNames;
+ int fullName; /* TABLE.COLUMN if no AS clause and is a direct table ref */
+ int srcName; /* COLUMN or TABLE.COLUMN if no AS clause and is direct */
#ifndef SQLITE_OMIT_EXPLAIN
/* If this is an EXPLAIN, skip this step */
@@ -119041,28 +122341,29 @@ static void generateColumnNames(
#endif
if( pParse->colNamesSet || db->mallocFailed ) return;
+ /* Column names are determined by the left-most term of a compound select */
+ while( pSelect->pPrior ) pSelect = pSelect->pPrior;
+ pTabList = pSelect->pSrc;
+ pEList = pSelect->pEList;
assert( v!=0 );
assert( pTabList!=0 );
pParse->colNamesSet = 1;
- fullNames = (db->flags & SQLITE_FullColNames)!=0;
- shortNames = (db->flags & SQLITE_ShortColNames)!=0;
+ fullName = (db->flags & SQLITE_FullColNames)!=0;
+ srcName = (db->flags & SQLITE_ShortColNames)!=0 || fullName;
sqlite3VdbeSetNumCols(v, pEList->nExpr);
for(i=0; inExpr; i++){
- Expr *p;
- p = pEList->a[i].pExpr;
- if( NEVER(p==0) ) continue;
+ Expr *p = pEList->a[i].pExpr;
+
+ assert( p!=0 );
if( pEList->a[i].zName ){
+ /* An AS clause always takes first priority */
char *zName = pEList->a[i].zName;
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
- }else if( p->op==TK_COLUMN || p->op==TK_AGG_COLUMN ){
- Table *pTab;
+ }else if( srcName && p->op==TK_COLUMN ){
char *zCol;
int iCol = p->iColumn;
- for(j=0; ALWAYS(jnSrc); j++){
- if( pTabList->a[j].iCursor==p->iTable ) break;
- }
- assert( jnSrc );
- pTab = pTabList->a[j].pTab;
+ pTab = p->pTab;
+ assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iColnCol) );
if( iCol<0 ){
@@ -119070,10 +122371,7 @@ static void generateColumnNames(
}else{
zCol = pTab->aCol[iCol].zName;
}
- if( !shortNames && !fullNames ){
- sqlite3VdbeSetColName(v, i, COLNAME_NAME,
- sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
- }else if( fullNames ){
+ if( fullName ){
char *zName = 0;
zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol);
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC);
@@ -119101,6 +122399,15 @@ static void generateColumnNames(
**
** Return SQLITE_OK on success. If a memory allocation error occurs,
** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM.
+**
+** The only guarantee that SQLite makes about column names is that if the
+** column has an AS clause assigning it a name, that will be the name used.
+** That is the only documented guarantee. However, countless applications
+** developed over the years have made baseless assumptions about column names
+** and will break if those assumptions changes. Hence, use extreme caution
+** when modifying this routine to avoid breaking legacy.
+**
+** See Also: generateColumnNames()
*/
SQLITE_PRIVATE int sqlite3ColumnsFromExprList(
Parse *pParse, /* Parsing context */
@@ -119113,7 +122420,6 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList(
u32 cnt; /* Index added to make the name unique */
Column *aCol, *pCol; /* For looping over result columns */
int nCol; /* Number of columns in the result set */
- Expr *p; /* Expression for a single result column */
char *zName; /* Column name */
int nName; /* Size of name in zName[] */
Hash ht; /* Hash table of column names */
@@ -119134,20 +122440,18 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList(
for(i=0, pCol=aCol; imallocFailed; i++, pCol++){
/* Get an appropriate name for the column
*/
- p = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
if( (zName = pEList->a[i].zName)!=0 ){
/* If the column contains an "AS " phrase, use as the name */
}else{
- Expr *pColExpr = p; /* The expression that is the result column name */
- Table *pTab; /* Table associated with this expression */
+ Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
while( pColExpr->op==TK_DOT ){
pColExpr = pColExpr->pRight;
assert( pColExpr!=0 );
}
- if( pColExpr->op==TK_COLUMN && ALWAYS(pColExpr->pTab!=0) ){
+ if( pColExpr->op==TK_COLUMN && pColExpr->pTab!=0 ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
- pTab = pColExpr->pTab;
+ Table *pTab = pColExpr->pTab;
if( iCol<0 ) iCol = pTab->iPKey;
zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
}else if( pColExpr->op==TK_ID ){
@@ -119158,7 +122462,11 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList(
zName = pEList->a[i].zSpan;
}
}
- zName = sqlite3MPrintf(db, "%s", zName);
+ if( zName ){
+ zName = sqlite3DbStrDup(db, zName);
+ }else{
+ zName = sqlite3MPrintf(db,"column%d",i+1);
+ }
/* Make sure the column name is unique. If the name is not unique,
** append an integer to the name so that it becomes unique.
@@ -119271,7 +122579,7 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
/* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
** is disabled */
assert( db->lookaside.bDisable );
- pTab->nRef = 1;
+ pTab->nTabRef = 1;
pTab->zName = 0;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
@@ -119502,6 +122810,7 @@ static void generateWithRecursiveQuery(
/* Process the LIMIT and OFFSET clauses, if they exist */
addrBreak = sqlite3VdbeMakeLabel(v);
+ p->nSelectRow = 320; /* 4 billion rows */
computeLimitRegisters(pParse, p, addrBreak);
pLimit = p->pLimit;
pOffset = p->pOffset;
@@ -119886,11 +123195,6 @@ static int multiSelect(
if( dest.eDest!=priorOp ){
int iCont, iBreak, iStart;
assert( p->pEList );
- if( dest.eDest==SRT_Output ){
- Select *pFirst = p;
- while( pFirst->pPrior ) pFirst = pFirst->pPrior;
- generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList);
- }
iBreak = sqlite3VdbeMakeLabel(v);
iCont = sqlite3VdbeMakeLabel(v);
computeLimitRegisters(pParse, p, iBreak);
@@ -119961,17 +123265,12 @@ static int multiSelect(
** tables.
*/
assert( p->pEList );
- if( dest.eDest==SRT_Output ){
- Select *pFirst = p;
- while( pFirst->pPrior ) pFirst = pFirst->pPrior;
- generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList);
- }
iBreak = sqlite3VdbeMakeLabel(v);
iCont = sqlite3VdbeMakeLabel(v);
computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v);
r1 = sqlite3GetTempReg(pParse);
- iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1);
+ iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1);
sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, r1);
selectInnerLoop(pParse, p, p->pEList, tab1,
@@ -120138,7 +123437,8 @@ static int generateOutputSubroutine(
sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst,
r1, pDest->zAffSdst, pIn->nSdst);
sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
+ pIn->iSdst, pIn->nSdst);
sqlite3ReleaseTempReg(pParse, r1);
break;
}
@@ -120362,7 +123662,7 @@ static int multiSelectOrderBy(
if( pNew==0 ) return SQLITE_NOMEM_BKPT;
pNew->flags |= EP_IntValue;
pNew->u.iValue = i;
- pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
+ p->pOrderBy = pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
if( pOrderBy ) pOrderBy->a[nOrderBy++].u.x.iOrderByCol = (u16)i;
}
}
@@ -120572,14 +123872,6 @@ static int multiSelectOrderBy(
*/
sqlite3VdbeResolveLabel(v, labelEnd);
- /* Set the number of output columns
- */
- if( pDest->eDest==SRT_Output ){
- Select *pFirst = pPrior;
- while( pFirst->pPrior ) pFirst = pFirst->pPrior;
- generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList);
- }
-
/* Reassembly the compound query so that it will be freed correctly
** by the calling function */
if( p->pPrior ){
@@ -120596,9 +123888,24 @@ static int multiSelectOrderBy(
#endif
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+
+/* An instance of the SubstContext object describes an substitution edit
+** to be performed on a parse tree.
+**
+** All references to columns in table iTable are to be replaced by corresponding
+** expressions in pEList.
+*/
+typedef struct SubstContext {
+ Parse *pParse; /* The parsing context */
+ int iTable; /* Replace references to this table */
+ int iNewTable; /* New table number */
+ int isLeftJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */
+ ExprList *pEList; /* Replacement expressions */
+} SubstContext;
+
/* Forward Declarations */
-static void substExprList(sqlite3*, ExprList*, int, ExprList*);
-static void substSelect(sqlite3*, Select *, int, ExprList*, int);
+static void substExprList(SubstContext*, ExprList*);
+static void substSelect(SubstContext*, Select*, int);
/*
** Scan through the expression pExpr. Replace every reference to
@@ -120609,74 +123916,95 @@ static void substSelect(sqlite3*, Select *, int, ExprList*, int);
** This routine is part of the flattening procedure. A subquery
** whose result set is defined by pEList appears as entry in the
** FROM clause of a SELECT such that the VDBE cursor assigned to that
-** FORM clause entry is iTable. This routine make the necessary
+** FORM clause entry is iTable. This routine makes the necessary
** changes to pExpr so that it refers directly to the source table
** of the subquery rather the result set of the subquery.
*/
static Expr *substExpr(
- sqlite3 *db, /* Report malloc errors to this connection */
- Expr *pExpr, /* Expr in which substitution occurs */
- int iTable, /* Table to be substituted */
- ExprList *pEList /* Substitute expressions */
+ SubstContext *pSubst, /* Description of the substitution */
+ Expr *pExpr /* Expr in which substitution occurs */
){
if( pExpr==0 ) return 0;
- if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
+ if( ExprHasProperty(pExpr, EP_FromJoin) && pExpr->iRightJoinTable==pSubst->iTable ){
+ pExpr->iRightJoinTable = pSubst->iNewTable;
+ }
+ if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){
if( pExpr->iColumn<0 ){
pExpr->op = TK_NULL;
}else{
Expr *pNew;
- assert( pEList!=0 && pExpr->iColumnnExpr );
+ Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
+ Expr ifNullRow;
+ assert( pSubst->pEList!=0 && pExpr->iColumnpEList->nExpr );
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
- pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0);
- sqlite3ExprDelete(db, pExpr);
- pExpr = pNew;
+ if( sqlite3ExprIsVector(pCopy) ){
+ sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
+ }else{
+ sqlite3 *db = pSubst->pParse->db;
+ if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){
+ memset(&ifNullRow, 0, sizeof(ifNullRow));
+ ifNullRow.op = TK_IF_NULL_ROW;
+ ifNullRow.pLeft = pCopy;
+ ifNullRow.iTable = pSubst->iNewTable;
+ pCopy = &ifNullRow;
+ }
+ pNew = sqlite3ExprDup(db, pCopy, 0);
+ if( pNew && pSubst->isLeftJoin ){
+ ExprSetProperty(pNew, EP_CanBeNull);
+ }
+ if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){
+ pNew->iRightJoinTable = pExpr->iRightJoinTable;
+ ExprSetProperty(pNew, EP_FromJoin);
+ }
+ sqlite3ExprDelete(db, pExpr);
+ pExpr = pNew;
+ }
}
}else{
- pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList);
- pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList);
+ if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){
+ pExpr->iTable = pSubst->iNewTable;
+ }
+ pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
+ pExpr->pRight = substExpr(pSubst, pExpr->pRight);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- substSelect(db, pExpr->x.pSelect, iTable, pEList, 1);
+ substSelect(pSubst, pExpr->x.pSelect, 1);
}else{
- substExprList(db, pExpr->x.pList, iTable, pEList);
+ substExprList(pSubst, pExpr->x.pList);
}
}
return pExpr;
}
static void substExprList(
- sqlite3 *db, /* Report malloc errors here */
- ExprList *pList, /* List to scan and in which to make substitutes */
- int iTable, /* Table to be substituted */
- ExprList *pEList /* Substitute values */
+ SubstContext *pSubst, /* Description of the substitution */
+ ExprList *pList /* List to scan and in which to make substitutes */
){
int i;
if( pList==0 ) return;
for(i=0; inExpr; i++){
- pList->a[i].pExpr = substExpr(db, pList->a[i].pExpr, iTable, pEList);
+ pList->a[i].pExpr = substExpr(pSubst, pList->a[i].pExpr);
}
}
static void substSelect(
- sqlite3 *db, /* Report malloc errors here */
- Select *p, /* SELECT statement in which to make substitutions */
- int iTable, /* Table to be replaced */
- ExprList *pEList, /* Substitute values */
- int doPrior /* Do substitutes on p->pPrior too */
+ SubstContext *pSubst, /* Description of the substitution */
+ Select *p, /* SELECT statement in which to make substitutions */
+ int doPrior /* Do substitutes on p->pPrior too */
){
SrcList *pSrc;
struct SrcList_item *pItem;
int i;
if( !p ) return;
do{
- substExprList(db, p->pEList, iTable, pEList);
- substExprList(db, p->pGroupBy, iTable, pEList);
- substExprList(db, p->pOrderBy, iTable, pEList);
- p->pHaving = substExpr(db, p->pHaving, iTable, pEList);
- p->pWhere = substExpr(db, p->pWhere, iTable, pEList);
+ substExprList(pSubst, p->pEList);
+ substExprList(pSubst, p->pGroupBy);
+ substExprList(pSubst, p->pOrderBy);
+ p->pHaving = substExpr(pSubst, p->pHaving);
+ p->pWhere = substExpr(pSubst, p->pWhere);
pSrc = p->pSrc;
assert( pSrc!=0 );
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- substSelect(db, pItem->pSelect, iTable, pEList, 1);
+ substSelect(pSubst, pItem->pSelect, 1);
if( pItem->fg.isTabFunc ){
- substExprList(db, pItem->u1.pFuncArg, iTable, pEList);
+ substExprList(pSubst, pItem->u1.pFuncArg);
}
}
}while( doPrior && (p = p->pPrior)!=0 );
@@ -120719,8 +124047,10 @@ static void substSelect(
** FROM-clause subquery that is a candidate for flattening. (2b is
** due to ticket [2f7170d73bf9abf80] from 2015-02-09.)
**
-** (3) The subquery is not the right operand of a left outer join
-** (Originally ticket #306. Strengthened by ticket #3300)
+** (3) The subquery is not the right operand of a LEFT JOIN
+** or (a) the subquery is not itself a join and (b) the FROM clause
+** of the subquery does not contain a virtual table and (c) the
+** outer query is not an aggregate.
**
** (4) The subquery is not DISTINCT.
**
@@ -120732,7 +124062,7 @@ static void substSelect(
** DISTINCT.
**
** (7) The subquery has a FROM clause. TODO: For subqueries without
-** A FROM clause, consider adding a FROM close with the special
+** A FROM clause, consider adding a FROM clause with the special
** table sqlite_once that consists of a single row containing a
** single NULL.
**
@@ -120836,8 +124166,9 @@ static int flattenSubquery(
Select *pSub1; /* Pointer to the rightmost select in sub-query */
SrcList *pSrc; /* The FROM clause of the outer query */
SrcList *pSubSrc; /* The FROM clause of the subquery */
- ExprList *pList; /* The result set of the outer query */
int iParent; /* VDBE cursor number of the pSub result set temp table */
+ int iNewParent = -1;/* Replacement table for iParent */
+ int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */
int i; /* Loop counter */
Expr *pWhere; /* The WHERE clause */
struct SrcList_item *pSubitem; /* The subquery */
@@ -120864,7 +124195,7 @@ static int flattenSubquery(
return 0; /* Restriction (2b) */
}
}
-
+
pSubSrc = pSub->pSrc;
assert( pSubSrc );
/* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
@@ -120902,10 +124233,9 @@ static int flattenSubquery(
return 0; /* Restriction (23) */
}
- /* OBSOLETE COMMENT 1:
- ** Restriction 3: If the subquery is a join, make sure the subquery is
- ** not used as the right operand of an outer join. Examples of why this
- ** is not allowed:
+ /*
+ ** If the subquery is the right operand of a LEFT JOIN, then the
+ ** subquery may not be a join itself. Example of why this is not allowed:
**
** t1 LEFT OUTER JOIN (t2 JOIN t3)
**
@@ -120915,28 +124245,27 @@ static int flattenSubquery(
**
** which is not at all the same thing.
**
- ** OBSOLETE COMMENT 2:
- ** Restriction 12: If the subquery is the right operand of a left outer
- ** join, make sure the subquery has no WHERE clause.
- ** An examples of why this is not allowed:
+ ** If the subquery is the right operand of a LEFT JOIN, then the outer
+ ** query cannot be an aggregate. This is an artifact of the way aggregates
+ ** are processed - there is no mechanism to determine if the LEFT JOIN
+ ** table should be all-NULL.
**
- ** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0)
- **
- ** If we flatten the above, we would get
- **
- ** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0
- **
- ** But the t2.x>0 test will always fail on a NULL row of t2, which
- ** effectively converts the OUTER JOIN into an INNER JOIN.
- **
- ** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE:
- ** Ticket #3300 shows that flattening the right term of a LEFT JOIN
- ** is fraught with danger. Best to avoid the whole thing. If the
- ** subquery is the right term of a LEFT JOIN, then do not flatten.
+ ** See also tickets #306, #350, and #3300.
*/
if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
- return 0;
+ isLeftJoin = 1;
+ if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){
+ return 0; /* Restriction (3) */
+ }
}
+#ifdef SQLITE_EXTRA_IFNULLROW
+ else if( iFrom>0 && !isAgg ){
+ /* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for
+ ** every reference to any result column from subquery in a join, even though
+ ** they are not necessary. This will stress-test the OP_IfNullRow opcode. */
+ isLeftJoin = -1;
+ }
+#endif
/* Restriction 17: If the sub-query is a compound SELECT, then it must
** use only the UNION ALL operator. And none of the simple select queries
@@ -121073,12 +124402,12 @@ static int flattenSubquery(
*/
if( ALWAYS(pSubitem->pTab!=0) ){
Table *pTabToDel = pSubitem->pTab;
- if( pTabToDel->nRef==1 ){
+ if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
pTabToDel->pNextZombie = pToplevel->pZombieTab;
pToplevel->pZombieTab = pTabToDel;
}else{
- pTabToDel->nRef--;
+ pTabToDel->nTabRef--;
}
pSubitem->pTab = 0;
}
@@ -121144,6 +124473,7 @@ static int flattenSubquery(
sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing);
assert( pSrc->a[i+iFrom].fg.isTabFunc==0 );
pSrc->a[i+iFrom] = pSubSrc->a[i];
+ iNewParent = pSubSrc->a[i].iCursor;
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
pSrc->a[iFrom].fg.jointype = jointype;
@@ -121160,14 +124490,6 @@ static int flattenSubquery(
** We look at every expression in the outer query and every place we see
** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
*/
- pList = pParent->pEList;
- for(i=0; inExpr; i++){
- if( pList->a[i].zName==0 ){
- char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan);
- sqlite3Dequote(zName);
- pList->a[i].zName = zName;
- }
- }
if( pSub->pOrderBy ){
/* At this point, any non-zero iOrderByCol values indicate that the
** ORDER BY column expression is identical to the iOrderByCol'th
@@ -121189,6 +124511,9 @@ static int flattenSubquery(
pSub->pOrderBy = 0;
}
pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
+ if( isLeftJoin>0 ){
+ setJoinExpr(pWhere, iNewParent);
+ }
if( subqueryIsAgg ){
assert( pParent->pHaving==0 );
pParent->pHaving = pParent->pWhere;
@@ -121201,7 +124526,15 @@ static int flattenSubquery(
}else{
pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
}
- substSelect(db, pParent, iParent, pSub->pEList, 0);
+ if( db->mallocFailed==0 ){
+ SubstContext x;
+ x.pParse = pParse;
+ x.iTable = iParent;
+ x.iNewTable = iNewParent;
+ x.isLeftJoin = isLeftJoin;
+ x.pEList = pSub->pEList;
+ substSelect(&x, pParent, 0);
+ }
/* The flattened query is distinct if either the inner or the
** outer query is distinct.
@@ -121275,7 +124608,7 @@ static int flattenSubquery(
** terms are duplicated into the subquery.
*/
static int pushDownWhereTerms(
- sqlite3 *db, /* The database connection (for malloc()) */
+ Parse *pParse, /* Parse context (for malloc() and error reporting) */
Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
Expr *pWhere, /* The WHERE clause of the outer query */
int iCursor /* Cursor number of the subquery */
@@ -121296,16 +124629,22 @@ static int pushDownWhereTerms(
return 0; /* restriction (3) */
}
while( pWhere->op==TK_AND ){
- nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor);
+ nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor);
pWhere = pWhere->pLeft;
}
if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
nChng++;
while( pSubq ){
- pNew = sqlite3ExprDup(db, pWhere, 0);
- pNew = substExpr(db, pNew, iCursor, pSubq->pEList);
- pSubq->pWhere = sqlite3ExprAnd(db, pSubq->pWhere, pNew);
+ SubstContext x;
+ pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
+ x.pParse = pParse;
+ x.iTable = iCursor;
+ x.iNewTable = iCursor;
+ x.isLeftJoin = 0;
+ x.pEList = pSubq->pEList;
+ pNew = substExpr(&x, pNew);
+ pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
pSubq = pSubq->pPrior;
}
}
@@ -121597,7 +124936,7 @@ static int withExpand(
assert( pFrom->pTab==0 );
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ) return WRC_Abort;
- pTab->nRef = 1;
+ pTab->nTabRef = 1;
pTab->zName = sqlite3DbStrDup(db, pCte->zName);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
@@ -121620,25 +124959,33 @@ static int withExpand(
){
pItem->pTab = pTab;
pItem->fg.isRecursive = 1;
- pTab->nRef++;
+ pTab->nTabRef++;
pSel->selFlags |= SF_Recursive;
}
}
}
/* Only one recursive reference is permitted. */
- if( pTab->nRef>2 ){
+ if( pTab->nTabRef>2 ){
sqlite3ErrorMsg(
pParse, "multiple references to recursive table: %s", pCte->zName
);
return SQLITE_ERROR;
}
- assert( pTab->nRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nRef==2 ));
+ assert( pTab->nTabRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
pCte->zCteErr = "circular reference: %s";
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
- sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel);
+ if( bMayRecursive ){
+ Select *pPrior = pSel->pPrior;
+ assert( pPrior->pWith==0 );
+ pPrior->pWith = pSel->pWith;
+ sqlite3WalkSelect(pWalker, pPrior);
+ pPrior->pWith = 0;
+ }else{
+ sqlite3WalkSelect(pWalker, pSel);
+ }
pParse->pWith = pWith;
for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
@@ -121682,10 +125029,12 @@ static int withExpand(
*/
static void selectPopWith(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
- With *pWith = findRightmost(p)->pWith;
- if( pWith!=0 ){
- assert( pParse->pWith==pWith );
- pParse->pWith = pWith->pOuter;
+ if( pParse->pWith && p->pPrior==0 ){
+ With *pWith = findRightmost(p)->pWith;
+ if( pWith!=0 ){
+ assert( pParse->pWith==pWith );
+ pParse->pWith = pWith->pOuter;
+ }
}
}
#else
@@ -121735,8 +125084,8 @@ static int selectExpander(Walker *pWalker, Select *p){
}
pTabList = p->pSrc;
pEList = p->pEList;
- if( pWalker->xSelectCallback2==selectPopWith ){
- sqlite3WithPush(pParse, findRightmost(p)->pWith, 0);
+ if( p->pWith ){
+ sqlite3WithPush(pParse, p->pWith, 0);
}
/* Make sure cursor numbers have been assigned to all entries in
@@ -121766,7 +125115,7 @@ static int selectExpander(Walker *pWalker, Select *p){
if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ) return WRC_Abort;
- pTab->nRef = 1;
+ pTab->nTabRef = 1;
pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
while( pSel->pPrior ){ pSel = pSel->pPrior; }
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
@@ -121779,13 +125128,13 @@ static int selectExpander(Walker *pWalker, Select *p){
assert( pFrom->pTab==0 );
pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
if( pTab==0 ) return WRC_Abort;
- if( pTab->nRef==0xffff ){
+ if( pTab->nTabRef>=0xffff ){
sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
pTab->zName);
pFrom->pTab = 0;
return WRC_Abort;
}
- pTab->nRef++;
+ pTab->nTabRef++;
if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){
return WRC_Abort;
}
@@ -121935,10 +125284,10 @@ static int selectExpander(Walker *pWalker, Select *p){
if( longNames || pTabList->nSrc>1 ){
Expr *pLeft;
pLeft = sqlite3Expr(db, TK_ID, zTabName);
- pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
+ pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
if( zSchemaName ){
pLeft = sqlite3Expr(db, TK_ID, zSchemaName);
- pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0);
+ pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr);
}
if( longNames ){
zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
@@ -122000,6 +125349,25 @@ SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
return WRC_Continue;
}
+/*
+** No-op routine for the parse-tree walker for SELECT statements.
+** subquery in the parser tree.
+*/
+SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ return WRC_Continue;
+}
+
+#if SQLITE_DEBUG
+/*
+** Always assert. This xSelectCallback2 implementation proves that the
+** xSelectCallback2 is never invoked.
+*/
+SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker *NotUsed, Select *NotUsed2){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ assert( 0 );
+}
+#endif
/*
** This routine "expands" a SELECT statement and all of its subqueries.
** For additional information on what it means to "expand" a SELECT
@@ -122015,17 +125383,15 @@ SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
*/
static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
Walker w;
- memset(&w, 0, sizeof(w));
w.xExprCallback = sqlite3ExprWalkNoop;
w.pParse = pParse;
if( pParse->hasCompound ){
w.xSelectCallback = convertCompoundSelectToSubquery;
+ w.xSelectCallback2 = 0;
sqlite3WalkSelect(&w, pSelect);
}
w.xSelectCallback = selectExpander;
- if( (pSelect->selFlags & SF_MultiValue)==0 ){
- w.xSelectCallback2 = selectPopWith;
- }
+ w.xSelectCallback2 = selectPopWith;
sqlite3WalkSelect(&w, pSelect);
}
@@ -122081,7 +125447,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
#ifndef SQLITE_OMIT_SUBQUERY
Walker w;
- memset(&w, 0, sizeof(w));
+ w.xSelectCallback = sqlite3SelectWalkNoop;
w.xSelectCallback2 = selectAddSubqueryTypeInfo;
w.xExprCallback = sqlite3ExprWalkNoop;
w.pParse = pParse;
@@ -122175,8 +125541,8 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){
ExprList *pList = pF->pExpr->x.pList;
assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
- sqlite3VdbeAddOp4(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0, 0,
- (void*)pF->pFunc, P4_FUNCDEF);
+ sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0);
+ sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
}
}
@@ -122227,8 +125593,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem;
sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ);
}
- sqlite3VdbeAddOp4(v, OP_AggStep0, 0, regAgg, pF->iMem,
- (void*)pF->pFunc, P4_FUNCDEF);
+ sqlite3VdbeAddOp3(v, OP_AggStep0, 0, regAgg, pF->iMem);
+ sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nArg);
sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
@@ -122288,6 +125654,187 @@ static void explainSimpleCount(
# define explainSimpleCount(a,b,c)
#endif
+/*
+** Context object for havingToWhereExprCb().
+*/
+struct HavingToWhereCtx {
+ Expr **ppWhere;
+ ExprList *pGroupBy;
+};
+
+/*
+** sqlite3WalkExpr() callback used by havingToWhere().
+**
+** If the node passed to the callback is a TK_AND node, return
+** WRC_Continue to tell sqlite3WalkExpr() to iterate through child nodes.
+**
+** Otherwise, return WRC_Prune. In this case, also check if the
+** sub-expression matches the criteria for being moved to the WHERE
+** clause. If so, add it to the WHERE clause and replace the sub-expression
+** within the HAVING expression with a constant "1".
+*/
+static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op!=TK_AND ){
+ struct HavingToWhereCtx *p = pWalker->u.pHavingCtx;
+ if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, p->pGroupBy) ){
+ sqlite3 *db = pWalker->pParse->db;
+ Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0);
+ if( pNew ){
+ Expr *pWhere = *(p->ppWhere);
+ SWAP(Expr, *pNew, *pExpr);
+ pNew = sqlite3ExprAnd(db, pWhere, pNew);
+ *(p->ppWhere) = pNew;
+ }
+ }
+ return WRC_Prune;
+ }
+ return WRC_Continue;
+}
+
+/*
+** Transfer eligible terms from the HAVING clause of a query, which is
+** processed after grouping, to the WHERE clause, which is processed before
+** grouping. For example, the query:
+**
+** SELECT * FROM WHERE a=? GROUP BY b HAVING b=? AND c=?
+**
+** can be rewritten as:
+**
+** SELECT * FROM WHERE a=? AND b=? GROUP BY b HAVING c=?
+**
+** A term of the HAVING expression is eligible for transfer if it consists
+** entirely of constants and expressions that are also GROUP BY terms that
+** use the "BINARY" collation sequence.
+*/
+static void havingToWhere(
+ Parse *pParse,
+ ExprList *pGroupBy,
+ Expr *pHaving,
+ Expr **ppWhere
+){
+ struct HavingToWhereCtx sCtx;
+ Walker sWalker;
+
+ sCtx.ppWhere = ppWhere;
+ sCtx.pGroupBy = pGroupBy;
+
+ memset(&sWalker, 0, sizeof(sWalker));
+ sWalker.pParse = pParse;
+ sWalker.xExprCallback = havingToWhereExprCb;
+ sWalker.u.pHavingCtx = &sCtx;
+ sqlite3WalkExpr(&sWalker, pHaving);
+}
+
+/*
+** Check to see if the pThis entry of pTabList is a self-join of a prior view.
+** If it is, then return the SrcList_item for the prior view. If it is not,
+** then return 0.
+*/
+static struct SrcList_item *isSelfJoinView(
+ SrcList *pTabList, /* Search for self-joins in this FROM clause */
+ struct SrcList_item *pThis /* Search for prior reference to this subquery */
+){
+ struct SrcList_item *pItem;
+ for(pItem = pTabList->a; pItempSelect==0 ) continue;
+ if( pItem->fg.viaCoroutine ) continue;
+ if( pItem->zName==0 ) continue;
+ if( sqlite3_stricmp(pItem->zDatabase, pThis->zDatabase)!=0 ) continue;
+ if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue;
+ if( sqlite3ExprCompare(0,
+ pThis->pSelect->pWhere, pItem->pSelect->pWhere, -1)
+ ){
+ /* The view was modified by some other optimization such as
+ ** pushDownWhereTerms() */
+ continue;
+ }
+ return pItem;
+ }
+ return 0;
+}
+
+#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
+/*
+** Attempt to transform a query of the form
+**
+** SELECT count(*) FROM (SELECT x FROM t1 UNION ALL SELECT y FROM t2)
+**
+** Into this:
+**
+** SELECT (SELECT count(*) FROM t1)+(SELECT count(*) FROM t2)
+**
+** The transformation only works if all of the following are true:
+**
+** * The subquery is a UNION ALL of two or more terms
+** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries
+** * The outer query is a simple count(*)
+**
+** Return TRUE if the optimization is undertaken.
+*/
+static int countOfViewOptimization(Parse *pParse, Select *p){
+ Select *pSub, *pPrior;
+ Expr *pExpr;
+ Expr *pCount;
+ sqlite3 *db;
+ if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate query */
+ if( p->pEList->nExpr!=1 ) return 0; /* Single result column */
+ pExpr = p->pEList->a[0].pExpr;
+ if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */
+ if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Must be count() */
+ if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */
+ if( p->pSrc->nSrc!=1 ) return 0; /* One table in the FROM clause */
+ pSub = p->pSrc->a[0].pSelect;
+ if( pSub==0 ) return 0; /* The FROM is a subquery */
+ if( pSub->pPrior==0 ) return 0; /* Must be a compound subquery */
+ do{
+ if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
+ if( pSub->pWhere ) return 0; /* No WHERE clause */
+ if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
+ pSub = pSub->pPrior; /* Repeat over compound terms */
+ }while( pSub );
+
+ /* If we reach this point, that means it is OK to perform the transformation */
+
+ db = pParse->db;
+ pCount = pExpr;
+ pExpr = 0;
+ pSub = p->pSrc->a[0].pSelect;
+ p->pSrc->a[0].pSelect = 0;
+ sqlite3SrcListDelete(db, p->pSrc);
+ p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*p->pSrc));
+ while( pSub ){
+ Expr *pTerm;
+ pPrior = pSub->pPrior;
+ pSub->pPrior = 0;
+ pSub->pNext = 0;
+ pSub->selFlags |= SF_Aggregate;
+ pSub->selFlags &= ~SF_Compound;
+ pSub->nSelectRow = 0;
+ sqlite3ExprListDelete(db, pSub->pEList);
+ pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount;
+ pSub->pEList = sqlite3ExprListAppend(pParse, 0, pTerm);
+ pTerm = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
+ sqlite3PExprAddSelect(pParse, pTerm, pSub);
+ if( pExpr==0 ){
+ pExpr = pTerm;
+ }else{
+ pExpr = sqlite3PExpr(pParse, TK_PLUS, pTerm, pExpr);
+ }
+ pSub = pPrior;
+ }
+ p->pEList->a[0].pExpr = pExpr;
+ p->selFlags &= ~SF_Aggregate;
+
+#if SELECTTRACE_ENABLED
+ if( sqlite3SelectTrace & 0x400 ){
+ SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n"));
+ sqlite3TreeViewSelect(0, p, 0);
+ }
+#endif
+ return 1;
+}
+#endif /* SQLITE_COUNTOFVIEW_OPTIMIZATION */
+
/*
** Generate code for the SELECT statement given in the p argument.
**
@@ -122372,6 +125919,14 @@ SQLITE_PRIVATE int sqlite3Select(
}
#endif
+ /* Get a pointer the VDBE under construction, allocating a new VDBE if one
+ ** does not already exist */
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) goto select_end;
+ if( pDest->eDest==SRT_Output ){
+ generateColumnNames(pParse, p);
+ }
+
/* Try to flatten subqueries in the FROM clause up into the main query
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
@@ -122407,11 +125962,6 @@ SQLITE_PRIVATE int sqlite3Select(
}
#endif
- /* Get a pointer the VDBE under construction, allocating a new VDBE if one
- ** does not already exist */
- v = sqlite3GetVdbe(pParse);
- if( v==0 ) goto select_end;
-
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* Handle compound SELECT statements using the separate multiSelect()
** procedure.
@@ -122427,13 +125977,38 @@ SQLITE_PRIVATE int sqlite3Select(
}
#endif
- /* Generate code for all sub-queries in the FROM clause
+ /* For each term in the FROM clause, do two things:
+ ** (1) Authorized unreferenced tables
+ ** (2) Generate code for all sub-queries
*/
-#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; inSrc; i++){
struct SrcList_item *pItem = &pTabList->a[i];
SelectDest dest;
- Select *pSub = pItem->pSelect;
+ Select *pSub;
+
+ /* Issue SQLITE_READ authorizations with a fake column name for any tables that
+ ** are referenced but from which no values are extracted. Examples of where these
+ ** kinds of null SQLITE_READ authorizations would occur:
+ **
+ ** SELECT count(*) FROM t1; -- SQLITE_READ t1.""
+ ** SELECT t1.* FROM t1, t2; -- SQLITE_READ t2.""
+ **
+ ** The fake column name is an empty string. It is possible for a table to
+ ** have a column named by the empty string, in which case there is no way to
+ ** distinguish between an unreferenced table and an actual reference to the
+ ** "" column. The original design was for the fake column name to be a NULL,
+ ** which would be unambiguous. But legacy authorization callbacks might
+ ** assume the column name is non-NULL and segfault. The use of an empty string
+ ** for the fake column name seems safer.
+ */
+ if( pItem->colUsed==0 ){
+ sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase);
+ }
+
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+ /* Generate code for all sub-queries in the FROM clause
+ */
+ pSub = pItem->pSelect;
if( pSub==0 ) continue;
/* Sometimes the code for a subquery will be generated more than
@@ -122444,6 +126019,10 @@ SQLITE_PRIVATE int sqlite3Select(
** to be invoked again. */
if( pItem->addrFillSub ){
if( pItem->fg.viaCoroutine==0 ){
+ /* The subroutine that manifests the view might be a one-time routine,
+ ** or it might need to be rerun on each iteration because it
+ ** encodes a correlated subquery. */
+ testcase( sqlite3VdbeGetOp(v, pItem->addrFillSub)->opcode==OP_Once );
sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
}
continue;
@@ -122462,7 +126041,7 @@ SQLITE_PRIVATE int sqlite3Select(
** inside the subquery. This can help the subquery to run more efficiently.
*/
if( (pItem->fg.jointype & JT_OUTER)==0
- && pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
+ && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor)
){
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
@@ -122518,6 +126097,8 @@ SQLITE_PRIVATE int sqlite3Select(
int topAddr;
int onceAddr = 0;
int retAddr;
+ struct SrcList_item *pPrior;
+
assert( pItem->addrFillSub==0 );
pItem->regReturn = ++pParse->nMem;
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
@@ -122531,9 +126112,17 @@ SQLITE_PRIVATE int sqlite3Select(
}else{
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
}
- sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
- explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
- sqlite3Select(pParse, pSub, &dest);
+ pPrior = isSelfJoinView(pTabList, pItem);
+ if( pPrior ){
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
+ explainSetInteger(pItem->iSelectId, pPrior->iSelectId);
+ assert( pPrior->pSelect!=0 );
+ pSub->nSelectRow = pPrior->pSelect->nSelectRow;
+ }else{
+ sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
+ explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
+ sqlite3Select(pParse, pSub, &dest);
+ }
pItem->pTab->nRowLogEst = pSub->nSelectRow;
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
@@ -122543,8 +126132,8 @@ SQLITE_PRIVATE int sqlite3Select(
}
if( db->mallocFailed ) goto select_end;
pParse->nHeight -= sqlite3SelectExprHeight(p);
- }
#endif
+ }
/* Various elements of the SELECT copied into local variables for
** convenience */
@@ -122561,6 +126150,16 @@ SQLITE_PRIVATE int sqlite3Select(
}
#endif
+#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
+ if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView)
+ && countOfViewOptimization(pParse, p)
+ ){
+ if( db->mallocFailed ) goto select_end;
+ pEList = p->pEList;
+ pTabList = p->pSrc;
+ }
+#endif
+
/* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
** if the select-list is the same as the ORDER BY list, then this query
** can be rewritten as a GROUP BY. In other words, this:
@@ -122624,7 +126223,9 @@ SQLITE_PRIVATE int sqlite3Select(
/* Set the limiter.
*/
iEnd = sqlite3VdbeMakeLabel(v);
- p->nSelectRow = 320; /* 4 billion rows */
+ if( (p->selFlags & SF_FixedLimit)==0 ){
+ p->nSelectRow = 320; /* 4 billion rows */
+ }
computeLimitRegisters(pParse, p, iEnd);
if( p->iLimit==0 && sSort.addrSortIndex>=0 ){
sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen);
@@ -122750,6 +126351,11 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3ExprAnalyzeAggList(&sNC, pEList);
sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy);
if( pHaving ){
+ if( pGroupBy ){
+ assert( pWhere==p->pWhere );
+ havingToWhere(pParse, pGroupBy, pHaving, &p->pWhere);
+ pWhere = p->pWhere;
+ }
sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
}
sAggInfo.nAccumulator = sAggInfo.nColumn;
@@ -123102,7 +126708,7 @@ SQLITE_PRIVATE int sqlite3Select(
** of output.
*/
resetAccumulator(pParse, &sAggInfo);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax, 0,flag,0);
if( pWInfo==0 ){
sqlite3ExprListDelete(db, pDel);
goto select_end;
@@ -123155,12 +126761,6 @@ SQLITE_PRIVATE int sqlite3Select(
select_end:
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
- /* Identify column names if results of the SELECT are to be output.
- */
- if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){
- generateColumnNames(pParse, pTabList, pEList);
- }
-
sqlite3DbFree(db, sAggInfo.aCol);
sqlite3DbFree(db, sAggInfo.aFunc);
#if SELECTTRACE_ENABLED
@@ -123191,8 +126791,6 @@ select_end:
** if they are not used.
*/
/* #include "sqliteInt.h" */
-/* #include */
-/* #include */
#ifndef SQLITE_OMIT_GET_TABLE
@@ -123683,9 +127281,10 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(
if( v==0 ) goto triggerfinish_cleanup;
sqlite3BeginWriteOperation(pParse, 0, iDb);
z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
+ testcase( z==0 );
sqlite3NestedParse(pParse,
"INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), zName,
+ db->aDb[iDb].zDbSName, MASTER_NAME, zName,
pTrig->table, z);
sqlite3DbFree(db, z);
sqlite3ChangeCookie(pParse, iDb);
@@ -123936,7 +127535,7 @@ SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
if( (v = sqlite3GetVdbe(pParse))!=0 ){
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pTrigger->zName
+ db->aDb[iDb].zDbSName, MASTER_NAME, pTrigger->zName
);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0);
@@ -124548,14 +128147,14 @@ SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc,
pCol->affinity, &pValue);
if( pValue ){
- sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM);
+ sqlite3VdbeAppendP4(v, pValue, P4_MEM);
}
-#ifndef SQLITE_OMIT_FLOATING_POINT
- if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
- sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
- }
-#endif
}
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
+ }
+#endif
}
/*
@@ -124584,7 +128183,7 @@ SQLITE_PRIVATE void sqlite3Update(
int iDataCur; /* Cursor for the canonical data btree */
int iIdxCur; /* Cursor for the first index */
sqlite3 *db; /* The database structure */
- int *aRegIdx = 0; /* One register assigned to each index to be updated */
+ int *aRegIdx = 0; /* First register in array assigned to each index */
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
** an expression for the i-th column of the table.
** aXRef[i]==-1 if the i-th column is not changed. */
@@ -124596,10 +128195,11 @@ SQLITE_PRIVATE void sqlite3Update(
AuthContext sContext; /* The authorization context */
NameContext sNC; /* The name-context to resolve expressions in */
int iDb; /* Database containing the table being updated */
- int okOnePass; /* True for one-pass algorithm without the FIFO */
+ int eOnePass; /* ONEPASS_XXX value from where.c */
int hasFK; /* True if foreign key processing is required */
int labelBreak; /* Jump here to break out of UPDATE loop */
int labelContinue; /* Jump here to continue next step of UPDATE loop */
+ int flags; /* Flags for sqlite3WhereBegin() */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True when updating a view (INSTEAD OF trigger) */
@@ -124610,6 +128210,10 @@ SQLITE_PRIVATE void sqlite3Update(
int iEph = 0; /* Ephemeral table holding all primary key values */
int nKey = 0; /* Number of elements in regKey for WITHOUT ROWID */
int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
+ int addrOpen = 0; /* Address of OP_OpenEphemeral */
+ int iPk = 0; /* First of nPk cells holding PRIMARY KEY value */
+ i16 nPk = 0; /* Number of components of the PRIMARY KEY */
+ int bReplace = 0; /* True if REPLACE conflict resolution might happen */
/* Register Allocations */
int regRowCount = 0; /* A count of rows changed */
@@ -124759,14 +128363,21 @@ SQLITE_PRIVATE void sqlite3Update(
*/
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int reg;
- if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){
+ if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){
reg = ++pParse->nMem;
+ pParse->nMem += pIdx->nColumn;
}else{
reg = 0;
for(i=0; inKeyCol; i++){
i16 iIdxCol = pIdx->aiColumn[i];
if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){
reg = ++pParse->nMem;
+ pParse->nMem += pIdx->nColumn;
+ if( (onError==OE_Replace)
+ || (onError==OE_Default && pIdx->onError==OE_Replace)
+ ){
+ bReplace = 1;
+ }
break;
}
}
@@ -124774,6 +128385,11 @@ SQLITE_PRIVATE void sqlite3Update(
if( reg==0 ) aToOpen[j+1] = 0;
aRegIdx[j] = reg;
}
+ if( bReplace ){
+ /* If REPLACE conflict resolution might be invoked, open cursors on all
+ ** indexes in case they are needed to delete records. */
+ memset(aToOpen, 1, nIdx+1);
+ }
/* Begin generating code. */
v = sqlite3GetVdbe(pParse);
@@ -124826,110 +128442,130 @@ SQLITE_PRIVATE void sqlite3Update(
}
#endif
- /* Begin the database scan
- */
+ /* Initialize the count of updated rows */
+ if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){
+ regRowCount = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
+ }
+
if( HasRowid(pTab) ){
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
- pWInfo = sqlite3WhereBegin(
- pParse, pTabList, pWhere, 0, 0,
- WHERE_ONEPASS_DESIRED | WHERE_SEEK_TABLE, iIdxCur
- );
- if( pWInfo==0 ) goto update_cleanup;
- okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
-
- /* Remember the rowid of every item to be updated.
- */
- sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
- if( !okOnePass ){
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
- }
-
- /* End the database scan loop.
- */
- sqlite3WhereEnd(pWInfo);
}else{
- int iPk; /* First of nPk memory cells holding PRIMARY KEY value */
- i16 nPk; /* Number of components of the PRIMARY KEY */
- int addrOpen; /* Address of the OpenEphemeral instruction */
-
assert( pPk!=0 );
nPk = pPk->nKeyCol;
iPk = pParse->nMem+1;
pParse->nMem += nPk;
regKey = ++pParse->nMem;
iEph = pParse->nTab++;
+
sqlite3VdbeAddOp2(v, OP_Null, 0, iPk);
addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,
- WHERE_ONEPASS_DESIRED, iIdxCur);
- if( pWInfo==0 ) goto update_cleanup;
- okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
+ }
+
+ /* Begin the database scan.
+ **
+ ** Do not consider a single-pass strategy for a multi-row update if
+ ** there are any triggers or foreign keys to process, or rows may
+ ** be deleted as a result of REPLACE conflict handling. Any of these
+ ** things might disturb a cursor being used to scan through the table
+ ** or index, causing a single-pass approach to malfunction. */
+ flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE;
+ if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
+ flags |= WHERE_ONEPASS_MULTIROW;
+ }
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags, iIdxCur);
+ if( pWInfo==0 ) goto update_cleanup;
+
+ /* A one-pass strategy that might update more than one row may not
+ ** be used if any column of the index used for the scan is being
+ ** updated. Otherwise, if there is an index on "b", statements like
+ ** the following could create an infinite loop:
+ **
+ ** UPDATE t1 SET b=b+1 WHERE b>?
+ **
+ ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI
+ ** strategy that uses an index for which one or more columns are being
+ ** updated. */
+ eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
+ if( eOnePass==ONEPASS_MULTI ){
+ int iCur = aiCurOnePass[1];
+ if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){
+ eOnePass = ONEPASS_OFF;
+ }
+ assert( iCur!=iDataCur || !HasRowid(pTab) );
+ }
+
+ if( HasRowid(pTab) ){
+ /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF
+ ** mode, write the rowid into the FIFO. In either of the one-pass modes,
+ ** leave it in register regOldRowid. */
+ sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
+ if( eOnePass==ONEPASS_OFF ){
+ sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
+ }
+ }else{
+ /* Read the PK of the current row into an array of registers. In
+ ** ONEPASS_OFF mode, serialize the array into a record and store it in
+ ** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change
+ ** the OP_OpenEphemeral instruction to a Noop (the ephemeral table
+ ** is not required) and leave the PK fields in the array of registers. */
for(i=0; iaiColumn[i]>=0 );
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i],
- iPk+i);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i);
}
- if( okOnePass ){
+ if( eOnePass ){
sqlite3VdbeChangeToNoop(v, addrOpen);
nKey = nPk;
regKey = iPk;
}else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey,
sqlite3IndexAffinityStr(db, pPk), nPk);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk);
}
- sqlite3WhereEnd(pWInfo);
}
- /* Initialize the count of updated rows
- */
- if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){
- regRowCount = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
+ if( eOnePass!=ONEPASS_MULTI ){
+ sqlite3WhereEnd(pWInfo);
}
labelBreak = sqlite3VdbeMakeLabel(v);
if( !isView ){
- /*
- ** Open every index that needs updating. Note that if any
- ** index could potentially invoke a REPLACE conflict resolution
- ** action, then we need to open all indices because we might need
- ** to be deleting some records.
- */
- if( onError==OE_Replace ){
- memset(aToOpen, 1, nIdx+1);
- }else{
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->onError==OE_Replace ){
- memset(aToOpen, 1, nIdx+1);
- break;
- }
- }
- }
- if( okOnePass ){
+ int addrOnce = 0;
+
+ /* Open every index that needs updating. */
+ if( eOnePass!=ONEPASS_OFF ){
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0;
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0;
}
+
+ if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){
+ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
+ }
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen,
0, 0);
+ if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
}
/* Top of the update loop */
- if( okOnePass ){
- if( aToOpen[iDataCur-iBaseCur] && !isView ){
+ if( eOnePass!=ONEPASS_OFF ){
+ if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){
assert( pPk );
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
VdbeCoverageNeverTaken(v);
}
- labelContinue = labelBreak;
+ if( eOnePass==ONEPASS_SINGLE ){
+ labelContinue = labelBreak;
+ }else{
+ labelContinue = sqlite3VdbeMakeLabel(v);
+ }
sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
VdbeCoverageIf(v, pPk==0);
VdbeCoverageIf(v, pPk!=0);
}else if( pPk ){
labelContinue = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
- addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey);
+ addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey);
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
VdbeCoverage(v);
}else{
@@ -125047,7 +128683,6 @@ SQLITE_PRIVATE void sqlite3Update(
if( !isView ){
int addr1 = 0; /* Address of jump instruction */
- int bReplace = 0; /* True if REPLACE conflict resolution might happen */
/* Do constraint checks. */
assert( regOldRowid>0 );
@@ -125083,14 +128718,18 @@ SQLITE_PRIVATE void sqlite3Update(
assert( regNew==regNewRowid+1 );
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
sqlite3VdbeAddOp3(v, OP_Delete, iDataCur,
- OPFLAG_ISUPDATE | ((hasFK || chngKey || pPk!=0) ? 0 : OPFLAG_ISNOOP),
+ OPFLAG_ISUPDATE | ((hasFK>1 || chngKey) ? 0 : OPFLAG_ISNOOP),
regNewRowid
);
+ if( eOnePass==ONEPASS_MULTI ){
+ assert( hasFK==0 && chngKey==0 );
+ sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION);
+ }
if( !pParse->nested ){
- sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE);
+ sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
}
#else
- if( hasFK || chngKey || pPk!=0 ){
+ if( hasFK>1 || chngKey ){
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
}
#endif
@@ -125103,8 +128742,11 @@ SQLITE_PRIVATE void sqlite3Update(
}
/* Insert the new index entries and the new record. */
- sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
- regNewRowid, aRegIdx, 1, 0, 0);
+ sqlite3CompleteInsertion(
+ pParse, pTab, iDataCur, iIdxCur, regNewRowid, aRegIdx,
+ OPFLAG_ISUPDATE | (eOnePass==ONEPASS_MULTI ? OPFLAG_SAVEPOSITION : 0),
+ 0, 0
+ );
/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
** handle rows (possibly in other tables) that refer via a foreign key
@@ -125126,8 +128768,11 @@ SQLITE_PRIVATE void sqlite3Update(
/* Repeat the above with the next record to be updated, until
** all record selected by the WHERE clause have been updated.
*/
- if( okOnePass ){
+ if( eOnePass==ONEPASS_SINGLE ){
/* Nothing to do at end-of-loop for a single-pass */
+ }else if( eOnePass==ONEPASS_MULTI ){
+ sqlite3VdbeResolveLabel(v, labelContinue);
+ sqlite3WhereEnd(pWInfo);
}else if( pPk ){
sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v);
@@ -125136,15 +128781,6 @@ SQLITE_PRIVATE void sqlite3Update(
}
sqlite3VdbeResolveLabel(v, labelBreak);
- /* Close all tables */
- for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- assert( aRegIdx );
- if( aToOpen[i+1] ){
- sqlite3VdbeAddOp2(v, OP_Close, iIdxCur+i, 0);
- }
- }
- if( iDataCur=2 || iDb==0) ){
+ int iDb = 0;
+ if( v==0 ) return;
+ if( pNm ){
+#ifndef SQLITE_BUG_COMPATIBLE_20160819
+ /* Default behavior: Report an error if the argument to VACUUM is
+ ** not recognized */
+ iDb = sqlite3TwoPartName(pParse, pNm, pNm, &pNm);
+ if( iDb<0 ) return;
+#else
+ /* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments
+ ** to VACUUM are silently ignored. This is a back-out of a bug fix that
+ ** occurred on 2016-08-19 (https://www.sqlite.org/src/info/083f9e6270).
+ ** The buggy behavior is required for binary compatibility with some
+ ** legacy applications. */
+ iDb = sqlite3FindDb(pParse->db, pNm);
+ if( iDb<0 ) iDb = 0;
+#endif
+ }
+ if( iDb!=1 ){
sqlite3VdbeAddOp1(v, OP_Vacuum, iDb);
sqlite3VdbeUsesBtree(v, iDb);
}
@@ -125496,7 +129149,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
int nKey;
char *zKey;
- sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
+ sqlite3CodecGetKey(db, iDb, (void**)&zKey, &nKey);
if( nKey ) db->nextPagesize = 0;
}
#endif
@@ -125694,6 +129347,41 @@ struct VtabCtx {
int bDeclared; /* True after sqlite3_declare_vtab() is called */
};
+/*
+** Construct and install a Module object for a virtual table. When this
+** routine is called, it is guaranteed that all appropriate locks are held
+** and the module is not already part of the connection.
+*/
+SQLITE_PRIVATE Module *sqlite3VtabCreateModule(
+ sqlite3 *db, /* Database in which module is registered */
+ const char *zName, /* Name assigned to this module */
+ const sqlite3_module *pModule, /* The definition of the module */
+ void *pAux, /* Context pointer for xCreate/xConnect */
+ void (*xDestroy)(void *) /* Module destructor function */
+){
+ Module *pMod;
+ int nName = sqlite3Strlen30(zName);
+ pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1);
+ if( pMod ){
+ Module *pDel;
+ char *zCopy = (char *)(&pMod[1]);
+ memcpy(zCopy, zName, nName+1);
+ pMod->zName = zCopy;
+ pMod->pModule = pModule;
+ pMod->pAux = pAux;
+ pMod->xDestroy = xDestroy;
+ pMod->pEpoTab = 0;
+ pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod);
+ assert( pDel==0 || pDel==pMod );
+ if( pDel ){
+ sqlite3OomFault(db);
+ sqlite3DbFree(db, pDel);
+ pMod = 0;
+ }
+ }
+ return pMod;
+}
+
/*
** The actual function that does the work of creating a new module.
** This function implements the sqlite3_create_module() and
@@ -125707,35 +129395,15 @@ static int createModule(
void (*xDestroy)(void *) /* Module destructor function */
){
int rc = SQLITE_OK;
- int nName;
sqlite3_mutex_enter(db->mutex);
- nName = sqlite3Strlen30(zName);
if( sqlite3HashFind(&db->aModule, zName) ){
rc = SQLITE_MISUSE_BKPT;
}else{
- Module *pMod;
- pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1);
- if( pMod ){
- Module *pDel;
- char *zCopy = (char *)(&pMod[1]);
- memcpy(zCopy, zName, nName+1);
- pMod->zName = zCopy;
- pMod->pModule = pModule;
- pMod->pAux = pAux;
- pMod->xDestroy = xDestroy;
- pMod->pEpoTab = 0;
- pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod);
- assert( pDel==0 || pDel==pMod );
- if( pDel ){
- sqlite3OomFault(db);
- sqlite3DbFree(db, pDel);
- }
- }
+ (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy);
}
rc = sqlite3ApiExit(db, rc);
if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux);
-
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -125990,8 +129658,7 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse(
iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
assert( iDb>=0 );
- pTable->tabFlags |= TF_Virtual;
- pTable->nModuleArg = 0;
+ assert( pTable->nModuleArg==0 );
addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
addModuleArgument(db, pTable, 0);
addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName));
@@ -126074,7 +129741,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
"UPDATE %Q.%s "
"SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
"WHERE rowid=#%d",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
+ db->aDb[iDb].zDbSName, MASTER_NAME,
pTab->zName,
pTab->zName,
zStmt,
@@ -126279,7 +129946,7 @@ SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
int rc;
assert( pTab );
- if( (pTab->tabFlags & TF_Virtual)==0 || sqlite3GetVTable(db, pTab) ){
+ if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){
return SQLITE_OK;
}
@@ -126349,7 +130016,7 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab,
const char *zMod;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
- assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable );
+ assert( pTab && IsVirtual(pTab) && !pTab->pVTable );
/* Locate the required virtual table module */
zMod = pTab->azModuleArg[0];
@@ -126403,7 +130070,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
return SQLITE_MISUSE_BKPT;
}
pTab = pCtx->pTab;
- assert( (pTab->tabFlags & TF_Virtual)!=0 );
+ assert( IsVirtual(pTab) );
pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
if( pParse==0 ){
@@ -126417,7 +130084,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
&& pParse->pNewTable
&& !db->mallocFailed
&& !pParse->pNewTable->pSelect
- && (pParse->pNewTable->tabFlags & TF_Virtual)==0
+ && !IsVirtual(pParse->pNewTable)
){
if( !pTab->aCol ){
Table *pNew = pParse->pNewTable;
@@ -126705,8 +130372,8 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(
if( NEVER(pExpr==0) ) return pDef;
if( pExpr->op!=TK_COLUMN ) return pDef;
pTab = pExpr->pTab;
- if( NEVER(pTab==0) ) return pDef;
- if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef;
+ if( pTab==0 ) return pDef;
+ if( !IsVirtual(pTab) ) return pDef;
pVtab = sqlite3GetVTable(db, pTab)->pVtab;
assert( pVtab!=0 );
assert( pVtab->pModule!=0 );
@@ -126799,10 +130466,9 @@ SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){
return 0;
}
pMod->pEpoTab = pTab;
- pTab->nRef = 1;
+ pTab->nTabRef = 1;
pTab->pSchema = db->aDb[0].pSchema;
- pTab->tabFlags |= TF_Virtual;
- pTab->nModuleArg = 0;
+ assert( pTab->nModuleArg==0 );
pTab->iPKey = -1;
addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName));
addModuleArgument(db, pTab, 0);
@@ -126873,7 +130539,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
if( !p ){
rc = SQLITE_MISUSE_BKPT;
}else{
- assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 );
+ assert( p->pTab==0 || IsVirtual(p->pTab) );
p->pVTable->bConstraint = (u8)va_arg(ap, int);
}
break;
@@ -127041,6 +130707,7 @@ struct WhereLoop {
u16 nEq; /* Number of equality constraints */
u16 nBtm; /* Size of BTM vector */
u16 nTop; /* Size of TOP vector */
+ u16 nIdxCol; /* Index column used for ORDER BY */
Index *pIndex; /* Index used, or NULL */
} btree;
struct { /* Information for virtual tables */
@@ -127200,6 +130867,7 @@ struct WhereTerm {
#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */
#define TERM_LIKE 0x400 /* The original LIKE operator */
#define TERM_IS 0x800 /* Term.pExpr is an IS operator */
+#define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */
/*
** An instance of the WhereScan object is used as an iterator for locating
@@ -127289,6 +130957,7 @@ struct WhereAndInfo {
** no gaps.
*/
struct WhereMaskSet {
+ int bVarSelect; /* Used by sqlite3WhereExprUsage() */
int n; /* Number of assigned cursor values */
int ix[BMS]; /* Cursor assigned to each bit */
};
@@ -127312,8 +130981,13 @@ struct WhereLoopBuilder {
UnpackedRecord *pRec; /* Probe for stat4 (if required) */
int nRecValid; /* Number of valid fields currently in pRec */
#endif
+ unsigned int bldFlags; /* SQLITE_BLDF_* flags */
};
+/* Allowed values for WhereLoopBuider.bldFlags */
+#define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */
+#define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */
+
/*
** The WHERE clause processing routine has two halves. The
** first part does the start of the WHERE loop and the second
@@ -127328,7 +131002,8 @@ struct WhereInfo {
Parse *pParse; /* Parsing and code generating context */
SrcList *pTabList; /* List of tables in the join */
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
- ExprList *pDistinctSet; /* DISTINCT over all these values */
+ ExprList *pResultSet; /* Result set of the query */
+ Expr *pWhere; /* The complete WHERE clause */
LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
int iContinue; /* Jump here to continue with next record */
@@ -128416,10 +132091,10 @@ static void codeCursorHint(
**
** Normally, this is just:
**
-** OP_Seek $iCur $iRowid
+** OP_DeferredSeek $iCur $iRowid
**
** However, if the scan currently being coded is a branch of an OR-loop and
-** the statement currently being coded is a SELECT, then P3 of the OP_Seek
+** the statement currently being coded is a SELECT, then P3 of OP_DeferredSeek
** is set to iIdxCur and P4 is set to point to an array of integers
** containing one entry for each column of the table cursor iCur is open
** on. For each table column, if the column is the i'th column of the
@@ -128438,7 +132113,7 @@ static void codeDeferredSeek(
assert( iIdxCur>0 );
assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
- sqlite3VdbeAddOp3(v, OP_Seek, iIdxCur, 0, iCur);
+ sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur);
if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
&& DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask)
){
@@ -128489,6 +132164,69 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
}
}
+/* An instance of the IdxExprTrans object carries information about a
+** mapping from an expression on table columns into a column in an index
+** down through the Walker.
+*/
+typedef struct IdxExprTrans {
+ Expr *pIdxExpr; /* The index expression */
+ int iTabCur; /* The cursor of the corresponding table */
+ int iIdxCur; /* The cursor for the index */
+ int iIdxCol; /* The column for the index */
+} IdxExprTrans;
+
+/* The walker node callback used to transform matching expressions into
+** a reference to an index column for an index on an expression.
+**
+** If pExpr matches, then transform it into a reference to the index column
+** that contains the value of pExpr.
+*/
+static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
+ IdxExprTrans *pX = p->u.pIdxTrans;
+ if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
+ pExpr->op = TK_COLUMN;
+ pExpr->iTable = pX->iIdxCur;
+ pExpr->iColumn = pX->iIdxCol;
+ pExpr->pTab = 0;
+ return WRC_Prune;
+ }else{
+ return WRC_Continue;
+ }
+}
+
+/*
+** For an indexes on expression X, locate every instance of expression X in pExpr
+** and change that subexpression into a reference to the appropriate column of
+** the index.
+*/
+static void whereIndexExprTrans(
+ Index *pIdx, /* The Index */
+ int iTabCur, /* Cursor of the table that is being indexed */
+ int iIdxCur, /* Cursor of the index itself */
+ WhereInfo *pWInfo /* Transform expressions in this WHERE clause */
+){
+ int iIdxCol; /* Column number of the index */
+ ExprList *aColExpr; /* Expressions that are indexed */
+ Walker w;
+ IdxExprTrans x;
+ aColExpr = pIdx->aColExpr;
+ if( aColExpr==0 ) return; /* Not an index on expressions */
+ memset(&w, 0, sizeof(w));
+ w.xExprCallback = whereIndexExprTransNode;
+ w.u.pIdxTrans = &x;
+ x.iTabCur = iTabCur;
+ x.iIdxCur = iIdxCur;
+ for(iIdxCol=0; iIdxColnExpr; iIdxCol++){
+ if( pIdx->aiColumn[iIdxCol]!=XN_EXPR ) continue;
+ assert( aColExpr->a[iIdxCol].pExpr!=0 );
+ x.iIdxCol = iIdxCol;
+ x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
+ sqlite3WalkExpr(&w, pWInfo->pWhere);
+ sqlite3WalkExprList(&w, pWInfo->pOrderBy);
+ sqlite3WalkExprList(&w, pWInfo->pResultSet);
+ }
+}
+
/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
@@ -128512,9 +132250,12 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
Vdbe *v; /* The prepared stmt under constructions */
struct SrcList_item *pTabItem; /* FROM clause term being coded */
int addrBrk; /* Jump here to break out of the loop */
+ int addrHalt; /* addrBrk for the outermost loop */
int addrCont; /* Jump here to continue with next cycle */
int iRowidReg = 0; /* Rowid is stored in this register, if not zero */
int iReleaseReg = 0; /* Temp register to free before returning */
+ Index *pIdx = 0; /* Index used by loop (if any) */
+ int iLoop; /* Iteration of constraint generator loop */
pParse = pWInfo->pParse;
v = pParse->pVdbe;
@@ -128553,6 +132294,11 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
VdbeComment((v, "init LEFT JOIN no-match flag"));
}
+ /* Compute a safe address to jump to if we discover that the table for
+ ** this loop is empty and can never contribute content. */
+ for(j=iLevel; j>0 && pWInfo->a[j].iLeftJoin==0; j--){}
+ addrHalt = pWInfo->a[j].addrBrk;
+
/* Special case of a FROM clause subquery implemented as a co-routine */
if( pTabItem->fg.viaCoroutine ){
int regYield = pTabItem->regReturn;
@@ -128592,7 +132338,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1);
sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg,
pLoop->u.vtab.idxStr,
- pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC);
+ pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC);
VdbeCoverage(v);
pLoop->u.vtab.needFree = 0;
pLevel->p1 = iCur;
@@ -128625,7 +132371,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
/* Generate code that will continue to the next row if
** the IN constraint is not satisfied */
- pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0, 0);
+ pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0);
assert( pCompare!=0 || db->mallocFailed );
if( pCompare ){
pCompare->pLeft = pTerm->pExpr->pLeft;
@@ -128737,7 +132483,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
sqlite3ExprCacheAffinityChange(pParse, r1, 1);
sqlite3ReleaseTempReg(pParse, rTemp);
}else{
- sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk);
+ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
}
@@ -128835,7 +132581,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
int endEq; /* True if range end uses ==, >= or <= */
int start_constraints; /* Start of range is constrained */
int nConstraint; /* Number of constraint terms */
- Index *pIdx; /* The index we will be using */
int iIdxCur; /* The VDBE cursor for the index */
int nExtraReg = 0; /* Number of extra registers needed */
int op; /* Instruction opcode */
@@ -129041,7 +132786,10 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
}else if( HasRowid(pIdx->pTable) ){
- if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE)!=0 ){
+ if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE) || (
+ (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE)
+ && (pWInfo->eOnePass==ONEPASS_SINGLE)
+ )){
iRowidReg = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
@@ -129061,6 +132809,13 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
iRowidReg, pPk->nKeyCol); VdbeCoverage(v);
}
+ /* If pIdx is an index on one or more expressions, then look through
+ ** all the expressions in pWInfo and try to transform matching expressions
+ ** into reference to index columns.
+ */
+ whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
+
+
/* Record the instruction used to terminate the loop. */
if( pLoop->wsFlags & WHERE_ONEROW ){
pLevel->op = OP_Noop;
@@ -129076,6 +132831,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
}else{
assert( pLevel->p5==0 );
}
+ if( omitTable ) pIdx = 0;
}else
#ifndef SQLITE_OMIT_OR_OPTIMIZATION
@@ -129224,7 +132980,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
}
if( pAndExpr ){
- pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr, 0);
+ pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr);
}
}
@@ -129297,7 +133053,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
}
if( iSet>=0 ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid);
- sqlite3VdbeAddOp3(v, OP_IdxInsert, regRowset, regRowid, 0);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, regRowset, regRowid,
+ r, nPk);
if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
}
@@ -129379,7 +133136,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
codeCursorHint(pTabItem, pWInfo, pLevel, 0);
pLevel->op = aStep[bRev];
pLevel->p1 = iCur;
- pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
+ pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrHalt);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
@@ -129392,43 +133149,75 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
/* Insert code to test every subexpression that can be completely
** computed using the current set of tables.
+ **
+ ** This loop may run between one and three times, depending on the
+ ** constraints to be generated. The value of stack variable iLoop
+ ** determines the constraints coded by each iteration, as follows:
+ **
+ ** iLoop==1: Code only expressions that are entirely covered by pIdx.
+ ** iLoop==2: Code remaining expressions that do not contain correlated
+ ** sub-queries.
+ ** iLoop==3: Code all remaining expressions.
+ **
+ ** An effort is made to skip unnecessary iterations of the loop.
*/
- for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
- Expr *pE;
- int skipLikeAddr = 0;
- testcase( pTerm->wtFlags & TERM_VIRTUAL );
- testcase( pTerm->wtFlags & TERM_CODED );
- if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
- if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
- testcase( pWInfo->untestedTerms==0
- && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 );
- pWInfo->untestedTerms = 1;
- continue;
- }
- pE = pTerm->pExpr;
- assert( pE!=0 );
- if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
- continue;
- }
- if( pTerm->wtFlags & TERM_LIKECOND ){
- /* If the TERM_LIKECOND flag is set, that means that the range search
- ** is sufficient to guarantee that the LIKE operator is true, so we
- ** can skip the call to the like(A,B) function. But this only works
- ** for strings. So do not skip the call to the function on the pass
- ** that compares BLOBs. */
+ iLoop = (pIdx ? 1 : 2);
+ do{
+ int iNext = 0; /* Next value for iLoop */
+ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
+ Expr *pE;
+ int skipLikeAddr = 0;
+ testcase( pTerm->wtFlags & TERM_VIRTUAL );
+ testcase( pTerm->wtFlags & TERM_CODED );
+ if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+ if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
+ testcase( pWInfo->untestedTerms==0
+ && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 );
+ pWInfo->untestedTerms = 1;
+ continue;
+ }
+ pE = pTerm->pExpr;
+ assert( pE!=0 );
+ if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
+ continue;
+ }
+
+ if( iLoop==1 && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){
+ iNext = 2;
+ continue;
+ }
+ if( iLoop<3 && (pTerm->wtFlags & TERM_VARSELECT) ){
+ if( iNext==0 ) iNext = 3;
+ continue;
+ }
+
+ if( pTerm->wtFlags & TERM_LIKECOND ){
+ /* If the TERM_LIKECOND flag is set, that means that the range search
+ ** is sufficient to guarantee that the LIKE operator is true, so we
+ ** can skip the call to the like(A,B) function. But this only works
+ ** for strings. So do not skip the call to the function on the pass
+ ** that compares BLOBs. */
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
- continue;
+ continue;
#else
- u32 x = pLevel->iLikeRepCntr;
- assert( x>0 );
- skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)? OP_IfNot : OP_If, (int)(x>>1));
- VdbeCoverage(v);
+ u32 x = pLevel->iLikeRepCntr;
+ assert( x>0 );
+ skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If, (int)(x>>1));
+ VdbeCoverage(v);
#endif
+ }
+#ifdef WHERETRACE_ENABLED /* 0xffff */
+ if( sqlite3WhereTrace ){
+ VdbeNoopComment((v, "WhereTerm[%d] (%p) priority=%d",
+ pWC->nTerm-j, pTerm, iLoop));
+ }
+#endif
+ sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
+ if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
+ pTerm->wtFlags |= TERM_CODED;
}
- sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
- if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
- pTerm->wtFlags |= TERM_CODED;
- }
+ iLoop = iNext;
+ }while( iLoop>0 );
/* Insert code to test for implied constraints based on transitivity
** of the "==" operator.
@@ -129704,19 +133493,10 @@ static int isLikeOrGlob(
#endif
pList = pExpr->x.pList;
pLeft = pList->a[1].pExpr;
- if( pLeft->op!=TK_COLUMN
- || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
- || IsVirtual(pLeft->pTab) /* Value might be numeric */
- ){
- /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
- ** be the name of an indexed column with TEXT affinity. */
- return 0;
- }
- assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr);
op = pRight->op;
- if( op==TK_VARIABLE ){
+ if( op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){
Vdbe *pReprepare = pParse->pReprepare;
int iCol = pRight->iColumn;
pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB);
@@ -129729,6 +133509,23 @@ static int isLikeOrGlob(
z = pRight->u.zToken;
}
if( z ){
+
+ /* If the RHS begins with a digit or a minus sign, then the LHS must
+ ** be an ordinary column (not a virtual table column) with TEXT affinity.
+ ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false
+ ** even though "lhs LIKE rhs" is true. But if the RHS does not start
+ ** with a digit or '-', then "lhs LIKE rhs" will always be false if
+ ** the LHS is numeric and so the optimization still works.
+ */
+ if( sqlite3Isdigit(z[0]) || z[0]=='-' ){
+ if( pLeft->op!=TK_COLUMN
+ || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
+ || IsVirtual(pLeft->pTab) /* Value might be numeric */
+ ){
+ sqlite3ValueFree(pVal);
+ return 0;
+ }
+ }
cnt = 0;
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
cnt++;
@@ -129889,8 +133686,8 @@ static void whereCombineDisjuncts(
&& (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
- if( sqlite3ExprCompare(pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
- if( sqlite3ExprCompare(pOne->pExpr->pRight, pTwo->pExpr->pRight, -1) )return;
+ if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
+ if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return;
/* If we reach this point, it means the two subterms can be combined */
if( (eOp & (eOp-1))!=0 ){
if( eOp & (WO_LT|WO_LE) ){
@@ -130225,7 +134022,7 @@ static void exprAnalyzeOrTerm(
}
assert( pLeft!=0 );
pDup = sqlite3ExprDup(db, pLeft, 0);
- pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0, 0);
+ pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
if( pNew ){
int idxNew;
transferJoinMarkings(pNew, pExpr);
@@ -130313,8 +134110,8 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){
** Expression pExpr is one operand of a comparison operator that might
** be useful for indexing. This routine checks to see if pExpr appears
** in any index. Return TRUE (1) if pExpr is an indexed term and return
-** FALSE (0) if not. If TRUE is returned, also set *piCur to the cursor
-** number of the table that is indexed and *piColumn to the column number
+** FALSE (0) if not. If TRUE is returned, also set aiCurCol[0] to the cursor
+** number of the table that is indexed and aiCurCol[1] to the column number
** of the column that is indexed, or XN_EXPR (-2) if an expression is being
** indexed.
**
@@ -130322,18 +134119,37 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){
** true even if that particular column is not indexed, because the column
** might be added to an automatic index later.
*/
-static int exprMightBeIndexed(
+static SQLITE_NOINLINE int exprMightBeIndexed2(
SrcList *pFrom, /* The FROM clause */
- int op, /* The specific comparison operator */
Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */
- Expr *pExpr, /* An operand of a comparison operator */
- int *piCur, /* Write the referenced table cursor number here */
- int *piColumn /* Write the referenced table column number here */
+ int *aiCurCol, /* Write the referenced table cursor and column here */
+ Expr *pExpr /* An operand of a comparison operator */
){
Index *pIdx;
int i;
int iCur;
-
+ for(i=0; mPrereq>1; i++, mPrereq>>=1){}
+ iCur = pFrom->a[i].iCursor;
+ for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( pIdx->aColExpr==0 ) continue;
+ for(i=0; inKeyCol; i++){
+ if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
+ if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){
+ aiCurCol[0] = iCur;
+ aiCurCol[1] = XN_EXPR;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+static int exprMightBeIndexed(
+ SrcList *pFrom, /* The FROM clause */
+ Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */
+ int *aiCurCol, /* Write the referenced table cursor & column here */
+ Expr *pExpr, /* An operand of a comparison operator */
+ int op /* The specific comparison operator */
+){
/* If this expression is a vector to the left or right of a
** inequality constraint (>, <, >= or <=), perform the processing
** on the first element of the vector. */
@@ -130345,26 +134161,13 @@ static int exprMightBeIndexed(
}
if( pExpr->op==TK_COLUMN ){
- *piCur = pExpr->iTable;
- *piColumn = pExpr->iColumn;
+ aiCurCol[0] = pExpr->iTable;
+ aiCurCol[1] = pExpr->iColumn;
return 1;
}
if( mPrereq==0 ) return 0; /* No table references */
if( (mPrereq&(mPrereq-1))!=0 ) return 0; /* Refs more than one table */
- for(i=0; mPrereq>1; i++, mPrereq>>=1){}
- iCur = pFrom->a[i].iCursor;
- for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->aColExpr==0 ) continue;
- for(i=0; inKeyCol; i++){
- if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
- if( sqlite3ExprCompare(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){
- *piCur = iCur;
- *piColumn = XN_EXPR;
- return 1;
- }
- }
- }
- return 0;
+ return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
}
/*
@@ -130404,6 +134207,7 @@ static void exprAnalyze(
Parse *pParse = pWInfo->pParse; /* Parsing context */
sqlite3 *db = pParse->db; /* Database connection */
unsigned char eOp2; /* op2 value for LIKE/REGEXP/GLOB */
+ int nLeft; /* Number of elements on left side vector */
if( db->mallocFailed ){
return;
@@ -130427,19 +134231,25 @@ static void exprAnalyze(
}else{
pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight);
}
+ pMaskSet->bVarSelect = 0;
prereqAll = sqlite3WhereExprUsage(pMaskSet, pExpr);
+ if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT;
if( ExprHasProperty(pExpr, EP_FromJoin) ){
Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable);
prereqAll |= x;
extraRight = x-1; /* ON clause terms may not be used with an index
** on left table of a LEFT JOIN. Ticket #3015 */
+ if( (prereqAll>>1)>=x ){
+ sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
+ return;
+ }
}
pTerm->prereqAll = prereqAll;
pTerm->leftCursor = -1;
pTerm->iParent = -1;
pTerm->eOperator = 0;
if( allowedOp(op) ){
- int iCur, iColumn;
+ int aiCurCol[2];
Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
@@ -130450,14 +134260,14 @@ static void exprAnalyze(
pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr;
}
- if( exprMightBeIndexed(pSrc, op, prereqLeft, pLeft, &iCur, &iColumn) ){
- pTerm->leftCursor = iCur;
- pTerm->u.leftColumn = iColumn;
+ if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){
+ pTerm->leftCursor = aiCurCol[0];
+ pTerm->u.leftColumn = aiCurCol[1];
pTerm->eOperator = operatorMask(op) & opMask;
}
if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
if( pRight
- && exprMightBeIndexed(pSrc, op, pTerm->prereqRight, pRight, &iCur,&iColumn)
+ && exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op)
){
WhereTerm *pNew;
Expr *pDup;
@@ -130487,8 +134297,8 @@ static void exprAnalyze(
pNew = pTerm;
}
exprCommute(pParse, pDup);
- pNew->leftCursor = iCur;
- pNew->u.leftColumn = iColumn;
+ pNew->leftCursor = aiCurCol[0];
+ pNew->u.leftColumn = aiCurCol[1];
testcase( (prereqLeft | extraRight) != prereqLeft );
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
@@ -130523,7 +134333,7 @@ static void exprAnalyze(
int idxNew;
pNewExpr = sqlite3PExpr(pParse, ops[i],
sqlite3ExprDup(db, pExpr->pLeft, 0),
- sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0);
+ sqlite3ExprDup(db, pList->a[i].pExpr, 0));
transferJoinMarkings(pNewExpr, pExpr);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
@@ -130608,7 +134418,7 @@ static void exprAnalyze(
pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName),
- pStr1, 0);
+ pStr1);
transferJoinMarkings(pNewExpr1, pExpr);
idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags);
testcase( idxNew1==0 );
@@ -130616,7 +134426,7 @@ static void exprAnalyze(
pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName),
- pStr2, 0);
+ pStr2);
transferJoinMarkings(pNewExpr2, pExpr);
idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags);
testcase( idxNew2==0 );
@@ -130649,7 +134459,10 @@ static void exprAnalyze(
if( (prereqExpr & prereqColumn)==0 ){
Expr *pNewExpr;
pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
- 0, sqlite3ExprDup(db, pRight, 0), 0);
+ 0, sqlite3ExprDup(db, pRight, 0));
+ if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
+ ExprSetProperty(pNewExpr, EP_FromJoin);
+ }
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
pNewTerm = &pWC->a[idxNew];
@@ -130675,20 +134488,19 @@ static void exprAnalyze(
** is not a sub-select. */
if( pWC->op==TK_AND
&& (pExpr->op==TK_EQ || pExpr->op==TK_IS)
- && sqlite3ExprIsVector(pExpr->pLeft)
+ && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
+ && sqlite3ExprVectorSize(pExpr->pRight)==nLeft
&& ( (pExpr->pLeft->flags & EP_xIsSelect)==0
- || (pExpr->pRight->flags & EP_xIsSelect)==0
- )){
- int nLeft = sqlite3ExprVectorSize(pExpr->pLeft);
+ || (pExpr->pRight->flags & EP_xIsSelect)==0)
+ ){
int i;
- assert( nLeft==sqlite3ExprVectorSize(pExpr->pRight) );
for(i=0; ipLeft, i);
Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
- pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0);
+ pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
transferJoinMarkings(pNew, pExpr);
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
exprAnalyze(pSrc, pWC, idxNew);
@@ -130740,7 +134552,7 @@ static void exprAnalyze(
pNewExpr = sqlite3PExpr(pParse, TK_GT,
sqlite3ExprDup(db, pLeft, 0),
- sqlite3ExprAlloc(db, TK_NULL, 0, 0), 0);
+ sqlite3ExprAlloc(db, TK_NULL, 0, 0));
idxNew = whereClauseInsert(pWC, pNewExpr,
TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
@@ -130848,13 +134660,16 @@ SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
Bitmask mask;
if( p==0 ) return 0;
if( p->op==TK_COLUMN ){
- mask = sqlite3WhereGetMask(pMaskSet, p->iTable);
- return mask;
+ return sqlite3WhereGetMask(pMaskSet, p->iTable);
}
+ mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
assert( !ExprHasProperty(p, EP_TokenOnly) );
- mask = p->pRight ? sqlite3WhereExprUsage(pMaskSet, p->pRight) : 0;
if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft);
- if( ExprHasProperty(p, EP_xIsSelect) ){
+ if( p->pRight ){
+ mask |= sqlite3WhereExprUsage(pMaskSet, p->pRight);
+ assert( p->x.pList==0 );
+ }else if( ExprHasProperty(p, EP_xIsSelect) ){
+ if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
}else if( p->x.pList ){
mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
@@ -130926,7 +134741,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(
pColRef->iColumn = k++;
pColRef->pTab = pTab;
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef,
- sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
+ sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0));
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
}
}
@@ -131133,16 +134948,19 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
WhereTerm *pTerm; /* The term being tested */
int k = pScan->k; /* Where to start scanning */
- while( pScan->iEquiv<=pScan->nEquiv ){
- iCur = pScan->aiCur[pScan->iEquiv-1];
+ assert( pScan->iEquiv<=pScan->nEquiv );
+ pWC = pScan->pWC;
+ while(1){
iColumn = pScan->aiColumn[pScan->iEquiv-1];
- if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0;
- while( (pWC = pScan->pWC)!=0 ){
+ iCur = pScan->aiCur[pScan->iEquiv-1];
+ assert( pWC!=0 );
+ do{
for(pTerm=pWC->a+k; knTerm; k++, pTerm++){
if( pTerm->leftCursor==iCur
&& pTerm->u.leftColumn==iColumn
&& (iColumn!=XN_EXPR
- || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0)
+ || sqlite3ExprCompareSkip(pTerm->pExpr->pLeft,
+ pScan->pIdxExpr,iCur)==0)
&& (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
){
if( (pTerm->eOperator & WO_EQUIV)!=0
@@ -131187,15 +135005,17 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
testcase( pTerm->eOperator & WO_IS );
continue;
}
+ pScan->pWC = pWC;
pScan->k = k+1;
return pTerm;
}
}
}
- pScan->pWC = pScan->pWC->pOuter;
+ pWC = pWC->pOuter;
k = 0;
- }
- pScan->pWC = pScan->pOrigWC;
+ }while( pWC!=0 );
+ if( pScan->iEquiv>=pScan->nEquiv ) break;
+ pWC = pScan->pOrigWC;
k = 0;
pScan->iEquiv++;
}
@@ -131229,24 +135049,25 @@ static WhereTerm *whereScanInit(
u32 opMask, /* Operator(s) to scan for */
Index *pIdx /* Must be compatible with this index */
){
- int j = 0;
-
- /* memset(pScan, 0, sizeof(*pScan)); */
pScan->pOrigWC = pWC;
pScan->pWC = pWC;
pScan->pIdxExpr = 0;
+ pScan->idxaff = 0;
+ pScan->zCollName = 0;
if( pIdx ){
- j = iColumn;
+ int j = iColumn;
iColumn = pIdx->aiColumn[j];
- if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
- if( iColumn==pIdx->pTable->iPKey ) iColumn = XN_ROWID;
- }
- if( pIdx && iColumn>=0 ){
- pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
- pScan->zCollName = pIdx->azColl[j];
- }else{
- pScan->idxaff = 0;
- pScan->zCollName = 0;
+ if( iColumn==XN_EXPR ){
+ pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
+ pScan->zCollName = pIdx->azColl[j];
+ }else if( iColumn==pIdx->pTable->iPKey ){
+ iColumn = XN_ROWID;
+ }else if( iColumn>=0 ){
+ pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
+ pScan->zCollName = pIdx->azColl[j];
+ }
+ }else if( iColumn==XN_EXPR ){
+ return 0;
}
pScan->opMask = opMask;
pScan->k = 0;
@@ -131446,14 +135267,16 @@ static LogEst estLog(LogEst N){
** value stored in its output register.
*/
static void translateColumnToCopy(
- Vdbe *v, /* The VDBE containing code to translate */
+ Parse *pParse, /* Parsing context */
int iStart, /* Translate from this opcode to the end */
int iTabCur, /* OP_Column/OP_Rowid references to this table */
int iRegister, /* The first column is in this register */
int bIncrRowid /* If non-zero, transform OP_rowid to OP_AddImm(1) */
){
+ Vdbe *v = pParse->pVdbe;
VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart);
int iEnd = sqlite3VdbeCurrentAddr(v);
+ if( pParse->db->mallocFailed ) return;
for(; iStartp1!=iTabCur ) continue;
if( pOp->opcode==OP_Column ){
@@ -131535,6 +135358,15 @@ static int termCanDriveIndex(
char aff;
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
+ if( (pSrc->fg.jointype & JT_LEFT)
+ && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
+ && (pTerm->eOperator & WO_IS)
+ ){
+ /* Cannot use an IS term from the WHERE clause as an index driver for
+ ** the RHS of a LEFT JOIN. Such a term can only be used if it is from
+ ** the ON clause. */
+ return 0;
+ }
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
if( pTerm->u.leftColumn<0 ) return 0;
aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
@@ -131731,7 +135563,9 @@ static void constructAutomaticIndex(
if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
if( pTabItem->fg.viaCoroutine ){
sqlite3VdbeChangeP2(v, addrCounter, regBase+n);
- translateColumnToCopy(v, addrTop, pLevel->iTabCur, pTabItem->regResult, 1);
+ testcase( pParse->db->mallocFailed );
+ translateColumnToCopy(pParse, addrTop, pLevel->iTabCur,
+ pTabItem->regResult, 1);
sqlite3VdbeGoto(v, addrTop);
pTabItem->fg.viaCoroutine = 0;
}else{
@@ -132117,7 +135951,7 @@ static int whereKeyStats(
iGap = iGap/3;
}
aStat[0] = iLower + iGap;
- aStat[1] = pIdx->aAvgEq[iCol];
+ aStat[1] = pIdx->aAvgEq[nField-1];
}
/* Restore the pRec->nField value before returning. */
@@ -132711,7 +136545,7 @@ static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){
p->u.vtab.idxStr = 0;
}else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){
sqlite3DbFree(db, p->u.btree.pIndex->zColAff);
- sqlite3DbFree(db, p->u.btree.pIndex);
+ sqlite3DbFreeNN(db, p->u.btree.pIndex);
p->u.btree.pIndex = 0;
}
}
@@ -132721,7 +136555,7 @@ static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){
** Deallocate internal memory used by a WhereLoop object
*/
static void whereLoopClear(sqlite3 *db, WhereLoop *p){
- if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm);
+ if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFreeNN(db, p->aLTerm);
whereLoopClearUnion(db, p);
whereLoopInit(p);
}
@@ -132736,7 +136570,7 @@ static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){
paNew = sqlite3DbMallocRawNN(db, sizeof(p->aLTerm[0])*n);
if( paNew==0 ) return SQLITE_NOMEM_BKPT;
memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot);
- if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm);
+ if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFreeNN(db, p->aLTerm);
p->aLTerm = paNew;
p->nLSlot = n;
return SQLITE_OK;
@@ -132766,7 +136600,7 @@ static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
*/
static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
whereLoopClear(db, p);
- sqlite3DbFree(db, p);
+ sqlite3DbFreeNN(db, p);
}
/*
@@ -132787,7 +136621,7 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
pWInfo->pLoops = p->pNextLoop;
whereLoopDelete(db, p);
}
- sqlite3DbFree(db, pWInfo);
+ sqlite3DbFreeNN(db, pWInfo);
}
}
@@ -132870,16 +136704,17 @@ static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){
/*
** Search the list of WhereLoops in *ppPrev looking for one that can be
-** supplanted by pTemplate.
+** replaced by pTemplate.
**
-** Return NULL if the WhereLoop list contains an entry that can supplant
-** pTemplate, in other words if pTemplate does not belong on the list.
+** Return NULL if pTemplate does not belong on the WhereLoop list.
+** In other words if pTemplate ought to be dropped from further consideration.
**
-** If pX is a WhereLoop that pTemplate can supplant, then return the
+** If pX is a WhereLoop that pTemplate can replace, then return the
** link that points to pX.
**
-** If pTemplate cannot supplant any existing element of the list but needs
-** to be added to the list, then return a pointer to the tail of the list.
+** If pTemplate cannot replace any existing element of the list but needs
+** to be added to the list as a new entry, then return a pointer to the
+** tail of the list.
*/
static WhereLoop **whereLoopFindLesser(
WhereLoop **ppPrev,
@@ -133024,8 +136859,10 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
if( p!=0 ){
sqlite3DebugPrintf("replace: ");
whereLoopPrint(p, pBuilder->pWC);
+ sqlite3DebugPrintf(" with: ");
+ }else{
+ sqlite3DebugPrintf(" add: ");
}
- sqlite3DebugPrintf(" add: ");
whereLoopPrint(pTemplate, pBuilder->pWC);
}
#endif
@@ -133316,6 +137153,11 @@ static int whereLoopAddBtreeIndex(
continue;
}
+ if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){
+ pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE;
+ }else{
+ pBuilder->bldFlags |= SQLITE_BLDF_INDEXED;
+ }
pNew->wsFlags = saved_wsFlags;
pNew->u.btree.nEq = saved_nEq;
pNew->u.btree.nBtm = saved_nBtm;
@@ -133571,7 +137413,7 @@ static int indexMightHelpWithOrderBy(
}else if( (aColExpr = pIndex->aColExpr)!=0 ){
for(jj=0; jjnKeyCol; jj++){
if( pIndex->aiColumn[jj]!=XN_EXPR ) continue;
- if( sqlite3ExprCompare(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){
+ if( sqlite3ExprCompare(0, pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){
return 1;
}
}
@@ -133604,14 +137446,16 @@ static Bitmask columnsInIndex(Index *pIdx){
static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
int i;
WhereTerm *pTerm;
+ Parse *pParse = pWC->pWInfo->pParse;
while( pWhere->op==TK_AND ){
if( !whereUsablePartialIndex(iTab,pWC,pWhere->pLeft) ) return 0;
pWhere = pWhere->pRight;
}
+ if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){
Expr *pExpr = pTerm->pExpr;
- if( sqlite3ExprImpliesExpr(pExpr, pWhere, iTab)
- && (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab)
+ if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab)
+ && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
){
return 1;
}
@@ -133863,7 +137707,15 @@ static int whereLoopAddBtree(
}
}
+ pBuilder->bldFlags = 0;
rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
+ if( pBuilder->bldFlags==SQLITE_BLDF_INDEXED ){
+ /* If a non-unique index is used, or if a prefix of the key for
+ ** unique index is used (making the index functionally non-unique)
+ ** then the sqlite_stat1 data becomes important for scoring the
+ ** plan */
+ pTab->tabFlags |= TF_StatsUsed;
+ }
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
sqlite3Stat4ProbeFree(pBuilder->pRec);
pBuilder->nRecValid = 0;
@@ -134165,7 +138017,7 @@ static int whereLoopAddVirtual(
}
if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr);
- sqlite3DbFree(pParse->db, p);
+ sqlite3DbFreeNN(pParse->db, p);
return rc;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -134349,7 +138201,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
}
/*
-** Examine a WherePath (with the addition of the extra WhereLoop of the 5th
+** Examine a WherePath (with the addition of the extra WhereLoop of the 6th
** parameters) to see if it outputs rows in the requested ORDER BY
** (or GROUP BY) without requiring a separate sort operation. Return N:
**
@@ -134444,6 +138296,8 @@ static i8 wherePathSatisfiesOrderBy(
if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
if( pLoop->u.vtab.isOrdered ) obSat = obDone;
break;
+ }else{
+ pLoop->u.btree.nIdxCol = 0;
}
iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
@@ -134580,7 +138434,8 @@ static i8 wherePathSatisfiesOrderBy(
if( pOBExpr->iTable!=iCur ) continue;
if( pOBExpr->iColumn!=iColumn ) continue;
}else{
- if( sqlite3ExprCompare(pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){
+ if( sqlite3ExprCompare(0,
+ pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){
continue;
}
}
@@ -134589,6 +138444,7 @@ static i8 wherePathSatisfiesOrderBy(
if( !pColl ) pColl = db->pDfltColl;
if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
}
+ pLoop->u.btree.nIdxCol = j+1;
isMatch = 1;
break;
}
@@ -134878,6 +138734,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
rUnsorted, rCost));
}else{
rCost = rUnsorted;
+ rUnsorted -= 2; /* TUNING: Slight bias in favor of no-sort plans */
}
/* Check to see if pWLoop should be added to the set of
@@ -134909,8 +138766,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
** this candidate as not viable. */
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
- sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
+ sqlite3DebugPrintf("Skip %s cost=%-3d,%3d,%3d order=%c\n",
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
isOrdered>=0 ? isOrdered+'0' : '?');
}
#endif
@@ -134928,26 +138785,36 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pTo = &aTo[jj];
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
- sqlite3DebugPrintf("New %s cost=%-3d,%3d order=%c\n",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
+ sqlite3DebugPrintf("New %s cost=%-3d,%3d,%3d order=%c\n",
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
isOrdered>=0 ? isOrdered+'0' : '?');
}
#endif
}else{
/* Control reaches here if best-so-far path pTo=aTo[jj] covers the
- ** same set of loops and has the sam isOrdered setting as the
+ ** same set of loops and has the same isOrdered setting as the
** candidate path. Check to see if the candidate should replace
- ** pTo or if the candidate should be skipped */
- if( pTo->rCostrCost==rCost && pTo->nRow<=nOut) ){
+ ** pTo or if the candidate should be skipped.
+ **
+ ** The conditional is an expanded vector comparison equivalent to:
+ ** (pTo->rCost,pTo->nRow,pTo->rUnsorted) <= (rCost,nOut,rUnsorted)
+ */
+ if( pTo->rCostrCost==rCost
+ && (pTo->nRownRow==nOut && pTo->rUnsorted<=rUnsorted)
+ )
+ )
+ ){
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf(
- "Skip %s cost=%-3d,%3d order=%c",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
+ "Skip %s cost=%-3d,%3d,%3d order=%c",
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
isOrdered>=0 ? isOrdered+'0' : '?');
- sqlite3DebugPrintf(" vs %s cost=%-3d,%d order=%c\n",
+ sqlite3DebugPrintf(" vs %s cost=%-3d,%3d,%3d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
- pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
+ pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
}
#endif
/* Discard the candidate path from further consideration */
@@ -134960,12 +138827,12 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf(
- "Update %s cost=%-3d,%3d order=%c",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
+ "Update %s cost=%-3d,%3d,%3d order=%c",
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
isOrdered>=0 ? isOrdered+'0' : '?');
- sqlite3DebugPrintf(" was %s cost=%-3d,%3d order=%c\n",
+ sqlite3DebugPrintf(" was %s cost=%-3d,%3d,%3d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
- pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
+ pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
}
#endif
}
@@ -135020,7 +138887,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
if( nFrom==0 ){
sqlite3ErrorMsg(pParse, "no query solution");
- sqlite3DbFree(db, pSpace);
+ sqlite3DbFreeNN(db, pSpace);
return SQLITE_ERROR;
}
@@ -135043,9 +138910,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
&& nRowEst
){
Bitmask notUsed;
- int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pDistinctSet, pFrom,
+ int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used);
- if( rc==pWInfo->pDistinctSet->nExpr ){
+ if( rc==pWInfo->pResultSet->nExpr ){
pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
}
}
@@ -135096,7 +138963,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pWInfo->nRowOut = pFrom->nRow;
/* Free temporary memory and return success */
- sqlite3DbFree(db, pSpace);
+ sqlite3DbFreeNN(db, pSpace);
return SQLITE_OK;
}
@@ -135174,7 +139041,8 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
if( pLoop->wsFlags ){
pLoop->nOut = (LogEst)1;
pWInfo->a[0].pWLoop = pLoop;
- pLoop->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur);
+ assert( pWInfo->sMaskSet.n==1 && iCur==pWInfo->sMaskSet.ix[0] );
+ pLoop->maskSelf = 1; /* sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); */
pWInfo->a[0].iTabCur = iCur;
pWInfo->nRowOut = 1;
if( pWInfo->pOrderBy ) pWInfo->nOBSat = pWInfo->pOrderBy->nExpr;
@@ -135189,6 +139057,31 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
return 0;
}
+/*
+** Helper function for exprIsDeterministic().
+*/
+static int exprNodeIsDeterministic(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_ConstFunc)==0 ){
+ pWalker->eCode = 0;
+ return WRC_Abort;
+ }
+ return WRC_Continue;
+}
+
+/*
+** Return true if the expression contains no non-deterministic SQL
+** functions. Do not consider non-deterministic SQL functions that are
+** part of sub-select statements.
+*/
+static int exprIsDeterministic(Expr *p){
+ Walker w;
+ memset(&w, 0, sizeof(w));
+ w.eCode = 1;
+ w.xExprCallback = exprNodeIsDeterministic;
+ sqlite3WalkExpr(&w, p);
+ return w.eCode;
+}
+
/*
** Generate the beginning of the loop used for WHERE clause processing.
** The return value is a pointer to an opaque structure that contains
@@ -135282,7 +139175,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */
- ExprList *pDistinctSet, /* Try not to output two rows that duplicate these */
+ ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */
u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */
int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number
** If WHERE_USE_LIMIT, then the limit amount */
@@ -135358,7 +139251,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pWInfo->pParse = pParse;
pWInfo->pTabList = pTabList;
pWInfo->pOrderBy = pOrderBy;
- pWInfo->pDistinctSet = pDistinctSet;
+ pWInfo->pWhere = pWhere;
+ pWInfo->pResultSet = pResultSet;
pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
pWInfo->nLevel = nTabList;
pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
@@ -135386,17 +139280,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo);
sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND);
- /* Special case: a WHERE clause that is constant. Evaluate the
- ** expression and either jump over all of the code or fall thru.
- */
- for(ii=0; iinTerm; ii++){
- if( nTabList==0 || sqlite3ExprIsConstantNotJoin(sWLB.pWC->a[ii].pExpr) ){
- sqlite3ExprIfFalse(pParse, sWLB.pWC->a[ii].pExpr, pWInfo->iBreak,
- SQLITE_JUMPIFNULL);
- sWLB.pWC->a[ii].wtFlags |= TERM_CODED;
- }
- }
-
/* Special case: No FROM clause
*/
if( nTabList==0 ){
@@ -135425,9 +139308,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC);
}
#ifdef SQLITE_DEBUG
- for(ii=0; iinSrc; ii++){
- Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor);
- assert( m==MASKBIT(ii) );
+ {
+ Bitmask mx = 0;
+ for(ii=0; iinSrc; ii++){
+ Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor);
+ assert( m>=mx );
+ mx = m;
+ }
}
#endif
@@ -135435,14 +139322,33 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC);
if( db->mallocFailed ) goto whereBeginError;
+ /* Special case: WHERE terms that do not refer to any tables in the join
+ ** (constant expressions). Evaluate each such term, and jump over all the
+ ** generated code if the result is not true.
+ **
+ ** Do not do this if the expression contains non-deterministic functions
+ ** that are not within a sub-select. This is not strictly required, but
+ ** preserves SQLite's legacy behaviour in the following two cases:
+ **
+ ** FROM ... WHERE random()>0; -- eval random() once per row
+ ** FROM ... WHERE (SELECT random())>0; -- eval random() once overall
+ */
+ for(ii=0; iinTerm; ii++){
+ WhereTerm *pT = &sWLB.pWC->a[ii];
+ if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){
+ sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL);
+ pT->wtFlags |= TERM_CODED;
+ }
+ }
+
if( wctrlFlags & WHERE_WANT_DISTINCT ){
- if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pDistinctSet) ){
+ if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
/* The DISTINCT marking is pointless. Ignore it. */
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
}else if( pOrderBy==0 ){
/* Try to ORDER BY the result set to make distinct processing easier */
pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
- pWInfo->pOrderBy = pDistinctSet;
+ pWInfo->pOrderBy = pResultSet;
}
}
@@ -135471,7 +139377,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
"ABCDEFGHIJKLMNOPQRSTUVWYXZ";
for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
- p->cId = zLabel[i%sizeof(zLabel)];
+ p->cId = zLabel[i%(sizeof(zLabel)-1)];
whereLoopPrint(p, sWLB.pWC);
}
}
@@ -135518,10 +139424,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
#endif
/* Attempt to omit tables from the join that do not effect the result */
if( pWInfo->nLevel>=2
- && pDistinctSet!=0
+ && pResultSet!=0
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
){
- Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pDistinctSet);
+ Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet);
if( sWLB.pOrderBy ){
tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
}
@@ -135668,6 +139574,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0
&& (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0
&& (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0
+ && pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED
){
sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */
}
@@ -135756,14 +139663,43 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
int addr;
pLevel = &pWInfo->a[i];
pLoop = pLevel->pWLoop;
- sqlite3VdbeResolveLabel(v, pLevel->addrCont);
if( pLevel->op!=OP_Noop ){
+#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
+ int addrSeek = 0;
+ Index *pIdx;
+ int n;
+ if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
+ && (pLoop->wsFlags & WHERE_INDEXED)!=0
+ && (pIdx = pLoop->u.btree.pIndex)->hasStat1
+ && (n = pLoop->u.btree.nIdxCol)>0
+ && pIdx->aiRowLogEst[n]>=36
+ ){
+ int r1 = pParse->nMem+1;
+ int j, op;
+ for(j=0; jiIdxCur, j, r1+j);
+ }
+ pParse->nMem += n+1;
+ op = pLevel->op==OP_Prev ? OP_SeekLT : OP_SeekGT;
+ addrSeek = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n);
+ VdbeCoverageIf(v, op==OP_SeekLT);
+ VdbeCoverageIf(v, op==OP_SeekGT);
+ sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
+ }
+#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
+ /* The common case: Advance to the next row */
+ sqlite3VdbeResolveLabel(v, pLevel->addrCont);
sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
sqlite3VdbeChangeP5(v, pLevel->p5);
VdbeCoverage(v);
VdbeCoverageIf(v, pLevel->op==OP_Next);
VdbeCoverageIf(v, pLevel->op==OP_Prev);
VdbeCoverageIf(v, pLevel->op==OP_VNext);
+#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
+ if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek);
+#endif
+ }else{
+ sqlite3VdbeResolveLabel(v, pLevel->addrCont);
}
if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
struct InLoop *pIn;
@@ -135836,33 +139772,13 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
** the co-routine into OP_Copy of result contained in a register.
** OP_Rowid becomes OP_Null.
*/
- if( pTabItem->fg.viaCoroutine && !db->mallocFailed ){
- translateColumnToCopy(v, pLevel->addrBody, pLevel->iTabCur,
+ if( pTabItem->fg.viaCoroutine ){
+ testcase( pParse->db->mallocFailed );
+ translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur,
pTabItem->regResult, 0);
continue;
}
- /* Close all of the cursors that were opened by sqlite3WhereBegin.
- ** Except, do not close cursors that will be reused by the OR optimization
- ** (WHERE_OR_SUBCLAUSE). And do not close the OP_OpenWrite cursors
- ** created for the ONEPASS optimization.
- */
- if( (pTab->tabFlags & TF_Ephemeral)==0
- && pTab->pSelect==0
- && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
- ){
- int ws = pLoop->wsFlags;
- if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){
- sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
- }
- if( (ws & WHERE_INDEXED)!=0
- && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0
- && pLevel->iIdxCur!=pWInfo->aiCurOnePass[1]
- ){
- sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
- }
- }
-
/* If this scan uses an index, make VDBE code substitutions to read data
** from the index instead of from the table where possible. In some cases
** this optimization prevents the table from ever being read, which can
@@ -135901,10 +139817,13 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
pOp->p2 = x;
pOp->p1 = pLevel->iIdxCur;
}
- assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 );
+ assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0
+ || pWInfo->eOnePass );
}else if( pOp->opcode==OP_Rowid ){
pOp->p1 = pLevel->iIdxCur;
pOp->opcode = OP_IdxRowid;
+ }else if( pOp->opcode==OP_IfNullRow ){
+ pOp->p1 = pLevel->iIdxCur;
}
}
}
@@ -135965,6 +139884,19 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
*/
#define YYPARSEFREENEVERNULL 1
+/*
+** In the amalgamation, the parse.c file generated by lemon and the
+** tokenize.c file are concatenated. In that case, sqlite3RunParser()
+** has access to the the size of the yyParser object and so the parser
+** engine can be allocated from stack. In that case, only the
+** sqlite3ParserInit() and sqlite3ParserFinalize() routines are invoked
+** and the sqlite3ParserAlloc() and sqlite3ParserFree() routines can be
+** omitted.
+*/
+#ifdef SQLITE_AMALGAMATION
+# define sqlite3Parser_ENGINEALWAYSONSTACK 1
+#endif
+
/*
** Alternative datatype for the argument to the malloc() routine passed
** into sqlite3ParserAlloc(). The default is size_t.
@@ -136068,7 +140000,7 @@ static void disableLookaside(Parse *pParse){
ExprSpan *pLeft, /* The left operand, and output */
ExprSpan *pRight /* The right operand */
){
- pLeft->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0);
+ pLeft->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr);
pLeft->zEnd = pRight->zEnd;
}
@@ -136077,7 +140009,7 @@ static void disableLookaside(Parse *pParse){
*/
static void exprNot(Parse *pParse, int doNot, ExprSpan *pSpan){
if( doNot ){
- pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0, 0);
+ pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0);
}
}
@@ -136089,7 +140021,7 @@ static void disableLookaside(Parse *pParse){
ExprSpan *pOperand, /* The operand, and output */
Token *pPostOp /* The operand token for setting the span */
){
- pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0);
+ pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0);
pOperand->zEnd = &pPostOp->z[pPostOp->n];
}
@@ -136114,7 +140046,7 @@ static void disableLookaside(Parse *pParse){
Token *pPreOp /* The operand token for setting the span */
){
pOut->zStart = pPreOp->z;
- pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0);
+ pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0);
pOut->zEnd = pOperand->zEnd;
}
@@ -136201,7 +140133,7 @@ static void disableLookaside(Parse *pParse){
#define YYCODETYPE unsigned char
#define YYNOCODE 252
#define YYACTIONTYPE unsigned short int
-#define YYWILDCARD 96
+#define YYWILDCARD 69
#define sqlite3ParserTOKENTYPE Token
typedef union {
int yyinit;
@@ -136227,16 +140159,16 @@ typedef union {
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
#define YYFALLBACK 1
-#define YYNSTATE 456
-#define YYNRULE 332
-#define YY_MAX_SHIFT 455
-#define YY_MIN_SHIFTREDUCE 668
-#define YY_MAX_SHIFTREDUCE 999
-#define YY_MIN_REDUCE 1000
-#define YY_MAX_REDUCE 1331
-#define YY_ERROR_ACTION 1332
-#define YY_ACCEPT_ACTION 1333
-#define YY_NO_ACTION 1334
+#define YYNSTATE 455
+#define YYNRULE 329
+#define YY_MAX_SHIFT 454
+#define YY_MIN_SHIFTREDUCE 664
+#define YY_MAX_SHIFTREDUCE 992
+#define YY_MIN_REDUCE 993
+#define YY_MAX_REDUCE 1321
+#define YY_ERROR_ACTION 1322
+#define YY_ACCEPT_ACTION 1323
+#define YY_NO_ACTION 1324
/************* End control #defines *******************************************/
/* Define the yytestcase() macro to be a no-op if is not already defined
@@ -136308,463 +140240,463 @@ typedef union {
** yy_default[] Default action for each state.
**
*********** Begin parsing tables **********************************************/
-#define YY_ACTTAB_COUNT (1567)
+#define YY_ACTTAB_COUNT (1565)
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 325, 832, 351, 825, 5, 203, 203, 819, 99, 100,
- /* 10 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98,
- /* 20 */ 98, 98, 98, 301, 96, 96, 96, 96, 95, 95,
- /* 30 */ 94, 94, 94, 93, 351, 325, 977, 977, 824, 824,
- /* 40 */ 826, 947, 354, 99, 100, 90, 842, 842, 854, 857,
- /* 50 */ 846, 846, 97, 97, 98, 98, 98, 98, 338, 96,
- /* 60 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351,
- /* 70 */ 95, 95, 94, 94, 94, 93, 351, 791, 977, 977,
- /* 80 */ 325, 94, 94, 94, 93, 351, 792, 75, 99, 100,
- /* 90 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98,
- /* 100 */ 98, 98, 98, 450, 96, 96, 96, 96, 95, 95,
- /* 110 */ 94, 94, 94, 93, 351, 1333, 155, 155, 2, 325,
- /* 120 */ 275, 146, 132, 52, 52, 93, 351, 99, 100, 90,
- /* 130 */ 842, 842, 854, 857, 846, 846, 97, 97, 98, 98,
- /* 140 */ 98, 98, 101, 96, 96, 96, 96, 95, 95, 94,
- /* 150 */ 94, 94, 93, 351, 958, 958, 325, 268, 428, 413,
- /* 160 */ 411, 61, 752, 752, 99, 100, 90, 842, 842, 854,
- /* 170 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 60,
- /* 180 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93,
- /* 190 */ 351, 325, 270, 329, 273, 277, 959, 960, 250, 99,
- /* 200 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97,
- /* 210 */ 98, 98, 98, 98, 301, 96, 96, 96, 96, 95,
- /* 220 */ 95, 94, 94, 94, 93, 351, 325, 938, 1326, 698,
- /* 230 */ 706, 1326, 242, 412, 99, 100, 90, 842, 842, 854,
- /* 240 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 347,
- /* 250 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93,
- /* 260 */ 351, 325, 938, 1327, 384, 699, 1327, 381, 379, 99,
- /* 270 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97,
- /* 280 */ 98, 98, 98, 98, 701, 96, 96, 96, 96, 95,
- /* 290 */ 95, 94, 94, 94, 93, 351, 325, 92, 89, 178,
- /* 300 */ 833, 936, 373, 700, 99, 100, 90, 842, 842, 854,
- /* 310 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 375,
- /* 320 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93,
- /* 330 */ 351, 325, 1276, 947, 354, 818, 936, 739, 739, 99,
- /* 340 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97,
- /* 350 */ 98, 98, 98, 98, 230, 96, 96, 96, 96, 95,
- /* 360 */ 95, 94, 94, 94, 93, 351, 325, 969, 227, 92,
- /* 370 */ 89, 178, 373, 300, 99, 100, 90, 842, 842, 854,
- /* 380 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 921,
- /* 390 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93,
- /* 400 */ 351, 325, 449, 447, 447, 447, 147, 737, 737, 99,
- /* 410 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97,
- /* 420 */ 98, 98, 98, 98, 296, 96, 96, 96, 96, 95,
- /* 430 */ 95, 94, 94, 94, 93, 351, 325, 419, 231, 958,
- /* 440 */ 958, 158, 25, 422, 99, 100, 90, 842, 842, 854,
- /* 450 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 450,
- /* 460 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93,
- /* 470 */ 351, 443, 224, 224, 420, 958, 958, 962, 325, 52,
- /* 480 */ 52, 959, 960, 176, 415, 78, 99, 100, 90, 842,
- /* 490 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98,
- /* 500 */ 98, 379, 96, 96, 96, 96, 95, 95, 94, 94,
- /* 510 */ 94, 93, 351, 325, 428, 418, 298, 959, 960, 962,
- /* 520 */ 81, 99, 88, 90, 842, 842, 854, 857, 846, 846,
- /* 530 */ 97, 97, 98, 98, 98, 98, 717, 96, 96, 96,
- /* 540 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 843,
- /* 550 */ 843, 855, 858, 996, 318, 343, 379, 100, 90, 842,
- /* 560 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98,
- /* 570 */ 98, 450, 96, 96, 96, 96, 95, 95, 94, 94,
- /* 580 */ 94, 93, 351, 325, 350, 350, 350, 260, 377, 340,
- /* 590 */ 929, 52, 52, 90, 842, 842, 854, 857, 846, 846,
- /* 600 */ 97, 97, 98, 98, 98, 98, 361, 96, 96, 96,
- /* 610 */ 96, 95, 95, 94, 94, 94, 93, 351, 86, 445,
- /* 620 */ 847, 3, 1203, 361, 360, 378, 344, 813, 958, 958,
- /* 630 */ 1300, 86, 445, 729, 3, 212, 169, 287, 405, 282,
- /* 640 */ 404, 199, 232, 450, 300, 760, 83, 84, 280, 245,
- /* 650 */ 262, 365, 251, 85, 352, 352, 92, 89, 178, 83,
- /* 660 */ 84, 242, 412, 52, 52, 448, 85, 352, 352, 246,
- /* 670 */ 959, 960, 194, 455, 670, 402, 399, 398, 448, 243,
- /* 680 */ 221, 114, 434, 776, 361, 450, 397, 268, 747, 224,
- /* 690 */ 224, 132, 132, 198, 832, 434, 452, 451, 428, 427,
- /* 700 */ 819, 415, 734, 713, 132, 52, 52, 832, 268, 452,
- /* 710 */ 451, 734, 194, 819, 363, 402, 399, 398, 450, 1271,
- /* 720 */ 1271, 23, 958, 958, 86, 445, 397, 3, 228, 429,
- /* 730 */ 895, 824, 824, 826, 827, 19, 203, 720, 52, 52,
- /* 740 */ 428, 408, 439, 249, 824, 824, 826, 827, 19, 229,
- /* 750 */ 403, 153, 83, 84, 761, 177, 241, 450, 721, 85,
- /* 760 */ 352, 352, 120, 157, 959, 960, 58, 977, 409, 355,
- /* 770 */ 330, 448, 268, 428, 430, 320, 790, 32, 32, 86,
- /* 780 */ 445, 776, 3, 341, 98, 98, 98, 98, 434, 96,
- /* 790 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351,
- /* 800 */ 832, 120, 452, 451, 813, 887, 819, 83, 84, 977,
- /* 810 */ 813, 132, 410, 920, 85, 352, 352, 132, 407, 789,
- /* 820 */ 958, 958, 92, 89, 178, 917, 448, 262, 370, 261,
- /* 830 */ 82, 914, 80, 262, 370, 261, 776, 824, 824, 826,
- /* 840 */ 827, 19, 934, 434, 96, 96, 96, 96, 95, 95,
- /* 850 */ 94, 94, 94, 93, 351, 832, 74, 452, 451, 958,
- /* 860 */ 958, 819, 959, 960, 120, 92, 89, 178, 945, 2,
- /* 870 */ 918, 965, 268, 1, 976, 76, 445, 762, 3, 708,
- /* 880 */ 901, 901, 387, 958, 958, 757, 919, 371, 740, 778,
- /* 890 */ 756, 257, 824, 824, 826, 827, 19, 417, 741, 450,
- /* 900 */ 24, 959, 960, 83, 84, 369, 958, 958, 177, 226,
- /* 910 */ 85, 352, 352, 885, 315, 314, 313, 215, 311, 10,
- /* 920 */ 10, 683, 448, 349, 348, 959, 960, 909, 777, 157,
- /* 930 */ 120, 958, 958, 337, 776, 416, 711, 310, 450, 434,
- /* 940 */ 450, 321, 450, 791, 103, 200, 175, 450, 959, 960,
- /* 950 */ 908, 832, 792, 452, 451, 9, 9, 819, 10, 10,
- /* 960 */ 52, 52, 51, 51, 180, 716, 248, 10, 10, 171,
- /* 970 */ 170, 167, 339, 959, 960, 247, 984, 702, 702, 450,
- /* 980 */ 715, 233, 686, 982, 889, 983, 182, 914, 824, 824,
- /* 990 */ 826, 827, 19, 183, 256, 423, 132, 181, 394, 10,
- /* 1000 */ 10, 889, 891, 749, 958, 958, 917, 268, 985, 198,
- /* 1010 */ 985, 349, 348, 425, 415, 299, 817, 832, 326, 825,
- /* 1020 */ 120, 332, 133, 819, 268, 98, 98, 98, 98, 91,
- /* 1030 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93,
- /* 1040 */ 351, 157, 810, 371, 382, 359, 959, 960, 358, 268,
- /* 1050 */ 450, 918, 368, 324, 824, 824, 826, 450, 709, 450,
- /* 1060 */ 264, 380, 889, 450, 877, 746, 253, 919, 255, 433,
- /* 1070 */ 36, 36, 234, 450, 234, 120, 269, 37, 37, 12,
- /* 1080 */ 12, 334, 272, 27, 27, 450, 330, 118, 450, 162,
- /* 1090 */ 742, 280, 450, 38, 38, 450, 985, 356, 985, 450,
- /* 1100 */ 709, 1210, 450, 132, 450, 39, 39, 450, 40, 40,
- /* 1110 */ 450, 362, 41, 41, 450, 42, 42, 450, 254, 28,
- /* 1120 */ 28, 450, 29, 29, 31, 31, 450, 43, 43, 450,
- /* 1130 */ 44, 44, 450, 714, 45, 45, 450, 11, 11, 767,
- /* 1140 */ 450, 46, 46, 450, 268, 450, 105, 105, 450, 47,
- /* 1150 */ 47, 450, 48, 48, 450, 237, 33, 33, 450, 172,
- /* 1160 */ 49, 49, 450, 50, 50, 34, 34, 274, 122, 122,
- /* 1170 */ 450, 123, 123, 450, 124, 124, 450, 898, 56, 56,
- /* 1180 */ 450, 897, 35, 35, 450, 267, 450, 817, 450, 817,
- /* 1190 */ 106, 106, 450, 53, 53, 385, 107, 107, 450, 817,
- /* 1200 */ 108, 108, 817, 450, 104, 104, 121, 121, 119, 119,
- /* 1210 */ 450, 117, 112, 112, 450, 276, 450, 225, 111, 111,
- /* 1220 */ 450, 730, 450, 109, 109, 450, 673, 674, 675, 912,
- /* 1230 */ 110, 110, 317, 998, 55, 55, 57, 57, 692, 331,
- /* 1240 */ 54, 54, 26, 26, 696, 30, 30, 317, 937, 197,
- /* 1250 */ 196, 195, 335, 281, 336, 446, 331, 745, 689, 436,
- /* 1260 */ 440, 444, 120, 72, 386, 223, 175, 345, 757, 933,
- /* 1270 */ 20, 286, 319, 756, 815, 372, 374, 202, 202, 202,
- /* 1280 */ 263, 395, 285, 74, 208, 21, 696, 719, 718, 884,
- /* 1290 */ 120, 120, 120, 120, 120, 754, 278, 828, 77, 74,
- /* 1300 */ 726, 727, 785, 783, 880, 202, 999, 208, 894, 893,
- /* 1310 */ 894, 893, 694, 816, 763, 116, 774, 1290, 431, 432,
- /* 1320 */ 302, 999, 390, 303, 823, 697, 691, 680, 159, 289,
- /* 1330 */ 679, 884, 681, 952, 291, 218, 293, 7, 316, 828,
- /* 1340 */ 173, 805, 259, 364, 252, 911, 376, 713, 295, 435,
- /* 1350 */ 308, 168, 955, 993, 135, 400, 990, 284, 882, 881,
- /* 1360 */ 205, 928, 926, 59, 333, 62, 144, 156, 130, 72,
- /* 1370 */ 802, 366, 367, 393, 137, 185, 189, 160, 139, 383,
- /* 1380 */ 67, 896, 140, 141, 142, 148, 389, 812, 775, 266,
- /* 1390 */ 219, 190, 154, 391, 913, 876, 271, 406, 191, 322,
- /* 1400 */ 682, 733, 192, 342, 732, 724, 731, 711, 723, 421,
- /* 1410 */ 705, 71, 323, 6, 204, 771, 288, 79, 297, 346,
- /* 1420 */ 772, 704, 290, 283, 703, 770, 292, 294, 967, 239,
- /* 1430 */ 769, 102, 862, 438, 426, 240, 424, 442, 73, 213,
- /* 1440 */ 688, 238, 22, 453, 953, 214, 217, 216, 454, 677,
- /* 1450 */ 676, 671, 753, 125, 115, 235, 126, 669, 353, 166,
- /* 1460 */ 127, 244, 179, 357, 306, 304, 305, 307, 113, 892,
- /* 1470 */ 327, 890, 811, 328, 134, 128, 136, 138, 743, 258,
- /* 1480 */ 907, 184, 143, 129, 910, 186, 63, 64, 145, 187,
- /* 1490 */ 906, 65, 8, 66, 13, 188, 202, 899, 265, 149,
- /* 1500 */ 987, 388, 150, 685, 161, 392, 285, 193, 279, 396,
- /* 1510 */ 151, 401, 68, 14, 15, 722, 69, 236, 831, 131,
- /* 1520 */ 830, 860, 70, 751, 16, 414, 755, 4, 174, 220,
- /* 1530 */ 222, 784, 201, 152, 779, 77, 74, 17, 18, 875,
- /* 1540 */ 861, 859, 916, 864, 915, 207, 206, 942, 163, 437,
- /* 1550 */ 948, 943, 164, 209, 1002, 441, 863, 165, 210, 829,
- /* 1560 */ 695, 87, 312, 211, 1292, 1291, 309,
+ /* 0 */ 324, 410, 342, 747, 747, 203, 939, 353, 969, 98,
+ /* 10 */ 98, 98, 98, 91, 96, 96, 96, 96, 95, 95,
+ /* 20 */ 94, 94, 94, 93, 350, 1323, 155, 155, 2, 808,
+ /* 30 */ 971, 971, 98, 98, 98, 98, 20, 96, 96, 96,
+ /* 40 */ 96, 95, 95, 94, 94, 94, 93, 350, 92, 89,
+ /* 50 */ 178, 99, 100, 90, 847, 850, 839, 839, 97, 97,
+ /* 60 */ 98, 98, 98, 98, 350, 96, 96, 96, 96, 95,
+ /* 70 */ 95, 94, 94, 94, 93, 350, 324, 339, 969, 262,
+ /* 80 */ 364, 251, 212, 169, 287, 404, 282, 403, 199, 786,
+ /* 90 */ 242, 411, 21, 950, 378, 280, 93, 350, 787, 95,
+ /* 100 */ 95, 94, 94, 94, 93, 350, 971, 971, 96, 96,
+ /* 110 */ 96, 96, 95, 95, 94, 94, 94, 93, 350, 808,
+ /* 120 */ 328, 242, 411, 1235, 826, 1235, 132, 99, 100, 90,
+ /* 130 */ 847, 850, 839, 839, 97, 97, 98, 98, 98, 98,
+ /* 140 */ 449, 96, 96, 96, 96, 95, 95, 94, 94, 94,
+ /* 150 */ 93, 350, 324, 819, 348, 347, 120, 818, 120, 75,
+ /* 160 */ 52, 52, 950, 951, 952, 1084, 977, 146, 360, 262,
+ /* 170 */ 369, 261, 950, 975, 954, 976, 92, 89, 178, 370,
+ /* 180 */ 230, 370, 971, 971, 1141, 360, 359, 101, 818, 818,
+ /* 190 */ 820, 383, 24, 1286, 380, 427, 412, 368, 978, 379,
+ /* 200 */ 978, 1032, 324, 99, 100, 90, 847, 850, 839, 839,
+ /* 210 */ 97, 97, 98, 98, 98, 98, 372, 96, 96, 96,
+ /* 220 */ 96, 95, 95, 94, 94, 94, 93, 350, 950, 132,
+ /* 230 */ 890, 449, 971, 971, 890, 60, 94, 94, 94, 93,
+ /* 240 */ 350, 950, 951, 952, 954, 103, 360, 950, 384, 333,
+ /* 250 */ 697, 52, 52, 99, 100, 90, 847, 850, 839, 839,
+ /* 260 */ 97, 97, 98, 98, 98, 98, 1022, 96, 96, 96,
+ /* 270 */ 96, 95, 95, 94, 94, 94, 93, 350, 324, 454,
+ /* 280 */ 995, 449, 227, 61, 157, 243, 343, 114, 1025, 1211,
+ /* 290 */ 147, 826, 950, 372, 1071, 950, 319, 950, 951, 952,
+ /* 300 */ 194, 10, 10, 401, 398, 397, 1211, 1213, 971, 971,
+ /* 310 */ 757, 171, 170, 157, 396, 336, 950, 951, 952, 697,
+ /* 320 */ 819, 310, 153, 950, 818, 320, 82, 23, 80, 99,
+ /* 330 */ 100, 90, 847, 850, 839, 839, 97, 97, 98, 98,
+ /* 340 */ 98, 98, 888, 96, 96, 96, 96, 95, 95, 94,
+ /* 350 */ 94, 94, 93, 350, 324, 818, 818, 820, 277, 231,
+ /* 360 */ 300, 950, 951, 952, 950, 951, 952, 1211, 194, 25,
+ /* 370 */ 449, 401, 398, 397, 950, 354, 300, 449, 950, 74,
+ /* 380 */ 449, 1, 396, 132, 971, 971, 950, 224, 224, 808,
+ /* 390 */ 10, 10, 950, 951, 952, 1290, 132, 52, 52, 414,
+ /* 400 */ 52, 52, 1063, 1063, 338, 99, 100, 90, 847, 850,
+ /* 410 */ 839, 839, 97, 97, 98, 98, 98, 98, 1114, 96,
+ /* 420 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 350,
+ /* 430 */ 324, 1113, 427, 417, 701, 427, 426, 1260, 1260, 262,
+ /* 440 */ 369, 261, 950, 950, 951, 952, 752, 950, 951, 952,
+ /* 450 */ 449, 751, 449, 1058, 1037, 950, 951, 952, 442, 706,
+ /* 460 */ 971, 971, 1058, 393, 92, 89, 178, 446, 446, 446,
+ /* 470 */ 51, 51, 52, 52, 438, 773, 1024, 92, 89, 178,
+ /* 480 */ 172, 99, 100, 90, 847, 850, 839, 839, 97, 97,
+ /* 490 */ 98, 98, 98, 98, 198, 96, 96, 96, 96, 95,
+ /* 500 */ 95, 94, 94, 94, 93, 350, 324, 427, 407, 909,
+ /* 510 */ 694, 950, 951, 952, 92, 89, 178, 224, 224, 157,
+ /* 520 */ 241, 221, 418, 299, 771, 910, 415, 374, 449, 414,
+ /* 530 */ 58, 323, 1061, 1061, 1242, 378, 971, 971, 378, 772,
+ /* 540 */ 448, 911, 362, 735, 296, 681, 9, 9, 52, 52,
+ /* 550 */ 234, 329, 234, 256, 416, 736, 280, 99, 100, 90,
+ /* 560 */ 847, 850, 839, 839, 97, 97, 98, 98, 98, 98,
+ /* 570 */ 449, 96, 96, 96, 96, 95, 95, 94, 94, 94,
+ /* 580 */ 93, 350, 324, 422, 72, 449, 827, 120, 367, 449,
+ /* 590 */ 10, 10, 5, 301, 203, 449, 177, 969, 253, 419,
+ /* 600 */ 255, 771, 200, 175, 233, 10, 10, 836, 836, 36,
+ /* 610 */ 36, 1289, 971, 971, 724, 37, 37, 348, 347, 424,
+ /* 620 */ 203, 260, 771, 969, 232, 930, 1316, 870, 337, 1316,
+ /* 630 */ 421, 848, 851, 99, 100, 90, 847, 850, 839, 839,
+ /* 640 */ 97, 97, 98, 98, 98, 98, 268, 96, 96, 96,
+ /* 650 */ 96, 95, 95, 94, 94, 94, 93, 350, 324, 840,
+ /* 660 */ 449, 978, 813, 978, 1200, 449, 909, 969, 715, 349,
+ /* 670 */ 349, 349, 928, 177, 449, 930, 1317, 254, 198, 1317,
+ /* 680 */ 12, 12, 910, 402, 449, 27, 27, 250, 971, 971,
+ /* 690 */ 118, 716, 162, 969, 38, 38, 268, 176, 911, 771,
+ /* 700 */ 432, 1265, 939, 353, 39, 39, 316, 991, 324, 99,
+ /* 710 */ 100, 90, 847, 850, 839, 839, 97, 97, 98, 98,
+ /* 720 */ 98, 98, 928, 96, 96, 96, 96, 95, 95, 94,
+ /* 730 */ 94, 94, 93, 350, 449, 329, 449, 357, 971, 971,
+ /* 740 */ 1041, 316, 929, 340, 893, 893, 386, 669, 670, 671,
+ /* 750 */ 275, 1318, 317, 992, 40, 40, 41, 41, 268, 99,
+ /* 760 */ 100, 90, 847, 850, 839, 839, 97, 97, 98, 98,
+ /* 770 */ 98, 98, 449, 96, 96, 96, 96, 95, 95, 94,
+ /* 780 */ 94, 94, 93, 350, 324, 449, 355, 449, 992, 449,
+ /* 790 */ 1016, 330, 42, 42, 786, 270, 449, 273, 449, 228,
+ /* 800 */ 449, 298, 449, 787, 449, 28, 28, 29, 29, 31,
+ /* 810 */ 31, 449, 1141, 449, 971, 971, 43, 43, 44, 44,
+ /* 820 */ 45, 45, 11, 11, 46, 46, 887, 78, 887, 268,
+ /* 830 */ 268, 105, 105, 47, 47, 99, 100, 90, 847, 850,
+ /* 840 */ 839, 839, 97, 97, 98, 98, 98, 98, 449, 96,
+ /* 850 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 350,
+ /* 860 */ 324, 449, 117, 449, 1073, 158, 449, 691, 48, 48,
+ /* 870 */ 229, 1241, 449, 1250, 449, 414, 449, 334, 449, 245,
+ /* 880 */ 449, 33, 33, 49, 49, 449, 50, 50, 246, 1141,
+ /* 890 */ 971, 971, 34, 34, 122, 122, 123, 123, 124, 124,
+ /* 900 */ 56, 56, 268, 81, 249, 35, 35, 197, 196, 195,
+ /* 910 */ 324, 99, 100, 90, 847, 850, 839, 839, 97, 97,
+ /* 920 */ 98, 98, 98, 98, 449, 96, 96, 96, 96, 95,
+ /* 930 */ 95, 94, 94, 94, 93, 350, 449, 691, 449, 1141,
+ /* 940 */ 971, 971, 968, 1207, 106, 106, 268, 1209, 268, 1266,
+ /* 950 */ 2, 886, 268, 886, 335, 1040, 53, 53, 107, 107,
+ /* 960 */ 324, 99, 100, 90, 847, 850, 839, 839, 97, 97,
+ /* 970 */ 98, 98, 98, 98, 449, 96, 96, 96, 96, 95,
+ /* 980 */ 95, 94, 94, 94, 93, 350, 449, 1070, 449, 1066,
+ /* 990 */ 971, 971, 1039, 267, 108, 108, 445, 330, 331, 133,
+ /* 1000 */ 223, 175, 301, 225, 385, 1255, 104, 104, 121, 121,
+ /* 1010 */ 324, 99, 88, 90, 847, 850, 839, 839, 97, 97,
+ /* 1020 */ 98, 98, 98, 98, 1141, 96, 96, 96, 96, 95,
+ /* 1030 */ 95, 94, 94, 94, 93, 350, 449, 346, 449, 167,
+ /* 1040 */ 971, 971, 925, 810, 371, 318, 202, 202, 373, 263,
+ /* 1050 */ 394, 202, 74, 208, 721, 722, 119, 119, 112, 112,
+ /* 1060 */ 324, 406, 100, 90, 847, 850, 839, 839, 97, 97,
+ /* 1070 */ 98, 98, 98, 98, 449, 96, 96, 96, 96, 95,
+ /* 1080 */ 95, 94, 94, 94, 93, 350, 449, 752, 449, 344,
+ /* 1090 */ 971, 971, 751, 278, 111, 111, 74, 714, 713, 704,
+ /* 1100 */ 286, 877, 749, 1279, 257, 77, 109, 109, 110, 110,
+ /* 1110 */ 1230, 285, 1134, 90, 847, 850, 839, 839, 97, 97,
+ /* 1120 */ 98, 98, 98, 98, 1233, 96, 96, 96, 96, 95,
+ /* 1130 */ 95, 94, 94, 94, 93, 350, 86, 444, 449, 3,
+ /* 1140 */ 1193, 449, 1069, 132, 351, 120, 1013, 86, 444, 780,
+ /* 1150 */ 3, 1091, 202, 376, 447, 351, 1229, 120, 55, 55,
+ /* 1160 */ 449, 57, 57, 822, 873, 447, 449, 208, 449, 704,
+ /* 1170 */ 449, 877, 237, 433, 435, 120, 439, 428, 361, 120,
+ /* 1180 */ 54, 54, 132, 449, 433, 826, 52, 52, 26, 26,
+ /* 1190 */ 30, 30, 381, 132, 408, 443, 826, 689, 264, 389,
+ /* 1200 */ 116, 269, 272, 32, 32, 83, 84, 120, 274, 120,
+ /* 1210 */ 120, 276, 85, 351, 451, 450, 83, 84, 818, 1054,
+ /* 1220 */ 1038, 427, 429, 85, 351, 451, 450, 120, 120, 818,
+ /* 1230 */ 377, 218, 281, 822, 1107, 1140, 86, 444, 409, 3,
+ /* 1240 */ 1087, 1098, 430, 431, 351, 302, 303, 1146, 1021, 818,
+ /* 1250 */ 818, 820, 821, 19, 447, 1015, 1004, 1003, 1005, 1273,
+ /* 1260 */ 818, 818, 820, 821, 19, 289, 159, 291, 293, 7,
+ /* 1270 */ 315, 173, 259, 433, 1129, 363, 252, 1232, 375, 1037,
+ /* 1280 */ 295, 434, 168, 986, 399, 826, 284, 1204, 1203, 205,
+ /* 1290 */ 1276, 308, 1249, 86, 444, 983, 3, 1247, 332, 144,
+ /* 1300 */ 130, 351, 72, 135, 59, 83, 84, 756, 137, 365,
+ /* 1310 */ 1126, 447, 85, 351, 451, 450, 139, 226, 818, 140,
+ /* 1320 */ 156, 62, 314, 314, 313, 215, 311, 366, 392, 678,
+ /* 1330 */ 433, 185, 141, 1234, 142, 160, 148, 1136, 1198, 382,
+ /* 1340 */ 189, 67, 826, 180, 388, 248, 1218, 1099, 219, 818,
+ /* 1350 */ 818, 820, 821, 19, 247, 190, 266, 154, 390, 271,
+ /* 1360 */ 191, 192, 83, 84, 1006, 405, 1057, 182, 321, 85,
+ /* 1370 */ 351, 451, 450, 1056, 183, 818, 341, 132, 181, 706,
+ /* 1380 */ 1055, 420, 76, 444, 1029, 3, 322, 1028, 283, 1048,
+ /* 1390 */ 351, 1095, 1027, 1288, 1047, 71, 204, 6, 288, 290,
+ /* 1400 */ 447, 1096, 1094, 1093, 79, 292, 818, 818, 820, 821,
+ /* 1410 */ 19, 294, 297, 437, 345, 441, 102, 1184, 1077, 433,
+ /* 1420 */ 238, 425, 73, 305, 239, 304, 325, 240, 423, 306,
+ /* 1430 */ 307, 826, 213, 1012, 22, 945, 452, 214, 216, 217,
+ /* 1440 */ 453, 1001, 115, 996, 125, 126, 235, 127, 665, 352,
+ /* 1450 */ 326, 83, 84, 358, 166, 244, 179, 327, 85, 351,
+ /* 1460 */ 451, 450, 134, 356, 818, 113, 885, 806, 883, 136,
+ /* 1470 */ 128, 138, 738, 258, 184, 899, 143, 145, 63, 64,
+ /* 1480 */ 65, 66, 129, 902, 187, 186, 898, 8, 13, 188,
+ /* 1490 */ 265, 891, 149, 202, 980, 818, 818, 820, 821, 19,
+ /* 1500 */ 150, 387, 161, 680, 285, 391, 151, 395, 400, 193,
+ /* 1510 */ 68, 14, 236, 279, 15, 69, 717, 825, 131, 824,
+ /* 1520 */ 853, 70, 746, 16, 413, 750, 4, 174, 220, 222,
+ /* 1530 */ 152, 779, 857, 774, 201, 77, 74, 868, 17, 854,
+ /* 1540 */ 852, 908, 18, 907, 207, 206, 934, 163, 436, 210,
+ /* 1550 */ 935, 164, 209, 165, 440, 856, 823, 690, 87, 211,
+ /* 1560 */ 309, 312, 1281, 940, 1280,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 19, 95, 53, 97, 22, 24, 24, 101, 27, 28,
- /* 10 */ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
- /* 20 */ 39, 40, 41, 152, 43, 44, 45, 46, 47, 48,
- /* 30 */ 49, 50, 51, 52, 53, 19, 55, 55, 132, 133,
- /* 40 */ 134, 1, 2, 27, 28, 29, 30, 31, 32, 33,
- /* 50 */ 34, 35, 36, 37, 38, 39, 40, 41, 187, 43,
- /* 60 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- /* 70 */ 47, 48, 49, 50, 51, 52, 53, 61, 97, 97,
- /* 80 */ 19, 49, 50, 51, 52, 53, 70, 26, 27, 28,
- /* 90 */ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
- /* 100 */ 39, 40, 41, 152, 43, 44, 45, 46, 47, 48,
- /* 110 */ 49, 50, 51, 52, 53, 144, 145, 146, 147, 19,
- /* 120 */ 16, 22, 92, 172, 173, 52, 53, 27, 28, 29,
- /* 130 */ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
- /* 140 */ 40, 41, 81, 43, 44, 45, 46, 47, 48, 49,
- /* 150 */ 50, 51, 52, 53, 55, 56, 19, 152, 207, 208,
- /* 160 */ 115, 24, 117, 118, 27, 28, 29, 30, 31, 32,
- /* 170 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 79,
- /* 180 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 190 */ 53, 19, 88, 157, 90, 23, 97, 98, 193, 27,
- /* 200 */ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- /* 210 */ 38, 39, 40, 41, 152, 43, 44, 45, 46, 47,
- /* 220 */ 48, 49, 50, 51, 52, 53, 19, 22, 23, 172,
- /* 230 */ 23, 26, 119, 120, 27, 28, 29, 30, 31, 32,
- /* 240 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 187,
- /* 250 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 260 */ 53, 19, 22, 23, 228, 23, 26, 231, 152, 27,
- /* 270 */ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- /* 280 */ 38, 39, 40, 41, 172, 43, 44, 45, 46, 47,
- /* 290 */ 48, 49, 50, 51, 52, 53, 19, 221, 222, 223,
- /* 300 */ 23, 96, 152, 172, 27, 28, 29, 30, 31, 32,
- /* 310 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 152,
- /* 320 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 330 */ 53, 19, 0, 1, 2, 23, 96, 190, 191, 27,
- /* 340 */ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- /* 350 */ 38, 39, 40, 41, 238, 43, 44, 45, 46, 47,
- /* 360 */ 48, 49, 50, 51, 52, 53, 19, 185, 218, 221,
- /* 370 */ 222, 223, 152, 152, 27, 28, 29, 30, 31, 32,
- /* 380 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 241,
- /* 390 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 400 */ 53, 19, 152, 168, 169, 170, 22, 190, 191, 27,
- /* 410 */ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- /* 420 */ 38, 39, 40, 41, 152, 43, 44, 45, 46, 47,
- /* 430 */ 48, 49, 50, 51, 52, 53, 19, 19, 218, 55,
- /* 440 */ 56, 24, 22, 152, 27, 28, 29, 30, 31, 32,
- /* 450 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 152,
- /* 460 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 470 */ 53, 250, 194, 195, 56, 55, 56, 55, 19, 172,
- /* 480 */ 173, 97, 98, 152, 206, 138, 27, 28, 29, 30,
- /* 490 */ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- /* 500 */ 41, 152, 43, 44, 45, 46, 47, 48, 49, 50,
- /* 510 */ 51, 52, 53, 19, 207, 208, 152, 97, 98, 97,
- /* 520 */ 138, 27, 28, 29, 30, 31, 32, 33, 34, 35,
- /* 530 */ 36, 37, 38, 39, 40, 41, 181, 43, 44, 45,
- /* 540 */ 46, 47, 48, 49, 50, 51, 52, 53, 19, 30,
- /* 550 */ 31, 32, 33, 247, 248, 19, 152, 28, 29, 30,
- /* 560 */ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- /* 570 */ 41, 152, 43, 44, 45, 46, 47, 48, 49, 50,
- /* 580 */ 51, 52, 53, 19, 168, 169, 170, 238, 19, 53,
- /* 590 */ 152, 172, 173, 29, 30, 31, 32, 33, 34, 35,
- /* 600 */ 36, 37, 38, 39, 40, 41, 152, 43, 44, 45,
- /* 610 */ 46, 47, 48, 49, 50, 51, 52, 53, 19, 20,
- /* 620 */ 101, 22, 23, 169, 170, 56, 207, 85, 55, 56,
- /* 630 */ 23, 19, 20, 26, 22, 99, 100, 101, 102, 103,
- /* 640 */ 104, 105, 238, 152, 152, 210, 47, 48, 112, 152,
- /* 650 */ 108, 109, 110, 54, 55, 56, 221, 222, 223, 47,
- /* 660 */ 48, 119, 120, 172, 173, 66, 54, 55, 56, 152,
- /* 670 */ 97, 98, 99, 148, 149, 102, 103, 104, 66, 154,
- /* 680 */ 23, 156, 83, 26, 230, 152, 113, 152, 163, 194,
- /* 690 */ 195, 92, 92, 30, 95, 83, 97, 98, 207, 208,
- /* 700 */ 101, 206, 179, 180, 92, 172, 173, 95, 152, 97,
- /* 710 */ 98, 188, 99, 101, 219, 102, 103, 104, 152, 119,
- /* 720 */ 120, 196, 55, 56, 19, 20, 113, 22, 193, 163,
- /* 730 */ 11, 132, 133, 134, 135, 136, 24, 65, 172, 173,
- /* 740 */ 207, 208, 250, 152, 132, 133, 134, 135, 136, 193,
- /* 750 */ 78, 84, 47, 48, 49, 98, 199, 152, 86, 54,
- /* 760 */ 55, 56, 196, 152, 97, 98, 209, 55, 163, 244,
- /* 770 */ 107, 66, 152, 207, 208, 164, 175, 172, 173, 19,
- /* 780 */ 20, 124, 22, 111, 38, 39, 40, 41, 83, 43,
- /* 790 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- /* 800 */ 95, 196, 97, 98, 85, 152, 101, 47, 48, 97,
- /* 810 */ 85, 92, 207, 193, 54, 55, 56, 92, 49, 175,
- /* 820 */ 55, 56, 221, 222, 223, 12, 66, 108, 109, 110,
- /* 830 */ 137, 163, 139, 108, 109, 110, 26, 132, 133, 134,
- /* 840 */ 135, 136, 152, 83, 43, 44, 45, 46, 47, 48,
- /* 850 */ 49, 50, 51, 52, 53, 95, 26, 97, 98, 55,
- /* 860 */ 56, 101, 97, 98, 196, 221, 222, 223, 146, 147,
- /* 870 */ 57, 171, 152, 22, 26, 19, 20, 49, 22, 179,
- /* 880 */ 108, 109, 110, 55, 56, 116, 73, 219, 75, 124,
- /* 890 */ 121, 152, 132, 133, 134, 135, 136, 163, 85, 152,
- /* 900 */ 232, 97, 98, 47, 48, 237, 55, 56, 98, 5,
- /* 910 */ 54, 55, 56, 193, 10, 11, 12, 13, 14, 172,
- /* 920 */ 173, 17, 66, 47, 48, 97, 98, 152, 124, 152,
- /* 930 */ 196, 55, 56, 186, 124, 152, 106, 160, 152, 83,
- /* 940 */ 152, 164, 152, 61, 22, 211, 212, 152, 97, 98,
- /* 950 */ 152, 95, 70, 97, 98, 172, 173, 101, 172, 173,
- /* 960 */ 172, 173, 172, 173, 60, 181, 62, 172, 173, 47,
- /* 970 */ 48, 123, 186, 97, 98, 71, 100, 55, 56, 152,
- /* 980 */ 181, 186, 21, 107, 152, 109, 82, 163, 132, 133,
- /* 990 */ 134, 135, 136, 89, 16, 207, 92, 93, 19, 172,
- /* 1000 */ 173, 169, 170, 195, 55, 56, 12, 152, 132, 30,
- /* 1010 */ 134, 47, 48, 186, 206, 225, 152, 95, 114, 97,
- /* 1020 */ 196, 245, 246, 101, 152, 38, 39, 40, 41, 42,
- /* 1030 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 1040 */ 53, 152, 163, 219, 152, 141, 97, 98, 193, 152,
- /* 1050 */ 152, 57, 91, 164, 132, 133, 134, 152, 55, 152,
- /* 1060 */ 152, 237, 230, 152, 103, 193, 88, 73, 90, 75,
- /* 1070 */ 172, 173, 183, 152, 185, 196, 152, 172, 173, 172,
- /* 1080 */ 173, 217, 152, 172, 173, 152, 107, 22, 152, 24,
- /* 1090 */ 193, 112, 152, 172, 173, 152, 132, 242, 134, 152,
- /* 1100 */ 97, 140, 152, 92, 152, 172, 173, 152, 172, 173,
- /* 1110 */ 152, 100, 172, 173, 152, 172, 173, 152, 140, 172,
- /* 1120 */ 173, 152, 172, 173, 172, 173, 152, 172, 173, 152,
- /* 1130 */ 172, 173, 152, 152, 172, 173, 152, 172, 173, 213,
- /* 1140 */ 152, 172, 173, 152, 152, 152, 172, 173, 152, 172,
- /* 1150 */ 173, 152, 172, 173, 152, 210, 172, 173, 152, 26,
- /* 1160 */ 172, 173, 152, 172, 173, 172, 173, 152, 172, 173,
- /* 1170 */ 152, 172, 173, 152, 172, 173, 152, 59, 172, 173,
- /* 1180 */ 152, 63, 172, 173, 152, 193, 152, 152, 152, 152,
- /* 1190 */ 172, 173, 152, 172, 173, 77, 172, 173, 152, 152,
- /* 1200 */ 172, 173, 152, 152, 172, 173, 172, 173, 172, 173,
- /* 1210 */ 152, 22, 172, 173, 152, 152, 152, 22, 172, 173,
- /* 1220 */ 152, 152, 152, 172, 173, 152, 7, 8, 9, 163,
- /* 1230 */ 172, 173, 22, 23, 172, 173, 172, 173, 166, 167,
- /* 1240 */ 172, 173, 172, 173, 55, 172, 173, 22, 23, 108,
- /* 1250 */ 109, 110, 217, 152, 217, 166, 167, 163, 163, 163,
- /* 1260 */ 163, 163, 196, 130, 217, 211, 212, 217, 116, 23,
- /* 1270 */ 22, 101, 26, 121, 23, 23, 23, 26, 26, 26,
- /* 1280 */ 23, 23, 112, 26, 26, 37, 97, 100, 101, 55,
- /* 1290 */ 196, 196, 196, 196, 196, 23, 23, 55, 26, 26,
- /* 1300 */ 7, 8, 23, 152, 23, 26, 96, 26, 132, 132,
- /* 1310 */ 134, 134, 23, 152, 152, 26, 152, 122, 152, 191,
- /* 1320 */ 152, 96, 234, 152, 152, 152, 152, 152, 197, 210,
- /* 1330 */ 152, 97, 152, 152, 210, 233, 210, 198, 150, 97,
- /* 1340 */ 184, 201, 239, 214, 214, 201, 239, 180, 214, 227,
- /* 1350 */ 200, 198, 155, 67, 243, 176, 69, 175, 175, 175,
- /* 1360 */ 122, 159, 159, 240, 159, 240, 22, 220, 27, 130,
- /* 1370 */ 201, 18, 159, 18, 189, 158, 158, 220, 192, 159,
- /* 1380 */ 137, 236, 192, 192, 192, 189, 74, 189, 159, 235,
- /* 1390 */ 159, 158, 22, 177, 201, 201, 159, 107, 158, 177,
- /* 1400 */ 159, 174, 158, 76, 174, 182, 174, 106, 182, 125,
- /* 1410 */ 174, 107, 177, 22, 159, 216, 215, 137, 159, 53,
- /* 1420 */ 216, 176, 215, 174, 174, 216, 215, 215, 174, 229,
- /* 1430 */ 216, 129, 224, 177, 126, 229, 127, 177, 128, 25,
- /* 1440 */ 162, 226, 26, 161, 13, 153, 6, 153, 151, 151,
- /* 1450 */ 151, 151, 205, 165, 178, 178, 165, 4, 3, 22,
- /* 1460 */ 165, 142, 15, 94, 202, 204, 203, 201, 16, 23,
- /* 1470 */ 249, 23, 120, 249, 246, 111, 131, 123, 20, 16,
- /* 1480 */ 1, 125, 123, 111, 56, 64, 37, 37, 131, 122,
- /* 1490 */ 1, 37, 5, 37, 22, 107, 26, 80, 140, 80,
- /* 1500 */ 87, 72, 107, 20, 24, 19, 112, 105, 23, 79,
- /* 1510 */ 22, 79, 22, 22, 22, 58, 22, 79, 23, 68,
- /* 1520 */ 23, 23, 26, 116, 22, 26, 23, 22, 122, 23,
- /* 1530 */ 23, 56, 64, 22, 124, 26, 26, 64, 64, 23,
- /* 1540 */ 23, 23, 23, 11, 23, 22, 26, 23, 22, 24,
- /* 1550 */ 1, 23, 22, 26, 251, 24, 23, 22, 122, 23,
- /* 1560 */ 23, 22, 15, 122, 122, 122, 23,
+ /* 0 */ 19, 115, 19, 117, 118, 24, 1, 2, 27, 79,
+ /* 10 */ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ /* 20 */ 90, 91, 92, 93, 94, 144, 145, 146, 147, 58,
+ /* 30 */ 49, 50, 79, 80, 81, 82, 22, 84, 85, 86,
+ /* 40 */ 87, 88, 89, 90, 91, 92, 93, 94, 221, 222,
+ /* 50 */ 223, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 60 */ 79, 80, 81, 82, 94, 84, 85, 86, 87, 88,
+ /* 70 */ 89, 90, 91, 92, 93, 94, 19, 94, 97, 108,
+ /* 80 */ 109, 110, 99, 100, 101, 102, 103, 104, 105, 32,
+ /* 90 */ 119, 120, 78, 27, 152, 112, 93, 94, 41, 88,
+ /* 100 */ 89, 90, 91, 92, 93, 94, 49, 50, 84, 85,
+ /* 110 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 58,
+ /* 120 */ 157, 119, 120, 163, 68, 163, 65, 70, 71, 72,
+ /* 130 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ /* 140 */ 152, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ /* 150 */ 93, 94, 19, 97, 88, 89, 196, 101, 196, 26,
+ /* 160 */ 172, 173, 96, 97, 98, 210, 100, 22, 152, 108,
+ /* 170 */ 109, 110, 27, 107, 27, 109, 221, 222, 223, 219,
+ /* 180 */ 238, 219, 49, 50, 152, 169, 170, 54, 132, 133,
+ /* 190 */ 134, 228, 232, 171, 231, 207, 208, 237, 132, 237,
+ /* 200 */ 134, 179, 19, 70, 71, 72, 73, 74, 75, 76,
+ /* 210 */ 77, 78, 79, 80, 81, 82, 152, 84, 85, 86,
+ /* 220 */ 87, 88, 89, 90, 91, 92, 93, 94, 27, 65,
+ /* 230 */ 30, 152, 49, 50, 34, 52, 90, 91, 92, 93,
+ /* 240 */ 94, 96, 97, 98, 97, 22, 230, 27, 48, 217,
+ /* 250 */ 27, 172, 173, 70, 71, 72, 73, 74, 75, 76,
+ /* 260 */ 77, 78, 79, 80, 81, 82, 172, 84, 85, 86,
+ /* 270 */ 87, 88, 89, 90, 91, 92, 93, 94, 19, 148,
+ /* 280 */ 149, 152, 218, 24, 152, 154, 207, 156, 172, 152,
+ /* 290 */ 22, 68, 27, 152, 163, 27, 164, 96, 97, 98,
+ /* 300 */ 99, 172, 173, 102, 103, 104, 169, 170, 49, 50,
+ /* 310 */ 90, 88, 89, 152, 113, 186, 96, 97, 98, 96,
+ /* 320 */ 97, 160, 57, 27, 101, 164, 137, 196, 139, 70,
+ /* 330 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ /* 340 */ 81, 82, 11, 84, 85, 86, 87, 88, 89, 90,
+ /* 350 */ 91, 92, 93, 94, 19, 132, 133, 134, 23, 218,
+ /* 360 */ 152, 96, 97, 98, 96, 97, 98, 230, 99, 22,
+ /* 370 */ 152, 102, 103, 104, 27, 244, 152, 152, 27, 26,
+ /* 380 */ 152, 22, 113, 65, 49, 50, 27, 194, 195, 58,
+ /* 390 */ 172, 173, 96, 97, 98, 185, 65, 172, 173, 206,
+ /* 400 */ 172, 173, 190, 191, 186, 70, 71, 72, 73, 74,
+ /* 410 */ 75, 76, 77, 78, 79, 80, 81, 82, 175, 84,
+ /* 420 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ /* 430 */ 19, 175, 207, 208, 23, 207, 208, 119, 120, 108,
+ /* 440 */ 109, 110, 27, 96, 97, 98, 116, 96, 97, 98,
+ /* 450 */ 152, 121, 152, 179, 180, 96, 97, 98, 250, 106,
+ /* 460 */ 49, 50, 188, 19, 221, 222, 223, 168, 169, 170,
+ /* 470 */ 172, 173, 172, 173, 250, 124, 172, 221, 222, 223,
+ /* 480 */ 26, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 490 */ 79, 80, 81, 82, 50, 84, 85, 86, 87, 88,
+ /* 500 */ 89, 90, 91, 92, 93, 94, 19, 207, 208, 12,
+ /* 510 */ 23, 96, 97, 98, 221, 222, 223, 194, 195, 152,
+ /* 520 */ 199, 23, 19, 225, 26, 28, 152, 152, 152, 206,
+ /* 530 */ 209, 164, 190, 191, 241, 152, 49, 50, 152, 124,
+ /* 540 */ 152, 44, 219, 46, 152, 21, 172, 173, 172, 173,
+ /* 550 */ 183, 107, 185, 16, 163, 58, 112, 70, 71, 72,
+ /* 560 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ /* 570 */ 152, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ /* 580 */ 93, 94, 19, 207, 130, 152, 23, 196, 64, 152,
+ /* 590 */ 172, 173, 22, 152, 24, 152, 98, 27, 61, 96,
+ /* 600 */ 63, 26, 211, 212, 186, 172, 173, 49, 50, 172,
+ /* 610 */ 173, 23, 49, 50, 26, 172, 173, 88, 89, 186,
+ /* 620 */ 24, 238, 124, 27, 238, 22, 23, 103, 187, 26,
+ /* 630 */ 152, 73, 74, 70, 71, 72, 73, 74, 75, 76,
+ /* 640 */ 77, 78, 79, 80, 81, 82, 152, 84, 85, 86,
+ /* 650 */ 87, 88, 89, 90, 91, 92, 93, 94, 19, 101,
+ /* 660 */ 152, 132, 23, 134, 140, 152, 12, 97, 36, 168,
+ /* 670 */ 169, 170, 69, 98, 152, 22, 23, 140, 50, 26,
+ /* 680 */ 172, 173, 28, 51, 152, 172, 173, 193, 49, 50,
+ /* 690 */ 22, 59, 24, 97, 172, 173, 152, 152, 44, 124,
+ /* 700 */ 46, 0, 1, 2, 172, 173, 22, 23, 19, 70,
+ /* 710 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ /* 720 */ 81, 82, 69, 84, 85, 86, 87, 88, 89, 90,
+ /* 730 */ 91, 92, 93, 94, 152, 107, 152, 193, 49, 50,
+ /* 740 */ 181, 22, 23, 111, 108, 109, 110, 7, 8, 9,
+ /* 750 */ 16, 247, 248, 69, 172, 173, 172, 173, 152, 70,
+ /* 760 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ /* 770 */ 81, 82, 152, 84, 85, 86, 87, 88, 89, 90,
+ /* 780 */ 91, 92, 93, 94, 19, 152, 242, 152, 69, 152,
+ /* 790 */ 166, 167, 172, 173, 32, 61, 152, 63, 152, 193,
+ /* 800 */ 152, 152, 152, 41, 152, 172, 173, 172, 173, 172,
+ /* 810 */ 173, 152, 152, 152, 49, 50, 172, 173, 172, 173,
+ /* 820 */ 172, 173, 172, 173, 172, 173, 132, 138, 134, 152,
+ /* 830 */ 152, 172, 173, 172, 173, 70, 71, 72, 73, 74,
+ /* 840 */ 75, 76, 77, 78, 79, 80, 81, 82, 152, 84,
+ /* 850 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ /* 860 */ 19, 152, 22, 152, 195, 24, 152, 27, 172, 173,
+ /* 870 */ 193, 193, 152, 152, 152, 206, 152, 217, 152, 152,
+ /* 880 */ 152, 172, 173, 172, 173, 152, 172, 173, 152, 152,
+ /* 890 */ 49, 50, 172, 173, 172, 173, 172, 173, 172, 173,
+ /* 900 */ 172, 173, 152, 138, 152, 172, 173, 108, 109, 110,
+ /* 910 */ 19, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 920 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88,
+ /* 930 */ 89, 90, 91, 92, 93, 94, 152, 97, 152, 152,
+ /* 940 */ 49, 50, 26, 193, 172, 173, 152, 152, 152, 146,
+ /* 950 */ 147, 132, 152, 134, 217, 181, 172, 173, 172, 173,
+ /* 960 */ 19, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 970 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88,
+ /* 980 */ 89, 90, 91, 92, 93, 94, 152, 193, 152, 193,
+ /* 990 */ 49, 50, 181, 193, 172, 173, 166, 167, 245, 246,
+ /* 1000 */ 211, 212, 152, 22, 217, 152, 172, 173, 172, 173,
+ /* 1010 */ 19, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 1020 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88,
+ /* 1030 */ 89, 90, 91, 92, 93, 94, 152, 187, 152, 123,
+ /* 1040 */ 49, 50, 23, 23, 23, 26, 26, 26, 23, 23,
+ /* 1050 */ 23, 26, 26, 26, 7, 8, 172, 173, 172, 173,
+ /* 1060 */ 19, 90, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 1070 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88,
+ /* 1080 */ 89, 90, 91, 92, 93, 94, 152, 116, 152, 217,
+ /* 1090 */ 49, 50, 121, 23, 172, 173, 26, 100, 101, 27,
+ /* 1100 */ 101, 27, 23, 122, 152, 26, 172, 173, 172, 173,
+ /* 1110 */ 152, 112, 163, 72, 73, 74, 75, 76, 77, 78,
+ /* 1120 */ 79, 80, 81, 82, 163, 84, 85, 86, 87, 88,
+ /* 1130 */ 89, 90, 91, 92, 93, 94, 19, 20, 152, 22,
+ /* 1140 */ 23, 152, 163, 65, 27, 196, 163, 19, 20, 23,
+ /* 1150 */ 22, 213, 26, 19, 37, 27, 152, 196, 172, 173,
+ /* 1160 */ 152, 172, 173, 27, 23, 37, 152, 26, 152, 97,
+ /* 1170 */ 152, 97, 210, 56, 163, 196, 163, 163, 100, 196,
+ /* 1180 */ 172, 173, 65, 152, 56, 68, 172, 173, 172, 173,
+ /* 1190 */ 172, 173, 152, 65, 163, 163, 68, 23, 152, 234,
+ /* 1200 */ 26, 152, 152, 172, 173, 88, 89, 196, 152, 196,
+ /* 1210 */ 196, 152, 95, 96, 97, 98, 88, 89, 101, 152,
+ /* 1220 */ 152, 207, 208, 95, 96, 97, 98, 196, 196, 101,
+ /* 1230 */ 96, 233, 152, 97, 152, 152, 19, 20, 207, 22,
+ /* 1240 */ 152, 152, 152, 191, 27, 152, 152, 152, 152, 132,
+ /* 1250 */ 133, 134, 135, 136, 37, 152, 152, 152, 152, 152,
+ /* 1260 */ 132, 133, 134, 135, 136, 210, 197, 210, 210, 198,
+ /* 1270 */ 150, 184, 239, 56, 201, 214, 214, 201, 239, 180,
+ /* 1280 */ 214, 227, 198, 38, 176, 68, 175, 175, 175, 122,
+ /* 1290 */ 155, 200, 159, 19, 20, 40, 22, 159, 159, 22,
+ /* 1300 */ 70, 27, 130, 243, 240, 88, 89, 90, 189, 18,
+ /* 1310 */ 201, 37, 95, 96, 97, 98, 192, 5, 101, 192,
+ /* 1320 */ 220, 240, 10, 11, 12, 13, 14, 159, 18, 17,
+ /* 1330 */ 56, 158, 192, 201, 192, 220, 189, 189, 201, 159,
+ /* 1340 */ 158, 137, 68, 31, 45, 33, 236, 159, 159, 132,
+ /* 1350 */ 133, 134, 135, 136, 42, 158, 235, 22, 177, 159,
+ /* 1360 */ 158, 158, 88, 89, 159, 107, 174, 55, 177, 95,
+ /* 1370 */ 96, 97, 98, 174, 62, 101, 47, 65, 66, 106,
+ /* 1380 */ 174, 125, 19, 20, 174, 22, 177, 176, 174, 182,
+ /* 1390 */ 27, 216, 174, 174, 182, 107, 159, 22, 215, 215,
+ /* 1400 */ 37, 216, 216, 216, 137, 215, 132, 133, 134, 135,
+ /* 1410 */ 136, 215, 159, 177, 94, 177, 129, 224, 205, 56,
+ /* 1420 */ 226, 126, 128, 203, 229, 204, 114, 229, 127, 202,
+ /* 1430 */ 201, 68, 25, 162, 26, 13, 161, 153, 153, 6,
+ /* 1440 */ 151, 151, 178, 151, 165, 165, 178, 165, 4, 3,
+ /* 1450 */ 249, 88, 89, 141, 22, 142, 15, 249, 95, 96,
+ /* 1460 */ 97, 98, 246, 67, 101, 16, 23, 120, 23, 131,
+ /* 1470 */ 111, 123, 20, 16, 125, 1, 123, 131, 78, 78,
+ /* 1480 */ 78, 78, 111, 96, 122, 35, 1, 5, 22, 107,
+ /* 1490 */ 140, 53, 53, 26, 60, 132, 133, 134, 135, 136,
+ /* 1500 */ 107, 43, 24, 20, 112, 19, 22, 52, 52, 105,
+ /* 1510 */ 22, 22, 52, 23, 22, 22, 29, 23, 39, 23,
+ /* 1520 */ 23, 26, 116, 22, 26, 23, 22, 122, 23, 23,
+ /* 1530 */ 22, 96, 11, 124, 35, 26, 26, 23, 35, 23,
+ /* 1540 */ 23, 23, 35, 23, 22, 26, 23, 22, 24, 122,
+ /* 1550 */ 23, 22, 26, 22, 24, 23, 23, 23, 22, 122,
+ /* 1560 */ 23, 15, 122, 1, 122,
};
-#define YY_SHIFT_USE_DFLT (1567)
-#define YY_SHIFT_COUNT (455)
-#define YY_SHIFT_MIN (-94)
-#define YY_SHIFT_MAX (1549)
+#define YY_SHIFT_USE_DFLT (1565)
+#define YY_SHIFT_COUNT (454)
+#define YY_SHIFT_MIN (-114)
+#define YY_SHIFT_MAX (1562)
static const short yy_shift_ofst[] = {
- /* 0 */ 40, 599, 904, 612, 760, 760, 760, 760, 725, -19,
- /* 10 */ 16, 16, 100, 760, 760, 760, 760, 760, 760, 760,
- /* 20 */ 876, 876, 573, 542, 719, 600, 61, 137, 172, 207,
- /* 30 */ 242, 277, 312, 347, 382, 417, 459, 459, 459, 459,
- /* 40 */ 459, 459, 459, 459, 459, 459, 459, 459, 459, 459,
- /* 50 */ 459, 459, 459, 494, 459, 529, 564, 564, 705, 760,
- /* 60 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760,
- /* 70 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760,
- /* 80 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760,
- /* 90 */ 856, 760, 760, 760, 760, 760, 760, 760, 760, 760,
- /* 100 */ 760, 760, 760, 760, 987, 746, 746, 746, 746, 746,
- /* 110 */ 801, 23, 32, 949, 961, 979, 964, 964, 949, 73,
- /* 120 */ 113, -51, 1567, 1567, 1567, 536, 536, 536, 99, 99,
- /* 130 */ 813, 813, 667, 205, 240, 949, 949, 949, 949, 949,
- /* 140 */ 949, 949, 949, 949, 949, 949, 949, 949, 949, 949,
- /* 150 */ 949, 949, 949, 949, 949, 332, 1011, 422, 422, 113,
- /* 160 */ 30, 30, 30, 30, 30, 30, 1567, 1567, 1567, 922,
- /* 170 */ -94, -94, 384, 613, 828, 420, 765, 804, 851, 949,
- /* 180 */ 949, 949, 949, 949, 949, 949, 949, 949, 949, 949,
- /* 190 */ 949, 949, 949, 949, 949, 672, 672, 672, 949, 949,
- /* 200 */ 657, 949, 949, 949, -18, 949, 949, 994, 949, 949,
- /* 210 */ 949, 949, 949, 949, 949, 949, 949, 949, 772, 1118,
- /* 220 */ 712, 712, 712, 810, 45, 769, 1219, 1133, 418, 418,
- /* 230 */ 569, 1133, 569, 830, 607, 663, 882, 418, 693, 882,
- /* 240 */ 882, 848, 1152, 1065, 1286, 1238, 1238, 1287, 1287, 1238,
- /* 250 */ 1344, 1341, 1239, 1353, 1353, 1353, 1353, 1238, 1355, 1239,
- /* 260 */ 1344, 1341, 1341, 1239, 1238, 1355, 1243, 1312, 1238, 1238,
- /* 270 */ 1355, 1370, 1238, 1355, 1238, 1355, 1370, 1290, 1290, 1290,
- /* 280 */ 1327, 1370, 1290, 1301, 1290, 1327, 1290, 1290, 1284, 1304,
- /* 290 */ 1284, 1304, 1284, 1304, 1284, 1304, 1238, 1391, 1238, 1280,
- /* 300 */ 1370, 1366, 1366, 1370, 1302, 1308, 1310, 1309, 1239, 1414,
- /* 310 */ 1416, 1431, 1431, 1440, 1440, 1440, 1440, 1567, 1567, 1567,
- /* 320 */ 1567, 1567, 1567, 1567, 1567, 519, 978, 1210, 1225, 104,
- /* 330 */ 1141, 1189, 1246, 1248, 1251, 1252, 1253, 1257, 1258, 1273,
- /* 340 */ 1003, 1187, 1293, 1170, 1272, 1279, 1234, 1281, 1176, 1177,
- /* 350 */ 1289, 1242, 1195, 1453, 1455, 1437, 1319, 1447, 1369, 1452,
- /* 360 */ 1446, 1448, 1352, 1345, 1364, 1354, 1458, 1356, 1463, 1479,
- /* 370 */ 1359, 1357, 1449, 1450, 1454, 1456, 1372, 1428, 1421, 1367,
- /* 380 */ 1489, 1487, 1472, 1388, 1358, 1417, 1470, 1419, 1413, 1429,
- /* 390 */ 1395, 1480, 1483, 1486, 1394, 1402, 1488, 1430, 1490, 1491,
- /* 400 */ 1485, 1492, 1432, 1457, 1494, 1438, 1451, 1495, 1497, 1498,
- /* 410 */ 1496, 1407, 1502, 1503, 1505, 1499, 1406, 1506, 1507, 1475,
- /* 420 */ 1468, 1511, 1410, 1509, 1473, 1510, 1474, 1516, 1509, 1517,
- /* 430 */ 1518, 1519, 1520, 1521, 1523, 1532, 1524, 1526, 1525, 1527,
- /* 440 */ 1528, 1530, 1531, 1527, 1533, 1535, 1536, 1537, 1539, 1436,
- /* 450 */ 1441, 1442, 1443, 1543, 1547, 1549,
+ /* 0 */ 5, 1117, 1312, 1128, 1274, 1274, 1274, 1274, 61, -19,
+ /* 10 */ 57, 57, 183, 1274, 1274, 1274, 1274, 1274, 1274, 1274,
+ /* 20 */ 66, 66, 201, -29, 331, 318, 133, 259, 335, 411,
+ /* 30 */ 487, 563, 639, 689, 765, 841, 891, 891, 891, 891,
+ /* 40 */ 891, 891, 891, 891, 891, 891, 891, 891, 891, 891,
+ /* 50 */ 891, 891, 891, 941, 891, 991, 1041, 1041, 1217, 1274,
+ /* 60 */ 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274,
+ /* 70 */ 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274,
+ /* 80 */ 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274,
+ /* 90 */ 1363, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274,
+ /* 100 */ 1274, 1274, 1274, 1274, -70, -47, -47, -47, -47, -47,
+ /* 110 */ 24, 11, 146, 296, 524, 444, 529, 529, 296, 3,
+ /* 120 */ 2, -30, 1565, 1565, 1565, -17, -17, -17, 145, 145,
+ /* 130 */ 497, 497, 265, 603, 653, 296, 296, 296, 296, 296,
+ /* 140 */ 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
+ /* 150 */ 296, 296, 296, 296, 296, 701, 1078, 147, 147, 2,
+ /* 160 */ 164, 164, 164, 164, 164, 164, 1565, 1565, 1565, 223,
+ /* 170 */ 56, 56, 268, 269, 220, 347, 351, 415, 359, 296,
+ /* 180 */ 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
+ /* 190 */ 296, 296, 296, 296, 296, 632, 632, 632, 296, 296,
+ /* 200 */ 498, 296, 296, 296, 570, 296, 296, 654, 296, 296,
+ /* 210 */ 296, 296, 296, 296, 296, 296, 296, 296, 636, 200,
+ /* 220 */ 596, 596, 596, 575, -114, 971, 740, 454, 503, 503,
+ /* 230 */ 1134, 454, 1134, 353, 588, 628, 762, 503, 189, 762,
+ /* 240 */ 762, 916, 330, 668, 1245, 1167, 1167, 1255, 1255, 1167,
+ /* 250 */ 1277, 1230, 1172, 1291, 1291, 1291, 1291, 1167, 1310, 1172,
+ /* 260 */ 1277, 1230, 1230, 1172, 1167, 1310, 1204, 1299, 1167, 1167,
+ /* 270 */ 1310, 1335, 1167, 1310, 1167, 1310, 1335, 1258, 1258, 1258,
+ /* 280 */ 1329, 1335, 1258, 1273, 1258, 1329, 1258, 1258, 1256, 1288,
+ /* 290 */ 1256, 1288, 1256, 1288, 1256, 1288, 1167, 1375, 1167, 1267,
+ /* 300 */ 1335, 1320, 1320, 1335, 1287, 1295, 1294, 1301, 1172, 1407,
+ /* 310 */ 1408, 1422, 1422, 1433, 1433, 1433, 1565, 1565, 1565, 1565,
+ /* 320 */ 1565, 1565, 1565, 1565, 558, 537, 684, 719, 734, 799,
+ /* 330 */ 840, 1019, 14, 1020, 1021, 1025, 1026, 1027, 1070, 1072,
+ /* 340 */ 997, 1047, 999, 1079, 1126, 1074, 1141, 694, 819, 1174,
+ /* 350 */ 1136, 981, 1444, 1446, 1432, 1313, 1441, 1396, 1449, 1443,
+ /* 360 */ 1445, 1347, 1338, 1359, 1348, 1452, 1349, 1457, 1474, 1353,
+ /* 370 */ 1346, 1400, 1401, 1402, 1403, 1371, 1387, 1450, 1362, 1485,
+ /* 380 */ 1482, 1466, 1382, 1350, 1438, 1467, 1439, 1434, 1458, 1393,
+ /* 390 */ 1478, 1483, 1486, 1392, 1404, 1484, 1455, 1488, 1489, 1490,
+ /* 400 */ 1492, 1456, 1487, 1493, 1460, 1479, 1494, 1496, 1497, 1495,
+ /* 410 */ 1406, 1501, 1502, 1504, 1498, 1405, 1505, 1506, 1435, 1499,
+ /* 420 */ 1508, 1409, 1509, 1503, 1510, 1507, 1514, 1509, 1516, 1517,
+ /* 430 */ 1518, 1519, 1520, 1522, 1521, 1523, 1525, 1524, 1526, 1527,
+ /* 440 */ 1529, 1530, 1526, 1532, 1531, 1533, 1534, 1536, 1427, 1437,
+ /* 450 */ 1440, 1442, 1537, 1546, 1562,
};
-#define YY_REDUCE_USE_DFLT (-130)
-#define YY_REDUCE_COUNT (324)
-#define YY_REDUCE_MIN (-129)
-#define YY_REDUCE_MAX (1300)
+#define YY_REDUCE_USE_DFLT (-174)
+#define YY_REDUCE_COUNT (323)
+#define YY_REDUCE_MIN (-173)
+#define YY_REDUCE_MAX (1292)
static const short yy_reduce_ofst[] = {
- /* 0 */ -29, 566, 525, 605, -49, 307, 491, 533, 668, 435,
- /* 10 */ 601, 644, 148, 747, 786, 795, 419, 788, 827, 790,
- /* 20 */ 454, 832, 889, 495, 824, 734, 76, 76, 76, 76,
- /* 30 */ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- /* 40 */ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- /* 50 */ 76, 76, 76, 76, 76, 76, 76, 76, 783, 898,
- /* 60 */ 905, 907, 911, 921, 933, 936, 940, 943, 947, 950,
- /* 70 */ 952, 955, 958, 962, 965, 969, 974, 977, 980, 984,
- /* 80 */ 988, 991, 993, 996, 999, 1002, 1006, 1010, 1018, 1021,
- /* 90 */ 1024, 1028, 1032, 1034, 1036, 1040, 1046, 1051, 1058, 1062,
- /* 100 */ 1064, 1068, 1070, 1073, 76, 76, 76, 76, 76, 76,
- /* 110 */ 76, 76, 76, 855, 36, 523, 235, 416, 777, 76,
- /* 120 */ 278, 76, 76, 76, 76, 700, 700, 700, 150, 220,
- /* 130 */ 147, 217, 221, 306, 306, 611, 5, 535, 556, 620,
- /* 140 */ 720, 872, 897, 116, 864, 349, 1035, 1037, 404, 1047,
- /* 150 */ 992, -129, 1050, 492, 62, 722, 879, 1072, 1089, 808,
- /* 160 */ 1066, 1094, 1095, 1096, 1097, 1098, 776, 1054, 557, 57,
- /* 170 */ 112, 131, 167, 182, 250, 272, 291, 331, 364, 438,
- /* 180 */ 497, 517, 591, 653, 690, 739, 775, 798, 892, 908,
- /* 190 */ 924, 930, 1015, 1063, 1069, 355, 784, 799, 981, 1101,
- /* 200 */ 926, 1151, 1161, 1162, 945, 1164, 1166, 1128, 1168, 1171,
- /* 210 */ 1172, 250, 1173, 1174, 1175, 1178, 1180, 1181, 1088, 1102,
- /* 220 */ 1119, 1124, 1126, 926, 1131, 1139, 1188, 1140, 1129, 1130,
- /* 230 */ 1103, 1144, 1107, 1179, 1156, 1167, 1182, 1134, 1122, 1183,
- /* 240 */ 1184, 1150, 1153, 1197, 1111, 1202, 1203, 1123, 1125, 1205,
- /* 250 */ 1147, 1185, 1169, 1186, 1190, 1191, 1192, 1213, 1217, 1193,
- /* 260 */ 1157, 1196, 1198, 1194, 1220, 1218, 1145, 1154, 1229, 1231,
- /* 270 */ 1233, 1216, 1237, 1240, 1241, 1244, 1222, 1227, 1230, 1232,
- /* 280 */ 1223, 1235, 1236, 1245, 1249, 1226, 1250, 1254, 1199, 1201,
- /* 290 */ 1204, 1207, 1209, 1211, 1214, 1212, 1255, 1208, 1259, 1215,
- /* 300 */ 1256, 1200, 1206, 1260, 1247, 1261, 1263, 1262, 1266, 1278,
- /* 310 */ 1282, 1292, 1294, 1297, 1298, 1299, 1300, 1221, 1224, 1228,
- /* 320 */ 1288, 1291, 1276, 1277, 1295,
+ /* 0 */ -119, 1014, 131, 1031, -12, 225, 228, 300, -40, -45,
+ /* 10 */ 243, 256, 293, 129, 218, 418, 79, 376, 433, 298,
+ /* 20 */ 16, 137, 367, 323, -38, 391, -173, -173, -173, -173,
+ /* 30 */ -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+ /* 40 */ -173, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+ /* 50 */ -173, -173, -173, -173, -173, -173, -173, -173, 374, 437,
+ /* 60 */ 443, 508, 513, 522, 532, 582, 584, 620, 633, 635,
+ /* 70 */ 637, 644, 646, 648, 650, 652, 659, 661, 696, 709,
+ /* 80 */ 711, 714, 720, 722, 724, 726, 728, 733, 772, 784,
+ /* 90 */ 786, 822, 834, 836, 884, 886, 922, 934, 936, 986,
+ /* 100 */ 989, 1008, 1016, 1018, -173, -173, -173, -173, -173, -173,
+ /* 110 */ -173, -173, -173, 544, -37, 274, 299, 501, 161, -173,
+ /* 120 */ 193, -173, -173, -173, -173, 22, 22, 22, 64, 141,
+ /* 130 */ 212, 342, 208, 504, 504, 132, 494, 606, 677, 678,
+ /* 140 */ 750, 794, 796, -58, 32, 383, 660, 737, 386, 787,
+ /* 150 */ 800, 441, 872, 224, 850, 803, 949, 624, 830, 669,
+ /* 160 */ 961, 979, 983, 1011, 1013, 1032, 753, 789, 321, 94,
+ /* 170 */ 116, 304, 375, 210, 388, 392, 478, 545, 649, 721,
+ /* 180 */ 727, 736, 752, 795, 853, 952, 958, 1004, 1040, 1046,
+ /* 190 */ 1049, 1050, 1056, 1059, 1067, 559, 774, 811, 1068, 1080,
+ /* 200 */ 938, 1082, 1083, 1088, 962, 1089, 1090, 1052, 1093, 1094,
+ /* 210 */ 1095, 388, 1096, 1103, 1104, 1105, 1106, 1107, 965, 998,
+ /* 220 */ 1055, 1057, 1058, 938, 1069, 1071, 1120, 1073, 1061, 1062,
+ /* 230 */ 1033, 1076, 1039, 1108, 1087, 1099, 1111, 1066, 1054, 1112,
+ /* 240 */ 1113, 1091, 1084, 1135, 1060, 1133, 1138, 1064, 1081, 1139,
+ /* 250 */ 1100, 1119, 1109, 1124, 1127, 1140, 1142, 1168, 1173, 1132,
+ /* 260 */ 1115, 1147, 1148, 1137, 1180, 1182, 1110, 1121, 1188, 1189,
+ /* 270 */ 1197, 1181, 1200, 1202, 1205, 1203, 1191, 1192, 1199, 1206,
+ /* 280 */ 1207, 1209, 1210, 1211, 1214, 1212, 1218, 1219, 1175, 1183,
+ /* 290 */ 1185, 1184, 1186, 1190, 1187, 1196, 1237, 1193, 1253, 1194,
+ /* 300 */ 1236, 1195, 1198, 1238, 1213, 1221, 1220, 1227, 1229, 1271,
+ /* 310 */ 1275, 1284, 1285, 1289, 1290, 1292, 1201, 1208, 1216, 1279,
+ /* 320 */ 1280, 1264, 1268, 1282,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 1281, 1271, 1271, 1271, 1203, 1203, 1203, 1203, 1271, 1096,
- /* 10 */ 1125, 1125, 1255, 1332, 1332, 1332, 1332, 1332, 1332, 1202,
- /* 20 */ 1332, 1332, 1332, 1332, 1271, 1100, 1131, 1332, 1332, 1332,
- /* 30 */ 1332, 1204, 1205, 1332, 1332, 1332, 1254, 1256, 1141, 1140,
- /* 40 */ 1139, 1138, 1237, 1112, 1136, 1129, 1133, 1204, 1198, 1199,
- /* 50 */ 1197, 1201, 1205, 1332, 1132, 1167, 1182, 1166, 1332, 1332,
- /* 60 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 70 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 80 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 90 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 100 */ 1332, 1332, 1332, 1332, 1176, 1181, 1188, 1180, 1177, 1169,
- /* 110 */ 1168, 1170, 1171, 1332, 1019, 1067, 1332, 1332, 1332, 1172,
- /* 120 */ 1332, 1173, 1185, 1184, 1183, 1262, 1289, 1288, 1332, 1332,
- /* 130 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 140 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 150 */ 1332, 1332, 1332, 1332, 1332, 1281, 1271, 1025, 1025, 1332,
- /* 160 */ 1271, 1271, 1271, 1271, 1271, 1271, 1267, 1100, 1091, 1332,
- /* 170 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 180 */ 1259, 1257, 1332, 1218, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 190 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 200 */ 1332, 1332, 1332, 1332, 1096, 1332, 1332, 1332, 1332, 1332,
- /* 210 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1283, 1332, 1232,
- /* 220 */ 1096, 1096, 1096, 1098, 1080, 1090, 1004, 1135, 1114, 1114,
- /* 230 */ 1321, 1135, 1321, 1042, 1303, 1039, 1125, 1114, 1200, 1125,
- /* 240 */ 1125, 1097, 1090, 1332, 1324, 1105, 1105, 1323, 1323, 1105,
- /* 250 */ 1146, 1070, 1135, 1076, 1076, 1076, 1076, 1105, 1016, 1135,
- /* 260 */ 1146, 1070, 1070, 1135, 1105, 1016, 1236, 1318, 1105, 1105,
- /* 270 */ 1016, 1211, 1105, 1016, 1105, 1016, 1211, 1068, 1068, 1068,
- /* 280 */ 1057, 1211, 1068, 1042, 1068, 1057, 1068, 1068, 1118, 1113,
- /* 290 */ 1118, 1113, 1118, 1113, 1118, 1113, 1105, 1206, 1105, 1332,
- /* 300 */ 1211, 1215, 1215, 1211, 1130, 1119, 1128, 1126, 1135, 1022,
- /* 310 */ 1060, 1286, 1286, 1282, 1282, 1282, 1282, 1329, 1329, 1267,
- /* 320 */ 1298, 1298, 1044, 1044, 1298, 1332, 1332, 1332, 1332, 1332,
- /* 330 */ 1332, 1293, 1332, 1220, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 340 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 350 */ 1332, 1332, 1152, 1332, 1000, 1264, 1332, 1332, 1263, 1332,
- /* 360 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 370 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1320,
- /* 380 */ 1332, 1332, 1332, 1332, 1332, 1332, 1235, 1234, 1332, 1332,
- /* 390 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 400 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332,
- /* 410 */ 1332, 1082, 1332, 1332, 1332, 1307, 1332, 1332, 1332, 1332,
- /* 420 */ 1332, 1332, 1332, 1127, 1332, 1120, 1332, 1332, 1311, 1332,
- /* 430 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1273,
- /* 440 */ 1332, 1332, 1332, 1272, 1332, 1332, 1332, 1332, 1332, 1154,
- /* 450 */ 1332, 1153, 1157, 1332, 1010, 1332,
+ /* 0 */ 1270, 1260, 1260, 1260, 1193, 1193, 1193, 1193, 1260, 1088,
+ /* 10 */ 1117, 1117, 1244, 1322, 1322, 1322, 1322, 1322, 1322, 1192,
+ /* 20 */ 1322, 1322, 1322, 1322, 1260, 1092, 1123, 1322, 1322, 1322,
+ /* 30 */ 1322, 1194, 1195, 1322, 1322, 1322, 1243, 1245, 1133, 1132,
+ /* 40 */ 1131, 1130, 1226, 1104, 1128, 1121, 1125, 1194, 1188, 1189,
+ /* 50 */ 1187, 1191, 1195, 1322, 1124, 1158, 1172, 1157, 1322, 1322,
+ /* 60 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 70 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 80 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 90 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 100 */ 1322, 1322, 1322, 1322, 1166, 1171, 1178, 1170, 1167, 1160,
+ /* 110 */ 1159, 1161, 1162, 1322, 1011, 1059, 1322, 1322, 1322, 1163,
+ /* 120 */ 1322, 1164, 1175, 1174, 1173, 1251, 1278, 1277, 1322, 1322,
+ /* 130 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 140 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 150 */ 1322, 1322, 1322, 1322, 1322, 1270, 1260, 1017, 1017, 1322,
+ /* 160 */ 1260, 1260, 1260, 1260, 1260, 1260, 1256, 1092, 1083, 1322,
+ /* 170 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 180 */ 1248, 1246, 1322, 1208, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 190 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 200 */ 1322, 1322, 1322, 1322, 1088, 1322, 1322, 1322, 1322, 1322,
+ /* 210 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1272, 1322, 1221,
+ /* 220 */ 1088, 1088, 1088, 1090, 1072, 1082, 997, 1127, 1106, 1106,
+ /* 230 */ 1311, 1127, 1311, 1034, 1292, 1031, 1117, 1106, 1190, 1117,
+ /* 240 */ 1117, 1089, 1082, 1322, 1314, 1097, 1097, 1313, 1313, 1097,
+ /* 250 */ 1138, 1062, 1127, 1068, 1068, 1068, 1068, 1097, 1008, 1127,
+ /* 260 */ 1138, 1062, 1062, 1127, 1097, 1008, 1225, 1308, 1097, 1097,
+ /* 270 */ 1008, 1201, 1097, 1008, 1097, 1008, 1201, 1060, 1060, 1060,
+ /* 280 */ 1049, 1201, 1060, 1034, 1060, 1049, 1060, 1060, 1110, 1105,
+ /* 290 */ 1110, 1105, 1110, 1105, 1110, 1105, 1097, 1196, 1097, 1322,
+ /* 300 */ 1201, 1205, 1205, 1201, 1122, 1111, 1120, 1118, 1127, 1014,
+ /* 310 */ 1052, 1275, 1275, 1271, 1271, 1271, 1319, 1319, 1256, 1287,
+ /* 320 */ 1287, 1036, 1036, 1287, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 330 */ 1282, 1322, 1210, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 340 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 350 */ 1322, 1143, 1322, 993, 1253, 1322, 1322, 1252, 1322, 1322,
+ /* 360 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 370 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1310, 1322,
+ /* 380 */ 1322, 1322, 1322, 1322, 1322, 1224, 1223, 1322, 1322, 1322,
+ /* 390 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 400 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ /* 410 */ 1074, 1322, 1322, 1322, 1296, 1322, 1322, 1322, 1322, 1322,
+ /* 420 */ 1322, 1322, 1119, 1322, 1112, 1322, 1322, 1301, 1322, 1322,
+ /* 430 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1262, 1322,
+ /* 440 */ 1322, 1322, 1261, 1322, 1322, 1322, 1322, 1322, 1145, 1322,
+ /* 450 */ 1144, 1148, 1322, 1002, 1322,
};
/********** End of lemon-generated parsing tables *****************************/
@@ -136786,100 +140718,73 @@ static const YYACTIONTYPE yy_default[] = {
static const YYCODETYPE yyFallback[] = {
0, /* $ => nothing */
0, /* SEMI => nothing */
- 55, /* EXPLAIN => ID */
- 55, /* QUERY => ID */
- 55, /* PLAN => ID */
- 55, /* BEGIN => ID */
+ 27, /* EXPLAIN => ID */
+ 27, /* QUERY => ID */
+ 27, /* PLAN => ID */
+ 27, /* BEGIN => ID */
0, /* TRANSACTION => nothing */
- 55, /* DEFERRED => ID */
- 55, /* IMMEDIATE => ID */
- 55, /* EXCLUSIVE => ID */
+ 27, /* DEFERRED => ID */
+ 27, /* IMMEDIATE => ID */
+ 27, /* EXCLUSIVE => ID */
0, /* COMMIT => nothing */
- 55, /* END => ID */
- 55, /* ROLLBACK => ID */
- 55, /* SAVEPOINT => ID */
- 55, /* RELEASE => ID */
+ 27, /* END => ID */
+ 27, /* ROLLBACK => ID */
+ 27, /* SAVEPOINT => ID */
+ 27, /* RELEASE => ID */
0, /* TO => nothing */
0, /* TABLE => nothing */
0, /* CREATE => nothing */
- 55, /* IF => ID */
+ 27, /* IF => ID */
0, /* NOT => nothing */
0, /* EXISTS => nothing */
- 55, /* TEMP => ID */
+ 27, /* TEMP => ID */
0, /* LP => nothing */
0, /* RP => nothing */
0, /* AS => nothing */
- 55, /* WITHOUT => ID */
+ 27, /* WITHOUT => ID */
0, /* COMMA => nothing */
- 0, /* OR => nothing */
- 0, /* AND => nothing */
- 0, /* IS => nothing */
- 55, /* MATCH => ID */
- 55, /* LIKE_KW => ID */
- 0, /* BETWEEN => nothing */
- 0, /* IN => nothing */
- 0, /* ISNULL => nothing */
- 0, /* NOTNULL => nothing */
- 0, /* NE => nothing */
- 0, /* EQ => nothing */
- 0, /* GT => nothing */
- 0, /* LE => nothing */
- 0, /* LT => nothing */
- 0, /* GE => nothing */
- 0, /* ESCAPE => nothing */
- 0, /* BITAND => nothing */
- 0, /* BITOR => nothing */
- 0, /* LSHIFT => nothing */
- 0, /* RSHIFT => nothing */
- 0, /* PLUS => nothing */
- 0, /* MINUS => nothing */
- 0, /* STAR => nothing */
- 0, /* SLASH => nothing */
- 0, /* REM => nothing */
- 0, /* CONCAT => nothing */
- 0, /* COLLATE => nothing */
- 0, /* BITNOT => nothing */
0, /* ID => nothing */
- 0, /* INDEXED => nothing */
- 55, /* ABORT => ID */
- 55, /* ACTION => ID */
- 55, /* AFTER => ID */
- 55, /* ANALYZE => ID */
- 55, /* ASC => ID */
- 55, /* ATTACH => ID */
- 55, /* BEFORE => ID */
- 55, /* BY => ID */
- 55, /* CASCADE => ID */
- 55, /* CAST => ID */
- 55, /* COLUMNKW => ID */
- 55, /* CONFLICT => ID */
- 55, /* DATABASE => ID */
- 55, /* DESC => ID */
- 55, /* DETACH => ID */
- 55, /* EACH => ID */
- 55, /* FAIL => ID */
- 55, /* FOR => ID */
- 55, /* IGNORE => ID */
- 55, /* INITIALLY => ID */
- 55, /* INSTEAD => ID */
- 55, /* NO => ID */
- 55, /* KEY => ID */
- 55, /* OF => ID */
- 55, /* OFFSET => ID */
- 55, /* PRAGMA => ID */
- 55, /* RAISE => ID */
- 55, /* RECURSIVE => ID */
- 55, /* REPLACE => ID */
- 55, /* RESTRICT => ID */
- 55, /* ROW => ID */
- 55, /* TRIGGER => ID */
- 55, /* VACUUM => ID */
- 55, /* VIEW => ID */
- 55, /* VIRTUAL => ID */
- 55, /* WITH => ID */
- 55, /* REINDEX => ID */
- 55, /* RENAME => ID */
- 55, /* CTIME_KW => ID */
+ 27, /* ABORT => ID */
+ 27, /* ACTION => ID */
+ 27, /* AFTER => ID */
+ 27, /* ANALYZE => ID */
+ 27, /* ASC => ID */
+ 27, /* ATTACH => ID */
+ 27, /* BEFORE => ID */
+ 27, /* BY => ID */
+ 27, /* CASCADE => ID */
+ 27, /* CAST => ID */
+ 27, /* COLUMNKW => ID */
+ 27, /* CONFLICT => ID */
+ 27, /* DATABASE => ID */
+ 27, /* DESC => ID */
+ 27, /* DETACH => ID */
+ 27, /* EACH => ID */
+ 27, /* FAIL => ID */
+ 27, /* FOR => ID */
+ 27, /* IGNORE => ID */
+ 27, /* INITIALLY => ID */
+ 27, /* INSTEAD => ID */
+ 27, /* LIKE_KW => ID */
+ 27, /* MATCH => ID */
+ 27, /* NO => ID */
+ 27, /* KEY => ID */
+ 27, /* OF => ID */
+ 27, /* OFFSET => ID */
+ 27, /* PRAGMA => ID */
+ 27, /* RAISE => ID */
+ 27, /* RECURSIVE => ID */
+ 27, /* REPLACE => ID */
+ 27, /* RESTRICT => ID */
+ 27, /* ROW => ID */
+ 27, /* TRIGGER => ID */
+ 27, /* VACUUM => ID */
+ 27, /* VIEW => ID */
+ 27, /* VIRTUAL => ID */
+ 27, /* WITH => ID */
+ 27, /* REINDEX => ID */
+ 27, /* RENAME => ID */
+ 27, /* CTIME_KW => ID */
};
#endif /* YYFALLBACK */
@@ -136925,6 +140830,7 @@ struct yyParser {
yyStackEntry yystk0; /* First stack entry */
#else
yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
+ yyStackEntry *yystackEnd; /* Last entry in the stack */
#endif
};
typedef struct yyParser yyParser;
@@ -136971,25 +140877,25 @@ static const char *const yyTokenName[] = {
"ROLLBACK", "SAVEPOINT", "RELEASE", "TO",
"TABLE", "CREATE", "IF", "NOT",
"EXISTS", "TEMP", "LP", "RP",
- "AS", "WITHOUT", "COMMA", "OR",
- "AND", "IS", "MATCH", "LIKE_KW",
- "BETWEEN", "IN", "ISNULL", "NOTNULL",
- "NE", "EQ", "GT", "LE",
- "LT", "GE", "ESCAPE", "BITAND",
- "BITOR", "LSHIFT", "RSHIFT", "PLUS",
- "MINUS", "STAR", "SLASH", "REM",
- "CONCAT", "COLLATE", "BITNOT", "ID",
- "INDEXED", "ABORT", "ACTION", "AFTER",
- "ANALYZE", "ASC", "ATTACH", "BEFORE",
- "BY", "CASCADE", "CAST", "COLUMNKW",
- "CONFLICT", "DATABASE", "DESC", "DETACH",
- "EACH", "FAIL", "FOR", "IGNORE",
- "INITIALLY", "INSTEAD", "NO", "KEY",
- "OF", "OFFSET", "PRAGMA", "RAISE",
- "RECURSIVE", "REPLACE", "RESTRICT", "ROW",
- "TRIGGER", "VACUUM", "VIEW", "VIRTUAL",
- "WITH", "REINDEX", "RENAME", "CTIME_KW",
- "ANY", "STRING", "JOIN_KW", "CONSTRAINT",
+ "AS", "WITHOUT", "COMMA", "ID",
+ "ABORT", "ACTION", "AFTER", "ANALYZE",
+ "ASC", "ATTACH", "BEFORE", "BY",
+ "CASCADE", "CAST", "COLUMNKW", "CONFLICT",
+ "DATABASE", "DESC", "DETACH", "EACH",
+ "FAIL", "FOR", "IGNORE", "INITIALLY",
+ "INSTEAD", "LIKE_KW", "MATCH", "NO",
+ "KEY", "OF", "OFFSET", "PRAGMA",
+ "RAISE", "RECURSIVE", "REPLACE", "RESTRICT",
+ "ROW", "TRIGGER", "VACUUM", "VIEW",
+ "VIRTUAL", "WITH", "REINDEX", "RENAME",
+ "CTIME_KW", "ANY", "OR", "AND",
+ "IS", "BETWEEN", "IN", "ISNULL",
+ "NOTNULL", "NE", "EQ", "GT",
+ "LE", "LT", "GE", "ESCAPE",
+ "BITAND", "BITOR", "LSHIFT", "RSHIFT",
+ "PLUS", "MINUS", "STAR", "SLASH",
+ "REM", "CONCAT", "COLLATE", "BITNOT",
+ "INDEXED", "STRING", "JOIN_KW", "CONSTRAINT",
"DEFAULT", "NULL", "PRIMARY", "UNIQUE",
"CHECK", "REFERENCES", "AUTOINCR", "ON",
"INSERT", "DELETE", "UPDATE", "SET",
@@ -137043,330 +140949,327 @@ static const char *const yyRuleName[] = {
/* 5 */ "transtype ::= DEFERRED",
/* 6 */ "transtype ::= IMMEDIATE",
/* 7 */ "transtype ::= EXCLUSIVE",
- /* 8 */ "cmd ::= COMMIT trans_opt",
- /* 9 */ "cmd ::= END trans_opt",
- /* 10 */ "cmd ::= ROLLBACK trans_opt",
- /* 11 */ "cmd ::= SAVEPOINT nm",
- /* 12 */ "cmd ::= RELEASE savepoint_opt nm",
- /* 13 */ "cmd ::= ROLLBACK trans_opt TO savepoint_opt nm",
- /* 14 */ "create_table ::= createkw temp TABLE ifnotexists nm dbnm",
- /* 15 */ "createkw ::= CREATE",
- /* 16 */ "ifnotexists ::=",
- /* 17 */ "ifnotexists ::= IF NOT EXISTS",
- /* 18 */ "temp ::= TEMP",
- /* 19 */ "temp ::=",
- /* 20 */ "create_table_args ::= LP columnlist conslist_opt RP table_options",
- /* 21 */ "create_table_args ::= AS select",
- /* 22 */ "table_options ::=",
- /* 23 */ "table_options ::= WITHOUT nm",
- /* 24 */ "columnname ::= nm typetoken",
- /* 25 */ "typetoken ::=",
- /* 26 */ "typetoken ::= typename LP signed RP",
- /* 27 */ "typetoken ::= typename LP signed COMMA signed RP",
- /* 28 */ "typename ::= typename ID|STRING",
- /* 29 */ "ccons ::= CONSTRAINT nm",
- /* 30 */ "ccons ::= DEFAULT term",
- /* 31 */ "ccons ::= DEFAULT LP expr RP",
- /* 32 */ "ccons ::= DEFAULT PLUS term",
- /* 33 */ "ccons ::= DEFAULT MINUS term",
- /* 34 */ "ccons ::= DEFAULT ID|INDEXED",
- /* 35 */ "ccons ::= NOT NULL onconf",
- /* 36 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
- /* 37 */ "ccons ::= UNIQUE onconf",
- /* 38 */ "ccons ::= CHECK LP expr RP",
- /* 39 */ "ccons ::= REFERENCES nm eidlist_opt refargs",
- /* 40 */ "ccons ::= defer_subclause",
- /* 41 */ "ccons ::= COLLATE ID|STRING",
- /* 42 */ "autoinc ::=",
- /* 43 */ "autoinc ::= AUTOINCR",
- /* 44 */ "refargs ::=",
- /* 45 */ "refargs ::= refargs refarg",
- /* 46 */ "refarg ::= MATCH nm",
- /* 47 */ "refarg ::= ON INSERT refact",
- /* 48 */ "refarg ::= ON DELETE refact",
- /* 49 */ "refarg ::= ON UPDATE refact",
- /* 50 */ "refact ::= SET NULL",
- /* 51 */ "refact ::= SET DEFAULT",
- /* 52 */ "refact ::= CASCADE",
- /* 53 */ "refact ::= RESTRICT",
- /* 54 */ "refact ::= NO ACTION",
- /* 55 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
- /* 56 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
- /* 57 */ "init_deferred_pred_opt ::=",
- /* 58 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
- /* 59 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
- /* 60 */ "conslist_opt ::=",
- /* 61 */ "tconscomma ::= COMMA",
- /* 62 */ "tcons ::= CONSTRAINT nm",
- /* 63 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf",
- /* 64 */ "tcons ::= UNIQUE LP sortlist RP onconf",
- /* 65 */ "tcons ::= CHECK LP expr RP onconf",
- /* 66 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt",
- /* 67 */ "defer_subclause_opt ::=",
- /* 68 */ "onconf ::=",
- /* 69 */ "onconf ::= ON CONFLICT resolvetype",
- /* 70 */ "orconf ::=",
- /* 71 */ "orconf ::= OR resolvetype",
- /* 72 */ "resolvetype ::= IGNORE",
- /* 73 */ "resolvetype ::= REPLACE",
- /* 74 */ "cmd ::= DROP TABLE ifexists fullname",
- /* 75 */ "ifexists ::= IF EXISTS",
- /* 76 */ "ifexists ::=",
- /* 77 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select",
- /* 78 */ "cmd ::= DROP VIEW ifexists fullname",
- /* 79 */ "cmd ::= select",
- /* 80 */ "select ::= with selectnowith",
- /* 81 */ "selectnowith ::= selectnowith multiselect_op oneselect",
- /* 82 */ "multiselect_op ::= UNION",
- /* 83 */ "multiselect_op ::= UNION ALL",
- /* 84 */ "multiselect_op ::= EXCEPT|INTERSECT",
- /* 85 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
- /* 86 */ "values ::= VALUES LP nexprlist RP",
- /* 87 */ "values ::= values COMMA LP exprlist RP",
- /* 88 */ "distinct ::= DISTINCT",
- /* 89 */ "distinct ::= ALL",
- /* 90 */ "distinct ::=",
- /* 91 */ "sclp ::=",
- /* 92 */ "selcollist ::= sclp expr as",
- /* 93 */ "selcollist ::= sclp STAR",
- /* 94 */ "selcollist ::= sclp nm DOT STAR",
- /* 95 */ "as ::= AS nm",
- /* 96 */ "as ::=",
- /* 97 */ "from ::=",
- /* 98 */ "from ::= FROM seltablist",
- /* 99 */ "stl_prefix ::= seltablist joinop",
- /* 100 */ "stl_prefix ::=",
- /* 101 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
- /* 102 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt",
- /* 103 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
- /* 104 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
- /* 105 */ "dbnm ::=",
- /* 106 */ "dbnm ::= DOT nm",
- /* 107 */ "fullname ::= nm dbnm",
- /* 108 */ "joinop ::= COMMA|JOIN",
- /* 109 */ "joinop ::= JOIN_KW JOIN",
- /* 110 */ "joinop ::= JOIN_KW nm JOIN",
- /* 111 */ "joinop ::= JOIN_KW nm nm JOIN",
- /* 112 */ "on_opt ::= ON expr",
- /* 113 */ "on_opt ::=",
- /* 114 */ "indexed_opt ::=",
- /* 115 */ "indexed_opt ::= INDEXED BY nm",
- /* 116 */ "indexed_opt ::= NOT INDEXED",
- /* 117 */ "using_opt ::= USING LP idlist RP",
- /* 118 */ "using_opt ::=",
- /* 119 */ "orderby_opt ::=",
- /* 120 */ "orderby_opt ::= ORDER BY sortlist",
- /* 121 */ "sortlist ::= sortlist COMMA expr sortorder",
- /* 122 */ "sortlist ::= expr sortorder",
- /* 123 */ "sortorder ::= ASC",
- /* 124 */ "sortorder ::= DESC",
- /* 125 */ "sortorder ::=",
- /* 126 */ "groupby_opt ::=",
- /* 127 */ "groupby_opt ::= GROUP BY nexprlist",
- /* 128 */ "having_opt ::=",
- /* 129 */ "having_opt ::= HAVING expr",
- /* 130 */ "limit_opt ::=",
- /* 131 */ "limit_opt ::= LIMIT expr",
- /* 132 */ "limit_opt ::= LIMIT expr OFFSET expr",
- /* 133 */ "limit_opt ::= LIMIT expr COMMA expr",
- /* 134 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt",
- /* 135 */ "where_opt ::=",
- /* 136 */ "where_opt ::= WHERE expr",
- /* 137 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt",
- /* 138 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 139 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
- /* 140 */ "setlist ::= nm EQ expr",
- /* 141 */ "setlist ::= LP idlist RP EQ expr",
- /* 142 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select",
- /* 143 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES",
- /* 144 */ "insert_cmd ::= INSERT orconf",
- /* 145 */ "insert_cmd ::= REPLACE",
- /* 146 */ "idlist_opt ::=",
- /* 147 */ "idlist_opt ::= LP idlist RP",
- /* 148 */ "idlist ::= idlist COMMA nm",
- /* 149 */ "idlist ::= nm",
- /* 150 */ "expr ::= LP expr RP",
- /* 151 */ "term ::= NULL",
- /* 152 */ "expr ::= ID|INDEXED",
- /* 153 */ "expr ::= JOIN_KW",
- /* 154 */ "expr ::= nm DOT nm",
- /* 155 */ "expr ::= nm DOT nm DOT nm",
- /* 156 */ "term ::= FLOAT|BLOB",
- /* 157 */ "term ::= STRING",
- /* 158 */ "term ::= INTEGER",
- /* 159 */ "expr ::= VARIABLE",
- /* 160 */ "expr ::= expr COLLATE ID|STRING",
- /* 161 */ "expr ::= CAST LP expr AS typetoken RP",
- /* 162 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
- /* 163 */ "expr ::= ID|INDEXED LP STAR RP",
- /* 164 */ "term ::= CTIME_KW",
- /* 165 */ "expr ::= LP nexprlist COMMA expr RP",
- /* 166 */ "expr ::= expr AND expr",
- /* 167 */ "expr ::= expr OR expr",
- /* 168 */ "expr ::= expr LT|GT|GE|LE expr",
- /* 169 */ "expr ::= expr EQ|NE expr",
- /* 170 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
- /* 171 */ "expr ::= expr PLUS|MINUS expr",
- /* 172 */ "expr ::= expr STAR|SLASH|REM expr",
- /* 173 */ "expr ::= expr CONCAT expr",
- /* 174 */ "likeop ::= LIKE_KW|MATCH",
- /* 175 */ "likeop ::= NOT LIKE_KW|MATCH",
- /* 176 */ "expr ::= expr likeop expr",
- /* 177 */ "expr ::= expr likeop expr ESCAPE expr",
- /* 178 */ "expr ::= expr ISNULL|NOTNULL",
- /* 179 */ "expr ::= expr NOT NULL",
- /* 180 */ "expr ::= expr IS expr",
- /* 181 */ "expr ::= expr IS NOT expr",
- /* 182 */ "expr ::= NOT expr",
- /* 183 */ "expr ::= BITNOT expr",
- /* 184 */ "expr ::= MINUS expr",
- /* 185 */ "expr ::= PLUS expr",
- /* 186 */ "between_op ::= BETWEEN",
- /* 187 */ "between_op ::= NOT BETWEEN",
- /* 188 */ "expr ::= expr between_op expr AND expr",
- /* 189 */ "in_op ::= IN",
- /* 190 */ "in_op ::= NOT IN",
- /* 191 */ "expr ::= expr in_op LP exprlist RP",
- /* 192 */ "expr ::= LP select RP",
- /* 193 */ "expr ::= expr in_op LP select RP",
- /* 194 */ "expr ::= expr in_op nm dbnm paren_exprlist",
- /* 195 */ "expr ::= EXISTS LP select RP",
- /* 196 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 197 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 198 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 199 */ "case_else ::= ELSE expr",
- /* 200 */ "case_else ::=",
- /* 201 */ "case_operand ::= expr",
- /* 202 */ "case_operand ::=",
- /* 203 */ "exprlist ::=",
- /* 204 */ "nexprlist ::= nexprlist COMMA expr",
- /* 205 */ "nexprlist ::= expr",
- /* 206 */ "paren_exprlist ::=",
- /* 207 */ "paren_exprlist ::= LP exprlist RP",
- /* 208 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
- /* 209 */ "uniqueflag ::= UNIQUE",
- /* 210 */ "uniqueflag ::=",
- /* 211 */ "eidlist_opt ::=",
- /* 212 */ "eidlist_opt ::= LP eidlist RP",
- /* 213 */ "eidlist ::= eidlist COMMA nm collate sortorder",
- /* 214 */ "eidlist ::= nm collate sortorder",
- /* 215 */ "collate ::=",
- /* 216 */ "collate ::= COLLATE ID|STRING",
- /* 217 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 218 */ "cmd ::= VACUUM",
- /* 219 */ "cmd ::= VACUUM nm",
- /* 220 */ "cmd ::= PRAGMA nm dbnm",
- /* 221 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
- /* 222 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 223 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 224 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
- /* 225 */ "plus_num ::= PLUS INTEGER|FLOAT",
- /* 226 */ "minus_num ::= MINUS INTEGER|FLOAT",
- /* 227 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
- /* 228 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 229 */ "trigger_time ::= BEFORE",
- /* 230 */ "trigger_time ::= AFTER",
- /* 231 */ "trigger_time ::= INSTEAD OF",
- /* 232 */ "trigger_time ::=",
- /* 233 */ "trigger_event ::= DELETE|INSERT",
- /* 234 */ "trigger_event ::= UPDATE",
- /* 235 */ "trigger_event ::= UPDATE OF idlist",
- /* 236 */ "when_clause ::=",
- /* 237 */ "when_clause ::= WHEN expr",
- /* 238 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 239 */ "trigger_cmd_list ::= trigger_cmd SEMI",
- /* 240 */ "trnm ::= nm DOT nm",
- /* 241 */ "tridxby ::= INDEXED BY nm",
- /* 242 */ "tridxby ::= NOT INDEXED",
- /* 243 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
- /* 244 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select",
- /* 245 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
- /* 246 */ "trigger_cmd ::= select",
- /* 247 */ "expr ::= RAISE LP IGNORE RP",
- /* 248 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 249 */ "raisetype ::= ROLLBACK",
- /* 250 */ "raisetype ::= ABORT",
- /* 251 */ "raisetype ::= FAIL",
- /* 252 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 253 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 254 */ "cmd ::= DETACH database_kw_opt expr",
- /* 255 */ "key_opt ::=",
- /* 256 */ "key_opt ::= KEY expr",
- /* 257 */ "cmd ::= REINDEX",
- /* 258 */ "cmd ::= REINDEX nm dbnm",
- /* 259 */ "cmd ::= ANALYZE",
- /* 260 */ "cmd ::= ANALYZE nm dbnm",
- /* 261 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 262 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
- /* 263 */ "add_column_fullname ::= fullname",
- /* 264 */ "cmd ::= create_vtab",
- /* 265 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 266 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
- /* 267 */ "vtabarg ::=",
- /* 268 */ "vtabargtoken ::= ANY",
- /* 269 */ "vtabargtoken ::= lp anylist RP",
- /* 270 */ "lp ::= LP",
- /* 271 */ "with ::=",
- /* 272 */ "with ::= WITH wqlist",
- /* 273 */ "with ::= WITH RECURSIVE wqlist",
- /* 274 */ "wqlist ::= nm eidlist_opt AS LP select RP",
- /* 275 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
- /* 276 */ "input ::= cmdlist",
- /* 277 */ "cmdlist ::= cmdlist ecmd",
- /* 278 */ "cmdlist ::= ecmd",
- /* 279 */ "ecmd ::= SEMI",
- /* 280 */ "ecmd ::= explain cmdx SEMI",
- /* 281 */ "explain ::=",
- /* 282 */ "trans_opt ::=",
- /* 283 */ "trans_opt ::= TRANSACTION",
- /* 284 */ "trans_opt ::= TRANSACTION nm",
- /* 285 */ "savepoint_opt ::= SAVEPOINT",
- /* 286 */ "savepoint_opt ::=",
- /* 287 */ "cmd ::= create_table create_table_args",
- /* 288 */ "columnlist ::= columnlist COMMA columnname carglist",
- /* 289 */ "columnlist ::= columnname carglist",
- /* 290 */ "nm ::= ID|INDEXED",
- /* 291 */ "nm ::= STRING",
- /* 292 */ "nm ::= JOIN_KW",
- /* 293 */ "typetoken ::= typename",
- /* 294 */ "typename ::= ID|STRING",
- /* 295 */ "signed ::= plus_num",
- /* 296 */ "signed ::= minus_num",
- /* 297 */ "carglist ::= carglist ccons",
- /* 298 */ "carglist ::=",
- /* 299 */ "ccons ::= NULL onconf",
- /* 300 */ "conslist_opt ::= COMMA conslist",
- /* 301 */ "conslist ::= conslist tconscomma tcons",
- /* 302 */ "conslist ::= tcons",
- /* 303 */ "tconscomma ::=",
- /* 304 */ "defer_subclause_opt ::= defer_subclause",
- /* 305 */ "resolvetype ::= raisetype",
- /* 306 */ "selectnowith ::= oneselect",
- /* 307 */ "oneselect ::= values",
- /* 308 */ "sclp ::= selcollist COMMA",
- /* 309 */ "as ::= ID|STRING",
- /* 310 */ "expr ::= term",
- /* 311 */ "exprlist ::= nexprlist",
- /* 312 */ "nmnum ::= plus_num",
- /* 313 */ "nmnum ::= nm",
- /* 314 */ "nmnum ::= ON",
- /* 315 */ "nmnum ::= DELETE",
- /* 316 */ "nmnum ::= DEFAULT",
- /* 317 */ "plus_num ::= INTEGER|FLOAT",
- /* 318 */ "foreach_clause ::=",
- /* 319 */ "foreach_clause ::= FOR EACH ROW",
- /* 320 */ "trnm ::= nm",
- /* 321 */ "tridxby ::=",
- /* 322 */ "database_kw_opt ::= DATABASE",
- /* 323 */ "database_kw_opt ::=",
- /* 324 */ "kwcolumn_opt ::=",
- /* 325 */ "kwcolumn_opt ::= COLUMNKW",
- /* 326 */ "vtabarglist ::= vtabarg",
- /* 327 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 328 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 329 */ "anylist ::=",
- /* 330 */ "anylist ::= anylist LP anylist RP",
- /* 331 */ "anylist ::= anylist ANY",
+ /* 8 */ "cmd ::= COMMIT|END trans_opt",
+ /* 9 */ "cmd ::= ROLLBACK trans_opt",
+ /* 10 */ "cmd ::= SAVEPOINT nm",
+ /* 11 */ "cmd ::= RELEASE savepoint_opt nm",
+ /* 12 */ "cmd ::= ROLLBACK trans_opt TO savepoint_opt nm",
+ /* 13 */ "create_table ::= createkw temp TABLE ifnotexists nm dbnm",
+ /* 14 */ "createkw ::= CREATE",
+ /* 15 */ "ifnotexists ::=",
+ /* 16 */ "ifnotexists ::= IF NOT EXISTS",
+ /* 17 */ "temp ::= TEMP",
+ /* 18 */ "temp ::=",
+ /* 19 */ "create_table_args ::= LP columnlist conslist_opt RP table_options",
+ /* 20 */ "create_table_args ::= AS select",
+ /* 21 */ "table_options ::=",
+ /* 22 */ "table_options ::= WITHOUT nm",
+ /* 23 */ "columnname ::= nm typetoken",
+ /* 24 */ "typetoken ::=",
+ /* 25 */ "typetoken ::= typename LP signed RP",
+ /* 26 */ "typetoken ::= typename LP signed COMMA signed RP",
+ /* 27 */ "typename ::= typename ID|STRING",
+ /* 28 */ "ccons ::= CONSTRAINT nm",
+ /* 29 */ "ccons ::= DEFAULT term",
+ /* 30 */ "ccons ::= DEFAULT LP expr RP",
+ /* 31 */ "ccons ::= DEFAULT PLUS term",
+ /* 32 */ "ccons ::= DEFAULT MINUS term",
+ /* 33 */ "ccons ::= DEFAULT ID|INDEXED",
+ /* 34 */ "ccons ::= NOT NULL onconf",
+ /* 35 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
+ /* 36 */ "ccons ::= UNIQUE onconf",
+ /* 37 */ "ccons ::= CHECK LP expr RP",
+ /* 38 */ "ccons ::= REFERENCES nm eidlist_opt refargs",
+ /* 39 */ "ccons ::= defer_subclause",
+ /* 40 */ "ccons ::= COLLATE ID|STRING",
+ /* 41 */ "autoinc ::=",
+ /* 42 */ "autoinc ::= AUTOINCR",
+ /* 43 */ "refargs ::=",
+ /* 44 */ "refargs ::= refargs refarg",
+ /* 45 */ "refarg ::= MATCH nm",
+ /* 46 */ "refarg ::= ON INSERT refact",
+ /* 47 */ "refarg ::= ON DELETE refact",
+ /* 48 */ "refarg ::= ON UPDATE refact",
+ /* 49 */ "refact ::= SET NULL",
+ /* 50 */ "refact ::= SET DEFAULT",
+ /* 51 */ "refact ::= CASCADE",
+ /* 52 */ "refact ::= RESTRICT",
+ /* 53 */ "refact ::= NO ACTION",
+ /* 54 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
+ /* 55 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
+ /* 56 */ "init_deferred_pred_opt ::=",
+ /* 57 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
+ /* 58 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
+ /* 59 */ "conslist_opt ::=",
+ /* 60 */ "tconscomma ::= COMMA",
+ /* 61 */ "tcons ::= CONSTRAINT nm",
+ /* 62 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf",
+ /* 63 */ "tcons ::= UNIQUE LP sortlist RP onconf",
+ /* 64 */ "tcons ::= CHECK LP expr RP onconf",
+ /* 65 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt",
+ /* 66 */ "defer_subclause_opt ::=",
+ /* 67 */ "onconf ::=",
+ /* 68 */ "onconf ::= ON CONFLICT resolvetype",
+ /* 69 */ "orconf ::=",
+ /* 70 */ "orconf ::= OR resolvetype",
+ /* 71 */ "resolvetype ::= IGNORE",
+ /* 72 */ "resolvetype ::= REPLACE",
+ /* 73 */ "cmd ::= DROP TABLE ifexists fullname",
+ /* 74 */ "ifexists ::= IF EXISTS",
+ /* 75 */ "ifexists ::=",
+ /* 76 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select",
+ /* 77 */ "cmd ::= DROP VIEW ifexists fullname",
+ /* 78 */ "cmd ::= select",
+ /* 79 */ "select ::= with selectnowith",
+ /* 80 */ "selectnowith ::= selectnowith multiselect_op oneselect",
+ /* 81 */ "multiselect_op ::= UNION",
+ /* 82 */ "multiselect_op ::= UNION ALL",
+ /* 83 */ "multiselect_op ::= EXCEPT|INTERSECT",
+ /* 84 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
+ /* 85 */ "values ::= VALUES LP nexprlist RP",
+ /* 86 */ "values ::= values COMMA LP exprlist RP",
+ /* 87 */ "distinct ::= DISTINCT",
+ /* 88 */ "distinct ::= ALL",
+ /* 89 */ "distinct ::=",
+ /* 90 */ "sclp ::=",
+ /* 91 */ "selcollist ::= sclp expr as",
+ /* 92 */ "selcollist ::= sclp STAR",
+ /* 93 */ "selcollist ::= sclp nm DOT STAR",
+ /* 94 */ "as ::= AS nm",
+ /* 95 */ "as ::=",
+ /* 96 */ "from ::=",
+ /* 97 */ "from ::= FROM seltablist",
+ /* 98 */ "stl_prefix ::= seltablist joinop",
+ /* 99 */ "stl_prefix ::=",
+ /* 100 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
+ /* 101 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt",
+ /* 102 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
+ /* 103 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
+ /* 104 */ "dbnm ::=",
+ /* 105 */ "dbnm ::= DOT nm",
+ /* 106 */ "fullname ::= nm dbnm",
+ /* 107 */ "joinop ::= COMMA|JOIN",
+ /* 108 */ "joinop ::= JOIN_KW JOIN",
+ /* 109 */ "joinop ::= JOIN_KW nm JOIN",
+ /* 110 */ "joinop ::= JOIN_KW nm nm JOIN",
+ /* 111 */ "on_opt ::= ON expr",
+ /* 112 */ "on_opt ::=",
+ /* 113 */ "indexed_opt ::=",
+ /* 114 */ "indexed_opt ::= INDEXED BY nm",
+ /* 115 */ "indexed_opt ::= NOT INDEXED",
+ /* 116 */ "using_opt ::= USING LP idlist RP",
+ /* 117 */ "using_opt ::=",
+ /* 118 */ "orderby_opt ::=",
+ /* 119 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 120 */ "sortlist ::= sortlist COMMA expr sortorder",
+ /* 121 */ "sortlist ::= expr sortorder",
+ /* 122 */ "sortorder ::= ASC",
+ /* 123 */ "sortorder ::= DESC",
+ /* 124 */ "sortorder ::=",
+ /* 125 */ "groupby_opt ::=",
+ /* 126 */ "groupby_opt ::= GROUP BY nexprlist",
+ /* 127 */ "having_opt ::=",
+ /* 128 */ "having_opt ::= HAVING expr",
+ /* 129 */ "limit_opt ::=",
+ /* 130 */ "limit_opt ::= LIMIT expr",
+ /* 131 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 132 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 133 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt",
+ /* 134 */ "where_opt ::=",
+ /* 135 */ "where_opt ::= WHERE expr",
+ /* 136 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt",
+ /* 137 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 138 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
+ /* 139 */ "setlist ::= nm EQ expr",
+ /* 140 */ "setlist ::= LP idlist RP EQ expr",
+ /* 141 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select",
+ /* 142 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES",
+ /* 143 */ "insert_cmd ::= INSERT orconf",
+ /* 144 */ "insert_cmd ::= REPLACE",
+ /* 145 */ "idlist_opt ::=",
+ /* 146 */ "idlist_opt ::= LP idlist RP",
+ /* 147 */ "idlist ::= idlist COMMA nm",
+ /* 148 */ "idlist ::= nm",
+ /* 149 */ "expr ::= LP expr RP",
+ /* 150 */ "expr ::= ID|INDEXED",
+ /* 151 */ "expr ::= JOIN_KW",
+ /* 152 */ "expr ::= nm DOT nm",
+ /* 153 */ "expr ::= nm DOT nm DOT nm",
+ /* 154 */ "term ::= NULL|FLOAT|BLOB",
+ /* 155 */ "term ::= STRING",
+ /* 156 */ "term ::= INTEGER",
+ /* 157 */ "expr ::= VARIABLE",
+ /* 158 */ "expr ::= expr COLLATE ID|STRING",
+ /* 159 */ "expr ::= CAST LP expr AS typetoken RP",
+ /* 160 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
+ /* 161 */ "expr ::= ID|INDEXED LP STAR RP",
+ /* 162 */ "term ::= CTIME_KW",
+ /* 163 */ "expr ::= LP nexprlist COMMA expr RP",
+ /* 164 */ "expr ::= expr AND expr",
+ /* 165 */ "expr ::= expr OR expr",
+ /* 166 */ "expr ::= expr LT|GT|GE|LE expr",
+ /* 167 */ "expr ::= expr EQ|NE expr",
+ /* 168 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
+ /* 169 */ "expr ::= expr PLUS|MINUS expr",
+ /* 170 */ "expr ::= expr STAR|SLASH|REM expr",
+ /* 171 */ "expr ::= expr CONCAT expr",
+ /* 172 */ "likeop ::= NOT LIKE_KW|MATCH",
+ /* 173 */ "expr ::= expr likeop expr",
+ /* 174 */ "expr ::= expr likeop expr ESCAPE expr",
+ /* 175 */ "expr ::= expr ISNULL|NOTNULL",
+ /* 176 */ "expr ::= expr NOT NULL",
+ /* 177 */ "expr ::= expr IS expr",
+ /* 178 */ "expr ::= expr IS NOT expr",
+ /* 179 */ "expr ::= NOT expr",
+ /* 180 */ "expr ::= BITNOT expr",
+ /* 181 */ "expr ::= MINUS expr",
+ /* 182 */ "expr ::= PLUS expr",
+ /* 183 */ "between_op ::= BETWEEN",
+ /* 184 */ "between_op ::= NOT BETWEEN",
+ /* 185 */ "expr ::= expr between_op expr AND expr",
+ /* 186 */ "in_op ::= IN",
+ /* 187 */ "in_op ::= NOT IN",
+ /* 188 */ "expr ::= expr in_op LP exprlist RP",
+ /* 189 */ "expr ::= LP select RP",
+ /* 190 */ "expr ::= expr in_op LP select RP",
+ /* 191 */ "expr ::= expr in_op nm dbnm paren_exprlist",
+ /* 192 */ "expr ::= EXISTS LP select RP",
+ /* 193 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 194 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 195 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 196 */ "case_else ::= ELSE expr",
+ /* 197 */ "case_else ::=",
+ /* 198 */ "case_operand ::= expr",
+ /* 199 */ "case_operand ::=",
+ /* 200 */ "exprlist ::=",
+ /* 201 */ "nexprlist ::= nexprlist COMMA expr",
+ /* 202 */ "nexprlist ::= expr",
+ /* 203 */ "paren_exprlist ::=",
+ /* 204 */ "paren_exprlist ::= LP exprlist RP",
+ /* 205 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
+ /* 206 */ "uniqueflag ::= UNIQUE",
+ /* 207 */ "uniqueflag ::=",
+ /* 208 */ "eidlist_opt ::=",
+ /* 209 */ "eidlist_opt ::= LP eidlist RP",
+ /* 210 */ "eidlist ::= eidlist COMMA nm collate sortorder",
+ /* 211 */ "eidlist ::= nm collate sortorder",
+ /* 212 */ "collate ::=",
+ /* 213 */ "collate ::= COLLATE ID|STRING",
+ /* 214 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 215 */ "cmd ::= VACUUM",
+ /* 216 */ "cmd ::= VACUUM nm",
+ /* 217 */ "cmd ::= PRAGMA nm dbnm",
+ /* 218 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 219 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 220 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 221 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
+ /* 222 */ "plus_num ::= PLUS INTEGER|FLOAT",
+ /* 223 */ "minus_num ::= MINUS INTEGER|FLOAT",
+ /* 224 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
+ /* 225 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 226 */ "trigger_time ::= BEFORE|AFTER",
+ /* 227 */ "trigger_time ::= INSTEAD OF",
+ /* 228 */ "trigger_time ::=",
+ /* 229 */ "trigger_event ::= DELETE|INSERT",
+ /* 230 */ "trigger_event ::= UPDATE",
+ /* 231 */ "trigger_event ::= UPDATE OF idlist",
+ /* 232 */ "when_clause ::=",
+ /* 233 */ "when_clause ::= WHEN expr",
+ /* 234 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 235 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 236 */ "trnm ::= nm DOT nm",
+ /* 237 */ "tridxby ::= INDEXED BY nm",
+ /* 238 */ "tridxby ::= NOT INDEXED",
+ /* 239 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
+ /* 240 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select",
+ /* 241 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
+ /* 242 */ "trigger_cmd ::= select",
+ /* 243 */ "expr ::= RAISE LP IGNORE RP",
+ /* 244 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 245 */ "raisetype ::= ROLLBACK",
+ /* 246 */ "raisetype ::= ABORT",
+ /* 247 */ "raisetype ::= FAIL",
+ /* 248 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 249 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 250 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 251 */ "key_opt ::=",
+ /* 252 */ "key_opt ::= KEY expr",
+ /* 253 */ "cmd ::= REINDEX",
+ /* 254 */ "cmd ::= REINDEX nm dbnm",
+ /* 255 */ "cmd ::= ANALYZE",
+ /* 256 */ "cmd ::= ANALYZE nm dbnm",
+ /* 257 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 258 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
+ /* 259 */ "add_column_fullname ::= fullname",
+ /* 260 */ "cmd ::= create_vtab",
+ /* 261 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 262 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
+ /* 263 */ "vtabarg ::=",
+ /* 264 */ "vtabargtoken ::= ANY",
+ /* 265 */ "vtabargtoken ::= lp anylist RP",
+ /* 266 */ "lp ::= LP",
+ /* 267 */ "with ::=",
+ /* 268 */ "with ::= WITH wqlist",
+ /* 269 */ "with ::= WITH RECURSIVE wqlist",
+ /* 270 */ "wqlist ::= nm eidlist_opt AS LP select RP",
+ /* 271 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
+ /* 272 */ "input ::= cmdlist",
+ /* 273 */ "cmdlist ::= cmdlist ecmd",
+ /* 274 */ "cmdlist ::= ecmd",
+ /* 275 */ "ecmd ::= SEMI",
+ /* 276 */ "ecmd ::= explain cmdx SEMI",
+ /* 277 */ "explain ::=",
+ /* 278 */ "trans_opt ::=",
+ /* 279 */ "trans_opt ::= TRANSACTION",
+ /* 280 */ "trans_opt ::= TRANSACTION nm",
+ /* 281 */ "savepoint_opt ::= SAVEPOINT",
+ /* 282 */ "savepoint_opt ::=",
+ /* 283 */ "cmd ::= create_table create_table_args",
+ /* 284 */ "columnlist ::= columnlist COMMA columnname carglist",
+ /* 285 */ "columnlist ::= columnname carglist",
+ /* 286 */ "nm ::= ID|INDEXED",
+ /* 287 */ "nm ::= STRING",
+ /* 288 */ "nm ::= JOIN_KW",
+ /* 289 */ "typetoken ::= typename",
+ /* 290 */ "typename ::= ID|STRING",
+ /* 291 */ "signed ::= plus_num",
+ /* 292 */ "signed ::= minus_num",
+ /* 293 */ "carglist ::= carglist ccons",
+ /* 294 */ "carglist ::=",
+ /* 295 */ "ccons ::= NULL onconf",
+ /* 296 */ "conslist_opt ::= COMMA conslist",
+ /* 297 */ "conslist ::= conslist tconscomma tcons",
+ /* 298 */ "conslist ::= tcons",
+ /* 299 */ "tconscomma ::=",
+ /* 300 */ "defer_subclause_opt ::= defer_subclause",
+ /* 301 */ "resolvetype ::= raisetype",
+ /* 302 */ "selectnowith ::= oneselect",
+ /* 303 */ "oneselect ::= values",
+ /* 304 */ "sclp ::= selcollist COMMA",
+ /* 305 */ "as ::= ID|STRING",
+ /* 306 */ "expr ::= term",
+ /* 307 */ "likeop ::= LIKE_KW|MATCH",
+ /* 308 */ "exprlist ::= nexprlist",
+ /* 309 */ "nmnum ::= plus_num",
+ /* 310 */ "nmnum ::= nm",
+ /* 311 */ "nmnum ::= ON",
+ /* 312 */ "nmnum ::= DELETE",
+ /* 313 */ "nmnum ::= DEFAULT",
+ /* 314 */ "plus_num ::= INTEGER|FLOAT",
+ /* 315 */ "foreach_clause ::=",
+ /* 316 */ "foreach_clause ::= FOR EACH ROW",
+ /* 317 */ "trnm ::= nm",
+ /* 318 */ "tridxby ::=",
+ /* 319 */ "database_kw_opt ::= DATABASE",
+ /* 320 */ "database_kw_opt ::=",
+ /* 321 */ "kwcolumn_opt ::=",
+ /* 322 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 323 */ "vtabarglist ::= vtabarg",
+ /* 324 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 325 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 326 */ "anylist ::=",
+ /* 327 */ "anylist ::= anylist LP anylist RP",
+ /* 328 */ "anylist ::= anylist ANY",
};
#endif /* NDEBUG */
@@ -137413,6 +141316,34 @@ static int yyGrowStack(yyParser *p){
# define YYMALLOCARGTYPE size_t
#endif
+/* Initialize a new parser that has already been allocated.
+*/
+SQLITE_PRIVATE void sqlite3ParserInit(void *yypParser){
+ yyParser *pParser = (yyParser*)yypParser;
+#ifdef YYTRACKMAXSTACKDEPTH
+ pParser->yyhwm = 0;
+#endif
+#if YYSTACKDEPTH<=0
+ pParser->yytos = NULL;
+ pParser->yystack = NULL;
+ pParser->yystksz = 0;
+ if( yyGrowStack(pParser) ){
+ pParser->yystack = &pParser->yystk0;
+ pParser->yystksz = 1;
+ }
+#endif
+#ifndef YYNOERRORRECOVERY
+ pParser->yyerrcnt = -1;
+#endif
+ pParser->yytos = pParser->yystack;
+ pParser->yystack[0].stateno = 0;
+ pParser->yystack[0].major = 0;
+#if YYSTACKDEPTH>0
+ pParser->yystackEnd = &pParser->yystack[YYSTACKDEPTH-1];
+#endif
+}
+
+#ifndef sqlite3Parser_ENGINEALWAYSONSTACK
/*
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
@@ -137428,28 +141359,11 @@ static int yyGrowStack(yyParser *p){
SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){
yyParser *pParser;
pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
- if( pParser ){
-#ifdef YYTRACKMAXSTACKDEPTH
- pParser->yyhwm = 0;
-#endif
-#if YYSTACKDEPTH<=0
- pParser->yytos = NULL;
- pParser->yystack = NULL;
- pParser->yystksz = 0;
- if( yyGrowStack(pParser) ){
- pParser->yystack = &pParser->yystk0;
- pParser->yystksz = 1;
- }
-#endif
-#ifndef YYNOERRORRECOVERY
- pParser->yyerrcnt = -1;
-#endif
- pParser->yytos = pParser->yystack;
- pParser->yystack[0].stateno = 0;
- pParser->yystack[0].major = 0;
- }
+ if( pParser ) sqlite3ParserInit(pParser);
return pParser;
}
+#endif /* sqlite3Parser_ENGINEALWAYSONSTACK */
+
/* The following function deletes the "minor type" or semantic value
** associated with a symbol. The symbol can be either a terminal
@@ -137575,6 +141489,18 @@ static void yy_pop_parser_stack(yyParser *pParser){
yy_destructor(pParser, yytos->major, &yytos->minor);
}
+/*
+** Clear all secondary memory allocations from the parser
+*/
+SQLITE_PRIVATE void sqlite3ParserFinalize(void *p){
+ yyParser *pParser = (yyParser*)p;
+ while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
+#if YYSTACKDEPTH<=0
+ if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
+#endif
+}
+
+#ifndef sqlite3Parser_ENGINEALWAYSONSTACK
/*
** Deallocate and destroy a parser. Destructors are called for
** all stack elements before shutting the parser down.
@@ -137587,16 +141513,13 @@ SQLITE_PRIVATE void sqlite3ParserFree(
void *p, /* The parser to be deleted */
void (*freeProc)(void*) /* Function used to reclaim memory */
){
- yyParser *pParser = (yyParser*)p;
#ifndef YYPARSEFREENEVERNULL
- if( pParser==0 ) return;
+ if( p==0 ) return;
#endif
- while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
-#if YYSTACKDEPTH<=0
- if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
-#endif
- (*freeProc)((void*)pParser);
+ sqlite3ParserFinalize(p);
+ (*freeProc)(p);
}
+#endif /* sqlite3Parser_ENGINEALWAYSONSTACK */
/*
** Return the peak depth of the stack for a parser.
@@ -137707,7 +141630,6 @@ static int yy_find_reduce_action(
*/
static void yyStackOverflow(yyParser *yypParser){
sqlite3ParserARG_FETCH;
- yypParser->yytos--;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
@@ -137761,13 +141683,15 @@ static void yy_shift(
}
#endif
#if YYSTACKDEPTH>0
- if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH] ){
+ if( yypParser->yytos>yypParser->yystackEnd ){
+ yypParser->yytos--;
yyStackOverflow(yypParser);
return;
}
#else
if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){
if( yyGrowStack(yypParser) ){
+ yypParser->yytos--;
yyStackOverflow(yypParser);
return;
}
@@ -137787,341 +141711,338 @@ static void yy_shift(
** is used during the reduce.
*/
static const struct {
- YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
- unsigned char nrhs; /* Number of right-hand side symbols in the rule */
+ YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
+ signed char nrhs; /* Negative of the number of RHS symbols in the rule */
} yyRuleInfo[] = {
- { 147, 1 },
- { 147, 3 },
- { 148, 1 },
- { 149, 3 },
+ { 147, -1 },
+ { 147, -3 },
+ { 148, -1 },
+ { 149, -3 },
{ 150, 0 },
- { 150, 1 },
- { 150, 1 },
- { 150, 1 },
- { 149, 2 },
- { 149, 2 },
- { 149, 2 },
- { 149, 2 },
- { 149, 3 },
- { 149, 5 },
- { 154, 6 },
- { 156, 1 },
+ { 150, -1 },
+ { 150, -1 },
+ { 150, -1 },
+ { 149, -2 },
+ { 149, -2 },
+ { 149, -2 },
+ { 149, -3 },
+ { 149, -5 },
+ { 154, -6 },
+ { 156, -1 },
{ 158, 0 },
- { 158, 3 },
- { 157, 1 },
+ { 158, -3 },
+ { 157, -1 },
{ 157, 0 },
- { 155, 5 },
- { 155, 2 },
+ { 155, -5 },
+ { 155, -2 },
{ 162, 0 },
- { 162, 2 },
- { 164, 2 },
+ { 162, -2 },
+ { 164, -2 },
{ 166, 0 },
- { 166, 4 },
- { 166, 6 },
- { 167, 2 },
- { 171, 2 },
- { 171, 2 },
- { 171, 4 },
- { 171, 3 },
- { 171, 3 },
- { 171, 2 },
- { 171, 3 },
- { 171, 5 },
- { 171, 2 },
- { 171, 4 },
- { 171, 4 },
- { 171, 1 },
- { 171, 2 },
+ { 166, -4 },
+ { 166, -6 },
+ { 167, -2 },
+ { 171, -2 },
+ { 171, -2 },
+ { 171, -4 },
+ { 171, -3 },
+ { 171, -3 },
+ { 171, -2 },
+ { 171, -3 },
+ { 171, -5 },
+ { 171, -2 },
+ { 171, -4 },
+ { 171, -4 },
+ { 171, -1 },
+ { 171, -2 },
{ 176, 0 },
- { 176, 1 },
+ { 176, -1 },
{ 178, 0 },
- { 178, 2 },
- { 180, 2 },
- { 180, 3 },
- { 180, 3 },
- { 180, 3 },
- { 181, 2 },
- { 181, 2 },
- { 181, 1 },
- { 181, 1 },
- { 181, 2 },
- { 179, 3 },
- { 179, 2 },
+ { 178, -2 },
+ { 180, -2 },
+ { 180, -3 },
+ { 180, -3 },
+ { 180, -3 },
+ { 181, -2 },
+ { 181, -2 },
+ { 181, -1 },
+ { 181, -1 },
+ { 181, -2 },
+ { 179, -3 },
+ { 179, -2 },
{ 182, 0 },
- { 182, 2 },
- { 182, 2 },
+ { 182, -2 },
+ { 182, -2 },
{ 161, 0 },
- { 184, 1 },
- { 185, 2 },
- { 185, 7 },
- { 185, 5 },
- { 185, 5 },
- { 185, 10 },
+ { 184, -1 },
+ { 185, -2 },
+ { 185, -7 },
+ { 185, -5 },
+ { 185, -5 },
+ { 185, -10 },
{ 188, 0 },
{ 174, 0 },
- { 174, 3 },
+ { 174, -3 },
{ 189, 0 },
- { 189, 2 },
- { 190, 1 },
- { 190, 1 },
- { 149, 4 },
- { 192, 2 },
+ { 189, -2 },
+ { 190, -1 },
+ { 190, -1 },
+ { 149, -4 },
+ { 192, -2 },
{ 192, 0 },
- { 149, 9 },
- { 149, 4 },
- { 149, 1 },
- { 163, 2 },
- { 194, 3 },
- { 197, 1 },
- { 197, 2 },
- { 197, 1 },
- { 195, 9 },
- { 206, 4 },
- { 206, 5 },
- { 198, 1 },
- { 198, 1 },
+ { 149, -9 },
+ { 149, -4 },
+ { 149, -1 },
+ { 163, -2 },
+ { 194, -3 },
+ { 197, -1 },
+ { 197, -2 },
+ { 197, -1 },
+ { 195, -9 },
+ { 206, -4 },
+ { 206, -5 },
+ { 198, -1 },
+ { 198, -1 },
{ 198, 0 },
{ 209, 0 },
- { 199, 3 },
- { 199, 2 },
- { 199, 4 },
- { 210, 2 },
+ { 199, -3 },
+ { 199, -2 },
+ { 199, -4 },
+ { 210, -2 },
{ 210, 0 },
{ 200, 0 },
- { 200, 2 },
- { 212, 2 },
+ { 200, -2 },
+ { 212, -2 },
{ 212, 0 },
- { 211, 7 },
- { 211, 9 },
- { 211, 7 },
- { 211, 7 },
+ { 211, -7 },
+ { 211, -9 },
+ { 211, -7 },
+ { 211, -7 },
{ 159, 0 },
- { 159, 2 },
- { 193, 2 },
- { 213, 1 },
- { 213, 2 },
- { 213, 3 },
- { 213, 4 },
- { 215, 2 },
+ { 159, -2 },
+ { 193, -2 },
+ { 213, -1 },
+ { 213, -2 },
+ { 213, -3 },
+ { 213, -4 },
+ { 215, -2 },
{ 215, 0 },
{ 214, 0 },
- { 214, 3 },
- { 214, 2 },
- { 216, 4 },
+ { 214, -3 },
+ { 214, -2 },
+ { 216, -4 },
{ 216, 0 },
{ 204, 0 },
- { 204, 3 },
- { 186, 4 },
- { 186, 2 },
- { 175, 1 },
- { 175, 1 },
+ { 204, -3 },
+ { 186, -4 },
+ { 186, -2 },
+ { 175, -1 },
+ { 175, -1 },
{ 175, 0 },
{ 202, 0 },
- { 202, 3 },
+ { 202, -3 },
{ 203, 0 },
- { 203, 2 },
+ { 203, -2 },
{ 205, 0 },
- { 205, 2 },
- { 205, 4 },
- { 205, 4 },
- { 149, 6 },
+ { 205, -2 },
+ { 205, -4 },
+ { 205, -4 },
+ { 149, -6 },
{ 201, 0 },
- { 201, 2 },
- { 149, 8 },
- { 218, 5 },
- { 218, 7 },
- { 218, 3 },
- { 218, 5 },
- { 149, 6 },
- { 149, 7 },
- { 219, 2 },
- { 219, 1 },
+ { 201, -2 },
+ { 149, -8 },
+ { 218, -5 },
+ { 218, -7 },
+ { 218, -3 },
+ { 218, -5 },
+ { 149, -6 },
+ { 149, -7 },
+ { 219, -2 },
+ { 219, -1 },
{ 220, 0 },
- { 220, 3 },
- { 217, 3 },
- { 217, 1 },
- { 173, 3 },
- { 172, 1 },
- { 173, 1 },
- { 173, 1 },
- { 173, 3 },
- { 173, 5 },
- { 172, 1 },
- { 172, 1 },
- { 172, 1 },
- { 173, 1 },
- { 173, 3 },
- { 173, 6 },
- { 173, 5 },
- { 173, 4 },
- { 172, 1 },
- { 173, 5 },
- { 173, 3 },
- { 173, 3 },
- { 173, 3 },
- { 173, 3 },
- { 173, 3 },
- { 173, 3 },
- { 173, 3 },
- { 173, 3 },
- { 221, 1 },
- { 221, 2 },
- { 173, 3 },
- { 173, 5 },
- { 173, 2 },
- { 173, 3 },
- { 173, 3 },
- { 173, 4 },
- { 173, 2 },
- { 173, 2 },
- { 173, 2 },
- { 173, 2 },
- { 222, 1 },
- { 222, 2 },
- { 173, 5 },
- { 223, 1 },
- { 223, 2 },
- { 173, 5 },
- { 173, 3 },
- { 173, 5 },
- { 173, 5 },
- { 173, 4 },
- { 173, 5 },
- { 226, 5 },
- { 226, 4 },
- { 227, 2 },
+ { 220, -3 },
+ { 217, -3 },
+ { 217, -1 },
+ { 173, -3 },
+ { 173, -1 },
+ { 173, -1 },
+ { 173, -3 },
+ { 173, -5 },
+ { 172, -1 },
+ { 172, -1 },
+ { 172, -1 },
+ { 173, -1 },
+ { 173, -3 },
+ { 173, -6 },
+ { 173, -5 },
+ { 173, -4 },
+ { 172, -1 },
+ { 173, -5 },
+ { 173, -3 },
+ { 173, -3 },
+ { 173, -3 },
+ { 173, -3 },
+ { 173, -3 },
+ { 173, -3 },
+ { 173, -3 },
+ { 173, -3 },
+ { 221, -2 },
+ { 173, -3 },
+ { 173, -5 },
+ { 173, -2 },
+ { 173, -3 },
+ { 173, -3 },
+ { 173, -4 },
+ { 173, -2 },
+ { 173, -2 },
+ { 173, -2 },
+ { 173, -2 },
+ { 222, -1 },
+ { 222, -2 },
+ { 173, -5 },
+ { 223, -1 },
+ { 223, -2 },
+ { 173, -5 },
+ { 173, -3 },
+ { 173, -5 },
+ { 173, -5 },
+ { 173, -4 },
+ { 173, -5 },
+ { 226, -5 },
+ { 226, -4 },
+ { 227, -2 },
{ 227, 0 },
- { 225, 1 },
+ { 225, -1 },
{ 225, 0 },
{ 208, 0 },
- { 207, 3 },
- { 207, 1 },
+ { 207, -3 },
+ { 207, -1 },
{ 224, 0 },
- { 224, 3 },
- { 149, 12 },
- { 228, 1 },
+ { 224, -3 },
+ { 149, -12 },
+ { 228, -1 },
{ 228, 0 },
{ 177, 0 },
- { 177, 3 },
- { 187, 5 },
- { 187, 3 },
+ { 177, -3 },
+ { 187, -5 },
+ { 187, -3 },
{ 229, 0 },
- { 229, 2 },
- { 149, 4 },
- { 149, 1 },
- { 149, 2 },
- { 149, 3 },
- { 149, 5 },
- { 149, 6 },
- { 149, 5 },
- { 149, 6 },
- { 169, 2 },
- { 170, 2 },
- { 149, 5 },
- { 231, 11 },
- { 233, 1 },
- { 233, 1 },
- { 233, 2 },
+ { 229, -2 },
+ { 149, -4 },
+ { 149, -1 },
+ { 149, -2 },
+ { 149, -3 },
+ { 149, -5 },
+ { 149, -6 },
+ { 149, -5 },
+ { 149, -6 },
+ { 169, -2 },
+ { 170, -2 },
+ { 149, -5 },
+ { 231, -11 },
+ { 233, -1 },
+ { 233, -2 },
{ 233, 0 },
- { 234, 1 },
- { 234, 1 },
- { 234, 3 },
+ { 234, -1 },
+ { 234, -1 },
+ { 234, -3 },
{ 236, 0 },
- { 236, 2 },
- { 232, 3 },
- { 232, 2 },
- { 238, 3 },
- { 239, 3 },
- { 239, 2 },
- { 237, 7 },
- { 237, 5 },
- { 237, 5 },
- { 237, 1 },
- { 173, 4 },
- { 173, 6 },
- { 191, 1 },
- { 191, 1 },
- { 191, 1 },
- { 149, 4 },
- { 149, 6 },
- { 149, 3 },
+ { 236, -2 },
+ { 232, -3 },
+ { 232, -2 },
+ { 238, -3 },
+ { 239, -3 },
+ { 239, -2 },
+ { 237, -7 },
+ { 237, -5 },
+ { 237, -5 },
+ { 237, -1 },
+ { 173, -4 },
+ { 173, -6 },
+ { 191, -1 },
+ { 191, -1 },
+ { 191, -1 },
+ { 149, -4 },
+ { 149, -6 },
+ { 149, -3 },
{ 241, 0 },
- { 241, 2 },
- { 149, 1 },
- { 149, 3 },
- { 149, 1 },
- { 149, 3 },
- { 149, 6 },
- { 149, 7 },
- { 242, 1 },
- { 149, 1 },
- { 149, 4 },
- { 244, 8 },
+ { 241, -2 },
+ { 149, -1 },
+ { 149, -3 },
+ { 149, -1 },
+ { 149, -3 },
+ { 149, -6 },
+ { 149, -7 },
+ { 242, -1 },
+ { 149, -1 },
+ { 149, -4 },
+ { 244, -8 },
{ 246, 0 },
- { 247, 1 },
- { 247, 3 },
- { 248, 1 },
+ { 247, -1 },
+ { 247, -3 },
+ { 248, -1 },
{ 196, 0 },
- { 196, 2 },
- { 196, 3 },
- { 250, 6 },
- { 250, 8 },
- { 144, 1 },
- { 145, 2 },
- { 145, 1 },
- { 146, 1 },
- { 146, 3 },
+ { 196, -2 },
+ { 196, -3 },
+ { 250, -6 },
+ { 250, -8 },
+ { 144, -1 },
+ { 145, -2 },
+ { 145, -1 },
+ { 146, -1 },
+ { 146, -3 },
{ 147, 0 },
{ 151, 0 },
- { 151, 1 },
- { 151, 2 },
- { 153, 1 },
+ { 151, -1 },
+ { 151, -2 },
+ { 153, -1 },
{ 153, 0 },
- { 149, 2 },
- { 160, 4 },
- { 160, 2 },
- { 152, 1 },
- { 152, 1 },
- { 152, 1 },
- { 166, 1 },
- { 167, 1 },
- { 168, 1 },
- { 168, 1 },
- { 165, 2 },
+ { 149, -2 },
+ { 160, -4 },
+ { 160, -2 },
+ { 152, -1 },
+ { 152, -1 },
+ { 152, -1 },
+ { 166, -1 },
+ { 167, -1 },
+ { 168, -1 },
+ { 168, -1 },
+ { 165, -2 },
{ 165, 0 },
- { 171, 2 },
- { 161, 2 },
- { 183, 3 },
- { 183, 1 },
+ { 171, -2 },
+ { 161, -2 },
+ { 183, -3 },
+ { 183, -1 },
{ 184, 0 },
- { 188, 1 },
- { 190, 1 },
- { 194, 1 },
- { 195, 1 },
- { 209, 2 },
- { 210, 1 },
- { 173, 1 },
- { 208, 1 },
- { 230, 1 },
- { 230, 1 },
- { 230, 1 },
- { 230, 1 },
- { 230, 1 },
- { 169, 1 },
+ { 188, -1 },
+ { 190, -1 },
+ { 194, -1 },
+ { 195, -1 },
+ { 209, -2 },
+ { 210, -1 },
+ { 173, -1 },
+ { 221, -1 },
+ { 208, -1 },
+ { 230, -1 },
+ { 230, -1 },
+ { 230, -1 },
+ { 230, -1 },
+ { 230, -1 },
+ { 169, -1 },
{ 235, 0 },
- { 235, 3 },
- { 238, 1 },
+ { 235, -3 },
+ { 238, -1 },
{ 239, 0 },
- { 240, 1 },
+ { 240, -1 },
{ 240, 0 },
{ 243, 0 },
- { 243, 1 },
- { 245, 1 },
- { 245, 3 },
- { 246, 2 },
+ { 243, -1 },
+ { 245, -1 },
+ { 245, -3 },
+ { 246, -2 },
{ 249, 0 },
- { 249, 4 },
- { 249, 2 },
+ { 249, -4 },
+ { 249, -2 },
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -138144,7 +142065,7 @@ static void yy_reduce(
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
yysize = yyRuleInfo[yyruleno].nrhs;
fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt,
- yyRuleName[yyruleno], yymsp[-yysize].stateno);
+ yyRuleName[yyruleno], yymsp[yysize].stateno);
}
#endif /* NDEBUG */
@@ -138159,7 +142080,7 @@ static void yy_reduce(
}
#endif
#if YYSTACKDEPTH>0
- if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH-1] ){
+ if( yypParser->yytos>=yypParser->yystackEnd ){
yyStackOverflow(yypParser);
return;
}
@@ -138205,66 +142126,63 @@ static void yy_reduce(
case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7);
{yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-X*/}
break;
- case 8: /* cmd ::= COMMIT trans_opt */
- case 9: /* cmd ::= END trans_opt */ yytestcase(yyruleno==9);
-{sqlite3CommitTransaction(pParse);}
+ case 8: /* cmd ::= COMMIT|END trans_opt */
+ case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9);
+{sqlite3EndTransaction(pParse,yymsp[-1].major);}
break;
- case 10: /* cmd ::= ROLLBACK trans_opt */
-{sqlite3RollbackTransaction(pParse);}
- break;
- case 11: /* cmd ::= SAVEPOINT nm */
+ case 10: /* cmd ::= SAVEPOINT nm */
{
sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &yymsp[0].minor.yy0);
}
break;
- case 12: /* cmd ::= RELEASE savepoint_opt nm */
+ case 11: /* cmd ::= RELEASE savepoint_opt nm */
{
sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &yymsp[0].minor.yy0);
}
break;
- case 13: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
+ case 12: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
{
sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0);
}
break;
- case 14: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
+ case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy194,0,0,yymsp[-2].minor.yy194);
}
break;
- case 15: /* createkw ::= CREATE */
+ case 14: /* createkw ::= CREATE */
{disableLookaside(pParse);}
break;
- case 16: /* ifnotexists ::= */
- case 19: /* temp ::= */ yytestcase(yyruleno==19);
- case 22: /* table_options ::= */ yytestcase(yyruleno==22);
- case 42: /* autoinc ::= */ yytestcase(yyruleno==42);
- case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57);
- case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67);
- case 76: /* ifexists ::= */ yytestcase(yyruleno==76);
- case 90: /* distinct ::= */ yytestcase(yyruleno==90);
- case 215: /* collate ::= */ yytestcase(yyruleno==215);
+ case 15: /* ifnotexists ::= */
+ case 18: /* temp ::= */ yytestcase(yyruleno==18);
+ case 21: /* table_options ::= */ yytestcase(yyruleno==21);
+ case 41: /* autoinc ::= */ yytestcase(yyruleno==41);
+ case 56: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==56);
+ case 66: /* defer_subclause_opt ::= */ yytestcase(yyruleno==66);
+ case 75: /* ifexists ::= */ yytestcase(yyruleno==75);
+ case 89: /* distinct ::= */ yytestcase(yyruleno==89);
+ case 212: /* collate ::= */ yytestcase(yyruleno==212);
{yymsp[1].minor.yy194 = 0;}
break;
- case 17: /* ifnotexists ::= IF NOT EXISTS */
+ case 16: /* ifnotexists ::= IF NOT EXISTS */
{yymsp[-2].minor.yy194 = 1;}
break;
- case 18: /* temp ::= TEMP */
- case 43: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==43);
+ case 17: /* temp ::= TEMP */
+ case 42: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==42);
{yymsp[0].minor.yy194 = 1;}
break;
- case 20: /* create_table_args ::= LP columnlist conslist_opt RP table_options */
+ case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_options */
{
sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy194,0);
}
break;
- case 21: /* create_table_args ::= AS select */
+ case 20: /* create_table_args ::= AS select */
{
sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy243);
sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243);
}
break;
- case 23: /* table_options ::= WITHOUT nm */
+ case 22: /* table_options ::= WITHOUT nm */
{
if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){
yymsp[-1].minor.yy194 = TF_WithoutRowid | TF_NoVisibleRowid;
@@ -138274,183 +142192,183 @@ static void yy_reduce(
}
}
break;
- case 24: /* columnname ::= nm typetoken */
+ case 23: /* columnname ::= nm typetoken */
{sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
break;
- case 25: /* typetoken ::= */
- case 60: /* conslist_opt ::= */ yytestcase(yyruleno==60);
- case 96: /* as ::= */ yytestcase(yyruleno==96);
+ case 24: /* typetoken ::= */
+ case 59: /* conslist_opt ::= */ yytestcase(yyruleno==59);
+ case 95: /* as ::= */ yytestcase(yyruleno==95);
{yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;}
break;
- case 26: /* typetoken ::= typename LP signed RP */
+ case 25: /* typetoken ::= typename LP signed RP */
{
yymsp[-3].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z);
}
break;
- case 27: /* typetoken ::= typename LP signed COMMA signed RP */
+ case 26: /* typetoken ::= typename LP signed COMMA signed RP */
{
yymsp[-5].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
}
break;
- case 28: /* typename ::= typename ID|STRING */
+ case 27: /* typename ::= typename ID|STRING */
{yymsp[-1].minor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
break;
- case 29: /* ccons ::= CONSTRAINT nm */
- case 62: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==62);
+ case 28: /* ccons ::= CONSTRAINT nm */
+ case 61: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==61);
{pParse->constraintName = yymsp[0].minor.yy0;}
break;
- case 30: /* ccons ::= DEFAULT term */
- case 32: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==32);
+ case 29: /* ccons ::= DEFAULT term */
+ case 31: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==31);
{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy190);}
break;
- case 31: /* ccons ::= DEFAULT LP expr RP */
+ case 30: /* ccons ::= DEFAULT LP expr RP */
{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy190);}
break;
- case 33: /* ccons ::= DEFAULT MINUS term */
+ case 32: /* ccons ::= DEFAULT MINUS term */
{
ExprSpan v;
- v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy190.pExpr, 0, 0);
+ v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy190.pExpr, 0);
v.zStart = yymsp[-1].minor.yy0.z;
v.zEnd = yymsp[0].minor.yy190.zEnd;
sqlite3AddDefaultValue(pParse,&v);
}
break;
- case 34: /* ccons ::= DEFAULT ID|INDEXED */
+ case 33: /* ccons ::= DEFAULT ID|INDEXED */
{
ExprSpan v;
spanExpr(&v, pParse, TK_STRING, yymsp[0].minor.yy0);
sqlite3AddDefaultValue(pParse,&v);
}
break;
- case 35: /* ccons ::= NOT NULL onconf */
+ case 34: /* ccons ::= NOT NULL onconf */
{sqlite3AddNotNull(pParse, yymsp[0].minor.yy194);}
break;
- case 36: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
+ case 35: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy194,yymsp[0].minor.yy194,yymsp[-2].minor.yy194);}
break;
- case 37: /* ccons ::= UNIQUE onconf */
+ case 36: /* ccons ::= UNIQUE onconf */
{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy194,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
- case 38: /* ccons ::= CHECK LP expr RP */
+ case 37: /* ccons ::= CHECK LP expr RP */
{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy190.pExpr);}
break;
- case 39: /* ccons ::= REFERENCES nm eidlist_opt refargs */
+ case 38: /* ccons ::= REFERENCES nm eidlist_opt refargs */
{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy148,yymsp[0].minor.yy194);}
break;
- case 40: /* ccons ::= defer_subclause */
+ case 39: /* ccons ::= defer_subclause */
{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy194);}
break;
- case 41: /* ccons ::= COLLATE ID|STRING */
+ case 40: /* ccons ::= COLLATE ID|STRING */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
- case 44: /* refargs ::= */
+ case 43: /* refargs ::= */
{ yymsp[1].minor.yy194 = OE_None*0x0101; /* EV: R-19803-45884 */}
break;
- case 45: /* refargs ::= refargs refarg */
+ case 44: /* refargs ::= refargs refarg */
{ yymsp[-1].minor.yy194 = (yymsp[-1].minor.yy194 & ~yymsp[0].minor.yy497.mask) | yymsp[0].minor.yy497.value; }
break;
- case 46: /* refarg ::= MATCH nm */
+ case 45: /* refarg ::= MATCH nm */
{ yymsp[-1].minor.yy497.value = 0; yymsp[-1].minor.yy497.mask = 0x000000; }
break;
- case 47: /* refarg ::= ON INSERT refact */
+ case 46: /* refarg ::= ON INSERT refact */
{ yymsp[-2].minor.yy497.value = 0; yymsp[-2].minor.yy497.mask = 0x000000; }
break;
- case 48: /* refarg ::= ON DELETE refact */
+ case 47: /* refarg ::= ON DELETE refact */
{ yymsp[-2].minor.yy497.value = yymsp[0].minor.yy194; yymsp[-2].minor.yy497.mask = 0x0000ff; }
break;
- case 49: /* refarg ::= ON UPDATE refact */
+ case 48: /* refarg ::= ON UPDATE refact */
{ yymsp[-2].minor.yy497.value = yymsp[0].minor.yy194<<8; yymsp[-2].minor.yy497.mask = 0x00ff00; }
break;
- case 50: /* refact ::= SET NULL */
+ case 49: /* refact ::= SET NULL */
{ yymsp[-1].minor.yy194 = OE_SetNull; /* EV: R-33326-45252 */}
break;
- case 51: /* refact ::= SET DEFAULT */
+ case 50: /* refact ::= SET DEFAULT */
{ yymsp[-1].minor.yy194 = OE_SetDflt; /* EV: R-33326-45252 */}
break;
- case 52: /* refact ::= CASCADE */
+ case 51: /* refact ::= CASCADE */
{ yymsp[0].minor.yy194 = OE_Cascade; /* EV: R-33326-45252 */}
break;
- case 53: /* refact ::= RESTRICT */
+ case 52: /* refact ::= RESTRICT */
{ yymsp[0].minor.yy194 = OE_Restrict; /* EV: R-33326-45252 */}
break;
- case 54: /* refact ::= NO ACTION */
+ case 53: /* refact ::= NO ACTION */
{ yymsp[-1].minor.yy194 = OE_None; /* EV: R-33326-45252 */}
break;
- case 55: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+ case 54: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
{yymsp[-2].minor.yy194 = 0;}
break;
- case 56: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
- case 71: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==71);
- case 144: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==144);
+ case 55: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ case 70: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==70);
+ case 143: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==143);
{yymsp[-1].minor.yy194 = yymsp[0].minor.yy194;}
break;
- case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
- case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75);
- case 187: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==187);
- case 190: /* in_op ::= NOT IN */ yytestcase(yyruleno==190);
- case 216: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==216);
+ case 57: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
+ case 74: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==74);
+ case 184: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==184);
+ case 187: /* in_op ::= NOT IN */ yytestcase(yyruleno==187);
+ case 213: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==213);
{yymsp[-1].minor.yy194 = 1;}
break;
- case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+ case 58: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
{yymsp[-1].minor.yy194 = 0;}
break;
- case 61: /* tconscomma ::= COMMA */
+ case 60: /* tconscomma ::= COMMA */
{pParse->constraintName.n = 0;}
break;
- case 63: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+ case 62: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy148,yymsp[0].minor.yy194,yymsp[-2].minor.yy194,0);}
break;
- case 64: /* tcons ::= UNIQUE LP sortlist RP onconf */
+ case 63: /* tcons ::= UNIQUE LP sortlist RP onconf */
{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy148,yymsp[0].minor.yy194,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
- case 65: /* tcons ::= CHECK LP expr RP onconf */
+ case 64: /* tcons ::= CHECK LP expr RP onconf */
{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy190.pExpr);}
break;
- case 66: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+ case 65: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
{
sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy148, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy148, yymsp[-1].minor.yy194);
sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy194);
}
break;
- case 68: /* onconf ::= */
- case 70: /* orconf ::= */ yytestcase(yyruleno==70);
+ case 67: /* onconf ::= */
+ case 69: /* orconf ::= */ yytestcase(yyruleno==69);
{yymsp[1].minor.yy194 = OE_Default;}
break;
- case 69: /* onconf ::= ON CONFLICT resolvetype */
+ case 68: /* onconf ::= ON CONFLICT resolvetype */
{yymsp[-2].minor.yy194 = yymsp[0].minor.yy194;}
break;
- case 72: /* resolvetype ::= IGNORE */
+ case 71: /* resolvetype ::= IGNORE */
{yymsp[0].minor.yy194 = OE_Ignore;}
break;
- case 73: /* resolvetype ::= REPLACE */
- case 145: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==145);
+ case 72: /* resolvetype ::= REPLACE */
+ case 144: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==144);
{yymsp[0].minor.yy194 = OE_Replace;}
break;
- case 74: /* cmd ::= DROP TABLE ifexists fullname */
+ case 73: /* cmd ::= DROP TABLE ifexists fullname */
{
sqlite3DropTable(pParse, yymsp[0].minor.yy185, 0, yymsp[-1].minor.yy194);
}
break;
- case 77: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+ case 76: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
{
sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy148, yymsp[0].minor.yy243, yymsp[-7].minor.yy194, yymsp[-5].minor.yy194);
}
break;
- case 78: /* cmd ::= DROP VIEW ifexists fullname */
+ case 77: /* cmd ::= DROP VIEW ifexists fullname */
{
sqlite3DropTable(pParse, yymsp[0].minor.yy185, 1, yymsp[-1].minor.yy194);
}
break;
- case 79: /* cmd ::= select */
+ case 78: /* cmd ::= select */
{
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
sqlite3Select(pParse, yymsp[0].minor.yy243, &dest);
sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243);
}
break;
- case 80: /* select ::= with selectnowith */
+ case 79: /* select ::= with selectnowith */
{
Select *p = yymsp[0].minor.yy243;
if( p ){
@@ -138462,7 +142380,7 @@ static void yy_reduce(
yymsp[-1].minor.yy243 = p; /*A-overwrites-W*/
}
break;
- case 81: /* selectnowith ::= selectnowith multiselect_op oneselect */
+ case 80: /* selectnowith ::= selectnowith multiselect_op oneselect */
{
Select *pRhs = yymsp[0].minor.yy243;
Select *pLhs = yymsp[-2].minor.yy243;
@@ -138486,14 +142404,14 @@ static void yy_reduce(
yymsp[-2].minor.yy243 = pRhs;
}
break;
- case 82: /* multiselect_op ::= UNION */
- case 84: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==84);
+ case 81: /* multiselect_op ::= UNION */
+ case 83: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==83);
{yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-OP*/}
break;
- case 83: /* multiselect_op ::= UNION ALL */
+ case 82: /* multiselect_op ::= UNION ALL */
{yymsp[-1].minor.yy194 = TK_ALL;}
break;
- case 85: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ case 84: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
#if SELECTTRACE_ENABLED
Token s = yymsp[-8].minor.yy0; /*A-overwrites-S*/
@@ -138525,12 +142443,12 @@ static void yy_reduce(
#endif /* SELECTRACE_ENABLED */
}
break;
- case 86: /* values ::= VALUES LP nexprlist RP */
+ case 85: /* values ::= VALUES LP nexprlist RP */
{
yymsp[-3].minor.yy243 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy148,0,0,0,0,0,SF_Values,0,0);
}
break;
- case 87: /* values ::= values COMMA LP exprlist RP */
+ case 86: /* values ::= values COMMA LP exprlist RP */
{
Select *pRight, *pLeft = yymsp[-4].minor.yy243;
pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy148,0,0,0,0,0,SF_Values|SF_MultiValue,0,0);
@@ -138544,82 +142462,82 @@ static void yy_reduce(
}
}
break;
- case 88: /* distinct ::= DISTINCT */
+ case 87: /* distinct ::= DISTINCT */
{yymsp[0].minor.yy194 = SF_Distinct;}
break;
- case 89: /* distinct ::= ALL */
+ case 88: /* distinct ::= ALL */
{yymsp[0].minor.yy194 = SF_All;}
break;
- case 91: /* sclp ::= */
- case 119: /* orderby_opt ::= */ yytestcase(yyruleno==119);
- case 126: /* groupby_opt ::= */ yytestcase(yyruleno==126);
- case 203: /* exprlist ::= */ yytestcase(yyruleno==203);
- case 206: /* paren_exprlist ::= */ yytestcase(yyruleno==206);
- case 211: /* eidlist_opt ::= */ yytestcase(yyruleno==211);
+ case 90: /* sclp ::= */
+ case 118: /* orderby_opt ::= */ yytestcase(yyruleno==118);
+ case 125: /* groupby_opt ::= */ yytestcase(yyruleno==125);
+ case 200: /* exprlist ::= */ yytestcase(yyruleno==200);
+ case 203: /* paren_exprlist ::= */ yytestcase(yyruleno==203);
+ case 208: /* eidlist_opt ::= */ yytestcase(yyruleno==208);
{yymsp[1].minor.yy148 = 0;}
break;
- case 92: /* selcollist ::= sclp expr as */
+ case 91: /* selcollist ::= sclp expr as */
{
yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy148, yymsp[-1].minor.yy190.pExpr);
if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-2].minor.yy148, &yymsp[0].minor.yy0, 1);
sqlite3ExprListSetSpan(pParse,yymsp[-2].minor.yy148,&yymsp[-1].minor.yy190);
}
break;
- case 93: /* selcollist ::= sclp STAR */
+ case 92: /* selcollist ::= sclp STAR */
{
Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy148, p);
}
break;
- case 94: /* selcollist ::= sclp nm DOT STAR */
+ case 93: /* selcollist ::= sclp nm DOT STAR */
{
- Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, 0);
- Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
- Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
+ Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
+ Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
+ Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot);
}
break;
- case 95: /* as ::= AS nm */
- case 106: /* dbnm ::= DOT nm */ yytestcase(yyruleno==106);
- case 225: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==225);
- case 226: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==226);
+ case 94: /* as ::= AS nm */
+ case 105: /* dbnm ::= DOT nm */ yytestcase(yyruleno==105);
+ case 222: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==222);
+ case 223: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==223);
{yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;}
break;
- case 97: /* from ::= */
+ case 96: /* from ::= */
{yymsp[1].minor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy185));}
break;
- case 98: /* from ::= FROM seltablist */
+ case 97: /* from ::= FROM seltablist */
{
yymsp[-1].minor.yy185 = yymsp[0].minor.yy185;
sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy185);
}
break;
- case 99: /* stl_prefix ::= seltablist joinop */
+ case 98: /* stl_prefix ::= seltablist joinop */
{
if( ALWAYS(yymsp[-1].minor.yy185 && yymsp[-1].minor.yy185->nSrc>0) ) yymsp[-1].minor.yy185->a[yymsp[-1].minor.yy185->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy194;
}
break;
- case 100: /* stl_prefix ::= */
+ case 99: /* stl_prefix ::= */
{yymsp[1].minor.yy185 = 0;}
break;
- case 101: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ case 100: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
{
yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254);
sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy185, &yymsp[-2].minor.yy0);
}
break;
- case 102: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
+ case 101: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
{
yymsp[-8].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy185,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254);
sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy185, yymsp[-4].minor.yy148);
}
break;
- case 103: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+ case 102: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
{
yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy243,yymsp[-1].minor.yy72,yymsp[0].minor.yy254);
}
break;
- case 104: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+ case 103: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
if( yymsp[-6].minor.yy185==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy72==0 && yymsp[0].minor.yy254==0 ){
yymsp[-6].minor.yy185 = yymsp[-4].minor.yy185;
@@ -138643,96 +142561,96 @@ static void yy_reduce(
}
}
break;
- case 105: /* dbnm ::= */
- case 114: /* indexed_opt ::= */ yytestcase(yyruleno==114);
+ case 104: /* dbnm ::= */
+ case 113: /* indexed_opt ::= */ yytestcase(yyruleno==113);
{yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;}
break;
- case 107: /* fullname ::= nm dbnm */
+ case 106: /* fullname ::= nm dbnm */
{yymsp[-1].minor.yy185 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 108: /* joinop ::= COMMA|JOIN */
+ case 107: /* joinop ::= COMMA|JOIN */
{ yymsp[0].minor.yy194 = JT_INNER; }
break;
- case 109: /* joinop ::= JOIN_KW JOIN */
+ case 108: /* joinop ::= JOIN_KW JOIN */
{yymsp[-1].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
break;
- case 110: /* joinop ::= JOIN_KW nm JOIN */
+ case 109: /* joinop ::= JOIN_KW nm JOIN */
{yymsp[-2].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
break;
- case 111: /* joinop ::= JOIN_KW nm nm JOIN */
+ case 110: /* joinop ::= JOIN_KW nm nm JOIN */
{yymsp[-3].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
break;
- case 112: /* on_opt ::= ON expr */
- case 129: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==129);
- case 136: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==136);
- case 199: /* case_else ::= ELSE expr */ yytestcase(yyruleno==199);
+ case 111: /* on_opt ::= ON expr */
+ case 128: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==128);
+ case 135: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==135);
+ case 196: /* case_else ::= ELSE expr */ yytestcase(yyruleno==196);
{yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr;}
break;
- case 113: /* on_opt ::= */
- case 128: /* having_opt ::= */ yytestcase(yyruleno==128);
- case 135: /* where_opt ::= */ yytestcase(yyruleno==135);
- case 200: /* case_else ::= */ yytestcase(yyruleno==200);
- case 202: /* case_operand ::= */ yytestcase(yyruleno==202);
+ case 112: /* on_opt ::= */
+ case 127: /* having_opt ::= */ yytestcase(yyruleno==127);
+ case 134: /* where_opt ::= */ yytestcase(yyruleno==134);
+ case 197: /* case_else ::= */ yytestcase(yyruleno==197);
+ case 199: /* case_operand ::= */ yytestcase(yyruleno==199);
{yymsp[1].minor.yy72 = 0;}
break;
- case 115: /* indexed_opt ::= INDEXED BY nm */
+ case 114: /* indexed_opt ::= INDEXED BY nm */
{yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
break;
- case 116: /* indexed_opt ::= NOT INDEXED */
+ case 115: /* indexed_opt ::= NOT INDEXED */
{yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;}
break;
- case 117: /* using_opt ::= USING LP idlist RP */
+ case 116: /* using_opt ::= USING LP idlist RP */
{yymsp[-3].minor.yy254 = yymsp[-1].minor.yy254;}
break;
- case 118: /* using_opt ::= */
- case 146: /* idlist_opt ::= */ yytestcase(yyruleno==146);
+ case 117: /* using_opt ::= */
+ case 145: /* idlist_opt ::= */ yytestcase(yyruleno==145);
{yymsp[1].minor.yy254 = 0;}
break;
- case 120: /* orderby_opt ::= ORDER BY sortlist */
- case 127: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==127);
+ case 119: /* orderby_opt ::= ORDER BY sortlist */
+ case 126: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==126);
{yymsp[-2].minor.yy148 = yymsp[0].minor.yy148;}
break;
- case 121: /* sortlist ::= sortlist COMMA expr sortorder */
+ case 120: /* sortlist ::= sortlist COMMA expr sortorder */
{
yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148,yymsp[-1].minor.yy190.pExpr);
sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy148,yymsp[0].minor.yy194);
}
break;
- case 122: /* sortlist ::= expr sortorder */
+ case 121: /* sortlist ::= expr sortorder */
{
yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy190.pExpr); /*A-overwrites-Y*/
sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy148,yymsp[0].minor.yy194);
}
break;
- case 123: /* sortorder ::= ASC */
+ case 122: /* sortorder ::= ASC */
{yymsp[0].minor.yy194 = SQLITE_SO_ASC;}
break;
- case 124: /* sortorder ::= DESC */
+ case 123: /* sortorder ::= DESC */
{yymsp[0].minor.yy194 = SQLITE_SO_DESC;}
break;
- case 125: /* sortorder ::= */
+ case 124: /* sortorder ::= */
{yymsp[1].minor.yy194 = SQLITE_SO_UNDEFINED;}
break;
- case 130: /* limit_opt ::= */
+ case 129: /* limit_opt ::= */
{yymsp[1].minor.yy354.pLimit = 0; yymsp[1].minor.yy354.pOffset = 0;}
break;
- case 131: /* limit_opt ::= LIMIT expr */
+ case 130: /* limit_opt ::= LIMIT expr */
{yymsp[-1].minor.yy354.pLimit = yymsp[0].minor.yy190.pExpr; yymsp[-1].minor.yy354.pOffset = 0;}
break;
- case 132: /* limit_opt ::= LIMIT expr OFFSET expr */
+ case 131: /* limit_opt ::= LIMIT expr OFFSET expr */
{yymsp[-3].minor.yy354.pLimit = yymsp[-2].minor.yy190.pExpr; yymsp[-3].minor.yy354.pOffset = yymsp[0].minor.yy190.pExpr;}
break;
- case 133: /* limit_opt ::= LIMIT expr COMMA expr */
+ case 132: /* limit_opt ::= LIMIT expr COMMA expr */
{yymsp[-3].minor.yy354.pOffset = yymsp[-2].minor.yy190.pExpr; yymsp[-3].minor.yy354.pLimit = yymsp[0].minor.yy190.pExpr;}
break;
- case 134: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */
+ case 133: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */
{
sqlite3WithPush(pParse, yymsp[-5].minor.yy285, 1);
sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy185, &yymsp[-1].minor.yy0);
sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy185,yymsp[0].minor.yy72);
}
break;
- case 137: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */
+ case 136: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */
{
sqlite3WithPush(pParse, yymsp[-7].minor.yy285, 1);
sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy185, &yymsp[-3].minor.yy0);
@@ -138740,90 +142658,88 @@ static void yy_reduce(
sqlite3Update(pParse,yymsp[-4].minor.yy185,yymsp[-1].minor.yy148,yymsp[0].minor.yy72,yymsp[-5].minor.yy194);
}
break;
- case 138: /* setlist ::= setlist COMMA nm EQ expr */
+ case 137: /* setlist ::= setlist COMMA nm EQ expr */
{
yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr);
sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, 1);
}
break;
- case 139: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
+ case 138: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
{
yymsp[-6].minor.yy148 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy148, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr);
}
break;
- case 140: /* setlist ::= nm EQ expr */
+ case 139: /* setlist ::= nm EQ expr */
{
yylhsminor.yy148 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy190.pExpr);
sqlite3ExprListSetName(pParse, yylhsminor.yy148, &yymsp[-2].minor.yy0, 1);
}
yymsp[-2].minor.yy148 = yylhsminor.yy148;
break;
- case 141: /* setlist ::= LP idlist RP EQ expr */
+ case 140: /* setlist ::= LP idlist RP EQ expr */
{
yymsp[-4].minor.yy148 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr);
}
break;
- case 142: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */
+ case 141: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */
{
sqlite3WithPush(pParse, yymsp[-5].minor.yy285, 1);
sqlite3Insert(pParse, yymsp[-2].minor.yy185, yymsp[0].minor.yy243, yymsp[-1].minor.yy254, yymsp[-4].minor.yy194);
}
break;
- case 143: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */
+ case 142: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */
{
sqlite3WithPush(pParse, yymsp[-6].minor.yy285, 1);
sqlite3Insert(pParse, yymsp[-3].minor.yy185, 0, yymsp[-2].minor.yy254, yymsp[-5].minor.yy194);
}
break;
- case 147: /* idlist_opt ::= LP idlist RP */
+ case 146: /* idlist_opt ::= LP idlist RP */
{yymsp[-2].minor.yy254 = yymsp[-1].minor.yy254;}
break;
- case 148: /* idlist ::= idlist COMMA nm */
+ case 147: /* idlist ::= idlist COMMA nm */
{yymsp[-2].minor.yy254 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);}
break;
- case 149: /* idlist ::= nm */
+ case 148: /* idlist ::= nm */
{yymsp[0].minor.yy254 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
break;
- case 150: /* expr ::= LP expr RP */
+ case 149: /* expr ::= LP expr RP */
{spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ yymsp[-2].minor.yy190.pExpr = yymsp[-1].minor.yy190.pExpr;}
break;
- case 151: /* term ::= NULL */
- case 156: /* term ::= FLOAT|BLOB */ yytestcase(yyruleno==156);
- case 157: /* term ::= STRING */ yytestcase(yyruleno==157);
-{spanExpr(&yymsp[0].minor.yy190,pParse,yymsp[0].major,yymsp[0].minor.yy0);/*A-overwrites-X*/}
- break;
- case 152: /* expr ::= ID|INDEXED */
- case 153: /* expr ::= JOIN_KW */ yytestcase(yyruleno==153);
+ case 150: /* expr ::= ID|INDEXED */
+ case 151: /* expr ::= JOIN_KW */ yytestcase(yyruleno==151);
{spanExpr(&yymsp[0].minor.yy190,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 154: /* expr ::= nm DOT nm */
+ case 152: /* expr ::= nm DOT nm */
{
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/
- yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
+ yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
}
break;
- case 155: /* expr ::= nm DOT nm DOT nm */
+ case 153: /* expr ::= nm DOT nm DOT nm */
{
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1);
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
- Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
+ Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3);
spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/
- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
+ yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
}
break;
- case 158: /* term ::= INTEGER */
+ case 154: /* term ::= NULL|FLOAT|BLOB */
+ case 155: /* term ::= STRING */ yytestcase(yyruleno==155);
+{spanExpr(&yymsp[0].minor.yy190,pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ break;
+ case 156: /* term ::= INTEGER */
{
yylhsminor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
yylhsminor.yy190.zStart = yymsp[0].minor.yy0.z;
yylhsminor.yy190.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n;
- if( yylhsminor.yy190.pExpr ) yylhsminor.yy190.pExpr->flags |= EP_Leaf;
}
yymsp[0].minor.yy190 = yylhsminor.yy190;
break;
- case 159: /* expr ::= VARIABLE */
+ case 157: /* expr ::= VARIABLE */
{
if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
u32 n = yymsp[0].minor.yy0.n;
@@ -138840,25 +142756,26 @@ static void yy_reduce(
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
yymsp[0].minor.yy190.pExpr = 0;
}else{
- yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, 0);
+ yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
if( yymsp[0].minor.yy190.pExpr ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy190.pExpr->iTable);
}
}
}
break;
- case 160: /* expr ::= expr COLLATE ID|STRING */
+ case 158: /* expr ::= expr COLLATE ID|STRING */
{
yymsp[-2].minor.yy190.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy190.pExpr, &yymsp[0].minor.yy0, 1);
yymsp[-2].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
break;
- case 161: /* expr ::= CAST LP expr AS typetoken RP */
+ case 159: /* expr ::= CAST LP expr AS typetoken RP */
{
spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/
- yymsp[-5].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy190.pExpr, 0, &yymsp[-1].minor.yy0);
+ yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
+ sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, 0);
}
break;
- case 162: /* expr ::= ID|INDEXED LP distinct exprlist RP */
+ case 160: /* expr ::= ID|INDEXED LP distinct exprlist RP */
{
if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
@@ -138871,24 +142788,24 @@ static void yy_reduce(
}
yymsp[-4].minor.yy190 = yylhsminor.yy190;
break;
- case 163: /* expr ::= ID|INDEXED LP STAR RP */
+ case 161: /* expr ::= ID|INDEXED LP STAR RP */
{
yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
spanSet(&yylhsminor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
yymsp[-3].minor.yy190 = yylhsminor.yy190;
break;
- case 164: /* term ::= CTIME_KW */
+ case 162: /* term ::= CTIME_KW */
{
yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0);
spanSet(&yylhsminor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
yymsp[0].minor.yy190 = yylhsminor.yy190;
break;
- case 165: /* expr ::= LP nexprlist COMMA expr RP */
+ case 163: /* expr ::= LP nexprlist COMMA expr RP */
{
ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy148, yymsp[-1].minor.yy190.pExpr);
- yylhsminor.yy190.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0, 0);
+ yylhsminor.yy190.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
if( yylhsminor.yy190.pExpr ){
yylhsminor.yy190.pExpr->x.pList = pList;
spanSet(&yylhsminor.yy190, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
@@ -138898,23 +142815,20 @@ static void yy_reduce(
}
yymsp[-4].minor.yy190 = yylhsminor.yy190;
break;
- case 166: /* expr ::= expr AND expr */
- case 167: /* expr ::= expr OR expr */ yytestcase(yyruleno==167);
- case 168: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==168);
- case 169: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==169);
- case 170: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==170);
- case 171: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==171);
- case 172: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==172);
- case 173: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==173);
+ case 164: /* expr ::= expr AND expr */
+ case 165: /* expr ::= expr OR expr */ yytestcase(yyruleno==165);
+ case 166: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==166);
+ case 167: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==167);
+ case 168: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==168);
+ case 169: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==169);
+ case 170: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==170);
+ case 171: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==171);
{spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);}
break;
- case 174: /* likeop ::= LIKE_KW|MATCH */
-{yymsp[0].minor.yy0=yymsp[0].minor.yy0;/*A-overwrites-X*/}
- break;
- case 175: /* likeop ::= NOT LIKE_KW|MATCH */
+ case 172: /* likeop ::= NOT LIKE_KW|MATCH */
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/}
break;
- case 176: /* expr ::= expr likeop expr */
+ case 173: /* expr ::= expr likeop expr */
{
ExprList *pList;
int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
@@ -138927,7 +142841,7 @@ static void yy_reduce(
if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc;
}
break;
- case 177: /* expr ::= expr likeop expr ESCAPE expr */
+ case 174: /* expr ::= expr likeop expr ESCAPE expr */
{
ExprList *pList;
int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
@@ -138941,43 +142855,43 @@ static void yy_reduce(
if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc;
}
break;
- case 178: /* expr ::= expr ISNULL|NOTNULL */
+ case 175: /* expr ::= expr ISNULL|NOTNULL */
{spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);}
break;
- case 179: /* expr ::= expr NOT NULL */
+ case 176: /* expr ::= expr NOT NULL */
{spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);}
break;
- case 180: /* expr ::= expr IS expr */
+ case 177: /* expr ::= expr IS expr */
{
spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);
binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-2].minor.yy190.pExpr, TK_ISNULL);
}
break;
- case 181: /* expr ::= expr IS NOT expr */
+ case 178: /* expr ::= expr IS NOT expr */
{
spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190);
binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, TK_NOTNULL);
}
break;
- case 182: /* expr ::= NOT expr */
- case 183: /* expr ::= BITNOT expr */ yytestcase(yyruleno==183);
+ case 179: /* expr ::= NOT expr */
+ case 180: /* expr ::= BITNOT expr */ yytestcase(yyruleno==180);
{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/}
break;
- case 184: /* expr ::= MINUS expr */
+ case 181: /* expr ::= MINUS expr */
{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/}
break;
- case 185: /* expr ::= PLUS expr */
+ case 182: /* expr ::= PLUS expr */
{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/}
break;
- case 186: /* between_op ::= BETWEEN */
- case 189: /* in_op ::= IN */ yytestcase(yyruleno==189);
+ case 183: /* between_op ::= BETWEEN */
+ case 186: /* in_op ::= IN */ yytestcase(yyruleno==186);
{yymsp[0].minor.yy194 = 0;}
break;
- case 188: /* expr ::= expr between_op expr AND expr */
+ case 185: /* expr ::= expr between_op expr AND expr */
{
ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr);
pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr);
- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0, 0);
+ yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0);
if( yymsp[-4].minor.yy190.pExpr ){
yymsp[-4].minor.yy190.pExpr->x.pList = pList;
}else{
@@ -138987,7 +142901,7 @@ static void yy_reduce(
yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd;
}
break;
- case 191: /* expr ::= expr in_op LP exprlist RP */
+ case 188: /* expr ::= expr in_op LP exprlist RP */
{
if( yymsp[-1].minor.yy148==0 ){
/* Expressions of the form
@@ -138999,7 +142913,7 @@ static void yy_reduce(
** regardless of the value of expr1.
*/
sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy190.pExpr);
- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy194]);
+ yymsp[-4].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy194],1);
}else if( yymsp[-1].minor.yy148->nExpr==1 ){
/* Expressions of the form:
**
@@ -139026,9 +142940,9 @@ static void yy_reduce(
pRHS->flags &= ~EP_Collate;
pRHS->flags |= EP_Generic;
}
- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy194 ? TK_NE : TK_EQ, yymsp[-4].minor.yy190.pExpr, pRHS, 0);
+ yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy194 ? TK_NE : TK_EQ, yymsp[-4].minor.yy190.pExpr, pRHS);
}else{
- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0);
+ yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0);
if( yymsp[-4].minor.yy190.pExpr ){
yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy148;
sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy190.pExpr);
@@ -139040,44 +142954,44 @@ static void yy_reduce(
yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
break;
- case 192: /* expr ::= LP select RP */
+ case 189: /* expr ::= LP select RP */
{
spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/
- yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
+ yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243);
}
break;
- case 193: /* expr ::= expr in_op LP select RP */
+ case 190: /* expr ::= expr in_op LP select RP */
{
- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0);
+ yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0);
sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, yymsp[-1].minor.yy243);
exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190);
yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
break;
- case 194: /* expr ::= expr in_op nm dbnm paren_exprlist */
+ case 191: /* expr ::= expr in_op nm dbnm paren_exprlist */
{
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);
Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
if( yymsp[0].minor.yy148 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy148);
- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0);
+ yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0);
sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, pSelect);
exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190);
yymsp[-4].minor.yy190.zEnd = yymsp[-1].minor.yy0.z ? &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n] : &yymsp[-2].minor.yy0.z[yymsp[-2].minor.yy0.n];
}
break;
- case 195: /* expr ::= EXISTS LP select RP */
+ case 192: /* expr ::= EXISTS LP select RP */
{
Expr *p;
spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/
- p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
+ p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243);
}
break;
- case 196: /* expr ::= CASE case_operand case_exprlist case_else END */
+ case 193: /* expr ::= CASE case_operand case_exprlist case_else END */
{
spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/
- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0, 0);
+ yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0);
if( yymsp[-4].minor.yy190.pExpr ){
yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy72 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[-1].minor.yy72) : yymsp[-2].minor.yy148;
sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy190.pExpr);
@@ -139087,80 +143001,80 @@ static void yy_reduce(
}
}
break;
- case 197: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ case 194: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr);
yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr);
}
break;
- case 198: /* case_exprlist ::= WHEN expr THEN expr */
+ case 195: /* case_exprlist ::= WHEN expr THEN expr */
{
yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr);
yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, yymsp[0].minor.yy190.pExpr);
}
break;
- case 201: /* case_operand ::= expr */
+ case 198: /* case_operand ::= expr */
{yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/}
break;
- case 204: /* nexprlist ::= nexprlist COMMA expr */
+ case 201: /* nexprlist ::= nexprlist COMMA expr */
{yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);}
break;
- case 205: /* nexprlist ::= expr */
+ case 202: /* nexprlist ::= expr */
{yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/}
break;
- case 207: /* paren_exprlist ::= LP exprlist RP */
- case 212: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==212);
+ case 204: /* paren_exprlist ::= LP exprlist RP */
+ case 209: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==209);
{yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;}
break;
- case 208: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ case 205: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
{
sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0,
sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy148, yymsp[-10].minor.yy194,
&yymsp[-11].minor.yy0, yymsp[0].minor.yy72, SQLITE_SO_ASC, yymsp[-8].minor.yy194, SQLITE_IDXTYPE_APPDEF);
}
break;
- case 209: /* uniqueflag ::= UNIQUE */
- case 250: /* raisetype ::= ABORT */ yytestcase(yyruleno==250);
+ case 206: /* uniqueflag ::= UNIQUE */
+ case 246: /* raisetype ::= ABORT */ yytestcase(yyruleno==246);
{yymsp[0].minor.yy194 = OE_Abort;}
break;
- case 210: /* uniqueflag ::= */
+ case 207: /* uniqueflag ::= */
{yymsp[1].minor.yy194 = OE_None;}
break;
- case 213: /* eidlist ::= eidlist COMMA nm collate sortorder */
+ case 210: /* eidlist ::= eidlist COMMA nm collate sortorder */
{
yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194);
}
break;
- case 214: /* eidlist ::= nm collate sortorder */
+ case 211: /* eidlist ::= nm collate sortorder */
{
yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/
}
break;
- case 217: /* cmd ::= DROP INDEX ifexists fullname */
+ case 214: /* cmd ::= DROP INDEX ifexists fullname */
{sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);}
break;
- case 218: /* cmd ::= VACUUM */
+ case 215: /* cmd ::= VACUUM */
{sqlite3Vacuum(pParse,0);}
break;
- case 219: /* cmd ::= VACUUM nm */
+ case 216: /* cmd ::= VACUUM nm */
{sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);}
break;
- case 220: /* cmd ::= PRAGMA nm dbnm */
+ case 217: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
break;
- case 221: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+ case 218: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
break;
- case 222: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ case 219: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
break;
- case 223: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+ case 220: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
break;
- case 224: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ case 221: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
break;
- case 227: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ case 224: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
Token all;
all.z = yymsp[-3].minor.yy0.z;
@@ -139168,53 +143082,50 @@ static void yy_reduce(
sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all);
}
break;
- case 228: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ case 225: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194);
yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/
}
break;
- case 229: /* trigger_time ::= BEFORE */
-{ yymsp[0].minor.yy194 = TK_BEFORE; }
+ case 226: /* trigger_time ::= BEFORE|AFTER */
+{ yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-X*/ }
break;
- case 230: /* trigger_time ::= AFTER */
-{ yymsp[0].minor.yy194 = TK_AFTER; }
- break;
- case 231: /* trigger_time ::= INSTEAD OF */
+ case 227: /* trigger_time ::= INSTEAD OF */
{ yymsp[-1].minor.yy194 = TK_INSTEAD;}
break;
- case 232: /* trigger_time ::= */
+ case 228: /* trigger_time ::= */
{ yymsp[1].minor.yy194 = TK_BEFORE; }
break;
- case 233: /* trigger_event ::= DELETE|INSERT */
- case 234: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==234);
+ case 229: /* trigger_event ::= DELETE|INSERT */
+ case 230: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==230);
{yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;}
break;
- case 235: /* trigger_event ::= UPDATE OF idlist */
+ case 231: /* trigger_event ::= UPDATE OF idlist */
{yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;}
break;
- case 236: /* when_clause ::= */
- case 255: /* key_opt ::= */ yytestcase(yyruleno==255);
+ case 232: /* when_clause ::= */
+ case 251: /* key_opt ::= */ yytestcase(yyruleno==251);
{ yymsp[1].minor.yy72 = 0; }
break;
- case 237: /* when_clause ::= WHEN expr */
- case 256: /* key_opt ::= KEY expr */ yytestcase(yyruleno==256);
+ case 233: /* when_clause ::= WHEN expr */
+ case 252: /* key_opt ::= KEY expr */ yytestcase(yyruleno==252);
{ yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; }
break;
- case 238: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ case 234: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
assert( yymsp[-2].minor.yy145!=0 );
yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145;
yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145;
}
break;
- case 239: /* trigger_cmd_list ::= trigger_cmd SEMI */
+ case 235: /* trigger_cmd_list ::= trigger_cmd SEMI */
{
assert( yymsp[-1].minor.yy145!=0 );
yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145;
}
break;
- case 240: /* trnm ::= nm DOT nm */
+ case 236: /* trnm ::= nm DOT nm */
{
yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
sqlite3ErrorMsg(pParse,
@@ -139222,215 +143133,220 @@ static void yy_reduce(
"statements within triggers");
}
break;
- case 241: /* tridxby ::= INDEXED BY nm */
+ case 237: /* tridxby ::= INDEXED BY nm */
{
sqlite3ErrorMsg(pParse,
"the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 242: /* tridxby ::= NOT INDEXED */
+ case 238: /* tridxby ::= NOT INDEXED */
{
sqlite3ErrorMsg(pParse,
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 243: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
+ case 239: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
{yymsp[-6].minor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy194);}
break;
- case 244: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */
+ case 240: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */
{yymsp[-4].minor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);/*A-overwrites-R*/}
break;
- case 245: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
+ case 241: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
{yymsp[-4].minor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);}
break;
- case 246: /* trigger_cmd ::= select */
+ case 242: /* trigger_cmd ::= select */
{yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/}
break;
- case 247: /* expr ::= RAISE LP IGNORE RP */
+ case 243: /* expr ::= RAISE LP IGNORE RP */
{
spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/
- yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
+ yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
if( yymsp[-3].minor.yy190.pExpr ){
yymsp[-3].minor.yy190.pExpr->affinity = OE_Ignore;
}
}
break;
- case 248: /* expr ::= RAISE LP raisetype COMMA nm RP */
+ case 244: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/
- yymsp[-5].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
+ yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
if( yymsp[-5].minor.yy190.pExpr ) {
yymsp[-5].minor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194;
}
}
break;
- case 249: /* raisetype ::= ROLLBACK */
+ case 245: /* raisetype ::= ROLLBACK */
{yymsp[0].minor.yy194 = OE_Rollback;}
break;
- case 251: /* raisetype ::= FAIL */
+ case 247: /* raisetype ::= FAIL */
{yymsp[0].minor.yy194 = OE_Fail;}
break;
- case 252: /* cmd ::= DROP TRIGGER ifexists fullname */
+ case 248: /* cmd ::= DROP TRIGGER ifexists fullname */
{
sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194);
}
break;
- case 253: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ case 249: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72);
}
break;
- case 254: /* cmd ::= DETACH database_kw_opt expr */
+ case 250: /* cmd ::= DETACH database_kw_opt expr */
{
sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr);
}
break;
- case 257: /* cmd ::= REINDEX */
+ case 253: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
break;
- case 258: /* cmd ::= REINDEX nm dbnm */
+ case 254: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 259: /* cmd ::= ANALYZE */
+ case 255: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
break;
- case 260: /* cmd ::= ANALYZE nm dbnm */
+ case 256: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 261: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+ case 257: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0);
}
break;
- case 262: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ case 258: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
{
yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n;
sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0);
}
break;
- case 263: /* add_column_fullname ::= fullname */
+ case 259: /* add_column_fullname ::= fullname */
{
disableLookaside(pParse);
sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185);
}
break;
- case 264: /* cmd ::= create_vtab */
+ case 260: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
- case 265: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 261: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
- case 266: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ case 262: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
{
sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194);
}
break;
- case 267: /* vtabarg ::= */
+ case 263: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
- case 268: /* vtabargtoken ::= ANY */
- case 269: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==269);
- case 270: /* lp ::= LP */ yytestcase(yyruleno==270);
+ case 264: /* vtabargtoken ::= ANY */
+ case 265: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==265);
+ case 266: /* lp ::= LP */ yytestcase(yyruleno==266);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
- case 271: /* with ::= */
+ case 267: /* with ::= */
{yymsp[1].minor.yy285 = 0;}
break;
- case 272: /* with ::= WITH wqlist */
+ case 268: /* with ::= WITH wqlist */
{ yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; }
break;
- case 273: /* with ::= WITH RECURSIVE wqlist */
+ case 269: /* with ::= WITH RECURSIVE wqlist */
{ yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; }
break;
- case 274: /* wqlist ::= nm eidlist_opt AS LP select RP */
+ case 270: /* wqlist ::= nm eidlist_opt AS LP select RP */
{
yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/
}
break;
- case 275: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
+ case 271: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
{
yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243);
}
break;
default:
- /* (276) input ::= cmdlist */ yytestcase(yyruleno==276);
- /* (277) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==277);
- /* (278) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=278);
- /* (279) ecmd ::= SEMI */ yytestcase(yyruleno==279);
- /* (280) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==280);
- /* (281) explain ::= */ yytestcase(yyruleno==281);
- /* (282) trans_opt ::= */ yytestcase(yyruleno==282);
- /* (283) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==283);
- /* (284) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==284);
- /* (285) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==285);
- /* (286) savepoint_opt ::= */ yytestcase(yyruleno==286);
- /* (287) cmd ::= create_table create_table_args */ yytestcase(yyruleno==287);
- /* (288) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==288);
- /* (289) columnlist ::= columnname carglist */ yytestcase(yyruleno==289);
- /* (290) nm ::= ID|INDEXED */ yytestcase(yyruleno==290);
- /* (291) nm ::= STRING */ yytestcase(yyruleno==291);
- /* (292) nm ::= JOIN_KW */ yytestcase(yyruleno==292);
- /* (293) typetoken ::= typename */ yytestcase(yyruleno==293);
- /* (294) typename ::= ID|STRING */ yytestcase(yyruleno==294);
- /* (295) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=295);
- /* (296) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=296);
- /* (297) carglist ::= carglist ccons */ yytestcase(yyruleno==297);
- /* (298) carglist ::= */ yytestcase(yyruleno==298);
- /* (299) ccons ::= NULL onconf */ yytestcase(yyruleno==299);
- /* (300) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==300);
- /* (301) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==301);
- /* (302) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=302);
- /* (303) tconscomma ::= */ yytestcase(yyruleno==303);
- /* (304) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=304);
- /* (305) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=305);
- /* (306) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=306);
- /* (307) oneselect ::= values */ yytestcase(yyruleno==307);
- /* (308) sclp ::= selcollist COMMA */ yytestcase(yyruleno==308);
- /* (309) as ::= ID|STRING */ yytestcase(yyruleno==309);
- /* (310) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=310);
- /* (311) exprlist ::= nexprlist */ yytestcase(yyruleno==311);
- /* (312) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=312);
- /* (313) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=313);
- /* (314) nmnum ::= ON */ yytestcase(yyruleno==314);
- /* (315) nmnum ::= DELETE */ yytestcase(yyruleno==315);
- /* (316) nmnum ::= DEFAULT */ yytestcase(yyruleno==316);
- /* (317) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==317);
- /* (318) foreach_clause ::= */ yytestcase(yyruleno==318);
- /* (319) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==319);
- /* (320) trnm ::= nm */ yytestcase(yyruleno==320);
- /* (321) tridxby ::= */ yytestcase(yyruleno==321);
- /* (322) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==322);
- /* (323) database_kw_opt ::= */ yytestcase(yyruleno==323);
- /* (324) kwcolumn_opt ::= */ yytestcase(yyruleno==324);
- /* (325) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==325);
- /* (326) vtabarglist ::= vtabarg */ yytestcase(yyruleno==326);
- /* (327) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==327);
- /* (328) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==328);
- /* (329) anylist ::= */ yytestcase(yyruleno==329);
- /* (330) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==330);
- /* (331) anylist ::= anylist ANY */ yytestcase(yyruleno==331);
+ /* (272) input ::= cmdlist */ yytestcase(yyruleno==272);
+ /* (273) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==273);
+ /* (274) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=274);
+ /* (275) ecmd ::= SEMI */ yytestcase(yyruleno==275);
+ /* (276) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==276);
+ /* (277) explain ::= */ yytestcase(yyruleno==277);
+ /* (278) trans_opt ::= */ yytestcase(yyruleno==278);
+ /* (279) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==279);
+ /* (280) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==280);
+ /* (281) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==281);
+ /* (282) savepoint_opt ::= */ yytestcase(yyruleno==282);
+ /* (283) cmd ::= create_table create_table_args */ yytestcase(yyruleno==283);
+ /* (284) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==284);
+ /* (285) columnlist ::= columnname carglist */ yytestcase(yyruleno==285);
+ /* (286) nm ::= ID|INDEXED */ yytestcase(yyruleno==286);
+ /* (287) nm ::= STRING */ yytestcase(yyruleno==287);
+ /* (288) nm ::= JOIN_KW */ yytestcase(yyruleno==288);
+ /* (289) typetoken ::= typename */ yytestcase(yyruleno==289);
+ /* (290) typename ::= ID|STRING */ yytestcase(yyruleno==290);
+ /* (291) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=291);
+ /* (292) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=292);
+ /* (293) carglist ::= carglist ccons */ yytestcase(yyruleno==293);
+ /* (294) carglist ::= */ yytestcase(yyruleno==294);
+ /* (295) ccons ::= NULL onconf */ yytestcase(yyruleno==295);
+ /* (296) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==296);
+ /* (297) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==297);
+ /* (298) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=298);
+ /* (299) tconscomma ::= */ yytestcase(yyruleno==299);
+ /* (300) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=300);
+ /* (301) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=301);
+ /* (302) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=302);
+ /* (303) oneselect ::= values */ yytestcase(yyruleno==303);
+ /* (304) sclp ::= selcollist COMMA */ yytestcase(yyruleno==304);
+ /* (305) as ::= ID|STRING */ yytestcase(yyruleno==305);
+ /* (306) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=306);
+ /* (307) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==307);
+ /* (308) exprlist ::= nexprlist */ yytestcase(yyruleno==308);
+ /* (309) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=309);
+ /* (310) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=310);
+ /* (311) nmnum ::= ON */ yytestcase(yyruleno==311);
+ /* (312) nmnum ::= DELETE */ yytestcase(yyruleno==312);
+ /* (313) nmnum ::= DEFAULT */ yytestcase(yyruleno==313);
+ /* (314) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==314);
+ /* (315) foreach_clause ::= */ yytestcase(yyruleno==315);
+ /* (316) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==316);
+ /* (317) trnm ::= nm */ yytestcase(yyruleno==317);
+ /* (318) tridxby ::= */ yytestcase(yyruleno==318);
+ /* (319) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==319);
+ /* (320) database_kw_opt ::= */ yytestcase(yyruleno==320);
+ /* (321) kwcolumn_opt ::= */ yytestcase(yyruleno==321);
+ /* (322) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==322);
+ /* (323) vtabarglist ::= vtabarg */ yytestcase(yyruleno==323);
+ /* (324) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==324);
+ /* (325) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==325);
+ /* (326) anylist ::= */ yytestcase(yyruleno==326);
+ /* (327) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==327);
+ /* (328) anylist ::= anylist ANY */ yytestcase(yyruleno==328);
break;
/********** End reduce actions ************************************************/
};
assert( yyrulenoYY_MAX_SHIFT ){
- yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
- }
- yymsp -= yysize-1;
+ yyact = yy_find_reduce_action(yymsp[yysize].stateno,(YYCODETYPE)yygoto);
+
+ /* There are no SHIFTREDUCE actions on nonterminals because the table
+ ** generator has simplified them to pure REDUCE actions. */
+ assert( !(yyact>YY_MAX_SHIFT && yyact<=YY_MAX_SHIFTREDUCE) );
+
+ /* It is not possible for a REDUCE to be followed by an error */
+ assert( yyact!=YY_ERROR_ACTION );
+
+ if( yyact==YY_ACCEPT_ACTION ){
+ yypParser->yytos += yysize;
+ yy_accept(yypParser);
+ }else{
+ yymsp += yysize+1;
yypParser->yytos = yymsp;
yymsp->stateno = (YYACTIONTYPE)yyact;
yymsp->major = (YYCODETYPE)yygoto;
yyTraceShift(yypParser, yyact);
- }else{
- assert( yyact == YY_ACCEPT_ACTION );
- yypParser->yytos -= yysize;
- yy_accept(yypParser);
}
}
@@ -139759,13 +143675,13 @@ static const unsigned char aiClass[] = {
/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 12, 17, 20, 10,
+/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 12, 17, 20, 10,
/* 5x */ 24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15, 4, 21, 18, 19, 27,
-/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 7,
+/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 6,
/* 7x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 8, 5, 5, 5, 8, 14, 8,
/* 8x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
/* 9x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* 9x */ 25, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27,
+/* Ax */ 27, 25, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27,
/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 27, 27, 27, 27, 27,
/* Cx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
/* Dx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
@@ -139836,134 +143752,145 @@ const unsigned char ebcdicToAscii[] = {
** on platforms with limited memory.
*/
/* Hash score: 182 */
+/* zKWText[] encodes 834 bytes of keyword text in 554 bytes */
+/* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */
+/* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */
+/* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */
+/* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERECURSIVE */
+/* BETWEENOTNULLIKECASCADELETECASECOLLATECREATECURRENT_DATEDETACH */
+/* IMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHEN */
+/* WHERENAMEAFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMIT */
+/* CONFLICTCROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAIL */
+/* FROMFULLGLOBYIFISNULLORDERESTRICTRIGHTROLLBACKROWUNIONUSING */
+/* VACUUMVIEWINITIALLY */
+static const char zKWText[553] = {
+ 'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H',
+ 'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G',
+ 'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A',
+ 'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F',
+ 'E','R','R','A','B','L','E','L','S','E','X','C','E','P','T','R','A','N',
+ 'S','A','C','T','I','O','N','A','T','U','R','A','L','T','E','R','A','I',
+ 'S','E','X','C','L','U','S','I','V','E','X','I','S','T','S','A','V','E',
+ 'P','O','I','N','T','E','R','S','E','C','T','R','I','G','G','E','R','E',
+ 'F','E','R','E','N','C','E','S','C','O','N','S','T','R','A','I','N','T',
+ 'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q',
+ 'U','E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S',
+ 'E','A','T','T','A','C','H','A','V','I','N','G','R','O','U','P','D','A',
+ 'T','E','B','E','G','I','N','N','E','R','E','C','U','R','S','I','V','E',
+ 'B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C','A',
+ 'S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L','A',
+ 'T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A',
+ 'T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E','J',
+ 'O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A','L',
+ 'Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U','E',
+ 'S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W','H',
+ 'E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C','E',
+ 'A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R','E',
+ 'M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M','M',
+ 'I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U','R',
+ 'R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M','A',
+ 'R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','D',
+ 'R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L','O',
+ 'B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S','T',
+ 'R','I','C','T','R','I','G','H','T','R','O','L','L','B','A','C','K','R',
+ 'O','W','U','N','I','O','N','U','S','I','N','G','V','A','C','U','U','M',
+ 'V','I','E','W','I','N','I','T','I','A','L','L','Y',
+};
+/* aKWHash[i] is the hash value for the i-th keyword */
+static const unsigned char aKWHash[127] = {
+ 76, 105, 117, 74, 0, 45, 0, 0, 82, 0, 77, 0, 0,
+ 42, 12, 78, 15, 0, 116, 85, 54, 112, 0, 19, 0, 0,
+ 121, 0, 119, 115, 0, 22, 93, 0, 9, 0, 0, 70, 71,
+ 0, 69, 6, 0, 48, 90, 102, 0, 118, 101, 0, 0, 44,
+ 0, 103, 24, 0, 17, 0, 122, 53, 23, 0, 5, 110, 25,
+ 96, 0, 0, 124, 106, 60, 123, 57, 28, 55, 0, 91, 0,
+ 100, 26, 0, 99, 0, 0, 0, 95, 92, 97, 88, 109, 14,
+ 39, 108, 0, 81, 0, 18, 89, 111, 32, 0, 120, 80, 113,
+ 62, 46, 84, 0, 0, 94, 40, 59, 114, 0, 36, 0, 0,
+ 29, 0, 86, 63, 64, 0, 20, 61, 0, 56,
+};
+/* aKWNext[] forms the hash collision chain. If aKWHash[i]==0
+** then the i-th keyword has no more hash collisions. Otherwise,
+** the next keyword with the same hash is aKWHash[i]-1. */
+static const unsigned char aKWNext[124] = {
+ 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
+ 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 0, 0, 50,
+ 0, 43, 3, 47, 0, 0, 0, 0, 30, 0, 58, 0, 38,
+ 0, 0, 0, 1, 66, 0, 0, 67, 0, 41, 0, 0, 0,
+ 0, 0, 0, 49, 65, 0, 0, 0, 0, 31, 52, 16, 34,
+ 10, 0, 0, 0, 0, 0, 0, 0, 11, 72, 79, 0, 8,
+ 0, 104, 98, 0, 107, 0, 87, 0, 75, 51, 0, 27, 37,
+ 73, 83, 0, 35, 68, 0, 0,
+};
+/* aKWLen[i] is the length (in bytes) of the i-th keyword */
+static const unsigned char aKWLen[124] = {
+ 7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6,
+ 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6,
+ 11, 6, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10,
+ 4, 6, 2, 3, 9, 4, 2, 6, 5, 7, 4, 5, 7,
+ 6, 6, 5, 6, 5, 5, 9, 7, 7, 3, 2, 4, 4,
+ 7, 3, 6, 4, 7, 6, 12, 6, 9, 4, 6, 5, 4,
+ 7, 6, 5, 6, 7, 5, 4, 5, 6, 5, 7, 3, 7,
+ 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 8, 8,
+ 2, 4, 4, 4, 4, 4, 2, 2, 6, 5, 8, 5, 8,
+ 3, 5, 5, 6, 4, 9, 3,
+};
+/* aKWOffset[i] is the index into zKWText[] of the start of
+** the text for the i-th keyword. */
+static const unsigned short int aKWOffset[124] = {
+ 0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33,
+ 36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81,
+ 86, 91, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152,
+ 159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 184, 188, 192,
+ 199, 204, 209, 212, 218, 221, 225, 234, 240, 240, 240, 243, 246,
+ 250, 251, 255, 261, 265, 272, 278, 290, 296, 305, 307, 313, 318,
+ 320, 327, 332, 337, 343, 349, 354, 358, 361, 367, 371, 378, 380,
+ 387, 389, 391, 400, 404, 410, 416, 424, 429, 429, 445, 452, 459,
+ 460, 467, 471, 475, 479, 483, 486, 488, 490, 496, 500, 508, 513,
+ 521, 524, 529, 534, 540, 544, 549,
+};
+/* aKWCode[i] is the parser symbol code for the i-th keyword */
+static const unsigned char aKWCode[124] = {
+ TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE,
+ TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN,
+ TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
+ TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE,
+ TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE,
+ TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW,
+ TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT,
+ TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO,
+ TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP,
+ TK_OR, TK_UNIQUE, TK_QUERY, TK_WITHOUT, TK_WITH,
+ TK_JOIN_KW, TK_RELEASE, TK_ATTACH, TK_HAVING, TK_GROUP,
+ TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RECURSIVE, TK_BETWEEN,
+ TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, TK_LIKE_KW,
+ TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE, TK_COLLATE,
+ TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, TK_JOIN,
+ TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA,
+ TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN,
+ TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE, TK_AND,
+ TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN, TK_CAST,
+ TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW,
+ TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS,
+ TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW,
+ TK_BY, TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT,
+ TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING,
+ TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL,
+};
+/* Check to see if z[0..n-1] is a keyword. If it is, write the
+** parser symbol code for that keyword into *pType. Always
+** return the integer n (the length of the token). */
static int keywordCode(const char *z, int n, int *pType){
- /* zText[] encodes 834 bytes of keywords in 554 bytes */
- /* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */
- /* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */
- /* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */
- /* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERECURSIVE */
- /* BETWEENOTNULLIKECASCADELETECASECOLLATECREATECURRENT_DATEDETACH */
- /* IMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHEN */
- /* WHERENAMEAFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMIT */
- /* CONFLICTCROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAIL */
- /* FROMFULLGLOBYIFISNULLORDERESTRICTRIGHTROLLBACKROWUNIONUSING */
- /* VACUUMVIEWINITIALLY */
- static const char zText[553] = {
- 'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H',
- 'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G',
- 'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A',
- 'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F',
- 'E','R','R','A','B','L','E','L','S','E','X','C','E','P','T','R','A','N',
- 'S','A','C','T','I','O','N','A','T','U','R','A','L','T','E','R','A','I',
- 'S','E','X','C','L','U','S','I','V','E','X','I','S','T','S','A','V','E',
- 'P','O','I','N','T','E','R','S','E','C','T','R','I','G','G','E','R','E',
- 'F','E','R','E','N','C','E','S','C','O','N','S','T','R','A','I','N','T',
- 'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q',
- 'U','E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S',
- 'E','A','T','T','A','C','H','A','V','I','N','G','R','O','U','P','D','A',
- 'T','E','B','E','G','I','N','N','E','R','E','C','U','R','S','I','V','E',
- 'B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C','A',
- 'S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L','A',
- 'T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A',
- 'T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E','J',
- 'O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A','L',
- 'Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U','E',
- 'S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W','H',
- 'E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C','E',
- 'A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R','E',
- 'M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M','M',
- 'I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U','R',
- 'R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M','A',
- 'R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','D',
- 'R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L','O',
- 'B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S','T',
- 'R','I','C','T','R','I','G','H','T','R','O','L','L','B','A','C','K','R',
- 'O','W','U','N','I','O','N','U','S','I','N','G','V','A','C','U','U','M',
- 'V','I','E','W','I','N','I','T','I','A','L','L','Y',
- };
- static const unsigned char aHash[127] = {
- 76, 105, 117, 74, 0, 45, 0, 0, 82, 0, 77, 0, 0,
- 42, 12, 78, 15, 0, 116, 85, 54, 112, 0, 19, 0, 0,
- 121, 0, 119, 115, 0, 22, 93, 0, 9, 0, 0, 70, 71,
- 0, 69, 6, 0, 48, 90, 102, 0, 118, 101, 0, 0, 44,
- 0, 103, 24, 0, 17, 0, 122, 53, 23, 0, 5, 110, 25,
- 96, 0, 0, 124, 106, 60, 123, 57, 28, 55, 0, 91, 0,
- 100, 26, 0, 99, 0, 0, 0, 95, 92, 97, 88, 109, 14,
- 39, 108, 0, 81, 0, 18, 89, 111, 32, 0, 120, 80, 113,
- 62, 46, 84, 0, 0, 94, 40, 59, 114, 0, 36, 0, 0,
- 29, 0, 86, 63, 64, 0, 20, 61, 0, 56,
- };
- static const unsigned char aNext[124] = {
- 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 0, 0, 50,
- 0, 43, 3, 47, 0, 0, 0, 0, 30, 0, 58, 0, 38,
- 0, 0, 0, 1, 66, 0, 0, 67, 0, 41, 0, 0, 0,
- 0, 0, 0, 49, 65, 0, 0, 0, 0, 31, 52, 16, 34,
- 10, 0, 0, 0, 0, 0, 0, 0, 11, 72, 79, 0, 8,
- 0, 104, 98, 0, 107, 0, 87, 0, 75, 51, 0, 27, 37,
- 73, 83, 0, 35, 68, 0, 0,
- };
- static const unsigned char aLen[124] = {
- 7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6,
- 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6,
- 11, 6, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10,
- 4, 6, 2, 3, 9, 4, 2, 6, 5, 7, 4, 5, 7,
- 6, 6, 5, 6, 5, 5, 9, 7, 7, 3, 2, 4, 4,
- 7, 3, 6, 4, 7, 6, 12, 6, 9, 4, 6, 5, 4,
- 7, 6, 5, 6, 7, 5, 4, 5, 6, 5, 7, 3, 7,
- 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 8, 8,
- 2, 4, 4, 4, 4, 4, 2, 2, 6, 5, 8, 5, 8,
- 3, 5, 5, 6, 4, 9, 3,
- };
- static const unsigned short int aOffset[124] = {
- 0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33,
- 36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81,
- 86, 91, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152,
- 159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 184, 188, 192,
- 199, 204, 209, 212, 218, 221, 225, 234, 240, 240, 240, 243, 246,
- 250, 251, 255, 261, 265, 272, 278, 290, 296, 305, 307, 313, 318,
- 320, 327, 332, 337, 343, 349, 354, 358, 361, 367, 371, 378, 380,
- 387, 389, 391, 400, 404, 410, 416, 424, 429, 429, 445, 452, 459,
- 460, 467, 471, 475, 479, 483, 486, 488, 490, 496, 500, 508, 513,
- 521, 524, 529, 534, 540, 544, 549,
- };
- static const unsigned char aCode[124] = {
- TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE,
- TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN,
- TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
- TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE,
- TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE,
- TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW,
- TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT,
- TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO,
- TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP,
- TK_OR, TK_UNIQUE, TK_QUERY, TK_WITHOUT, TK_WITH,
- TK_JOIN_KW, TK_RELEASE, TK_ATTACH, TK_HAVING, TK_GROUP,
- TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RECURSIVE, TK_BETWEEN,
- TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, TK_LIKE_KW,
- TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE, TK_COLLATE,
- TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, TK_JOIN,
- TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA,
- TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN,
- TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE, TK_AND,
- TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN, TK_CAST,
- TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW,
- TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS,
- TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW,
- TK_BY, TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT,
- TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING,
- TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL,
- };
int i, j;
const char *zKW;
if( n>=2 ){
i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127;
- for(i=((int)aHash[i])-1; i>=0; i=((int)aNext[i])-1){
- if( aLen[i]!=n ) continue;
+ for(i=((int)aKWHash[i])-1; i>=0; i=((int)aKWNext[i])-1){
+ if( aKWLen[i]!=n ) continue;
j = 0;
- zKW = &zText[aOffset[i]];
+ zKW = &zKWText[aKWOffset[i]];
#ifdef SQLITE_ASCII
while( jdb; /* The database connection */
int mxSqlLen; /* Max length of an SQL string */
+#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
+ yyParser sEngine; /* Space to hold the Lemon-generated Parser object */
+#endif
assert( zSql!=0 );
mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
@@ -140456,26 +144386,27 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
}
pParse->rc = SQLITE_OK;
pParse->zTail = zSql;
- i = 0;
assert( pzErrMsg!=0 );
/* sqlite3ParserTrace(stdout, "parser: "); */
+#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
+ pEngine = &sEngine;
+ sqlite3ParserInit(pEngine);
+#else
pEngine = sqlite3ParserAlloc(sqlite3Malloc);
if( pEngine==0 ){
sqlite3OomFault(db);
return SQLITE_NOMEM_BKPT;
}
+#endif
assert( pParse->pNewTable==0 );
assert( pParse->pNewTrigger==0 );
assert( pParse->nVar==0 );
- assert( pParse->nzVar==0 );
- assert( pParse->azVar==0 );
+ assert( pParse->pVList==0 );
while( 1 ){
- assert( i>=0 );
- if( zSql[i]!=0 ){
- pParse->sLastToken.z = &zSql[i];
- pParse->sLastToken.n = sqlite3GetToken((u8*)&zSql[i],&tokenType);
- i += pParse->sLastToken.n;
- if( i>mxSqlLen ){
+ if( zSql[0]!=0 ){
+ n = sqlite3GetToken((u8*)zSql, &tokenType);
+ mxSqlLen -= n;
+ if( mxSqlLen<0 ){
pParse->rc = SQLITE_TOOBIG;
break;
}
@@ -140489,6 +144420,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
}else{
tokenType = TK_SEMI;
}
+ zSql -= n;
}
if( tokenType>=TK_SPACE ){
assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );
@@ -140497,18 +144429,21 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
break;
}
if( tokenType==TK_ILLEGAL ){
- sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"",
- &pParse->sLastToken);
+ sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql);
break;
}
+ zSql += n;
}else{
+ pParse->sLastToken.z = zSql;
+ pParse->sLastToken.n = n;
sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse);
lastTokenParsed = tokenType;
+ zSql += n;
if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break;
}
}
assert( nErr==0 );
- pParse->zTail = &zSql[i];
+ pParse->zTail = zSql;
#ifdef YYTRACKMAXSTACKDEPTH
sqlite3_mutex_enter(sqlite3MallocMutex());
sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK,
@@ -140516,7 +144451,11 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
);
sqlite3_mutex_leave(sqlite3MallocMutex());
#endif /* YYDEBUG */
+#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
+ sqlite3ParserFinalize(pEngine);
+#else
sqlite3ParserFree(pEngine, sqlite3_free);
+#endif
if( db->mallocFailed ){
pParse->rc = SQLITE_NOMEM_BKPT;
}
@@ -140555,12 +144494,11 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree);
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
- for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]);
- sqlite3DbFree(db, pParse->azVar);
+ sqlite3DbFree(db, pParse->pVList);
while( pParse->pAinc ){
AutoincInfo *p = pParse->pAinc;
pParse->pAinc = p->pNext;
- sqlite3DbFree(db, p);
+ sqlite3DbFreeNN(db, p);
}
while( pParse->pZombieTab ){
Table *p = pParse->pZombieTab;
@@ -140987,6 +144925,9 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db);
#ifdef SQLITE_ENABLE_JSON1
SQLITE_PRIVATE int sqlite3Json1Init(sqlite3*);
#endif
+#ifdef SQLITE_ENABLE_STMTVTAB
+SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3*);
+#endif
#ifdef SQLITE_ENABLE_FTS5
SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*);
#endif
@@ -141749,6 +145690,8 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
va_start(ap, op);
switch( op ){
case SQLITE_DBCONFIG_MAINDBNAME: {
+ /* IMP: R-06824-28531 */
+ /* IMP: R-36257-52125 */
db->aDb[0].zDbSName = va_arg(ap,char*);
rc = SQLITE_OK;
break;
@@ -141769,6 +145712,8 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
{ SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
{ SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer },
{ SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension },
+ { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose },
+ { SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG },
};
unsigned int i;
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
@@ -141825,6 +145770,7 @@ static int binCollFunc(
/* EVIDENCE-OF: R-65033-28449 The built-in BINARY collation compares
** strings byte by byte using the memcmp() function from the standard C
** library. */
+ assert( pKey1 && pKey2 );
rc = memcmp(pKey1, pKey2, n);
if( rc==0 ){
if( padFlag
@@ -141879,6 +145825,21 @@ SQLITE_API sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){
return db->lastRowid;
}
+/*
+** Set the value returned by the sqlite3_last_insert_rowid() API function.
+*/
+SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) ){
+ (void)SQLITE_MISUSE_BKPT;
+ return;
+ }
+#endif
+ sqlite3_mutex_enter(db->mutex);
+ db->lastRowid = iRowid;
+ sqlite3_mutex_leave(db->mutex);
+}
+
/*
** Return the number of changes in the most recent call to sqlite3_exec().
*/
@@ -142342,10 +146303,10 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){
static const char* const aMsg[] = {
/* SQLITE_OK */ "not an error",
- /* SQLITE_ERROR */ "SQL logic error or missing database",
+ /* SQLITE_ERROR */ "SQL logic error",
/* SQLITE_INTERNAL */ 0,
/* SQLITE_PERM */ "access permission denied",
- /* SQLITE_ABORT */ "callback requested query abort",
+ /* SQLITE_ABORT */ "query aborted",
/* SQLITE_BUSY */ "database is locked",
/* SQLITE_LOCKED */ "database table is locked",
/* SQLITE_NOMEM */ "out of memory",
@@ -142357,17 +146318,21 @@ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){
/* SQLITE_FULL */ "database or disk is full",
/* SQLITE_CANTOPEN */ "unable to open database file",
/* SQLITE_PROTOCOL */ "locking protocol",
- /* SQLITE_EMPTY */ "table contains no data",
+ /* SQLITE_EMPTY */ 0,
/* SQLITE_SCHEMA */ "database schema has changed",
/* SQLITE_TOOBIG */ "string or blob too big",
/* SQLITE_CONSTRAINT */ "constraint failed",
/* SQLITE_MISMATCH */ "datatype mismatch",
- /* SQLITE_MISUSE */ "library routine called out of sequence",
+ /* SQLITE_MISUSE */ "bad parameter or other API misuse",
+#ifdef SQLITE_DISABLE_LFS
/* SQLITE_NOLFS */ "large file support is disabled",
+#else
+ /* SQLITE_NOLFS */ 0,
+#endif
/* SQLITE_AUTH */ "authorization denied",
- /* SQLITE_FORMAT */ "auxiliary database format error",
- /* SQLITE_RANGE */ "bind or column index out of range",
- /* SQLITE_NOTADB */ "file is encrypted or is not a database",
+ /* SQLITE_FORMAT */ 0,
+ /* SQLITE_RANGE */ "column index out of range",
+ /* SQLITE_NOTADB */ "file is not a database",
};
const char *zErr = "unknown error";
switch( rc ){
@@ -142526,7 +146491,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
*/
SQLITE_API void sqlite3_interrupt(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ){
+ if( !sqlite3SafetyCheckOk(db) && (db==0 || db->magic!=SQLITE_MAGIC_ZOMBIE) ){
(void)SQLITE_MISUSE_BKPT;
return;
}
@@ -143065,6 +147030,13 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
sqlite3Error(db, rc);
}
rc = sqlite3ApiExit(db, rc);
+
+ /* If there are no active statements, clear the interrupt flag at this
+ ** point. */
+ if( db->nVdbeActive==0 ){
+ db->u1.isInterrupted = 0;
+ }
+
sqlite3_mutex_leave(db->mutex);
return rc;
#endif
@@ -143200,12 +147172,9 @@ SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){
'o', 'u', 't', ' ', 'o', 'f', ' ', 'm', 'e', 'm', 'o', 'r', 'y', 0
};
static const u16 misuse[] = {
- 'l', 'i', 'b', 'r', 'a', 'r', 'y', ' ',
- 'r', 'o', 'u', 't', 'i', 'n', 'e', ' ',
- 'c', 'a', 'l', 'l', 'e', 'd', ' ',
- 'o', 'u', 't', ' ',
- 'o', 'f', ' ',
- 's', 'e', 'q', 'u', 'e', 'n', 'c', 'e', 0
+ 'b', 'a', 'd', ' ', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', ' ',
+ 'o', 'r', ' ', 'o', 't', 'h', 'e', 'r', ' ', 'A', 'P', 'I', ' ',
+ 'm', 'i', 's', 'u', 's', 'e', 0
};
const void *z;
@@ -143567,6 +147536,7 @@ SQLITE_PRIVATE int sqlite3ParseUri(
assert( octet>=0 && octet<256 );
if( octet==0 ){
+#ifndef SQLITE_ENABLE_URI_00_ERROR
/* This branch is taken when "%00" appears within the URI. In this
** case we ignore all text in the remainder of the path, name or
** value currently being parsed. So ignore the current character
@@ -143579,6 +147549,12 @@ SQLITE_PRIVATE int sqlite3ParseUri(
iIn++;
}
continue;
+#else
+ /* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */
+ *pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri");
+ rc = SQLITE_ERROR;
+ goto parse_uri_out;
+#endif
}
c = octet;
}else if( eState==1 && (c=='&' || c=='=') ){
@@ -143683,7 +147659,9 @@ SQLITE_PRIVATE int sqlite3ParseUri(
}else{
zFile = sqlite3_malloc64(nUri+2);
if( !zFile ) return SQLITE_NOMEM_BKPT;
- memcpy(zFile, zUri, nUri);
+ if( nUri ){
+ memcpy(zFile, zUri, nUri);
+ }
zFile[nUri] = '\0';
zFile[nUri+1] = '\0';
flags &= ~SQLITE_OPEN_URI;
@@ -143731,26 +147709,6 @@ static int openDatabase(
if( rc ) return rc;
#endif
- /* Only allow sensible combinations of bits in the flags argument.
- ** Throw an error if any non-sense combination is used. If we
- ** do not block illegal combinations here, it could trigger
- ** assert() statements in deeper layers. Sensible combinations
- ** are:
- **
- ** 1: SQLITE_OPEN_READONLY
- ** 2: SQLITE_OPEN_READWRITE
- ** 6: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
- */
- assert( SQLITE_OPEN_READONLY == 0x01 );
- assert( SQLITE_OPEN_READWRITE == 0x02 );
- assert( SQLITE_OPEN_CREATE == 0x04 );
- testcase( (1<<(flags&7))==0x02 ); /* READONLY */
- testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
- testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
- if( ((1<<(flags&7)) & 0x46)==0 ){
- return SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */
- }
-
if( sqlite3GlobalConfig.bCoreMutex==0 ){
isThreadsafe = 0;
}else if( flags & SQLITE_OPEN_NOMUTEX ){
@@ -143841,6 +147799,9 @@ static int openDatabase(
#endif
#if defined(SQLITE_ENABLE_FTS3_TOKENIZER)
| SQLITE_Fts3Tokenizer
+#endif
+#if defined(SQLITE_ENABLE_QPSG)
+ | SQLITE_EnableQPSG
#endif
;
sqlite3HashInit(&db->aCollSeq);
@@ -143869,9 +147830,30 @@ static int openDatabase(
db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0);
assert( db->pDfltColl!=0 );
- /* Parse the filename/URI argument. */
+ /* Parse the filename/URI argument
+ **
+ ** Only allow sensible combinations of bits in the flags argument.
+ ** Throw an error if any non-sense combination is used. If we
+ ** do not block illegal combinations here, it could trigger
+ ** assert() statements in deeper layers. Sensible combinations
+ ** are:
+ **
+ ** 1: SQLITE_OPEN_READONLY
+ ** 2: SQLITE_OPEN_READWRITE
+ ** 6: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
+ */
db->openFlags = flags;
- rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
+ assert( SQLITE_OPEN_READONLY == 0x01 );
+ assert( SQLITE_OPEN_READWRITE == 0x02 );
+ assert( SQLITE_OPEN_CREATE == 0x04 );
+ testcase( (1<<(flags&7))==0x02 ); /* READONLY */
+ testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
+ testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
+ if( ((1<<(flags&7)) & 0x46)==0 ){
+ rc = SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */
+ }else{
+ rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
+ }
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
@@ -143980,6 +147962,12 @@ static int openDatabase(
}
#endif
+#ifdef SQLITE_ENABLE_STMTVTAB
+ if( !db->mallocFailed && rc==SQLITE_OK){
+ rc = sqlite3StmtVtabInit(db);
+ }
+#endif
+
/* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
** mode. Doing nothing at all also makes NORMAL the default.
@@ -144022,16 +148010,18 @@ opendb_out:
#endif
#if defined(SQLITE_HAS_CODEC)
if( rc==SQLITE_OK ){
- const char *zHexKey = sqlite3_uri_parameter(zOpen, "hexkey");
- if( zHexKey && zHexKey[0] ){
+ const char *zKey;
+ if( (zKey = sqlite3_uri_parameter(zOpen, "hexkey"))!=0 && zKey[0] ){
u8 iByte;
int i;
- char zKey[40];
- for(i=0, iByte=0; inDb; i++){
- if( db->aDb[i].pBt
- && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zDbSName)==0)
- ){
- return db->aDb[i].pBt;
- }
- }
- return 0;
+ int iDb = zDbName ? sqlite3FindDbName(db, zDbName) : 0;
+ return iDb<0 ? 0 : db->aDb[iDb].pBt;
}
/*
@@ -144925,7 +148914,6 @@ SQLITE_API int sqlite3_snapshot_get(
){
int rc = SQLITE_ERROR;
#ifndef SQLITE_OMIT_WAL
- int iDb;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
@@ -144934,13 +148922,15 @@ SQLITE_API int sqlite3_snapshot_get(
#endif
sqlite3_mutex_enter(db->mutex);
- iDb = sqlite3FindDbName(db, zDb);
- if( iDb==0 || iDb>1 ){
- Btree *pBt = db->aDb[iDb].pBt;
- if( 0==sqlite3BtreeIsInTrans(pBt) ){
- rc = sqlite3BtreeBeginTrans(pBt, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
+ if( db->autoCommit==0 ){
+ int iDb = sqlite3FindDbName(db, zDb);
+ if( iDb==0 || iDb>1 ){
+ Btree *pBt = db->aDb[iDb].pBt;
+ if( 0==sqlite3BtreeIsInTrans(pBt) ){
+ rc = sqlite3BtreeBeginTrans(pBt, 0);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
+ }
}
}
}
@@ -144987,6 +148977,38 @@ SQLITE_API int sqlite3_snapshot_open(
return rc;
}
+/*
+** Recover as many snapshots as possible from the wal file associated with
+** schema zDb of database db.
+*/
+SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){
+ int rc = SQLITE_ERROR;
+ int iDb;
+#ifndef SQLITE_OMIT_WAL
+
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) ){
+ return SQLITE_MISUSE_BKPT;
+ }
+#endif
+
+ sqlite3_mutex_enter(db->mutex);
+ iDb = sqlite3FindDbName(db, zDb);
+ if( iDb==0 || iDb>1 ){
+ Btree *pBt = db->aDb[iDb].pBt;
+ if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
+ rc = sqlite3BtreeBeginTrans(pBt, 0);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt));
+ sqlite3BtreeCommit(pBt);
+ }
+ }
+ }
+ sqlite3_mutex_leave(db->mutex);
+#endif /* SQLITE_OMIT_WAL */
+ return rc;
+}
+
/*
** Free a snapshot handle obtained from sqlite3_snapshot_get().
*/
@@ -144995,6 +149017,58 @@ SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){
}
#endif /* SQLITE_ENABLE_SNAPSHOT */
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+/*
+** Given the name of a compile-time option, return true if that option
+** was used and false if not.
+**
+** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
+** is not required for a match.
+*/
+SQLITE_API int sqlite3_compileoption_used(const char *zOptName){
+ int i, n;
+ int nOpt;
+ const char **azCompileOpt;
+
+#if SQLITE_ENABLE_API_ARMOR
+ if( zOptName==0 ){
+ (void)SQLITE_MISUSE_BKPT;
+ return 0;
+ }
+#endif
+
+ azCompileOpt = sqlite3CompileOptions(&nOpt);
+
+ if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
+ n = sqlite3Strlen30(zOptName);
+
+ /* Since nOpt is normally in single digits, a linear search is
+ ** adequate. No need for a binary search. */
+ for(i=0; i=0 && N=0 );
return 5;
}
@@ -146728,6 +150807,7 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){
assert( p->pSegments==0 );
/* Free any prepared statements held */
+ sqlite3_finalize(p->pSeekStmt);
for(i=0; iaStmt); i++){
sqlite3_finalize(p->aStmt[i]);
}
@@ -147453,65 +151533,66 @@ static int fts3InitVtab(
break;
}
}
- if( iOpt==SizeofArray(aFts4Opt) ){
- sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
- rc = SQLITE_ERROR;
- }else{
- switch( iOpt ){
- case 0: /* MATCHINFO */
- if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
- sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
- rc = SQLITE_ERROR;
- }
- bNoDocsize = 1;
- break;
+ switch( iOpt ){
+ case 0: /* MATCHINFO */
+ if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
+ sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
+ rc = SQLITE_ERROR;
+ }
+ bNoDocsize = 1;
+ break;
- case 1: /* PREFIX */
- sqlite3_free(zPrefix);
- zPrefix = zVal;
- zVal = 0;
- break;
+ case 1: /* PREFIX */
+ sqlite3_free(zPrefix);
+ zPrefix = zVal;
+ zVal = 0;
+ break;
- case 2: /* COMPRESS */
- sqlite3_free(zCompress);
- zCompress = zVal;
- zVal = 0;
- break;
+ case 2: /* COMPRESS */
+ sqlite3_free(zCompress);
+ zCompress = zVal;
+ zVal = 0;
+ break;
- case 3: /* UNCOMPRESS */
- sqlite3_free(zUncompress);
- zUncompress = zVal;
- zVal = 0;
- break;
+ case 3: /* UNCOMPRESS */
+ sqlite3_free(zUncompress);
+ zUncompress = zVal;
+ zVal = 0;
+ break;
- case 4: /* ORDER */
- if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
- && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
- ){
- sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
- rc = SQLITE_ERROR;
- }
- bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
- break;
+ case 4: /* ORDER */
+ if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
+ && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
+ ){
+ sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
+ rc = SQLITE_ERROR;
+ }
+ bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
+ break;
- case 5: /* CONTENT */
- sqlite3_free(zContent);
- zContent = zVal;
- zVal = 0;
- break;
+ case 5: /* CONTENT */
+ sqlite3_free(zContent);
+ zContent = zVal;
+ zVal = 0;
+ break;
- case 6: /* LANGUAGEID */
- assert( iOpt==6 );
- sqlite3_free(zLanguageid);
- zLanguageid = zVal;
- zVal = 0;
- break;
+ case 6: /* LANGUAGEID */
+ assert( iOpt==6 );
+ sqlite3_free(zLanguageid);
+ zLanguageid = zVal;
+ zVal = 0;
+ break;
- case 7: /* NOTINDEXED */
- azNotindexed[nNotindexed++] = zVal;
- zVal = 0;
- break;
- }
+ case 7: /* NOTINDEXED */
+ azNotindexed[nNotindexed++] = zVal;
+ zVal = 0;
+ break;
+
+ default:
+ assert( iOpt==SizeofArray(aFts4Opt) );
+ sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
+ rc = SQLITE_ERROR;
+ break;
}
sqlite3_free(zVal);
}
@@ -147599,9 +151680,9 @@ static int fts3InitVtab(
p->pTokenizer = pTokenizer;
p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
p->bHasDocsize = (isFts4 && bNoDocsize==0);
- p->bHasStat = isFts4;
- p->bFts4 = isFts4;
- p->bDescIdx = bDescIdx;
+ p->bHasStat = (u8)isFts4;
+ p->bFts4 = (u8)isFts4;
+ p->bDescIdx = (u8)bDescIdx;
p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */
p->zContentTbl = zContent;
p->zLanguageid = zLanguageid;
@@ -147632,7 +151713,9 @@ static int fts3InitVtab(
char *z;
int n = 0;
z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
- memcpy(zCsr, z, n);
+ if( n>0 ){
+ memcpy(zCsr, z, n);
+ }
zCsr[n] = '\0';
sqlite3Fts3Dequote(zCsr);
p->azColumn[iCol] = zCsr;
@@ -147916,6 +151999,39 @@ static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
return SQLITE_OK;
}
+/*
+** Finalize the statement handle at pCsr->pStmt.
+**
+** Or, if that statement handle is one created by fts3CursorSeekStmt(),
+** and the Fts3Table.pSeekStmt slot is currently NULL, save the statement
+** pointer there instead of finalizing it.
+*/
+static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){
+ if( pCsr->bSeekStmt ){
+ Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
+ if( p->pSeekStmt==0 ){
+ p->pSeekStmt = pCsr->pStmt;
+ sqlite3_reset(pCsr->pStmt);
+ pCsr->pStmt = 0;
+ }
+ pCsr->bSeekStmt = 0;
+ }
+ sqlite3_finalize(pCsr->pStmt);
+}
+
+/*
+** Free all resources currently held by the cursor passed as the only
+** argument.
+*/
+static void fts3ClearCursor(Fts3Cursor *pCsr){
+ fts3CursorFinalizeStmt(pCsr);
+ sqlite3Fts3FreeDeferredTokens(pCsr);
+ sqlite3_free(pCsr->aDoclist);
+ sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
+ sqlite3Fts3ExprFree(pCsr->pExpr);
+ memset(&(&pCsr->base)[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
+}
+
/*
** Close the cursor. For additional information see the documentation
** on the xClose method of the virtual table interface.
@@ -147923,11 +152039,7 @@ static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
- sqlite3_finalize(pCsr->pStmt);
- sqlite3Fts3ExprFree(pCsr->pExpr);
- sqlite3Fts3FreeDeferredTokens(pCsr);
- sqlite3_free(pCsr->aDoclist);
- sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
+ fts3ClearCursor(pCsr);
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
sqlite3_free(pCsr);
return SQLITE_OK;
@@ -147941,20 +152053,23 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
**
** (or the equivalent for a content=xxx table) and set pCsr->pStmt to
** it. If an error occurs, return an SQLite error code.
-**
-** Otherwise, set *ppStmt to point to pCsr->pStmt and return SQLITE_OK.
*/
-static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){
+static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
int rc = SQLITE_OK;
if( pCsr->pStmt==0 ){
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
char *zSql;
- zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
- if( !zSql ) return SQLITE_NOMEM;
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
- sqlite3_free(zSql);
+ if( p->pSeekStmt ){
+ pCsr->pStmt = p->pSeekStmt;
+ p->pSeekStmt = 0;
+ }else{
+ zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
+ if( !zSql ) return SQLITE_NOMEM;
+ rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
+ sqlite3_free(zSql);
+ }
+ if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
}
- *ppStmt = pCsr->pStmt;
return rc;
}
@@ -147966,9 +152081,7 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
int rc = SQLITE_OK;
if( pCsr->isRequireSeek ){
- sqlite3_stmt *pStmt = 0;
-
- rc = fts3CursorSeekStmt(pCsr, &pStmt);
+ rc = fts3CursorSeekStmt(pCsr);
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
pCsr->isRequireSeek = 0;
@@ -148057,7 +152170,8 @@ static int fts3ScanInteriorNode(
isFirstTerm = 0;
zCsr += fts3GetVarint32(zCsr, &nSuffix);
- if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
+ assert( nPrefix>=0 && nSuffix>=0 );
+ if( &zCsr[nSuffix]>zEnd ){
rc = FTS_CORRUPT_VTAB;
goto finish_scan;
}
@@ -148867,7 +152981,7 @@ SQLITE_PRIVATE int sqlite3Fts3FirstFilter(
fts3ColumnlistCopy(0, &p);
}
- while( ppStmt);
- sqlite3_free(pCsr->aDoclist);
- sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
- sqlite3Fts3ExprFree(pCsr->pExpr);
- memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
+ fts3ClearCursor(pCsr);
/* Set the lower and upper bounds on docids to return */
pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
@@ -149488,13 +153598,13 @@ static int fts3FilterMethod(
);
}
if( zSql ){
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
+ rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
sqlite3_free(zSql);
}else{
rc = SQLITE_NOMEM;
}
}else if( eSearch==FTS3_DOCID_SEARCH ){
- rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
+ rc = fts3CursorSeekStmt(pCsr);
if( rc==SQLITE_OK ){
rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
}
@@ -149509,7 +153619,12 @@ static int fts3FilterMethod(
** routine to find out if it has reached the end of a result set.
*/
static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
- return ((Fts3Cursor *)pCursor)->isEof;
+ Fts3Cursor *pCsr = (Fts3Cursor*)pCursor;
+ if( pCsr->isEof ){
+ fts3ClearCursor(pCsr);
+ pCsr->isEof = 1;
+ }
+ return pCsr->isEof;
}
/*
@@ -149547,33 +153662,37 @@ static int fts3ColumnMethod(
/* The column value supplied by SQLite must be in range. */
assert( iCol>=0 && iCol<=p->nColumn+2 );
- if( iCol==p->nColumn+1 ){
- /* This call is a request for the "docid" column. Since "docid" is an
- ** alias for "rowid", use the xRowid() method to obtain the value.
- */
- sqlite3_result_int64(pCtx, pCsr->iPrevId);
- }else if( iCol==p->nColumn ){
- /* The extra column whose name is the same as the table.
- ** Return a blob which is a pointer to the cursor. */
- sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
- }else if( iCol==p->nColumn+2 && pCsr->pExpr ){
- sqlite3_result_int64(pCtx, pCsr->iLangid);
- }else{
- /* The requested column is either a user column (one that contains
- ** indexed data), or the language-id column. */
- rc = fts3CursorSeek(0, pCsr);
+ switch( iCol-p->nColumn ){
+ case 0:
+ /* The special 'table-name' column */
+ sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0);
+ break;
- if( rc==SQLITE_OK ){
- if( iCol==p->nColumn+2 ){
- int iLangid = 0;
- if( p->zLanguageid ){
- iLangid = sqlite3_column_int(pCsr->pStmt, p->nColumn+1);
- }
- sqlite3_result_int(pCtx, iLangid);
- }else if( sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){
+ case 1:
+ /* The docid column */
+ sqlite3_result_int64(pCtx, pCsr->iPrevId);
+ break;
+
+ case 2:
+ if( pCsr->pExpr ){
+ sqlite3_result_int64(pCtx, pCsr->iLangid);
+ break;
+ }else if( p->zLanguageid==0 ){
+ sqlite3_result_int(pCtx, 0);
+ break;
+ }else{
+ iCol = p->nColumn;
+ /* fall-through */
+ }
+
+ default:
+ /* A user column. Or, if this is a full-table scan, possibly the
+ ** language-id column. Seek the cursor. */
+ rc = fts3CursorSeek(0, pCsr);
+ if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)-1>iCol ){
sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
}
- }
+ break;
}
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
@@ -149622,8 +153741,10 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
Fts3Table *p = (Fts3Table*)pVtab;
- int rc = sqlite3Fts3PendingTermsFlush(p);
+ int rc;
+ i64 iLastRowid = sqlite3_last_insert_rowid(p->db);
+ rc = sqlite3Fts3PendingTermsFlush(p);
if( rc==SQLITE_OK
&& p->nLeafAdd>(nMinMerge/16)
&& p->nAutoincrmerge && p->nAutoincrmerge!=0xff
@@ -149638,6 +153759,7 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge);
}
sqlite3Fts3SegmentsClose(p);
+ sqlite3_set_last_insert_rowid(p->db, iLastRowid);
return rc;
}
@@ -149650,17 +153772,11 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
static int fts3SetHasStat(Fts3Table *p){
int rc = SQLITE_OK;
if( p->bHasStat==2 ){
- const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'";
- char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName);
- if( zSql ){
- sqlite3_stmt *pStmt = 0;
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- if( rc==SQLITE_OK ){
- int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW);
- rc = sqlite3_finalize(pStmt);
- if( rc==SQLITE_OK ) p->bHasStat = bHasStat;
- }
- sqlite3_free(zSql);
+ char *zTbl = sqlite3_mprintf("%s_stat", p->zName);
+ if( zTbl ){
+ int res = sqlite3_table_column_metadata(p->db, p->zDb, zTbl, 0,0,0,0,0,0);
+ sqlite3_free(zTbl);
+ p->bHasStat = (res==SQLITE_OK);
}else{
rc = SQLITE_NOMEM;
}
@@ -149767,18 +153883,17 @@ static int fts3FunctionArg(
sqlite3_value *pVal, /* argv[0] passed to function */
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
){
- Fts3Cursor *pRet;
- if( sqlite3_value_type(pVal)!=SQLITE_BLOB
- || sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
- ){
+ int rc;
+ *ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor");
+ if( (*ppCsr)!=0 ){
+ rc = SQLITE_OK;
+ }else{
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
sqlite3_result_error(pContext, zErr, -1);
sqlite3_free(zErr);
- return SQLITE_ERROR;
+ rc = SQLITE_ERROR;
}
- memcpy(&pRet, sqlite3_value_blob(pVal), sizeof(Fts3Cursor *));
- *ppCsr = pRet;
- return SQLITE_OK;
+ return rc;
}
/*
@@ -150165,7 +154280,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
#endif
/* Create the virtual table wrapper around the hash-table and overload
- ** the two scalar functions. If this is successful, register the
+ ** the four scalar functions. If this is successful, register the
** module with sqlite.
*/
if( SQLITE_OK==rc
@@ -150748,7 +154863,7 @@ static int fts3EvalIncrPhraseNext(
** one incremental token. In which case the bIncr flag is set. */
assert( p->bIncr==1 );
- if( p->nToken==1 && p->bIncr ){
+ if( p->nToken==1 ){
rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
&pDL->iDocid, &pDL->pList, &pDL->nList
);
@@ -150981,6 +155096,7 @@ static void fts3EvalTokenCosts(
** the number of overflow pages consumed by a record B bytes in size.
*/
static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
+ int rc = SQLITE_OK;
if( pCsr->nRowAvg==0 ){
/* The average document size, which is required to calculate the cost
** of each doclist, has not yet been determined. Read the required
@@ -150993,7 +155109,6 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
** data stored in all rows of each column of the table, from left
** to right.
*/
- int rc;
Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
sqlite3_stmt *pStmt;
sqlite3_int64 nDoc = 0;
@@ -151020,11 +155135,10 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
assert( pCsr->nRowAvg>0 );
rc = sqlite3_reset(pStmt);
- if( rc!=SQLITE_OK ) return rc;
}
*pnPage = pCsr->nRowAvg;
- return SQLITE_OK;
+ return rc;
}
/*
@@ -151374,7 +155488,8 @@ static void fts3EvalNextRow(
pExpr->iDocid = pLeft->iDocid;
pExpr->bEof = (pLeft->bEof || pRight->bEof);
if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){
- if( pRight->pPhrase && pRight->pPhrase->doclist.aAll ){
+ assert( pRight->eType==FTSQUERY_PHRASE );
+ if( pRight->pPhrase->doclist.aAll ){
Fts3Doclist *pDl = &pRight->pPhrase->doclist;
while( *pRc==SQLITE_OK && pRight->bEof==0 ){
memset(pDl->pList, 0, pDl->nList);
@@ -151403,7 +155518,7 @@ static void fts3EvalNextRow(
if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
fts3EvalNextRow(pCsr, pLeft, pRc);
- }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
+ }else if( pLeft->bEof || iCmp>0 ){
fts3EvalNextRow(pCsr, pRight, pRc);
}else{
fts3EvalNextRow(pCsr, pLeft, pRc);
@@ -151495,7 +155610,6 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
*/
if( *pRc==SQLITE_OK
&& pExpr->eType==FTSQUERY_NEAR
- && pExpr->bEof==0
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
){
Fts3Expr *p;
@@ -151504,42 +155618,39 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
/* Allocate temporary working space. */
for(p=pExpr; p->pLeft; p=p->pLeft){
+ assert( p->pRight->pPhrase->doclist.nList>0 );
nTmp += p->pRight->pPhrase->doclist.nList;
}
nTmp += p->pPhrase->doclist.nList;
- if( nTmp==0 ){
+ aTmp = sqlite3_malloc(nTmp*2);
+ if( !aTmp ){
+ *pRc = SQLITE_NOMEM;
res = 0;
}else{
- aTmp = sqlite3_malloc(nTmp*2);
- if( !aTmp ){
- *pRc = SQLITE_NOMEM;
- res = 0;
- }else{
- char *aPoslist = p->pPhrase->doclist.pList;
- int nToken = p->pPhrase->nToken;
+ char *aPoslist = p->pPhrase->doclist.pList;
+ int nToken = p->pPhrase->nToken;
- for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
- Fts3Phrase *pPhrase = p->pRight->pPhrase;
- int nNear = p->nNear;
- res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
- }
-
- aPoslist = pExpr->pRight->pPhrase->doclist.pList;
- nToken = pExpr->pRight->pPhrase->nToken;
- for(p=pExpr->pLeft; p && res; p=p->pLeft){
- int nNear;
- Fts3Phrase *pPhrase;
- assert( p->pParent && p->pParent->pLeft==p );
- nNear = p->pParent->nNear;
- pPhrase = (
- p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
- );
- res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
- }
+ for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
+ Fts3Phrase *pPhrase = p->pRight->pPhrase;
+ int nNear = p->nNear;
+ res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
}
- sqlite3_free(aTmp);
+ aPoslist = pExpr->pRight->pPhrase->doclist.pList;
+ nToken = pExpr->pRight->pPhrase->nToken;
+ for(p=pExpr->pLeft; p && res; p=p->pLeft){
+ int nNear;
+ Fts3Phrase *pPhrase;
+ assert( p->pParent && p->pParent->pLeft==p );
+ nNear = p->pParent->nNear;
+ pPhrase = (
+ p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
+ );
+ res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+ }
}
+
+ sqlite3_free(aTmp);
}
return res;
@@ -156699,7 +160810,8 @@ static int fts3SqlStmt(
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, NULL);
+ rc = sqlite3_prepare_v3(p->db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
+ &pStmt, NULL);
sqlite3_free(zSql);
assert( rc==SQLITE_OK || pStmt==0 );
p->aStmt[eStmt] = pStmt;
@@ -161248,11 +165360,14 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
** Convert the text beginning at *pz into an integer and return
** its value. Advance *pz to point to the first character past
** the integer.
+**
+** This function used for parameters to merge= and incrmerge=
+** commands.
*/
static int fts3Getint(const char **pz){
const char *z = *pz;
int i = 0;
- while( (*z)>='0' && (*z)<='9' ) i = 10*i + *(z++) - '0';
+ while( (*z)>='0' && (*z)<='9' && i<214748363 ) i = 10*i + *(z++) - '0';
*pz = z;
return i;
}
@@ -163818,16 +167933,16 @@ static int unicodeAddExceptions(
){
const unsigned char *z = (const unsigned char *)zIn;
const unsigned char *zTerm = &z[nIn];
- int iCode;
+ unsigned int iCode;
int nEntry = 0;
assert( bAlnum==0 || bAlnum==1 );
while( zi; j--) aNew[j] = aNew[j-1];
- aNew[i] = iCode;
+ aNew[i] = (int)iCode;
nNew++;
}
}
@@ -164000,7 +168115,7 @@ static int unicodeNext(
){
unicode_cursor *pCsr = (unicode_cursor *)pC;
unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
- int iCode = 0;
+ unsigned int iCode = 0;
char *zOut;
const unsigned char *z = &pCsr->aInput[pCsr->iOff];
const unsigned char *zStart = z;
@@ -164012,7 +168127,7 @@ static int unicodeNext(
** the input. */
while( z=zTerm ) return SQLITE_DONE;
@@ -164032,7 +168147,7 @@ static int unicodeNext(
/* Write the folded case of the last character read to the output */
zEnd = z;
- iOut = sqlite3FtsUnicodeFold(iCode, p->bRemoveDiacritic);
+ iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic);
if( iOut ){
WRITE_UTF8(zOut, iOut);
}
@@ -164040,8 +168155,8 @@ static int unicodeNext(
/* If the cursor is not at EOF, read the next character */
if( z>=zTerm ) break;
READ_UTF8(z, zTerm, iCode);
- }while( unicodeIsAlnum(p, iCode)
- || sqlite3FtsUnicodeIsdiacritic(iCode)
+ }while( unicodeIsAlnum(p, (int)iCode)
+ || sqlite3FtsUnicodeIsdiacritic((int)iCode)
);
/* Set the output variables and return. */
@@ -164205,9 +168320,9 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){
0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
};
- if( c<128 ){
- return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
- }else if( c<(1<<22) ){
+ if( (unsigned int)c<128 ){
+ return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
+ }else if( (unsigned int)c<(1<<22) ){
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
int iRes = 0;
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
@@ -164400,16 +168515,17 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
int ret = c;
- assert( c>=0 );
assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
if( c<128 ){
if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
}else if( c<65536 ){
+ const struct TableEntry *p;
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
int iLo = 0;
int iRes = -1;
+ assert( c>aEntry[0].iCode );
while( iHi>=iLo ){
int iTest = (iHi + iLo) / 2;
int cmp = (c - aEntry[iTest].iCode);
@@ -164420,14 +168536,12 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
iHi = iTest-1;
}
}
- assert( iRes<0 || c>=aEntry[iRes].iCode );
- if( iRes>=0 ){
- const struct TableEntry *p = &aEntry[iRes];
- if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
- ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
- assert( ret>0 );
- }
+ assert( iRes>=0 && c>=aEntry[iRes].iCode );
+ p = &aEntry[iRes];
+ if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
+ ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
+ assert( ret>0 );
}
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
@@ -164514,6 +168628,7 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
#ifndef SQLITE_AMALGAMATION
#include "sqlite3rtree.h"
typedef sqlite3_int64 i64;
+typedef sqlite3_uint64 u64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
@@ -164562,13 +168677,16 @@ struct Rtree {
sqlite3 *db; /* Host database connection */
int iNodeSize; /* Size in bytes of each node in the node table */
u8 nDim; /* Number of dimensions */
+ u8 nDim2; /* Twice the number of dimensions */
u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
u8 nBytesPerCell; /* Bytes consumed per cell */
+ u8 inWrTrans; /* True if inside write transaction */
int iDepth; /* Current depth of the r-tree structure */
char *zDb; /* Name of database containing r-tree table */
char *zName; /* Name of r-tree table */
- int nBusy; /* Current number of users of this structure */
+ u32 nBusy; /* Current number of users of this structure */
i64 nRowEst; /* Estimated number of rows in this table */
+ u32 nCursor; /* Number of open cursors */
/* List of nodes removed during a CondenseTree operation. List is
** linked together via the pointer normally used for hash chains -
@@ -164578,8 +168696,10 @@ struct Rtree {
RtreeNode *pDeleted;
int iReinsertHeight; /* Height of sub-trees Reinsert() has run on */
+ /* Blob I/O on xxx_node */
+ sqlite3_blob *pNodeBlob;
+
/* Statements to read/write/delete a record from xxx_node */
- sqlite3_stmt *pReadNode;
sqlite3_stmt *pWriteNode;
sqlite3_stmt *pDeleteNode;
@@ -164779,14 +168899,6 @@ struct RtreeGeomCallback {
void *pContext;
};
-
-/*
-** Value for the first field of every RtreeMatchArg object. The MATCH
-** operator tests that the first field of a blob operand matches this
-** value to avoid operating on invalid blobs (which could cause a segfault).
-*/
-#define RTREE_GEOMETRY_MAGIC 0x891245AB
-
/*
** An instance of this structure (in the form of a BLOB) is returned by
** the SQL functions that sqlite3_rtree_geometry_callback() and
@@ -164794,7 +168906,7 @@ struct RtreeGeomCallback {
** operand to the MATCH operator of an R-Tree.
*/
struct RtreeMatchArg {
- u32 magic; /* Always RTREE_GEOMETRY_MAGIC */
+ u32 iSize; /* Size of this object */
RtreeGeomCallback cb; /* Info about the callback functions */
int nParam; /* Number of parameters to the SQL function */
sqlite3_value **apSqlParam; /* Original SQL parameter values */
@@ -164808,6 +168920,58 @@ struct RtreeMatchArg {
# define MIN(x,y) ((x) > (y) ? (y) : (x))
#endif
+/* What version of GCC is being used. 0 means GCC is not being used .
+** Note that the GCC_VERSION macro will also be set correctly when using
+** clang, since clang works hard to be gcc compatible. So the gcc
+** optimizations will also work when compiling with clang.
+*/
+#ifndef GCC_VERSION
+#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
+# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
+#else
+# define GCC_VERSION 0
+#endif
+#endif
+
+/* The testcase() macro should already be defined in the amalgamation. If
+** it is not, make it a no-op.
+*/
+#ifndef SQLITE_AMALGAMATION
+# define testcase(X)
+#endif
+
+/*
+** Macros to determine whether the machine is big or little endian,
+** and whether or not that determination is run-time or compile-time.
+**
+** For best performance, an attempt is made to guess at the byte-order
+** using C-preprocessor macros. If that is unsuccessful, or if
+** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
+** at run-time.
+*/
+#ifndef SQLITE_BYTEORDER
+#if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
+ defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
+ defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
+ defined(__arm__)
+# define SQLITE_BYTEORDER 1234
+#elif defined(sparc) || defined(__ppc__)
+# define SQLITE_BYTEORDER 4321
+#else
+# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */
+#endif
+#endif
+
+
+/* What version of MSVC is being used. 0 means MSVC is not being used */
+#ifndef MSVC_VERSION
+#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC)
+# define MSVC_VERSION _MSC_VER
+#else
+# define MSVC_VERSION 0
+#endif
+#endif
+
/*
** Functions to deserialize a 16 bit integer, 32 bit real number and
** 64 bit integer. The deserialized value is returned.
@@ -164816,24 +168980,47 @@ static int readInt16(u8 *p){
return (p[0]<<8) + p[1];
}
static void readCoord(u8 *p, RtreeCoord *pCoord){
+ assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */
+#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
+ pCoord->u = _byteswap_ulong(*(u32*)p);
+#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
+ pCoord->u = __builtin_bswap32(*(u32*)p);
+#elif SQLITE_BYTEORDER==4321
+ pCoord->u = *(u32*)p;
+#else
pCoord->u = (
(((u32)p[0]) << 24) +
(((u32)p[1]) << 16) +
(((u32)p[2]) << 8) +
(((u32)p[3]) << 0)
);
+#endif
}
static i64 readInt64(u8 *p){
- return (
- (((i64)p[0]) << 56) +
- (((i64)p[1]) << 48) +
- (((i64)p[2]) << 40) +
- (((i64)p[3]) << 32) +
- (((i64)p[4]) << 24) +
- (((i64)p[5]) << 16) +
- (((i64)p[6]) << 8) +
- (((i64)p[7]) << 0)
+#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
+ u64 x;
+ memcpy(&x, p, 8);
+ return (i64)_byteswap_uint64(x);
+#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
+ u64 x;
+ memcpy(&x, p, 8);
+ return (i64)__builtin_bswap64(x);
+#elif SQLITE_BYTEORDER==4321
+ i64 x;
+ memcpy(&x, p, 8);
+ return x;
+#else
+ return (i64)(
+ (((u64)p[0]) << 56) +
+ (((u64)p[1]) << 48) +
+ (((u64)p[2]) << 40) +
+ (((u64)p[3]) << 32) +
+ (((u64)p[4]) << 24) +
+ (((u64)p[5]) << 16) +
+ (((u64)p[6]) << 8) +
+ (((u64)p[7]) << 0)
);
+#endif
}
/*
@@ -164841,23 +169028,43 @@ static i64 readInt64(u8 *p){
** 64 bit integer. The value returned is the number of bytes written
** to the argument buffer (always 2, 4 and 8 respectively).
*/
-static int writeInt16(u8 *p, int i){
+static void writeInt16(u8 *p, int i){
p[0] = (i>> 8)&0xFF;
p[1] = (i>> 0)&0xFF;
- return 2;
}
static int writeCoord(u8 *p, RtreeCoord *pCoord){
u32 i;
+ assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */
assert( sizeof(RtreeCoord)==4 );
assert( sizeof(u32)==4 );
+#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
+ i = __builtin_bswap32(pCoord->u);
+ memcpy(p, &i, 4);
+#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
+ i = _byteswap_ulong(pCoord->u);
+ memcpy(p, &i, 4);
+#elif SQLITE_BYTEORDER==4321
+ i = pCoord->u;
+ memcpy(p, &i, 4);
+#else
i = pCoord->u;
p[0] = (i>>24)&0xFF;
p[1] = (i>>16)&0xFF;
p[2] = (i>> 8)&0xFF;
p[3] = (i>> 0)&0xFF;
+#endif
return 4;
}
static int writeInt64(u8 *p, i64 i){
+#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
+ i = (i64)__builtin_bswap64((u64)i);
+ memcpy(p, &i, 8);
+#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
+ i = (i64)_byteswap_uint64((u64)i);
+ memcpy(p, &i, 8);
+#elif SQLITE_BYTEORDER==4321
+ memcpy(p, &i, 8);
+#else
p[0] = (i>>56)&0xFF;
p[1] = (i>>48)&0xFF;
p[2] = (i>>40)&0xFF;
@@ -164866,6 +169073,7 @@ static int writeInt64(u8 *p, i64 i){
p[5] = (i>>16)&0xFF;
p[6] = (i>> 8)&0xFF;
p[7] = (i>> 0)&0xFF;
+#endif
return 8;
}
@@ -164948,6 +169156,17 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
return pNode;
}
+/*
+** Clear the Rtree.pNodeBlob object
+*/
+static void nodeBlobReset(Rtree *pRtree){
+ if( pRtree->pNodeBlob && pRtree->inWrTrans==0 && pRtree->nCursor==0 ){
+ sqlite3_blob *pBlob = pRtree->pNodeBlob;
+ pRtree->pNodeBlob = 0;
+ sqlite3_blob_close(pBlob);
+ }
+}
+
/*
** Obtain a reference to an r-tree node.
*/
@@ -164957,9 +169176,8 @@ static int nodeAcquire(
RtreeNode *pParent, /* Either the parent node or NULL */
RtreeNode **ppNode /* OUT: Acquired node */
){
- int rc;
- int rc2 = SQLITE_OK;
- RtreeNode *pNode;
+ int rc = SQLITE_OK;
+ RtreeNode *pNode = 0;
/* Check if the requested node is already in the hash table. If so,
** increase its reference count and return it.
@@ -164975,28 +169193,45 @@ static int nodeAcquire(
return SQLITE_OK;
}
- sqlite3_bind_int64(pRtree->pReadNode, 1, iNode);
- rc = sqlite3_step(pRtree->pReadNode);
- if( rc==SQLITE_ROW ){
- const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0);
- if( pRtree->iNodeSize==sqlite3_column_bytes(pRtree->pReadNode, 0) ){
- pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize);
- if( !pNode ){
- rc2 = SQLITE_NOMEM;
- }else{
- pNode->pParent = pParent;
- pNode->zData = (u8 *)&pNode[1];
- pNode->nRef = 1;
- pNode->iNode = iNode;
- pNode->isDirty = 0;
- pNode->pNext = 0;
- memcpy(pNode->zData, zBlob, pRtree->iNodeSize);
- nodeReference(pParent);
- }
+ if( pRtree->pNodeBlob ){
+ sqlite3_blob *pBlob = pRtree->pNodeBlob;
+ pRtree->pNodeBlob = 0;
+ rc = sqlite3_blob_reopen(pBlob, iNode);
+ pRtree->pNodeBlob = pBlob;
+ if( rc ){
+ nodeBlobReset(pRtree);
+ if( rc==SQLITE_NOMEM ) return SQLITE_NOMEM;
+ }
+ }
+ if( pRtree->pNodeBlob==0 ){
+ char *zTab = sqlite3_mprintf("%s_node", pRtree->zName);
+ if( zTab==0 ) return SQLITE_NOMEM;
+ rc = sqlite3_blob_open(pRtree->db, pRtree->zDb, zTab, "data", iNode, 0,
+ &pRtree->pNodeBlob);
+ sqlite3_free(zTab);
+ }
+ if( rc ){
+ nodeBlobReset(pRtree);
+ *ppNode = 0;
+ /* If unable to open an sqlite3_blob on the desired row, that can only
+ ** be because the shadow tables hold erroneous data. */
+ if( rc==SQLITE_ERROR ) rc = SQLITE_CORRUPT_VTAB;
+ }else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){
+ pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize);
+ if( !pNode ){
+ rc = SQLITE_NOMEM;
+ }else{
+ pNode->pParent = pParent;
+ pNode->zData = (u8 *)&pNode[1];
+ pNode->nRef = 1;
+ pNode->iNode = iNode;
+ pNode->isDirty = 0;
+ pNode->pNext = 0;
+ rc = sqlite3_blob_read(pRtree->pNodeBlob, pNode->zData,
+ pRtree->iNodeSize, 0);
+ nodeReference(pParent);
}
}
- rc = sqlite3_reset(pRtree->pReadNode);
- if( rc==SQLITE_OK ) rc = rc2;
/* If the root node was just loaded, set pRtree->iDepth to the height
** of the r-tree structure. A height of zero means all data is stored on
@@ -165048,7 +169283,7 @@ static void nodeOverwriteCell(
int ii;
u8 *p = &pNode->zData[4 + pRtree->nBytesPerCell*iCell];
p += writeInt64(p, pCell->iRowid);
- for(ii=0; ii<(pRtree->nDim*2); ii++){
+ for(ii=0; iinDim2; ii++){
p += writeCoord(p, &pCell->aCoord[ii]);
}
pNode->isDirty = 1;
@@ -165182,13 +169417,16 @@ static void nodeGetCell(
){
u8 *pData;
RtreeCoord *pCoord;
- int ii;
+ int ii = 0;
pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell);
pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell);
pCoord = pCell->aCoord;
- for(ii=0; iinDim*2; ii++){
- readCoord(&pData[ii*4], &pCoord[ii]);
- }
+ do{
+ readCoord(pData, &pCoord[ii]);
+ readCoord(pData+4, &pCoord[ii+1]);
+ pData += 8;
+ ii += 2;
+ }while( iinDim2 );
}
@@ -165239,7 +169477,9 @@ static void rtreeReference(Rtree *pRtree){
static void rtreeRelease(Rtree *pRtree){
pRtree->nBusy--;
if( pRtree->nBusy==0 ){
- sqlite3_finalize(pRtree->pReadNode);
+ pRtree->inWrTrans = 0;
+ pRtree->nCursor = 0;
+ nodeBlobReset(pRtree);
sqlite3_finalize(pRtree->pWriteNode);
sqlite3_finalize(pRtree->pDeleteNode);
sqlite3_finalize(pRtree->pReadRowid);
@@ -165277,6 +169517,7 @@ static int rtreeDestroy(sqlite3_vtab *pVtab){
if( !zCreate ){
rc = SQLITE_NOMEM;
}else{
+ nodeBlobReset(pRtree);
rc = sqlite3_exec(pRtree->db, zCreate, 0, 0, 0);
sqlite3_free(zCreate);
}
@@ -165292,6 +169533,7 @@ static int rtreeDestroy(sqlite3_vtab *pVtab){
*/
static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
int rc = SQLITE_NOMEM;
+ Rtree *pRtree = (Rtree *)pVTab;
RtreeCursor *pCsr;
pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor));
@@ -165299,6 +169541,7 @@ static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
memset(pCsr, 0, sizeof(RtreeCursor));
pCsr->base.pVtab = pVTab;
rc = SQLITE_OK;
+ pRtree->nCursor++;
}
*ppCursor = (sqlite3_vtab_cursor *)pCsr;
@@ -165331,10 +169574,13 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){
Rtree *pRtree = (Rtree *)(cur->pVtab);
int ii;
RtreeCursor *pCsr = (RtreeCursor *)cur;
+ assert( pRtree->nCursor>0 );
freeCursorConstraints(pCsr);
sqlite3_free(pCsr->aPoint);
for(ii=0; iiaNode[ii]);
sqlite3_free(pCsr);
+ pRtree->nCursor--;
+ nodeBlobReset(pRtree);
return SQLITE_OK;
}
@@ -165357,15 +169603,22 @@ static int rtreeEof(sqlite3_vtab_cursor *cur){
** false. a[] is the four bytes of the on-disk record to be decoded.
** Store the results in "r".
**
-** There are three versions of this macro, one each for little-endian and
-** big-endian processors and a third generic implementation. The endian-
-** specific implementations are much faster and are preferred if the
-** processor endianness is known at compile-time. The SQLITE_BYTEORDER
-** macro is part of sqliteInt.h and hence the endian-specific
-** implementation will only be used if this module is compiled as part
-** of the amalgamation.
+** There are five versions of this macro. The last one is generic. The
+** other four are various architectures-specific optimizations.
*/
-#if defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==1234
+#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
+#define RTREE_DECODE_COORD(eInt, a, r) { \
+ RtreeCoord c; /* Coordinate decoded */ \
+ c.u = _byteswap_ulong(*(u32*)a); \
+ r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
+}
+#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
+#define RTREE_DECODE_COORD(eInt, a, r) { \
+ RtreeCoord c; /* Coordinate decoded */ \
+ c.u = __builtin_bswap32(*(u32*)a); \
+ r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
+}
+#elif SQLITE_BYTEORDER==1234
#define RTREE_DECODE_COORD(eInt, a, r) { \
RtreeCoord c; /* Coordinate decoded */ \
memcpy(&c.u,a,4); \
@@ -165373,7 +169626,7 @@ static int rtreeEof(sqlite3_vtab_cursor *cur){
((c.u&0xff)<<24)|((c.u&0xff00)<<8); \
r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
}
-#elif defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==4321
+#elif SQLITE_BYTEORDER==4321
#define RTREE_DECODE_COORD(eInt, a, r) { \
RtreeCoord c; /* Coordinate decoded */ \
memcpy(&c.u,a,4); \
@@ -165400,10 +169653,10 @@ static int rtreeCallbackConstraint(
sqlite3_rtree_dbl *prScore, /* OUT: score for the cell */
int *peWithin /* OUT: visibility of the cell */
){
- int i; /* Loop counter */
sqlite3_rtree_query_info *pInfo = pConstraint->pInfo; /* Callback info */
int nCoord = pInfo->nCoord; /* No. of coordinates */
int rc; /* Callback return code */
+ RtreeCoord c; /* Translator union */
sqlite3_rtree_dbl aCoord[RTREE_MAX_DIMENSIONS*2]; /* Decoded coordinates */
assert( pConstraint->op==RTREE_MATCH || pConstraint->op==RTREE_QUERY );
@@ -165413,13 +169666,41 @@ static int rtreeCallbackConstraint(
pInfo->iRowid = readInt64(pCellData);
}
pCellData += 8;
- for(i=0; iop==RTREE_MATCH ){
+ int eWithin = 0;
rc = pConstraint->u.xGeom((sqlite3_rtree_geometry*)pInfo,
- nCoord, aCoord, &i);
- if( i==0 ) *peWithin = NOT_WITHIN;
+ nCoord, aCoord, &eWithin);
+ if( eWithin==0 ) *peWithin = NOT_WITHIN;
*prScore = RTREE_ZERO;
}else{
pInfo->aCoord = aCoord;
@@ -165455,6 +169736,7 @@ static void rtreeNonleafConstraint(
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|| p->op==RTREE_GT || p->op==RTREE_EQ );
+ assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */
switch( p->op ){
case RTREE_LE:
case RTREE_LT:
@@ -165495,6 +169777,7 @@ static void rtreeLeafConstraint(
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|| p->op==RTREE_GT || p->op==RTREE_EQ );
pCellData += 8 + p->iCoord*4;
+ assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */
RTREE_DECODE_COORD(eInt, pCellData, xN);
switch( p->op ){
case RTREE_LE: if( xN <= p->u.rValue ) return; break;
@@ -165563,7 +169846,7 @@ static int rtreeSearchPointCompare(
}
/*
-** Interchange to search points in a cursor.
+** Interchange two search points in a cursor.
*/
static void rtreeSearchPointSwap(RtreeCursor *p, int i, int j){
RtreeSearchPoint t = p->aPoint[i];
@@ -165811,7 +170094,7 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){
if( rScoreeWithin = eWithin;
+ p->eWithin = (u8)eWithin;
p->id = x.id;
p->iCell = x.iCell;
RTREE_QUEUE_TRACE(pCur, "PUSH-S:");
@@ -165870,7 +170153,6 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
if( i==0 ){
sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
}else{
- if( rc ) return rc;
nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c);
#ifndef SQLITE_RTREE_INT_ONLY
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
@@ -165919,33 +170201,17 @@ static int findLeafNode(
** operator.
*/
static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
- RtreeMatchArg *pBlob; /* BLOB returned by geometry function */
+ RtreeMatchArg *pBlob, *pSrc; /* BLOB returned by geometry function */
sqlite3_rtree_query_info *pInfo; /* Callback information */
- int nBlob; /* Size of the geometry function blob */
- int nExpected; /* Expected size of the BLOB */
- /* Check that value is actually a blob. */
- if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR;
-
- /* Check that the blob is roughly the right size. */
- nBlob = sqlite3_value_bytes(pValue);
- if( nBlob<(int)sizeof(RtreeMatchArg) ){
- return SQLITE_ERROR;
- }
-
- pInfo = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pInfo)+nBlob );
+ pSrc = sqlite3_value_pointer(pValue, "RtreeMatchArg");
+ if( pSrc==0 ) return SQLITE_ERROR;
+ pInfo = (sqlite3_rtree_query_info*)
+ sqlite3_malloc64( sizeof(*pInfo)+pSrc->iSize );
if( !pInfo ) return SQLITE_NOMEM;
memset(pInfo, 0, sizeof(*pInfo));
pBlob = (RtreeMatchArg*)&pInfo[1];
-
- memcpy(pBlob, sqlite3_value_blob(pValue), nBlob);
- nExpected = (int)(sizeof(RtreeMatchArg) +
- pBlob->nParam*sizeof(sqlite3_value*) +
- (pBlob->nParam-1)*sizeof(RtreeDValue));
- if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){
- sqlite3_free(pInfo);
- return SQLITE_ERROR;
- }
+ memcpy(pBlob, pSrc, pSrc->iSize);
pInfo->pContext = pBlob->cb.pContext;
pInfo->nParam = pBlob->nParam;
pInfo->aParam = pBlob->aParam;
@@ -165999,7 +170265,7 @@ static int rtreeFilter(
p->id = iNode;
p->eWithin = PARTLY_WITHIN;
rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell);
- p->iCell = iCell;
+ p->iCell = (u8)iCell;
RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:");
}else{
pCsr->atEOF = 1;
@@ -166032,7 +170298,7 @@ static int rtreeFilter(
if( rc!=SQLITE_OK ){
break;
}
- p->pInfo->nCoord = pRtree->nDim*2;
+ p->pInfo->nCoord = pRtree->nDim2;
p->pInfo->anQueue = pCsr->anQueue;
p->pInfo->mxLevel = pRtree->iDepth + 1;
}else{
@@ -166047,7 +170313,7 @@ static int rtreeFilter(
}
if( rc==SQLITE_OK ){
RtreeSearchPoint *pNew;
- pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, pRtree->iDepth+1);
+ pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1));
if( pNew==0 ) return SQLITE_NOMEM;
pNew->id = 1;
pNew->iCell = 0;
@@ -166065,19 +170331,6 @@ static int rtreeFilter(
return rc;
}
-/*
-** Set the pIdxInfo->estimatedRows variable to nRow. Unless this
-** extension is currently being used by a version of SQLite too old to
-** support estimatedRows. In that case this function is a no-op.
-*/
-static void setEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){
-#if SQLITE_VERSION_NUMBER>=3008002
- if( sqlite3_libversion_number()>=3008002 ){
- pIdxInfo->estimatedRows = nRow;
- }
-#endif
-}
-
/*
** Rtree virtual table module xBestIndex method. There are three
** table scan strategies to choose from (in order from most to
@@ -166157,7 +170410,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
** a single row.
*/
pIdxInfo->estimatedCost = 30.0;
- setEstimatedRows(pIdxInfo, 1);
+ pIdxInfo->estimatedRows = 1;
return SQLITE_OK;
}
@@ -166175,7 +170428,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
break;
}
zIdxStr[iIdx++] = op;
- zIdxStr[iIdx++] = p->iColumn - 1 + '0';
+ zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0');
pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
pIdxInfo->aConstraintUsage[ii].omit = 1;
}
@@ -166189,7 +170442,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
nRow = pRtree->nRowEst >> (iIdx/2);
pIdxInfo->estimatedCost = (double)6.0 * (double)nRow;
- setEstimatedRows(pIdxInfo, nRow);
+ pIdxInfo->estimatedRows = nRow;
return rc;
}
@@ -166199,9 +170452,26 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
*/
static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
RtreeDValue area = (RtreeDValue)1;
- int ii;
- for(ii=0; ii<(pRtree->nDim*2); ii+=2){
- area = (area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])));
+ assert( pRtree->nDim>=1 && pRtree->nDim<=5 );
+#ifndef SQLITE_RTREE_INT_ONLY
+ if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
+ switch( pRtree->nDim ){
+ case 5: area = p->aCoord[9].f - p->aCoord[8].f;
+ case 4: area *= p->aCoord[7].f - p->aCoord[6].f;
+ case 3: area *= p->aCoord[5].f - p->aCoord[4].f;
+ case 2: area *= p->aCoord[3].f - p->aCoord[2].f;
+ default: area *= p->aCoord[1].f - p->aCoord[0].f;
+ }
+ }else
+#endif
+ {
+ switch( pRtree->nDim ){
+ case 5: area = p->aCoord[9].i - p->aCoord[8].i;
+ case 4: area *= p->aCoord[7].i - p->aCoord[6].i;
+ case 3: area *= p->aCoord[5].i - p->aCoord[4].i;
+ case 2: area *= p->aCoord[3].i - p->aCoord[2].i;
+ default: area *= p->aCoord[1].i - p->aCoord[0].i;
+ }
}
return area;
}
@@ -166211,11 +170481,12 @@ static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
** of the objects size in each dimension.
*/
static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){
- RtreeDValue margin = (RtreeDValue)0;
- int ii;
- for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ RtreeDValue margin = 0;
+ int ii = pRtree->nDim2 - 2;
+ do{
margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
- }
+ ii -= 2;
+ }while( ii>=0 );
return margin;
}
@@ -166223,17 +170494,19 @@ static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){
** Store the union of cells p1 and p2 in p1.
*/
static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
- int ii;
+ int ii = 0;
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
- for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ do{
p1->aCoord[ii].f = MIN(p1->aCoord[ii].f, p2->aCoord[ii].f);
p1->aCoord[ii+1].f = MAX(p1->aCoord[ii+1].f, p2->aCoord[ii+1].f);
- }
+ ii += 2;
+ }while( iinDim2 );
}else{
- for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ do{
p1->aCoord[ii].i = MIN(p1->aCoord[ii].i, p2->aCoord[ii].i);
p1->aCoord[ii+1].i = MAX(p1->aCoord[ii+1].i, p2->aCoord[ii+1].i);
- }
+ ii += 2;
+ }while( iinDim2 );
}
}
@@ -166244,7 +170517,7 @@ static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
int ii;
int isInt = (pRtree->eCoordType==RTREE_COORD_INT32);
- for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ for(ii=0; iinDim2; ii+=2){
RtreeCoord *a1 = &p1->aCoord[ii];
RtreeCoord *a2 = &p2->aCoord[ii];
if( (!isInt && (a2[0].fa1[1].f))
@@ -166279,7 +170552,7 @@ static RtreeDValue cellOverlap(
for(ii=0; iinDim*2); jj+=2){
+ for(jj=0; jjnDim2; jj+=2){
RtreeDValue x1, x2;
x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj]));
x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1]));
@@ -167335,7 +171608,7 @@ static int rtreeUpdate(
** This problem was discovered after years of use, so we silently ignore
** these kinds of misdeclared tables to avoid breaking any legacy.
*/
- assert( nData<=(pRtree->nDim*2 + 3) );
+ assert( nData<=(pRtree->nDim2 + 3) );
#ifndef SQLITE_RTREE_INT_ONLY
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
@@ -167425,6 +171698,27 @@ constraint:
return rc;
}
+/*
+** Called when a transaction starts.
+*/
+static int rtreeBeginTransaction(sqlite3_vtab *pVtab){
+ Rtree *pRtree = (Rtree *)pVtab;
+ assert( pRtree->inWrTrans==0 );
+ pRtree->inWrTrans++;
+ return SQLITE_OK;
+}
+
+/*
+** Called when a transaction completes (either by COMMIT or ROLLBACK).
+** The sqlite3_blob object should be released at this point.
+*/
+static int rtreeEndTransaction(sqlite3_vtab *pVtab){
+ Rtree *pRtree = (Rtree *)pVtab;
+ pRtree->inWrTrans = 0;
+ nodeBlobReset(pRtree);
+ return SQLITE_OK;
+}
+
/*
** The xRename method for rtree module virtual tables.
*/
@@ -167440,12 +171734,37 @@ static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){
, pRtree->zDb, pRtree->zName, zNewName
);
if( zSql ){
+ nodeBlobReset(pRtree);
rc = sqlite3_exec(pRtree->db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
return rc;
}
+/*
+** The xSavepoint method.
+**
+** This module does not need to do anything to support savepoints. However,
+** it uses this hook to close any open blob handle. This is done because a
+** DROP TABLE command - which fortunately always opens a savepoint - cannot
+** succeed if there are any open blob handles. i.e. if the blob handle were
+** not closed here, the following would fail:
+**
+** BEGIN;
+** INSERT INTO rtree...
+** DROP TABLE ; -- Would fail with SQLITE_LOCKED
+** COMMIT;
+*/
+static int rtreeSavepoint(sqlite3_vtab *pVtab, int iSavepoint){
+ Rtree *pRtree = (Rtree *)pVtab;
+ int iwt = pRtree->inWrTrans;
+ UNUSED_PARAMETER(iSavepoint);
+ pRtree->inWrTrans = 0;
+ nodeBlobReset(pRtree);
+ pRtree->inWrTrans = iwt;
+ return SQLITE_OK;
+}
+
/*
** This function populates the pRtree->nRowEst variable with an estimate
** of the number of rows in the virtual table. If possible, this is based
@@ -167491,7 +171810,7 @@ static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
}
static sqlite3_module rtreeModule = {
- 0, /* iVersion */
+ 2, /* iVersion */
rtreeCreate, /* xCreate - create a table */
rtreeConnect, /* xConnect - connect to an existing table */
rtreeBestIndex, /* xBestIndex - Determine search strategy */
@@ -167505,15 +171824,15 @@ static sqlite3_module rtreeModule = {
rtreeColumn, /* xColumn - read data */
rtreeRowid, /* xRowid - read data */
rtreeUpdate, /* xUpdate - write data */
- 0, /* xBegin - begin transaction */
- 0, /* xSync - sync transaction */
- 0, /* xCommit - commit transaction */
- 0, /* xRollback - rollback transaction */
+ rtreeBeginTransaction, /* xBegin - begin transaction */
+ rtreeEndTransaction, /* xSync - sync transaction */
+ rtreeEndTransaction, /* xCommit - commit transaction */
+ rtreeEndTransaction, /* xRollback - rollback transaction */
0, /* xFindFunction - function overloading */
rtreeRename, /* xRename - rename the table */
- 0, /* xSavepoint */
+ rtreeSavepoint, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
};
static int rtreeSqlInit(
@@ -167525,10 +171844,9 @@ static int rtreeSqlInit(
){
int rc = SQLITE_OK;
- #define N_STATEMENT 9
+ #define N_STATEMENT 8
static const char *azSql[N_STATEMENT] = {
- /* Read and write the xxx_node table */
- "SELECT data FROM '%q'.'%q_node' WHERE nodeno = :1",
+ /* Write the xxx_node table */
"INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)",
"DELETE FROM '%q'.'%q_node' WHERE nodeno = :1",
@@ -167566,21 +171884,21 @@ static int rtreeSqlInit(
}
}
- appStmt[0] = &pRtree->pReadNode;
- appStmt[1] = &pRtree->pWriteNode;
- appStmt[2] = &pRtree->pDeleteNode;
- appStmt[3] = &pRtree->pReadRowid;
- appStmt[4] = &pRtree->pWriteRowid;
- appStmt[5] = &pRtree->pDeleteRowid;
- appStmt[6] = &pRtree->pReadParent;
- appStmt[7] = &pRtree->pWriteParent;
- appStmt[8] = &pRtree->pDeleteParent;
+ appStmt[0] = &pRtree->pWriteNode;
+ appStmt[1] = &pRtree->pDeleteNode;
+ appStmt[2] = &pRtree->pReadRowid;
+ appStmt[3] = &pRtree->pWriteRowid;
+ appStmt[4] = &pRtree->pDeleteRowid;
+ appStmt[5] = &pRtree->pReadParent;
+ appStmt[6] = &pRtree->pWriteParent;
+ appStmt[7] = &pRtree->pDeleteParent;
rc = rtreeQueryStat1(db, pRtree);
for(i=0; iiNodeSize);
if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }else if( pRtree->iNodeSize<(512-64) ){
+ rc = SQLITE_CORRUPT;
+ *pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"",
+ pRtree->zName);
}
}
@@ -167712,9 +172034,10 @@ static int rtreeInit(
pRtree->base.pModule = &rtreeModule;
pRtree->zDb = (char *)&pRtree[1];
pRtree->zName = &pRtree->zDb[nDb+1];
- pRtree->nDim = (argc-4)/2;
- pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2;
- pRtree->eCoordType = eCoordType;
+ pRtree->nDim = (u8)((argc-4)/2);
+ pRtree->nDim2 = pRtree->nDim*2;
+ pRtree->nBytesPerCell = 8 + pRtree->nDim2*4;
+ pRtree->eCoordType = (u8)eCoordType;
memcpy(pRtree->zDb, argv[1], nDb);
memcpy(pRtree->zName, argv[2], nName);
@@ -167787,7 +172110,8 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
UNUSED_PARAMETER(nArg);
memset(&node, 0, sizeof(RtreeNode));
memset(&tree, 0, sizeof(Rtree));
- tree.nDim = sqlite3_value_int(apArg[0]);
+ tree.nDim = (u8)sqlite3_value_int(apArg[0]);
+ tree.nDim2 = tree.nDim*2;
tree.nBytesPerCell = 8 + 8 * tree.nDim;
node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
@@ -167800,7 +172124,7 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
nodeGetCell(&tree, &node, ii, &cell);
sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid);
nCell = (int)strlen(zCell);
- for(jj=0; jjmagic = RTREE_GEOMETRY_MAGIC;
+ pBlob->iSize = nBlob;
pBlob->cb = pGeomCtx[0];
pBlob->apSqlParam = (sqlite3_value**)&pBlob->aParam[nArg];
pBlob->nParam = nArg;
@@ -167942,7 +172266,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
sqlite3_result_error_nomem(ctx);
rtreeMatchArgFree(pBlob);
}else{
- sqlite3_result_blob(ctx, pBlob, nBlob, rtreeMatchArgFree);
+ sqlite3_result_pointer(ctx, pBlob, "RtreeMatchArg", rtreeMatchArgFree);
}
}
}
@@ -168508,38 +172832,36 @@ static void icuLoadCollation(
** Register the ICU extension functions with database db.
*/
SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){
- struct IcuScalar {
+ static const struct IcuScalar {
const char *zName; /* Function name */
- int nArg; /* Number of arguments */
- int enc; /* Optimal text encoding */
- void *pContext; /* sqlite3_user_data() context */
+ unsigned char nArg; /* Number of arguments */
+ unsigned short enc; /* Optimal text encoding */
+ unsigned char iContext; /* sqlite3_user_data() context */
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} scalars[] = {
- {"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc},
-
- {"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
- {"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
- {"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
- {"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
-
- {"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
- {"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
- {"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
- {"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
-
- {"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
- {"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
-
- {"icu_load_collation", 2, SQLITE_UTF8, (void*)db, icuLoadCollation},
+ {"icu_load_collation", 2, SQLITE_UTF8, 1, icuLoadCollation},
+ {"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc},
+ {"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
+ {"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
+ {"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
+ {"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
+ {"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
+ {"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
+ {"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
+ {"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
+ {"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
+ {"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
};
-
int rc = SQLITE_OK;
int i;
+
for(i=0; rc==SQLITE_OK && i<(int)(sizeof(scalars)/sizeof(scalars[0])); i++){
- struct IcuScalar *p = &scalars[i];
+ const struct IcuScalar *p = &scalars[i];
rc = sqlite3_create_function(
- db, p->zName, p->nArg, p->enc, p->pContext, p->xFunc, 0, 0
+ db, p->zName, p->nArg, p->enc,
+ p->iContext ? (void*)db : (void*)0,
+ p->xFunc, 0, 0
);
}
@@ -169342,10 +173664,10 @@ SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *pRbu);
**
** If an error has already occurred as part of an sqlite3rbu_step()
** or sqlite3rbu_open() call, or if one occurs within this function, an
-** SQLite error code is returned. Additionally, *pzErrmsg may be set to
-** point to a buffer containing a utf-8 formatted English language error
-** message. It is the responsibility of the caller to eventually free any
-** such buffer using sqlite3_free().
+** SQLite error code is returned. Additionally, if pzErrmsg is not NULL,
+** *pzErrmsg may be set to point to a buffer containing a utf-8 formatted
+** English language error message. It is the responsibility of the caller to
+** eventually free any such buffer using sqlite3_free().
**
** Otherwise, if no error occurs, this function returns SQLITE_OK if the
** update has been partially applied, or SQLITE_DONE if it has been
@@ -169770,6 +174092,7 @@ struct sqlite3rbu {
RbuObjIter objiter; /* Iterator for skipping through tbl/idx */
const char *zVfsName; /* Name of automatically created rbu vfs */
rbu_file *pTargetFd; /* File handle open on target db */
+ int nPagePerSector; /* Pages per sector for pTargetFd */
i64 iOalSz;
i64 nPhaseOneStep;
@@ -171747,7 +176070,7 @@ static RbuState *rbuLoadState(sqlite3rbu *p){
** Open the database handle and attach the RBU database as "rbu". If an
** error occurs, leave an error code and message in the RBU handle.
*/
-static void rbuOpenDatabase(sqlite3rbu *p){
+static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){
assert( p->rc || (p->dbMain==0 && p->dbRbu==0) );
assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 );
@@ -171822,7 +176145,7 @@ static void rbuOpenDatabase(sqlite3rbu *p){
}else{
RbuState *pState = rbuLoadState(p);
if( pState ){
- bOpen = (pState->eStage>RBU_STAGE_MOVE);
+ bOpen = (pState->eStage>=RBU_STAGE_MOVE);
rbuFreeState(pState);
}
}
@@ -171834,6 +176157,15 @@ static void rbuOpenDatabase(sqlite3rbu *p){
if( !rbuIsVacuum(p) ){
p->dbMain = rbuOpenDbhandle(p, p->zTarget, 1);
}else if( p->pRbuFd->pWalFd ){
+ if( pbRetry ){
+ p->pRbuFd->bNolock = 0;
+ sqlite3_close(p->dbRbu);
+ sqlite3_close(p->dbMain);
+ p->dbMain = 0;
+ p->dbRbu = 0;
+ *pbRetry = 1;
+ return;
+ }
p->rc = SQLITE_ERROR;
p->zErrmsg = sqlite3_mprintf("cannot vacuum wal mode database");
}else{
@@ -172014,16 +176346,35 @@ static void rbuSetupCheckpoint(sqlite3rbu *p, RbuState *pState){
if( rc2!=SQLITE_INTERNAL ) p->rc = rc2;
}
- if( p->rc==SQLITE_OK ){
+ if( p->rc==SQLITE_OK && p->nFrame>0 ){
p->eStage = RBU_STAGE_CKPT;
p->nStep = (pState ? pState->nRow : 0);
p->aBuf = rbuMalloc(p, p->pgsz);
p->iWalCksum = rbuShmChecksum(p);
}
- if( p->rc==SQLITE_OK && pState && pState->iWalCksum!=p->iWalCksum ){
- p->rc = SQLITE_DONE;
- p->eStage = RBU_STAGE_DONE;
+ if( p->rc==SQLITE_OK ){
+ if( p->nFrame==0 || (pState && pState->iWalCksum!=p->iWalCksum) ){
+ p->rc = SQLITE_DONE;
+ p->eStage = RBU_STAGE_DONE;
+ }else{
+ int nSectorSize;
+ sqlite3_file *pDb = p->pTargetFd->pReal;
+ sqlite3_file *pWal = p->pTargetFd->pWalFd->pReal;
+ assert( p->nPagePerSector==0 );
+ nSectorSize = pDb->pMethods->xSectorSize(pDb);
+ if( nSectorSize>p->pgsz ){
+ p->nPagePerSector = nSectorSize / p->pgsz;
+ }else{
+ p->nPagePerSector = 1;
+ }
+
+ /* Call xSync() on the wal file. This causes SQLite to sync the
+ ** directory in which the target database and the wal file reside, in
+ ** case it has not been synced since the rename() call in
+ ** rbuMoveOalFile(). */
+ p->rc = pWal->pMethods->xSync(pWal, SQLITE_SYNC_NORMAL);
+ }
}
}
@@ -172196,7 +176547,7 @@ static void rbuMoveOalFile(sqlite3rbu *p){
#endif
if( p->rc==SQLITE_OK ){
- rbuOpenDatabase(p);
+ rbuOpenDatabase(p, 0);
rbuSetupCheckpoint(p, 0);
}
}
@@ -172678,9 +177029,26 @@ SQLITE_API int sqlite3rbu_step(sqlite3rbu *p){
p->rc = SQLITE_DONE;
}
}else{
- RbuFrame *pFrame = &p->aFrame[p->nStep];
- rbuCheckpointFrame(p, pFrame);
- p->nStep++;
+ /* At one point the following block copied a single frame from the
+ ** wal file to the database file. So that one call to sqlite3rbu_step()
+ ** checkpointed a single frame.
+ **
+ ** However, if the sector-size is larger than the page-size, and the
+ ** application calls sqlite3rbu_savestate() or close() immediately
+ ** after this step, then rbu_step() again, then a power failure occurs,
+ ** then the database page written here may be damaged. Work around
+ ** this by checkpointing frames until the next page in the aFrame[]
+ ** lies on a different disk sector to the current one. */
+ u32 iSector;
+ do{
+ RbuFrame *pFrame = &p->aFrame[p->nStep];
+ iSector = (pFrame->iDbPage-1) / p->nPagePerSector;
+ rbuCheckpointFrame(p, pFrame);
+ p->nStep++;
+ }while( p->nStepnFrame
+ && iSector==((p->aFrame[p->nStep].iDbPage-1) / p->nPagePerSector)
+ && p->rc==SQLITE_OK
+ );
}
p->nProgress++;
}
@@ -172907,6 +177275,7 @@ static sqlite3rbu *openRbuHandle(
/* Open the target, RBU and state databases */
if( p->rc==SQLITE_OK ){
char *pCsr = (char*)&p[1];
+ int bRetry = 0;
if( zTarget ){
p->zTarget = pCsr;
memcpy(p->zTarget, zTarget, nTarget+1);
@@ -172918,7 +177287,18 @@ static sqlite3rbu *openRbuHandle(
if( zState ){
p->zState = rbuMPrintf(p, "%s", zState);
}
- rbuOpenDatabase(p);
+
+ /* If the first attempt to open the database file fails and the bRetry
+ ** flag it set, this means that the db was not opened because it seemed
+ ** to be a wal-mode db. But, this may have happened due to an earlier
+ ** RBU vacuum operation leaving an old wal file in the directory.
+ ** If this is the case, it will have been checkpointed and deleted
+ ** when the handle was closed and a second attempt to open the
+ ** database may succeed. */
+ rbuOpenDatabase(p, &bRetry);
+ if( bRetry ){
+ rbuOpenDatabase(p, 0);
+ }
}
if( p->rc==SQLITE_OK ){
@@ -173109,6 +177489,12 @@ SQLITE_API int sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){
p->rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, &p->zErrmsg);
}
+ /* Sync the db file if currently doing an incremental checkpoint */
+ if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_CKPT ){
+ sqlite3_file *pDb = p->pTargetFd->pReal;
+ p->rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL);
+ }
+
rbuSaveState(p, p->eStage);
if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){
@@ -173137,7 +177523,11 @@ SQLITE_API int sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){
rbuEditErrmsg(p);
rc = p->rc;
- *pzErrmsg = p->zErrmsg;
+ if( pzErrmsg ){
+ *pzErrmsg = p->zErrmsg;
+ }else{
+ sqlite3_free(p->zErrmsg);
+ }
sqlite3_free(p->zState);
sqlite3_free(p);
}else{
@@ -173233,6 +177623,12 @@ SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *p){
if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, 0);
}
+ /* Sync the db file */
+ if( rc==SQLITE_OK && p->eStage==RBU_STAGE_CKPT ){
+ sqlite3_file *pDb = p->pTargetFd->pReal;
+ rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL);
+ }
+
p->rc = rc;
rbuSaveState(p, p->eStage);
rc = p->rc;
@@ -174842,6 +179238,9 @@ SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3 *db){
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
+ 0, /* xSavepoint */
+ 0, /* xRelease */
+ 0, /* xRollbackTo */
};
return sqlite3_create_module(db, "dbstat", &dbstat_module, 0);
}
@@ -175227,9 +179626,7 @@ static int sessionSerializeValue(
if( aBuf ){
sessionVarintPut(&aBuf[1], n);
- memcpy(&aBuf[nVarint + 1], eType==SQLITE_TEXT ?
- sqlite3_value_text(pValue) : sqlite3_value_blob(pValue), n
- );
+ if( n ) memcpy(&aBuf[nVarint + 1], z, n);
}
nByte = 1 + nVarint + n;
@@ -176645,7 +181042,7 @@ static void sessionAppendBlob(
int nBlob,
int *pRc
){
- if( 0==sessionBufferGrow(p, nBlob, pRc) ){
+ if( nBlob>0 && 0==sessionBufferGrow(p, nBlob, pRc) ){
memcpy(&p->aBuf[p->nBuf], aBlob, nBlob);
p->nBuf += nBlob;
}
@@ -176831,13 +181228,13 @@ static int sessionAppendUpdate(
}
default: {
- int nByte;
- int nHdr = 1 + sessionVarintGet(&pCsr[1], &nByte);
+ int n;
+ int nHdr = 1 + sessionVarintGet(&pCsr[1], &n);
assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
- nAdvance = nHdr + nByte;
+ nAdvance = nHdr + n;
if( eType==sqlite3_column_type(pStmt, i)
- && nByte==sqlite3_column_bytes(pStmt, i)
- && 0==memcmp(&pCsr[nHdr], sqlite3_column_blob(pStmt, i), nByte)
+ && n==sqlite3_column_bytes(pStmt, i)
+ && (n==0 || 0==memcmp(&pCsr[nHdr], sqlite3_column_blob(pStmt, i), n))
){
break;
}
@@ -177691,11 +182088,12 @@ static int sessionChangesetNext(
p->in.iCurrent = p->in.iNext;
op = p->in.aData[p->in.iNext++];
- if( op=='T' || op=='P' ){
+ while( op=='T' || op=='P' ){
p->bPatchset = (op=='P');
if( sessionChangesetReadTblhdr(p) ) return p->rc;
if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc;
p->in.iCurrent = p->in.iNext;
+ if( p->in.iNext>=p->in.nData ) return SQLITE_DONE;
op = p->in.aData[p->in.iNext++];
}
@@ -177883,7 +182281,7 @@ SQLITE_API int sqlite3changeset_conflict(
if( !pIter->pConflict ){
return SQLITE_MISUSE;
}
- if( iVal<0 || iVal>=sqlite3_column_count(pIter->pConflict) ){
+ if( iVal<0 || iVal>=pIter->nCol ){
return SQLITE_RANGE;
}
*ppValue = sqlite3_column_value(pIter->pConflict, iVal);
@@ -178350,7 +182748,13 @@ static int sessionInsertRow(
sessionAppendStr(&buf, "INSERT INTO main.", &rc);
sessionAppendIdent(&buf, zTab, &rc);
- sessionAppendStr(&buf, " VALUES(?", &rc);
+ sessionAppendStr(&buf, "(", &rc);
+ for(i=0; i