diff --git a/src/Makefile b/src/Makefile index 4b56e393..8bb43ee4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -109,13 +109,13 @@ SERVER_OBJS= \ #geoip ifeq ($(USE_GEOIP),true) -override CXXFLAGS+= -DGEOIP -DGEOIPDATADIR -DPACKAGE_VERSION=\"1.5.1\" +override CXXFLAGS+= -DGEOIP -DGEOIPDATADIR -DPACKAGE_VERSION=\"1.6.9\" override INCLUDES+= -Imod/libGeoIP/ override SERVER_OBJS+= \ mod/geoipmod2-standalone.o \ mod/libGeoIP/GeoIP-standalone.o \ mod/libGeoIP/GeoIPCity-standalone.o \ - mod/libGeoIP/GeoIP_depreciated-standalone.o + mod/libGeoIP/GeoIP_deprecated-standalone.o endif #end of geoip diff --git a/src/Makefile.win32 b/src/Makefile.win32 index 50b32fdf..fba87791 100644 --- a/src/Makefile.win32 +++ b/src/Makefile.win32 @@ -84,13 +84,13 @@ SERVER_OBJS= \ #geoip ifeq ($(USE_GEOIP),true) -override CXXFLAGS+= -DGEOIPDATADIR -DGEOIP -DPACKAGE_VERSION=\"1.5.1\" +override CXXFLAGS+= -DGEOIPDATADIR -DGEOIP -DPACKAGE_VERSION=\"1.6.9\" override INCLUDES+= -Imod/libGeoIP/ override SERVER_OBJS+= \ mod/geoipmod2-standalone.o \ mod/libGeoIP/GeoIP-standalone.o \ mod/libGeoIP/GeoIPCity-standalone.o \ - mod/libGeoIP/GeoIP_depreciated-standalone.o + mod/libGeoIP/GeoIP_deprecated-standalone.o endif #end of geoip diff --git a/src/mod/libGeoIP/GeoIP.c b/src/mod/libGeoIP/GeoIP.c index ccef1785..e5ad49f4 100644 --- a/src/mod/libGeoIP/GeoIP.c +++ b/src/mod/libGeoIP/GeoIP.c @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ /* GeoIP.c * - * Copyright (C) 2006 MaxMind LLC + * Copyright (C) 2016 MaxMind, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,14 +19,28 @@ */ #include "GeoIP.h" +#include "GeoIP_internal.h" static geoipv6_t IPV6_NULL; -#if !defined(_WIN32) +#if defined(_WIN32) +#include + +#ifdef _MSC_VER +# if _MSC_VER < 1900 // VS 2015 supports snprintf +# define snprintf _snprintf +# endif +# if _MSC_VER >= 1400 // VS 2005+ deprecates fileno, lseek and read +# define fileno _fileno +# define read _read +# define lseek _lseek +# endif +#endif +#else #include #include #include -#endif /* !defined(_WIN32) */ +#endif /* defined(_WIN32) */ #include #include @@ -34,7 +48,7 @@ static geoipv6_t IPV6_NULL; #include #include #include /* for fstat */ -#include /* for fstat */ +#include /* for fstat */ #ifdef HAVE_GETTIMEOFDAY #include /* for gettimeofday */ @@ -44,6 +58,10 @@ static geoipv6_t IPV6_NULL; #include /* For uint32_t */ #endif +#if defined(_WIN32) && !defined(__MINGW32__) +#include "pread.h" +#endif + #ifdef _UNUSED #elif defined(__GNUC__) #define _UNUSED __attribute__ ((unused)) @@ -67,1950 +85,2654 @@ static geoipv6_t IPV6_NULL; #define WORLD_OFFSET 1353 #define FIPS_RANGE 360 -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} +#define DEBUG_MSGF(flags, fmt, ...) \ + { \ + if (((flags) & GEOIP_SILENCE) == 0) { \ + fprintf(stderr, fmt, ## __VA_ARGS__); } \ + } #ifndef HAVE_PREAD -#define pread(fd, buf, count, offset) \ - ( \ +#define pread(fd, buf, count, offset) \ + ( \ lseek(fd, offset, SEEK_SET) == offset ? \ - read(fd, buf, count) : \ - -1 \ - ) + read(fd, buf, count) : \ + -1 \ + ) #endif /* HAVE_PREAD */ -const char GeoIP_country_code[255][3] = { "--","AP","EU","AD","AE","AF","AG","AI","AL","AM","CW", - "AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB", - "BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO", - "BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD", - "CF","CG","CH","CI","CK","CL","CM","CN","CO","CR", - "CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO", - "DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ", - "FK","FM","FO","FR","SX","GA","GB","GD","GE","GF", - "GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT", - "GU","GW","GY","HK","HM","HN","HR","HT","HU","ID", - "IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO", - "JP","KE","KG","KH","KI","KM","KN","KP","KR","KW", - "KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT", - "LU","LV","LY","MA","MC","MD","MG","MH","MK","ML", - "MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV", - "MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI", - "NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF", - "PG","PH","PK","PL","PM","PN","PR","PS","PT","PW", - "PY","QA","RE","RO","RU","RW","SA","SB","SC","SD", - "SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO", - "SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH", - "TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW", - "TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE", - "VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA", - "ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE", - "BL","MF", "BQ", "SS" }; - -static const unsigned num_GeoIP_countries = (unsigned)(sizeof(GeoIP_country_code)/sizeof(GeoIP_country_code[0])); - -const char GeoIP_country_code3[255][4] = { "--","AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","CUW", - "AGO","ATA","ARG","ASM","AUT","AUS","ABW","AZE","BIH","BRB", - "BGD","BEL","BFA","BGR","BHR","BDI","BEN","BMU","BRN","BOL", - "BRA","BHS","BTN","BVT","BWA","BLR","BLZ","CAN","CCK","COD", - "CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI", - "CUB","CPV","CXR","CYP","CZE","DEU","DJI","DNK","DMA","DOM", - "DZA","ECU","EST","EGY","ESH","ERI","ESP","ETH","FIN","FJI", - "FLK","FSM","FRO","FRA","SXM","GAB","GBR","GRD","GEO","GUF", - "GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","SGS","GTM", - "GUM","GNB","GUY","HKG","HMD","HND","HRV","HTI","HUN","IDN", - "IRL","ISR","IND","IOT","IRQ","IRN","ISL","ITA","JAM","JOR", - "JPN","KEN","KGZ","KHM","KIR","COM","KNA","PRK","KOR","KWT", - "CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU", - "LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI", - "MMR","MNG","MAC","MNP","MTQ","MRT","MSR","MLT","MUS","MDV", - "MWI","MEX","MYS","MOZ","NAM","NCL","NER","NFK","NGA","NIC", - "NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER","PYF", - "PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW", - "PRY","QAT","REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN", - "SWE","SGP","SHN","SVN","SJM","SVK","SLE","SMR","SEN","SOM", - "SUR","STP","SLV","SYR","SWZ","TCA","TCD","ATF","TGO","THA", - "TJK","TKL","TKM","TUN","TON","TLS","TUR","TTO","TUV","TWN", - "TZA","UKR","UGA","UMI","USA","URY","UZB","VAT","VCT","VEN", - "VGB","VIR","VNM","VUT","WLF","WSM","YEM","MYT","SRB","ZAF", - "ZMB","MNE","ZWE","A1","A2","O1","ALA","GGY","IMN","JEY", - "BLM","MAF", "BES", "SSD" }; - -const char * GeoIP_utf8_country_name[255] = {"N/A","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Cura" "\xc3\xa7" "ao", - "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados", - "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia", - "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the", - "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica", - "Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic", - "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji", - "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","Sint Maarten (Dutch part)","Gabon","United Kingdom","Grenada","Georgia","French Guiana", - "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala", - "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia", - "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan", - "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait", - "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania", - "Luxembourg","Latvia","Libya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali", - "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives", - "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua", - "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia", - "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau", - "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan", - "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname", - "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand", - "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan", - "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela", - "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa", - "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey", - "Saint Barthelemy","Saint Martin", "Bonaire, Saint Eustatius and Saba", "South Sudan"}; - -const char * GeoIP_country_name[255] = {"N/A","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Curacao", - "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados", - "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia", - "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the", - "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica", - "Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic", - "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji", - "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","Sint Maarten (Dutch part)","Gabon","United Kingdom","Grenada","Georgia","French Guiana", - "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala", - "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia", - "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan", - "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait", - "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania", - "Luxembourg","Latvia","Libya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali", - "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives", - "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua", - "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia", - "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau", - "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan", - "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname", - "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand", - "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan", - "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela", - "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa", - "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey", - "Saint Barthelemy","Saint Martin", "Bonaire, Saint Eustatius and Saba", "South Sudan"}; +const char GeoIP_country_code[256][3] = +{ "--", "AP", "EU", "AD", "AE", "AF", + "AG", "AI", "AL", "AM", "CW", + "AO", "AQ", "AR", "AS", "AT", "AU", + "AW", "AZ", "BA", "BB", + "BD", "BE", "BF", "BG", "BH", "BI", + "BJ", "BM", "BN", "BO", + "BR", "BS", "BT", "BV", "BW", "BY", + "BZ", "CA", "CC", "CD", + "CF", "CG", "CH", "CI", "CK", "CL", + "CM", "CN", "CO", "CR", + "CU", "CV", "CX", "CY", "CZ", "DE", + "DJ", "DK", "DM", "DO", + "DZ", "EC", "EE", "EG", "EH", "ER", + "ES", "ET", "FI", "FJ", + "FK", "FM", "FO", "FR", "SX", "GA", + "GB", "GD", "GE", "GF", + "GH", "GI", "GL", "GM", "GN", "GP", + "GQ", "GR", "GS", "GT", + "GU", "GW", "GY", "HK", "HM", "HN", + "HR", "HT", "HU", "ID", + "IE", "IL", "IN", "IO", "IQ", "IR", + "IS", "IT", "JM", "JO", + "JP", "KE", "KG", "KH", "KI", "KM", + "KN", "KP", "KR", "KW", + "KY", "KZ", "LA", "LB", "LC", "LI", + "LK", "LR", "LS", "LT", + "LU", "LV", "LY", "MA", "MC", "MD", + "MG", "MH", "MK", "ML", + "MM", "MN", "MO", "MP", "MQ", "MR", + "MS", "MT", "MU", "MV", + "MW", "MX", "MY", "MZ", "NA", "NC", + "NE", "NF", "NG", "NI", + "NL", "NO", "NP", "NR", "NU", "NZ", + "OM", "PA", "PE", "PF", + "PG", "PH", "PK", "PL", "PM", "PN", + "PR", "PS", "PT", "PW", + "PY", "QA", "RE", "RO", "RU", "RW", + "SA", "SB", "SC", "SD", + "SE", "SG", "SH", "SI", "SJ", "SK", + "SL", "SM", "SN", "SO", + "SR", "ST", "SV", "SY", "SZ", "TC", + "TD", "TF", "TG", "TH", + "TJ", "TK", "TM", "TN", "TO", "TL", + "TR", "TT", "TV", "TW", + "TZ", "UA", "UG", "UM", "US", "UY", + "UZ", "VA", "VC", "VE", + "VG", "VI", "VN", "VU", "WF", "WS", + "YE", "YT", "RS", "ZA", + "ZM", "ME", "ZW", "A1", "A2", "O1", + "AX", "GG", "IM", "JE", + "BL", "MF", "BQ", "SS", "O1" }; + +static const unsigned num_GeoIP_countries = + (unsigned)(sizeof(GeoIP_country_code) / sizeof(GeoIP_country_code[0])); + +const char GeoIP_country_code3[256][4] = +{ "--", "AP", "EU", "AND", + "ARE", + "AFG", "ATG", "AIA", "ALB","ARM", "CUW", + "AGO", "ATA", "ARG", "ASM","AUT", + "AUS", "ABW", "AZE", "BIH","BRB", + "BGD", "BEL", "BFA", "BGR","BHR", + "BDI", "BEN", "BMU", "BRN","BOL", + "BRA", "BHS", "BTN", "BVT","BWA", + "BLR", "BLZ", "CAN", "CCK","COD", + "CAF", "COG", "CHE", "CIV","COK", + "CHL", "CMR", "CHN", "COL","CRI", + "CUB", "CPV", "CXR", "CYP","CZE", + "DEU", "DJI", "DNK", "DMA","DOM", + "DZA", "ECU", "EST", "EGY","ESH", + "ERI", "ESP", "ETH", "FIN","FJI", + "FLK", "FSM", "FRO", "FRA","SXM", + "GAB", "GBR", "GRD", "GEO","GUF", + "GHA", "GIB", "GRL", "GMB","GIN", + "GLP", "GNQ", "GRC", "SGS","GTM", + "GUM", "GNB", "GUY", "HKG","HMD", + "HND", "HRV", "HTI", "HUN","IDN", + "IRL", "ISR", "IND", "IOT","IRQ", + "IRN", "ISL", "ITA", "JAM","JOR", + "JPN", "KEN", "KGZ", "KHM","KIR", + "COM", "KNA", "PRK", "KOR","KWT", + "CYM", "KAZ", "LAO", "LBN","LCA", + "LIE", "LKA", "LBR", "LSO","LTU", + "LUX", "LVA", "LBY", "MAR","MCO", + "MDA", "MDG", "MHL", "MKD","MLI", + "MMR", "MNG", "MAC", "MNP","MTQ", + "MRT", "MSR", "MLT", "MUS","MDV", + "MWI", "MEX", "MYS", "MOZ","NAM", + "NCL", "NER", "NFK", "NGA","NIC", + "NLD", "NOR", "NPL", "NRU","NIU", + "NZL", "OMN", "PAN", "PER","PYF", + "PNG", "PHL", "PAK", "POL","SPM", + "PCN", "PRI", "PSE", "PRT","PLW", + "PRY", "QAT", "REU", "ROU","RUS", + "RWA", "SAU", "SLB", "SYC","SDN", + "SWE", "SGP", "SHN", "SVN","SJM", + "SVK", "SLE", "SMR", "SEN","SOM", + "SUR", "STP", "SLV", "SYR","SWZ", + "TCA", "TCD", "ATF", "TGO","THA", + "TJK", "TKL", "TKM", "TUN","TON", + "TLS", "TUR", "TTO", "TUV","TWN", + "TZA", "UKR", "UGA", "UMI","USA", + "URY", "UZB", "VAT", "VCT","VEN", + "VGB", "VIR", "VNM", "VUT","WLF", + "WSM", "YEM", "MYT", "SRB","ZAF", + "ZMB", "MNE", "ZWE", "A1", "A2", + "O1", "ALA", "GGY", "IMN","JEY", + "BLM", "MAF", "BES", "SSD","O1" }; + +const char * GeoIP_utf8_country_name[256] = +{ "N/A", + "Asia/Pacific Region", "Europe", + "Andorra", "United Arab Emirates", + "Afghanistan", "Antigua and Barbuda", + "Anguilla", + "Albania", "Armenia", + "Cura" "\xc3\xa7" "ao", + "Angola", + "Antarctica", "Argentina", + "American Samoa", "Austria", + "Australia", "Aruba", + "Azerbaijan", + "Bosnia and Herzegovina", "Barbados", + "Bangladesh", + "Belgium", "Burkina Faso", + "Bulgaria", "Bahrain", + "Burundi", "Benin", + "Bermuda", + "Brunei Darussalam", "Bolivia", + "Brazil", + "Bahamas", "Bhutan", + "Bouvet Island", "Botswana", + "Belarus", "Belize", + "Canada", + "Cocos (Keeling) Islands", + "Congo, The Democratic Republic of the", + "Central African Republic", + "Congo", "Switzerland", + "Cote D'Ivoire", "Cook Islands", + "Chile", "Cameroon", + "China", + "Colombia", "Costa Rica", + "Cuba", + "Cape Verde", "Christmas Island", + "Cyprus", "Czech Republic", + "Germany", "Djibouti", + "Denmark", + "Dominica", "Dominican Republic", + "Algeria", + "Ecuador", "Estonia", + "Egypt", "Western Sahara", + "Eritrea", "Spain", + "Ethiopia", + "Finland", "Fiji", + "Falkland Islands (Malvinas)", + "Micronesia, Federated States of", "Faroe Islands", + "France", "Sint Maarten (Dutch part)", + "Gabon", "United Kingdom", + "Grenada", + "Georgia", "French Guiana", + "Ghana", + "Gibraltar", "Greenland", + "Gambia", "Guinea", + "Guadeloupe", "Equatorial Guinea", + "Greece", + "South Georgia and the South Sandwich Islands","Guatemala", + "Guam", + "Guinea-Bissau", "Guyana", + "Hong Kong", + "Heard Island and McDonald Islands", + "Honduras", "Croatia", + "Haiti", + "Hungary", "Indonesia", + "Ireland", + "Israel", "India", + "British Indian Ocean Territory", "Iraq", + "Iran, Islamic Republic of", "Iceland", + "Italy", + "Jamaica", "Jordan", + "Japan", + "Kenya", "Kyrgyzstan", + "Cambodia", "Kiribati", + "Comoros", "Saint Kitts and Nevis", + "Korea, Democratic People's Republic of", "Korea, Republic of", + "Kuwait", + "Cayman Islands", + "Kazakhstan", + "Lao People's Democratic Republic", + "Lebanon", "Saint Lucia", + "Liechtenstein", "Sri Lanka", + "Liberia", + "Lesotho", "Lithuania", + "Luxembourg", + "Latvia", "Libya", + "Morocco", "Monaco", + "Moldova, Republic of", "Madagascar", + "Marshall Islands", "Macedonia", + "Mali", + "Myanmar", + "Mongolia", "Macau", + "Northern Mariana Islands", "Martinique", + "Mauritania", "Montserrat", + "Malta", + "Mauritius", "Maldives", + "Malawi", + "Mexico", "Malaysia", + "Mozambique", "Namibia", + "New Caledonia", "Niger", + "Norfolk Island", + "Nigeria", "Nicaragua", + "Netherlands", + "Norway", "Nepal", + "Nauru", "Niue", + "New Zealand", "Oman", + "Panama", + "Peru", "French Polynesia", + "Papua New Guinea", + "Philippines", "Pakistan", + "Poland", "Saint Pierre and Miquelon", + "Pitcairn Islands", "Puerto Rico", + "Palestinian Territory", "Portugal", + "Palau", + "Paraguay", + "Qatar", "Reunion", + "Romania", "Russian Federation", + "Rwanda", "Saudi Arabia", + "Solomon Islands", "Seychelles", + "Sudan", + "Sweden", + "Singapore", "Saint Helena", + "Slovenia", "Svalbard and Jan Mayen", + "Slovakia", "Sierra Leone", + "San Marino", + "Senegal", "Somalia", + "Suriname", + "Sao Tome and Principe", + "El Salvador", "Syrian Arab Republic", + "Swaziland", "Turks and Caicos Islands", + "Chad", "French Southern Territories", + "Togo", + "Thailand", + "Tajikistan", + "Tokelau", "Turkmenistan", + "Tunisia", "Tonga", + "Timor-Leste", "Turkey", + "Trinidad and Tobago", "Tuvalu", + "Taiwan", + "Tanzania, United Republic of", + "Ukraine", "Uganda", + "United States Minor Outlying Islands", "United States", + "Uruguay", "Uzbekistan", + "Holy See (Vatican City State)", + "Saint Vincent and the Grenadines", + "Venezuela", + "Virgin Islands, British", + "Virgin Islands, U.S.", "Vietnam", + "Vanuatu", "Wallis and Futuna", + "Samoa", "Yemen", + "Mayotte", + "Serbia", "South Africa", + "Zambia", + "Montenegro", "Zimbabwe", + "Anonymous Proxy", "Satellite Provider", + "Other", "Aland Islands", + "Guernsey", + "Isle of Man", "Jersey", + "Saint Barthelemy", + "Saint Martin", + "Bonaire, Saint Eustatius and Saba", + "South Sudan", "Other" }; + +const char * GeoIP_country_name[256] = +{ "N/A", + "Asia/Pacific Region", "Europe", + "Andorra", "United Arab Emirates", + "Afghanistan", "Antigua and Barbuda", + "Anguilla", + "Albania", "Armenia", + "Curacao", + "Angola", + "Antarctica", "Argentina", + "American Samoa", "Austria", + "Australia", "Aruba", + "Azerbaijan", + "Bosnia and Herzegovina", "Barbados", + "Bangladesh", + "Belgium", "Burkina Faso", + "Bulgaria", "Bahrain", + "Burundi", "Benin", + "Bermuda", + "Brunei Darussalam", "Bolivia", + "Brazil", + "Bahamas", "Bhutan", + "Bouvet Island", "Botswana", + "Belarus", "Belize", + "Canada", + "Cocos (Keeling) Islands", + "Congo, The Democratic Republic of the", + "Central African Republic", + "Congo", "Switzerland", + "Cote D'Ivoire", "Cook Islands", + "Chile", "Cameroon", + "China", + "Colombia", "Costa Rica", + "Cuba", + "Cape Verde", "Christmas Island", + "Cyprus", "Czech Republic", + "Germany", "Djibouti", + "Denmark", + "Dominica", "Dominican Republic", + "Algeria", + "Ecuador", "Estonia", + "Egypt", "Western Sahara", + "Eritrea", "Spain", + "Ethiopia", + "Finland", "Fiji", + "Falkland Islands (Malvinas)", + "Micronesia, Federated States of", "Faroe Islands", + "France", "Sint Maarten (Dutch part)", + "Gabon", "United Kingdom", + "Grenada", + "Georgia", "French Guiana", + "Ghana", + "Gibraltar", "Greenland", + "Gambia", "Guinea", + "Guadeloupe", "Equatorial Guinea", + "Greece", + "South Georgia and the South Sandwich Islands","Guatemala", + "Guam", + "Guinea-Bissau", "Guyana", + "Hong Kong", + "Heard Island and McDonald Islands", + "Honduras", "Croatia", + "Haiti", + "Hungary", "Indonesia", + "Ireland", + "Israel", "India", + "British Indian Ocean Territory", "Iraq", + "Iran, Islamic Republic of", "Iceland", + "Italy", + "Jamaica", "Jordan", + "Japan", + "Kenya", "Kyrgyzstan", + "Cambodia", "Kiribati", + "Comoros", "Saint Kitts and Nevis", + "Korea, Democratic People's Republic of", "Korea, Republic of", + "Kuwait", + "Cayman Islands", + "Kazakhstan", + "Lao People's Democratic Republic", + "Lebanon", "Saint Lucia", + "Liechtenstein", "Sri Lanka", + "Liberia", + "Lesotho", "Lithuania", + "Luxembourg", + "Latvia", "Libya", + "Morocco", "Monaco", + "Moldova, Republic of", "Madagascar", + "Marshall Islands", "Macedonia", + "Mali", + "Myanmar", + "Mongolia", "Macau", + "Northern Mariana Islands", "Martinique", + "Mauritania", "Montserrat", + "Malta", + "Mauritius", "Maldives", + "Malawi", + "Mexico", "Malaysia", + "Mozambique", "Namibia", + "New Caledonia", "Niger", + "Norfolk Island", + "Nigeria", "Nicaragua", + "Netherlands", + "Norway", "Nepal", + "Nauru", "Niue", + "New Zealand", "Oman", + "Panama", + "Peru", "French Polynesia", + "Papua New Guinea", + "Philippines", "Pakistan", + "Poland", "Saint Pierre and Miquelon", + "Pitcairn Islands", "Puerto Rico", + "Palestinian Territory", "Portugal", + "Palau", + "Paraguay", + "Qatar", "Reunion", + "Romania", "Russian Federation", + "Rwanda", "Saudi Arabia", + "Solomon Islands", "Seychelles", + "Sudan", + "Sweden", + "Singapore", "Saint Helena", + "Slovenia", "Svalbard and Jan Mayen", + "Slovakia", "Sierra Leone", + "San Marino", + "Senegal", "Somalia", + "Suriname", + "Sao Tome and Principe", + "El Salvador", "Syrian Arab Republic", + "Swaziland", "Turks and Caicos Islands", + "Chad", "French Southern Territories", + "Togo", + "Thailand", + "Tajikistan", + "Tokelau", "Turkmenistan", + "Tunisia", "Tonga", + "Timor-Leste", "Turkey", + "Trinidad and Tobago", "Tuvalu", + "Taiwan", + "Tanzania, United Republic of", + "Ukraine", "Uganda", + "United States Minor Outlying Islands", "United States", + "Uruguay", "Uzbekistan", + "Holy See (Vatican City State)", + "Saint Vincent and the Grenadines", + "Venezuela", + "Virgin Islands, British", + "Virgin Islands, U.S.", "Vietnam", + "Vanuatu", "Wallis and Futuna", + "Samoa", "Yemen", + "Mayotte", + "Serbia", "South Africa", + "Zambia", + "Montenegro", "Zimbabwe", + "Anonymous Proxy", "Satellite Provider", + "Other", "Aland Islands", + "Guernsey", + "Isle of Man", "Jersey", + "Saint Barthelemy", + "Saint Martin", + "Bonaire, Saint Eustatius and Saba", + "South Sudan", "Other" }; /* Possible continent codes are AF, AS, EU, NA, OC, SA for Africa, Asia, Europe, North America, Oceania -and South America. */ - -const char GeoIP_country_continent[255][3] = { - "--", "AS","EU","EU","AS","AS","NA","NA","EU","AS","NA", - "AF","AN","SA","OC","EU","OC","NA","AS","EU","NA", - "AS","EU","AF","EU","AS","AF","AF","NA","AS","SA", - "SA","NA","AS","AN","AF","EU","NA","NA","AS","AF", - "AF","AF","EU","AF","OC","SA","AF","AS","SA","NA", - "NA","AF","AS","AS","EU","EU","AF","EU","NA","NA", - "AF","SA","EU","AF","AF","AF","EU","AF","EU","OC", - "SA","OC","EU","EU","NA","AF","EU","NA","AS","SA", - "AF","EU","NA","AF","AF","NA","AF","EU","AN","NA", - "OC","AF","SA","AS","AN","NA","EU","NA","EU","AS", - "EU","AS","AS","AS","AS","AS","EU","EU","NA","AS", - "AS","AF","AS","AS","OC","AF","NA","AS","AS","AS", - "NA","AS","AS","AS","NA","EU","AS","AF","AF","EU", - "EU","EU","AF","AF","EU","EU","AF","OC","EU","AF", - "AS","AS","AS","OC","NA","AF","NA","EU","AF","AS", - "AF","NA","AS","AF","AF","OC","AF","OC","AF","NA", - "EU","EU","AS","OC","OC","OC","AS","NA","SA","OC", - "OC","AS","AS","EU","NA","OC","NA","AS","EU","OC", - "SA","AS","AF","EU","EU","AF","AS","OC","AF","AF", - "EU","AS","AF","EU","EU","EU","AF","EU","AF","AF", - "SA","AF","NA","AS","AF","NA","AF","AN","AF","AS", - "AS","OC","AS","AF","OC","AS","EU","NA","OC","AS", - "AF","EU","AF","OC","NA","SA","AS","EU","NA","SA", - "NA","NA","AS","OC","OC","OC","AS","AF","EU","AF", - "AF","EU","AF","--","--","--","EU","EU","EU","EU", - "NA","NA","NA", "AF" + and South America. */ + +const char GeoIP_country_continent[256][3] = { + "--", "AS", "EU", "EU", "AS", "AS", "NA", "NA", "EU", "AS", "NA", + "AF", "AN", "SA", "OC", "EU", "OC", "NA", "AS", "EU", "NA", + "AS", "EU", "AF", "EU", "AS", "AF", "AF", "NA", "AS", "SA", + "SA", "NA", "AS", "AN", "AF", "EU", "NA", "NA", "AS", "AF", + "AF", "AF", "EU", "AF", "OC", "SA", "AF", "AS", "SA", "NA", + "NA", "AF", "AS", "AS", "EU", "EU", "AF", "EU", "NA", "NA", + "AF", "SA", "EU", "AF", "AF", "AF", "EU", "AF", "EU", "OC", + "SA", "OC", "EU", "EU", "NA", "AF", "EU", "NA", "AS", "SA", + "AF", "EU", "NA", "AF", "AF", "NA", "AF", "EU", "AN", "NA", + "OC", "AF", "SA", "AS", "AN", "NA", "EU", "NA", "EU", "AS", + "EU", "AS", "AS", "AS", "AS", "AS", "EU", "EU", "NA", "AS", + "AS", "AF", "AS", "AS", "OC", "AF", "NA", "AS", "AS", "AS", + "NA", "AS", "AS", "AS", "NA", "EU", "AS", "AF", "AF", "EU", + "EU", "EU", "AF", "AF", "EU", "EU", "AF", "OC", "EU", "AF", + "AS", "AS", "AS", "OC", "NA", "AF", "NA", "EU", "AF", "AS", + "AF", "NA", "AS", "AF", "AF", "OC", "AF", "OC", "AF", "NA", + "EU", "EU", "AS", "OC", "OC", "OC", "AS", "NA", "SA", "OC", + "OC", "AS", "AS", "EU", "NA", "OC", "NA", "AS", "EU", "OC", + "SA", "AS", "AF", "EU", "EU", "AF", "AS", "OC", "AF", "AF", + "EU", "AS", "AF", "EU", "EU", "EU", "AF", "EU", "AF", "AF", + "SA", "AF", "NA", "AS", "AF", "NA", "AF", "AN", "AF", "AS", + "AS", "OC", "AS", "AF", "OC", "AS", "EU", "NA", "OC", "AS", + "AF", "EU", "AF", "OC", "NA", "SA", "AS", "EU", "NA", "SA", + "NA", "NA", "AS", "OC", "OC", "OC", "AS", "AF", "EU", "AF", + "AF", "EU", "AF", "--", "--", "--", "EU", "EU", "EU", "EU", + "NA", "NA", "NA", "AF", "--" }; -static const char * get_db_description(int dbtype){ +static const char * get_db_description(int dbtype) +{ const char * ptr; - if ( dbtype >= NUM_DB_TYPES || dbtype < 0 ) + if (dbtype >= NUM_DB_TYPES || dbtype < 0) { return "Unknown"; + } ptr = GeoIPDBDescription[dbtype]; return ptr == NULL ? "Unknown" : ptr; } -geoipv6_t _GeoIP_lookupaddress_v6 (const char *host); - +geoipv6_t _GeoIP_lookupaddress_v6(const char *host); + #if defined(_WIN32) -/* http://www.mail-archive.com/users@ipv6.org/msg02107.html */ -static const char * _GeoIP_inet_ntop(int af, const void *src, char *dst, socklen_t cnt) -{ - if (af == AF_INET) - { - struct sockaddr_in in; - memset(&in, 0, sizeof(in)); - in.sin_family = AF_INET; - memcpy(&in.sin_addr, src, sizeof(struct in_addr)); - getnameinfo((struct sockaddr *)&in, sizeof(struct -sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST); - return dst; - } - else if (af == AF_INET6) - { - struct sockaddr_in6 in; - memset(&in, 0, sizeof(in)); - in.sin6_family = AF_INET6; - memcpy(&in.sin6_addr, src, sizeof(struct in_addr6)); - getnameinfo((struct sockaddr *)&in, sizeof(struct -sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST); - return dst; - } - return NULL; -} - -static int _GeoIP_inet_pton(int af, const char *src, void *dst) -{ - struct addrinfo hints, *res, *ressave; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = af; - - if (getaddrinfo(src, NULL, &hints, &res) != 0) - { - fprintf(stderr, "Couldn't resolve host %s\n", src); - return -1; - } - - ressave = res; - - while (res) - { - memcpy(dst, res->ai_addr, res->ai_addrlen); - res = res->ai_next; - } - - freeaddrinfo(ressave); - return 0; +/* http://www.mail-archive.com/users@ipv6.org/msg02107.html */ +static const char * _GeoIP_inet_ntop(int af, const void *src, char *dst, + socklen_t cnt) +{ + if (af == AF_INET) { + struct sockaddr_in in; + memset(&in, 0, sizeof(in)); + in.sin_family = AF_INET; + memcpy(&in.sin_addr, src, sizeof(struct in_addr)); + getnameinfo((struct sockaddr *)&in, sizeof(struct + sockaddr_in), dst, cnt, NULL, + 0, + NI_NUMERICHOST); + return dst; + }else if (af == AF_INET6) { + struct sockaddr_in6 in; + memset(&in, 0, sizeof(in)); + in.sin6_family = AF_INET6; + memcpy(&in.sin6_addr, src, sizeof(struct in_addr6)); + getnameinfo((struct sockaddr *)&in, sizeof(struct + sockaddr_in6), dst, cnt, + NULL, 0, + NI_NUMERICHOST); + return dst; + } + return NULL; +} + +static int _GeoIP_inet_pton(int af, const char *src, void *dst) +{ + struct addrinfo hints, *res, *ressave; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = af; + + if (getaddrinfo(src, NULL, &hints, &res) != 0) { + return -1; + } + + ressave = res; + + while (res) { + memcpy(dst, res->ai_addr, res->ai_addrlen); + res = res->ai_next; + } + + freeaddrinfo(ressave); + return 0; } #else -static int _GeoIP_inet_pton(int af, const char *src, void *dst) { - return inet_pton(af, src, dst); +static int _GeoIP_inet_pton(int af, const char *src, void *dst) +{ + return inet_pton(af, src, dst); } -static const char * _GeoIP_inet_ntop(int af, const void *src, char *dst, socklen_t cnt) { - return inet_ntop(af, src, dst, cnt); +static const char * _GeoIP_inet_ntop(int af, const void *src, char *dst, + socklen_t cnt) +{ + return inet_ntop(af, src, dst, cnt); } +#endif /* defined(_WIN32) */ -#endif /* defined(_WIN32) */ - - -int __GEOIP_V6_IS_NULL(geoipv6_t v6) { - int i; - for (i=0;i<16;i++) { - if (v6.s6_addr[i]) - return 0; +int __GEOIP_V6_IS_NULL(geoipv6_t v6) +{ + int i; + for (i = 0; i < 16; i++) { + if (v6.s6_addr[i]) { + return 0; } - return 1; + } + return 1; } -void __GEOIP_PREPARE_TEREDO(geoipv6_t* v6){ - int i; - if ((v6->s6_addr[0]) != 0x20) return; - if ((v6->s6_addr[1]) != 0x01) return; - if ((v6->s6_addr[2]) != 0x00) return; - if ((v6->s6_addr[3]) != 0x00) return; +void __GEOIP_PREPARE_TEREDO(geoipv6_t * v6) +{ + int i; + if ((v6->s6_addr[0]) != 0x20) { + return; + } + if ((v6->s6_addr[1]) != 0x01) { + return; + } + if ((v6->s6_addr[2]) != 0x00) { + return; + } + if ((v6->s6_addr[3]) != 0x00) { + return; + } - for ( i = 0; i< 12; i++) - v6->s6_addr[i] = 0; - for ( ; i < 16; i++) - v6->s6_addr[i]^=0xff; + for (i = 0; i < 12; i++) { + v6->s6_addr[i] = 0; + } + for (; i < 16; i++) { + v6->s6_addr[i] ^= 0xff; + } } const char * GeoIPDBDescription[NUM_DB_TYPES] = { - NULL, - "GeoIP Country Edition", - "GeoIP City Edition, Rev 1", - "GeoIP Region Edition, Rev 1", - "GeoIP ISP Edition", - "GeoIP Organization Edition", - "GeoIP City Edition, Rev 0", - "GeoIP Region Edition, Rev 0", - "GeoIP Proxy Edition", - "GeoIP ASNum Edition", - "GeoIP Netspeed Edition", - "GeoIP Domain Name Edition", - "GeoIP Country V6 Edition", - "GeoIP LocationID ASCII Edition", - "GeoIP Accuracy Radius Edition", - NULL, - NULL, - "GeoIP Large Country Edition", - "GeoIP Large Country V6 Edition", - NULL, - "GeoIP CCM Edition", - "GeoIP ASNum V6 Edition", - "GeoIP ISP V6 Edition", - "GeoIP Organization V6 Edition", - "GeoIP Domain Name V6 Edition", - "GeoIP LocationID ASCII V6 Edition", - "GeoIP Registrar Edition", - "GeoIP Registrar V6 Edition", - "GeoIP UserType Edition", - "GeoIP UserType V6 Edition", - "GeoIP City Edition V6, Rev 1", - "GeoIP City Edition V6, Rev 0", - "GeoIP Netspeed Edition, Rev 1", - "GeoIP Netspeed Edition V6, Rev1", - "GeoIP Country Confidence Edition", - "GeoIP City Confidence Edition", - "GeoIP Region Confidence Edition", - "GeoIP Postal Confidence Edition", - "GeoIP Accuracy Radius Edition V6" + NULL, + "GeoIP Country Edition", + "GeoIP City Edition, Rev 1", + "GeoIP Region Edition, Rev 1", + "GeoIP ISP Edition", + "GeoIP Organization Edition", + "GeoIP City Edition, Rev 0", + "GeoIP Region Edition, Rev 0", + "GeoIP Proxy Edition", + "GeoIP ASNum Edition", + "GeoIP Netspeed Edition", + "GeoIP Domain Name Edition", + "GeoIP Country V6 Edition", + "GeoIP LocationID ASCII Edition", + "GeoIP Accuracy Radius Edition", + NULL, + NULL, + "GeoIP Large Country Edition", + "GeoIP Large Country V6 Edition", + NULL, + "GeoIP CCM Edition", + "GeoIP ASNum V6 Edition", + "GeoIP ISP V6 Edition", + "GeoIP Organization V6 Edition", + "GeoIP Domain Name V6 Edition", + "GeoIP LocationID ASCII V6 Edition", + "GeoIP Registrar Edition", + "GeoIP Registrar V6 Edition", + "GeoIP UserType Edition", + "GeoIP UserType V6 Edition", + "GeoIP City Edition V6, Rev 1", + "GeoIP City Edition V6, Rev 0", + "GeoIP Netspeed Edition, Rev 1", + "GeoIP Netspeed Edition V6, Rev1", + "GeoIP Country Confidence Edition", + "GeoIP City Confidence Edition", + "GeoIP Region Confidence Edition", + "GeoIP Postal Confidence Edition", + "GeoIP Accuracy Radius Edition V6" }; char * GeoIP_custom_directory = NULL; -void GeoIP_setup_custom_directory (char * dir) { - GeoIP_custom_directory = dir; +void GeoIP_setup_custom_directory(char * dir) +{ + GeoIP_custom_directory = dir; } -char *_GeoIP_full_path_to(const char *file_name) { - int len; - char *path = malloc(sizeof(char) * 1024); +char *_GeoIP_full_path_to(const char *file_name) +{ + int len; + char *path = malloc(sizeof(char) * 1024); - if (GeoIP_custom_directory == NULL){ + if (GeoIP_custom_directory == NULL) { #if !defined(_WIN32) - memset(path, 0, sizeof(char) * 1024); - snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", GEOIPDATADIR, file_name); + memset(path, 0, sizeof(char) * 1024); + snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", GEOIPDATADIR, + file_name); #else - char buf[MAX_PATH], *p, *q = NULL; - memset(buf, 0, sizeof(buf)); - len = GetModuleFileNameA(GetModuleHandle(NULL), buf, sizeof(buf) - 1); - for (p = buf + len; p > buf; p--) - if (*p == '\\') - { - if (!q) - q = p; - else - *p = '/'; - } - *q = 0; - memset(path, 0, sizeof(char) * 1024); - snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", buf, file_name); + char buf[MAX_PATH], *p, *q = NULL; + memset(buf, 0, sizeof(buf)); + len = GetModuleFileNameA(GetModuleHandle(NULL), buf, sizeof(buf) - 1); + for (p = buf + len; p > buf; p--) { + if (*p == '\\') { + if (!q) { + q = p; + } else{ + *p = '/'; + } + } + } + *q = 0; + memset(path, 0, sizeof(char) * 1024); + snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", buf, file_name); #endif - } else { - len = strlen(GeoIP_custom_directory); - if (GeoIP_custom_directory[len-1] != '/') { - snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", GeoIP_custom_directory, file_name); - } else { - snprintf(path, sizeof(char) * 1024 - 1, "%s%s", GeoIP_custom_directory, file_name); - } - } - return path; + } else { + len = strlen(GeoIP_custom_directory); + if (GeoIP_custom_directory[len - 1] != '/') { + snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", + GeoIP_custom_directory, + file_name); + } else { + snprintf(path, sizeof(char) * 1024 - 1, "%s%s", + GeoIP_custom_directory, + file_name); + } + } + return path; } char ** GeoIPDBFileName = NULL; -void _GeoIP_setup_dbfilename() { - if (NULL == GeoIPDBFileName) { - GeoIPDBFileName = malloc(sizeof(char *) * NUM_DB_TYPES); - memset(GeoIPDBFileName, 0, sizeof(char *) * NUM_DB_TYPES); - - GeoIPDBFileName[GEOIP_COUNTRY_EDITION] = _GeoIP_full_path_to("GeoIP.dat"); - GeoIPDBFileName[GEOIP_REGION_EDITION_REV0] = _GeoIP_full_path_to("GeoIPRegion.dat"); - GeoIPDBFileName[GEOIP_REGION_EDITION_REV1] = _GeoIP_full_path_to("GeoIPRegion.dat"); - GeoIPDBFileName[GEOIP_CITY_EDITION_REV0] = _GeoIP_full_path_to("GeoIPCity.dat"); - GeoIPDBFileName[GEOIP_CITY_EDITION_REV1] = _GeoIP_full_path_to("GeoIPCity.dat"); - GeoIPDBFileName[GEOIP_ISP_EDITION] = _GeoIP_full_path_to("GeoIPISP.dat"); - GeoIPDBFileName[GEOIP_ORG_EDITION] = _GeoIP_full_path_to("GeoIPOrg.dat"); - GeoIPDBFileName[GEOIP_PROXY_EDITION] = _GeoIP_full_path_to("GeoIPProxy.dat"); - GeoIPDBFileName[GEOIP_ASNUM_EDITION] = _GeoIP_full_path_to("GeoIPASNum.dat"); - GeoIPDBFileName[GEOIP_NETSPEED_EDITION] = _GeoIP_full_path_to("GeoIPNetSpeed.dat"); - GeoIPDBFileName[GEOIP_DOMAIN_EDITION] = _GeoIP_full_path_to("GeoIPDomain.dat"); - GeoIPDBFileName[GEOIP_COUNTRY_EDITION_V6] = _GeoIP_full_path_to("GeoIPv6.dat"); - GeoIPDBFileName[GEOIP_LOCATIONA_EDITION] = _GeoIP_full_path_to("GeoIPLocA.dat"); - GeoIPDBFileName[GEOIP_ACCURACYRADIUS_EDITION] = _GeoIP_full_path_to("GeoIPDistance.dat"); - GeoIPDBFileName[GEOIP_LARGE_COUNTRY_EDITION] = _GeoIP_full_path_to("GeoIP.dat"); - GeoIPDBFileName[GEOIP_LARGE_COUNTRY_EDITION_V6] = _GeoIP_full_path_to("GeoIPv6.dat"); - GeoIPDBFileName[GEOIP_ASNUM_EDITION_V6] = _GeoIP_full_path_to("GeoIPASNumv6.dat"); - GeoIPDBFileName[GEOIP_ISP_EDITION_V6] = _GeoIP_full_path_to("GeoIPISPv6.dat"); - GeoIPDBFileName[GEOIP_ORG_EDITION_V6] = _GeoIP_full_path_to("GeoIPOrgv6.dat"); - GeoIPDBFileName[GEOIP_DOMAIN_EDITION_V6] = _GeoIP_full_path_to("GeoIPDomainv6.dat"); - GeoIPDBFileName[GEOIP_LOCATIONA_EDITION_V6] = _GeoIP_full_path_to("GeoIPLocAv6.dat"); - GeoIPDBFileName[GEOIP_REGISTRAR_EDITION] = _GeoIP_full_path_to("GeoIPRegistrar.dat"); - GeoIPDBFileName[GEOIP_REGISTRAR_EDITION_V6] = _GeoIP_full_path_to("GeoIPRegistrarv6.dat"); - GeoIPDBFileName[GEOIP_USERTYPE_EDITION] = _GeoIP_full_path_to("GeoIPUserType.dat"); - GeoIPDBFileName[GEOIP_USERTYPE_EDITION_V6] = _GeoIP_full_path_to("GeoIPUserTypev6.dat"); - GeoIPDBFileName[GEOIP_CITY_EDITION_REV0_V6] = _GeoIP_full_path_to("GeoIPCityv6.dat"); - GeoIPDBFileName[GEOIP_CITY_EDITION_REV1_V6] = _GeoIP_full_path_to("GeoIPCityv6.dat"); - GeoIPDBFileName[GEOIP_NETSPEED_EDITION_REV1] = _GeoIP_full_path_to("GeoIPNetSpeedCell.dat"); - GeoIPDBFileName[GEOIP_NETSPEED_EDITION_REV1_V6] = _GeoIP_full_path_to("GeoIPNetSpeedCellv6.dat"); - GeoIPDBFileName[GEOIP_COUNTRYCONF_EDITION] = _GeoIP_full_path_to("GeoIPCountryConf.dat"); - GeoIPDBFileName[GEOIP_CITYCONF_EDITION] = _GeoIP_full_path_to("GeoIPCityConf.dat"); - GeoIPDBFileName[GEOIP_REGIONCONF_EDITION] = _GeoIP_full_path_to("GeoIPRegionConf.dat"); - GeoIPDBFileName[GEOIP_POSTALCONF_EDITION] = _GeoIP_full_path_to("GeoIPPostalConf.dat"); - GeoIPDBFileName[GEOIP_ACCURACYRADIUS_EDITION_V6] = _GeoIP_full_path_to("GeoIPDistancev6.dat"); - } +void _GeoIP_setup_dbfilename() +{ + if (NULL == GeoIPDBFileName) { + GeoIPDBFileName = malloc(sizeof(char *) * NUM_DB_TYPES); + memset(GeoIPDBFileName, 0, sizeof(char *) * NUM_DB_TYPES); + + GeoIPDBFileName[GEOIP_COUNTRY_EDITION] = _GeoIP_full_path_to( + "GeoIP.dat"); + GeoIPDBFileName[GEOIP_REGION_EDITION_REV0] = _GeoIP_full_path_to( + "GeoIPRegion.dat"); + GeoIPDBFileName[GEOIP_REGION_EDITION_REV1] = _GeoIP_full_path_to( + "GeoIPRegion.dat"); + GeoIPDBFileName[GEOIP_CITY_EDITION_REV0] = _GeoIP_full_path_to( + "GeoIPCity.dat"); + GeoIPDBFileName[GEOIP_CITY_EDITION_REV1] = _GeoIP_full_path_to( + "GeoIPCity.dat"); + GeoIPDBFileName[GEOIP_ISP_EDITION] = + _GeoIP_full_path_to("GeoIPISP.dat"); + GeoIPDBFileName[GEOIP_ORG_EDITION] = + _GeoIP_full_path_to("GeoIPOrg.dat"); + GeoIPDBFileName[GEOIP_PROXY_EDITION] = _GeoIP_full_path_to( + "GeoIPProxy.dat"); + GeoIPDBFileName[GEOIP_ASNUM_EDITION] = _GeoIP_full_path_to( + "GeoIPASNum.dat"); + GeoIPDBFileName[GEOIP_NETSPEED_EDITION] = _GeoIP_full_path_to( + "GeoIPNetSpeed.dat"); + GeoIPDBFileName[GEOIP_DOMAIN_EDITION] = _GeoIP_full_path_to( + "GeoIPDomain.dat"); + GeoIPDBFileName[GEOIP_COUNTRY_EDITION_V6] = _GeoIP_full_path_to( + "GeoIPv6.dat"); + GeoIPDBFileName[GEOIP_LOCATIONA_EDITION] = _GeoIP_full_path_to( + "GeoIPLocA.dat"); + GeoIPDBFileName[GEOIP_ACCURACYRADIUS_EDITION] = _GeoIP_full_path_to( + "GeoIPDistance.dat"); + GeoIPDBFileName[GEOIP_LARGE_COUNTRY_EDITION] = _GeoIP_full_path_to( + "GeoIP.dat"); + GeoIPDBFileName[GEOIP_LARGE_COUNTRY_EDITION_V6] = _GeoIP_full_path_to( + "GeoIPv6.dat"); + GeoIPDBFileName[GEOIP_ASNUM_EDITION_V6] = _GeoIP_full_path_to( + "GeoIPASNumv6.dat"); + GeoIPDBFileName[GEOIP_ISP_EDITION_V6] = _GeoIP_full_path_to( + "GeoIPISPv6.dat"); + GeoIPDBFileName[GEOIP_ORG_EDITION_V6] = _GeoIP_full_path_to( + "GeoIPOrgv6.dat"); + GeoIPDBFileName[GEOIP_DOMAIN_EDITION_V6] = _GeoIP_full_path_to( + "GeoIPDomainv6.dat"); + GeoIPDBFileName[GEOIP_LOCATIONA_EDITION_V6] = _GeoIP_full_path_to( + "GeoIPLocAv6.dat"); + GeoIPDBFileName[GEOIP_REGISTRAR_EDITION] = _GeoIP_full_path_to( + "GeoIPRegistrar.dat"); + GeoIPDBFileName[GEOIP_REGISTRAR_EDITION_V6] = _GeoIP_full_path_to( + "GeoIPRegistrarv6.dat"); + GeoIPDBFileName[GEOIP_USERTYPE_EDITION] = _GeoIP_full_path_to( + "GeoIPUserType.dat"); + GeoIPDBFileName[GEOIP_USERTYPE_EDITION_V6] = _GeoIP_full_path_to( + "GeoIPUserTypev6.dat"); + GeoIPDBFileName[GEOIP_CITY_EDITION_REV0_V6] = _GeoIP_full_path_to( + "GeoIPCityv6.dat"); + GeoIPDBFileName[GEOIP_CITY_EDITION_REV1_V6] = _GeoIP_full_path_to( + "GeoIPCityv6.dat"); + GeoIPDBFileName[GEOIP_NETSPEED_EDITION_REV1] = _GeoIP_full_path_to( + "GeoIPNetSpeedCell.dat"); + GeoIPDBFileName[GEOIP_NETSPEED_EDITION_REV1_V6] = _GeoIP_full_path_to( + "GeoIPNetSpeedCellv6.dat"); + GeoIPDBFileName[GEOIP_COUNTRYCONF_EDITION] = _GeoIP_full_path_to( + "GeoIPCountryConf.dat"); + GeoIPDBFileName[GEOIP_CITYCONF_EDITION] = _GeoIP_full_path_to( + "GeoIPCityConf.dat"); + GeoIPDBFileName[GEOIP_REGIONCONF_EDITION] = _GeoIP_full_path_to( + "GeoIPRegionConf.dat"); + GeoIPDBFileName[GEOIP_POSTALCONF_EDITION] = _GeoIP_full_path_to( + "GeoIPPostalConf.dat"); + GeoIPDBFileName[GEOIP_ACCURACYRADIUS_EDITION_V6] = _GeoIP_full_path_to( + "GeoIPDistancev6.dat"); + } } static -int _file_exists(const char *file_name) { - struct stat file_stat; - return( (stat(file_name, &file_stat) == 0) ? 1:0); -} - -char * _GeoIP_iso_8859_1__utf8(const char * iso) { - signed char c; - char k; - char * p; - char * t = (char *)iso; - int len = 0; - while ( ( c = *t++) ){ - if ( c < 0 ) - len++; - } - len += t - iso; - t = p = malloc( len ); - - if ( p ){ - while ( ( c = *iso++ ) ) { - if (c < 0 ) { - k = 0xc2; - if (c >= -64 ) - k++; - *t++ = k; - c &= ~0x40; - } - *t++ = c; - } - *t++ = 0x00; - } - return p; -} - -int GeoIP_is_private_ipnum_v4( unsigned long ipnum ){ -return ((ipnum >= 167772160U && ipnum <= 184549375U) - || (ipnum >= 2851995648U && ipnum <= 2852061183U) - || (ipnum >= 2886729728U && ipnum <= 2887778303U) - || (ipnum >= 3232235520U && ipnum <= 3232301055U) - || (ipnum >= 2130706432U && ipnum <= 2147483647U))? 1 : 0; -} - -int GeoIP_is_private_v4( const char * addr ){ - unsigned long ipnum = GeoIP_addr_to_num(addr); - return GeoIP_is_private_ipnum_v4(ipnum); -} - -int GeoIP_db_avail(int type) { - const char * filePath; - if (type < 0 || type >= NUM_DB_TYPES) { - return 0; - } - _GeoIP_setup_dbfilename(); - filePath = GeoIPDBFileName[type]; - if (NULL == filePath) { - return 0; - } - return _file_exists(filePath); -} - -static int _database_has_content( int database_type ){ - return ((database_type != GEOIP_COUNTRY_EDITION - && database_type != GEOIP_PROXY_EDITION - && database_type != GEOIP_NETSPEED_EDITION - && database_type != GEOIP_COUNTRY_EDITION_V6 - && database_type != GEOIP_LARGE_COUNTRY_EDITION - && database_type != GEOIP_LARGE_COUNTRY_EDITION_V6 - && database_type != GEOIP_REGION_EDITION_REV0 - && database_type != GEOIP_REGION_EDITION_REV1) ? 1 : 0 ); +int _file_exists(const char *file_name) +{ + struct stat file_stat; + return (stat(file_name, &file_stat) == 0) ? 1 : 0; } -static -void _setup_segments(GeoIP * gi) { - int i, j, segment_record_length; - unsigned char delim[3]; - unsigned char buf[LARGE_SEGMENT_RECORD_LENGTH]; - ssize_t silence _UNUSED; - int fno = fileno(gi->GeoIPDatabase); - - gi->databaseSegments = NULL; - - /* default to GeoIP Country Edition */ - gi->databaseType = GEOIP_COUNTRY_EDITION; - gi->record_length = STANDARD_RECORD_LENGTH; - lseek(fno, -3l, SEEK_END); - for (i = 0; i < STRUCTURE_INFO_MAX_SIZE; i++) { - silence = read(fno, delim, 3); - if (delim[0] == 255 && delim[1] == 255 && delim[2] == 255) { - silence = read(fno, &gi->databaseType, 1 ); - if (gi->databaseType >= 106) { - /* backwards compatibility with databases from April 2003 and earlier */ - gi->databaseType -= 105; - } - - if (gi->databaseType == GEOIP_REGION_EDITION_REV0) { - /* Region Edition, pre June 2003 */ - gi->databaseSegments = malloc(sizeof(int)); - gi->databaseSegments[0] = STATE_BEGIN_REV0; - } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) { - /* Region Edition, post June 2003 */ - gi->databaseSegments = malloc(sizeof(int)); - gi->databaseSegments[0] = STATE_BEGIN_REV1; - } else if (gi->databaseType == GEOIP_CITY_EDITION_REV0 || - gi->databaseType == GEOIP_CITY_EDITION_REV1 || - gi->databaseType == GEOIP_ORG_EDITION || - gi->databaseType == GEOIP_ORG_EDITION_V6 || - gi->databaseType == GEOIP_DOMAIN_EDITION || - gi->databaseType == GEOIP_DOMAIN_EDITION_V6 || - gi->databaseType == GEOIP_ISP_EDITION || - gi->databaseType == GEOIP_ISP_EDITION_V6 || - gi->databaseType == GEOIP_REGISTRAR_EDITION || - gi->databaseType == GEOIP_REGISTRAR_EDITION_V6 || - gi->databaseType == GEOIP_USERTYPE_EDITION || - gi->databaseType == GEOIP_USERTYPE_EDITION_V6 || - gi->databaseType == GEOIP_ASNUM_EDITION || - gi->databaseType == GEOIP_ASNUM_EDITION_V6 || - gi->databaseType == GEOIP_NETSPEED_EDITION_REV1 || - gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6 || - gi->databaseType == GEOIP_LOCATIONA_EDITION || - gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION || - gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION_V6 || - gi->databaseType == GEOIP_CITY_EDITION_REV0_V6 || - gi->databaseType == GEOIP_CITY_EDITION_REV1_V6 || - gi->databaseType == GEOIP_CITYCONF_EDITION || - gi->databaseType == GEOIP_COUNTRYCONF_EDITION || - gi->databaseType == GEOIP_REGIONCONF_EDITION || - gi->databaseType == GEOIP_POSTALCONF_EDITION - ) { - /* City/Org Editions have two segments, read offset of second segment */ - gi->databaseSegments = malloc(sizeof(int)); - gi->databaseSegments[0] = 0; - - segment_record_length = SEGMENT_RECORD_LENGTH; - - silence = read(fno, buf, segment_record_length ); - for (j = 0; j < segment_record_length; j++) { - gi->databaseSegments[0] += (buf[j] << (j * 8)); - } - - /* the record_length must be correct from here on */ - if (gi->databaseType == GEOIP_ORG_EDITION || - gi->databaseType == GEOIP_ORG_EDITION_V6 || - gi->databaseType == GEOIP_DOMAIN_EDITION || - gi->databaseType == GEOIP_DOMAIN_EDITION_V6 || - gi->databaseType == GEOIP_ISP_EDITION || - gi->databaseType == GEOIP_ISP_EDITION_V6 ) - gi->record_length = ORG_RECORD_LENGTH; - } - break; - } else { - lseek(fno, -4l, SEEK_CUR); - } - } - if (gi->databaseType == GEOIP_COUNTRY_EDITION || - gi->databaseType == GEOIP_PROXY_EDITION || - gi->databaseType == GEOIP_NETSPEED_EDITION || - gi->databaseType == GEOIP_COUNTRY_EDITION_V6 ) { - gi->databaseSegments = malloc(sizeof(int)); - gi->databaseSegments[0] = COUNTRY_BEGIN; - } - else if ( gi->databaseType == GEOIP_LARGE_COUNTRY_EDITION || - gi->databaseType == GEOIP_LARGE_COUNTRY_EDITION_V6 ) { - gi->databaseSegments = malloc(sizeof(int)); - gi->databaseSegments[0] = LARGE_COUNTRY_BEGIN; - } - +char * _GeoIP_iso_8859_1__utf8(const char * iso) +{ + signed char c; + char k; + char * p; + char * t = (char *)iso; + int len = 0; + while ( ( c = *t++) ) { + if (c < 0) { + len++; + } + } + len += t - iso; + t = p = malloc( len ); + + if (p) { + while ( ( c = *iso++ ) ) { + if (c < 0) { + k = (char)0xc2; + if (c >= -64) { + k++; + } + *t++ = k; + c &= ~0x40; + } + *t++ = c; + } + *t++ = 0x00; + } + return p; +} + +int GeoIP_is_private_ipnum_v4( unsigned long ipnum ) +{ + return ((ipnum >= 167772160U && ipnum <= 184549375U) + || (ipnum >= 2851995648U && ipnum <= 2852061183U) + || (ipnum >= 2886729728U && ipnum <= 2887778303U) + || (ipnum >= 3232235520U && ipnum <= 3232301055U) + || (ipnum >= 2130706432U && ipnum <= 2147483647U)) ? 1 : 0; +} + +int GeoIP_is_private_v4( const char * addr ) +{ + unsigned long ipnum = GeoIP_addr_to_num(addr); + return GeoIP_is_private_ipnum_v4(ipnum); +} + +int GeoIP_db_avail(int type) +{ + const char * filePath; + if (type < 0 || type >= NUM_DB_TYPES) { + return 0; + } + _GeoIP_setup_dbfilename(); + filePath = GeoIPDBFileName[type]; + if (NULL == filePath) { + return 0; + } + return _file_exists(filePath); +} + +static int _database_has_content( int database_type ) +{ + return (database_type != GEOIP_COUNTRY_EDITION + && database_type != GEOIP_PROXY_EDITION + && database_type != GEOIP_NETSPEED_EDITION + && database_type != GEOIP_COUNTRY_EDITION_V6 + && database_type != GEOIP_LARGE_COUNTRY_EDITION + && database_type != GEOIP_LARGE_COUNTRY_EDITION_V6 + && database_type != GEOIP_REGION_EDITION_REV0 + && database_type != GEOIP_REGION_EDITION_REV1) ? 1 : 0; +} + + +static ssize_t get_index_size(GeoIP * gi, struct stat *buf) +{ + ssize_t index_size; + unsigned int segment; + + if (!_database_has_content(gi->databaseType)) { + return buf->st_size; + } + + segment = gi->databaseSegments[0]; + index_size = segment * (ssize_t)gi->record_length * 2; + + /* check for overflow in multiplication */ + if (segment != 0 + && index_size / segment != (ssize_t)gi->record_length * 2) { + return -1; + } + + /* Index size should never exceed the size of the file */ + if (index_size > buf->st_size) { + return -1; + } + + return index_size; +} + +static void _setup_segments(GeoIP * gi) +{ + int i, j, segment_record_length; + unsigned char delim[3]; + unsigned char buf[LARGE_SEGMENT_RECORD_LENGTH]; + off_t offset = gi->size - 3; + int fno = fileno(gi->GeoIPDatabase); + + gi->databaseSegments = NULL; + + /* default to GeoIP Country Edition */ + gi->databaseType = GEOIP_COUNTRY_EDITION; + gi->record_length = STANDARD_RECORD_LENGTH; + + for (i = 0; i < STRUCTURE_INFO_MAX_SIZE; i++) { + if (pread(fno, delim, 3, offset) != 3) { + return; + } + offset += 3; + if (delim[0] == 255 && delim[1] == 255 && delim[2] == 255) { + if (pread(fno, &gi->databaseType, 1, offset) != 1) { + return; + } + offset++; + if (gi->databaseType >= 106) { + /* backwards compatibility with databases from April 2003 and earlier */ + gi->databaseType -= 105; + } + + if (gi->databaseType == GEOIP_REGION_EDITION_REV0) { + /* Region Edition, pre June 2003 */ + gi->databaseSegments = malloc(sizeof(unsigned int)); + if (gi->databaseSegments == NULL) { + return; + } + gi->databaseSegments[0] = STATE_BEGIN_REV0; + } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) { + /* Region Edition, post June 2003 */ + gi->databaseSegments = malloc(sizeof(unsigned int)); + if (gi->databaseSegments == NULL) { + return; + } + gi->databaseSegments[0] = STATE_BEGIN_REV1; + } else if (gi->databaseType == GEOIP_CITY_EDITION_REV0 || + gi->databaseType == GEOIP_CITY_EDITION_REV1 || + gi->databaseType == GEOIP_ORG_EDITION || + gi->databaseType == GEOIP_ORG_EDITION_V6 || + gi->databaseType == GEOIP_DOMAIN_EDITION || + gi->databaseType == GEOIP_DOMAIN_EDITION_V6 || + gi->databaseType == GEOIP_ISP_EDITION || + gi->databaseType == GEOIP_ISP_EDITION_V6 || + gi->databaseType == GEOIP_REGISTRAR_EDITION || + gi->databaseType == GEOIP_REGISTRAR_EDITION_V6 || + gi->databaseType == GEOIP_USERTYPE_EDITION || + gi->databaseType == GEOIP_USERTYPE_EDITION_V6 || + gi->databaseType == GEOIP_ASNUM_EDITION || + gi->databaseType == GEOIP_ASNUM_EDITION_V6 || + gi->databaseType == GEOIP_NETSPEED_EDITION_REV1 || + gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6 || + gi->databaseType == GEOIP_LOCATIONA_EDITION || + gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION || + gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION_V6 || + gi->databaseType == GEOIP_CITY_EDITION_REV0_V6 || + gi->databaseType == GEOIP_CITY_EDITION_REV1_V6 || + gi->databaseType == GEOIP_CITYCONF_EDITION || + gi->databaseType == GEOIP_COUNTRYCONF_EDITION || + gi->databaseType == GEOIP_REGIONCONF_EDITION || + gi->databaseType == GEOIP_POSTALCONF_EDITION + ) { + /* City/Org Editions have two segments, read offset of second segment */ + gi->databaseSegments = malloc(sizeof(unsigned int)); + if (gi->databaseSegments == NULL) { + return; + } + gi->databaseSegments[0] = 0; + segment_record_length = SEGMENT_RECORD_LENGTH; + + if (pread(fno, buf, segment_record_length, offset) + != segment_record_length) { + free(gi->databaseSegments); + gi->databaseSegments = NULL; + return; + } + + for (j = 0; j < segment_record_length; j++) { + gi->databaseSegments[0] += (buf[j] << (j * 8)); + } + + /* the record_length must be correct from here on */ + if (gi->databaseType == GEOIP_ORG_EDITION || + gi->databaseType == GEOIP_ORG_EDITION_V6 || + gi->databaseType == GEOIP_DOMAIN_EDITION || + gi->databaseType == GEOIP_DOMAIN_EDITION_V6 || + gi->databaseType == GEOIP_ISP_EDITION || + gi->databaseType == GEOIP_ISP_EDITION_V6) { + gi->record_length = ORG_RECORD_LENGTH; + } + } + break; + } else { + offset -= 4; + if (offset < 0) { + gi->databaseSegments = NULL; + return; + } + } + } + if (gi->databaseType == GEOIP_COUNTRY_EDITION || + gi->databaseType == GEOIP_PROXY_EDITION || + gi->databaseType == GEOIP_NETSPEED_EDITION || + gi->databaseType == GEOIP_COUNTRY_EDITION_V6) { + gi->databaseSegments = malloc(sizeof(unsigned int)); + if (gi->databaseSegments == NULL) { + return; + } + gi->databaseSegments[0] = COUNTRY_BEGIN; + }else if (gi->databaseType == GEOIP_LARGE_COUNTRY_EDITION || + gi->databaseType == GEOIP_LARGE_COUNTRY_EDITION_V6) { + gi->databaseSegments = malloc(sizeof(unsigned int)); + if (gi->databaseSegments == NULL) { + return; + } + gi->databaseSegments[0] = LARGE_COUNTRY_BEGIN; + } } static -int _check_mtime(GeoIP *gi) { - struct stat buf; - unsigned int idx_size; - -#if !defined(_WIN32) - struct timeval t; -#else /* !defined(_WIN32) */ - FILETIME ft; - ULONGLONG t; +void _check_mtime(GeoIP *gi) +{ + struct stat buf; + ssize_t idx_size; + +#if !defined(_WIN32) + struct timeval t; +#else /* !defined(_WIN32) */ + FILETIME ft; + ULONGLONG t; #endif /* !defined(_WIN32) */ - if (gi->flags & GEOIP_CHECK_CACHE) { - -#if !defined(_WIN32) - /* stat only has second granularity, so don't - * call it more than once a second */ - gettimeofday(&t, NULL); - if (t.tv_sec == gi->last_mtime_check){ - return 0; - } - gi->last_mtime_check = t.tv_sec; - -#else /* !defined(_WIN32) */ - - /* stat only has second granularity, so don't - call it more than once a second */ - GetSystemTimeAsFileTime(&ft); - t = FILETIME_TO_USEC(ft) / 1000 / 1000; - if (t == gi->last_mtime_check){ - return 0; - } - gi->last_mtime_check = t; - -#endif /* !defined(_WIN32) */ - - if (stat(gi->file_path, &buf) != -1) { - /* make sure that the database file is at least 60 - * seconds untouched. Otherwise we might load the - * database only partly and crash - */ - if (buf.st_mtime != gi->mtime && ( buf.st_mtime + 60 < gi->last_mtime_check ) ) { - /* GeoIP Database file updated */ - if (gi->flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE)) { - if ( gi->flags & GEOIP_MMAP_CACHE) { + if (gi->flags & GEOIP_CHECK_CACHE) { + #if !defined(_WIN32) - /* MMAP is only avail on UNIX */ - munmap(gi->cache, gi->size); - gi->cache = NULL; + /* stat only has second granularity, so don't + * call it more than once a second */ + if (0 != gettimeofday(&t, NULL)) { + DEBUG_MSGF(gi->flags, + "Error calling gettimeofday: %s\n", + strerror(errno)); + return; + } + + if (t.tv_sec == gi->last_mtime_check) { + return; + } + gi->last_mtime_check = t.tv_sec; + +#else /* !defined(_WIN32) */ + + /* stat only has second granularity, so don't + call it more than once a second */ + GetSystemTimeAsFileTime(&ft); + t = FILETIME_TO_USEC(ft) / 1000 / 1000; + if (t == gi->last_mtime_check) { + return; + } + gi->last_mtime_check = t; + +#endif /* !defined(_WIN32) */ + + if (stat(gi->file_path, &buf) != -1) { + /* make sure that the database file is at least 60 + * seconds untouched. Otherwise we might load the + * database only partly and crash + */ + if (buf.st_mtime != gi->mtime && + ( buf.st_mtime + 60 < gi->last_mtime_check ) ) { + /* GeoIP Database file updated */ + if (gi->flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE)) { + if (gi->cache && (gi->flags & GEOIP_MMAP_CACHE)) { +#if !defined(_WIN32) + /* MMAP is only avail on UNIX */ + munmap(gi->cache, gi->size); + gi->cache = NULL; #endif - } else { - /* reload database into memory cache */ - if ((gi->cache = (unsigned char*) realloc(gi->cache, buf.st_size)) == NULL) { - fprintf(stderr,"Out of memory when reloading %s\n",gi->file_path); - return -1; - } - } - } - /* refresh filehandle */ - fclose(gi->GeoIPDatabase); - gi->GeoIPDatabase = fopen(gi->file_path,"rb"); - if (gi->GeoIPDatabase == NULL) { - fprintf(stderr,"Error Opening file %s when reloading\n",gi->file_path); - return -1; - } - gi->mtime = buf.st_mtime; - gi->size = buf.st_size; - - if ( gi->flags & GEOIP_MMAP_CACHE) { + } else { + /* reload database into memory cache */ + if ((gi->cache = + (unsigned char *)realloc(gi->cache, + buf.st_size)) == + NULL) { + DEBUG_MSGF(gi->flags, + "Out of memory when reloading %s\n", + gi->file_path); + return; + } + } + } + /* refresh filehandle */ + fclose(gi->GeoIPDatabase); + gi->GeoIPDatabase = fopen(gi->file_path, "rb"); + if (gi->GeoIPDatabase == NULL) { + DEBUG_MSGF(gi->flags, + "Error Opening file %s when reloading\n", + gi->file_path); + return; + } + gi->mtime = buf.st_mtime; + gi->size = buf.st_size; + + if (gi->flags & GEOIP_MMAP_CACHE) { #if defined(_WIN32) - fprintf(stderr, "GEOIP_MMAP_CACHE is not supported on WIN32\n"); - gi->cache = 0; - return -1; + DEBUG_MSGF(gi->flags, + "GEOIP_MMAP_CACHE is not supported on WIN32\n"); + gi->cache = 0; + return; #else - gi->cache = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fileno(gi->GeoIPDatabase), 0); - if ( gi->cache == MAP_FAILED ) { + gi->cache = + mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fileno( + gi->GeoIPDatabase), 0); + if (gi->cache == MAP_FAILED) { + + DEBUG_MSGF(gi->flags, + "Error remapping file %s when reloading\n", + gi->file_path); + + gi->cache = NULL; + return; + } +#endif + } else if (gi->flags & GEOIP_MEMORY_CACHE) { + if (pread(fileno(gi->GeoIPDatabase), gi->cache, buf.st_size, + 0) != (ssize_t)buf.st_size) { + DEBUG_MSGF(gi->flags, + "Error reading file %s when reloading\n", + gi->file_path); + return; + } + } - fprintf(stderr,"Error remapping file %s when reloading\n",gi->file_path); + if (gi->databaseSegments != NULL) { + free(gi->databaseSegments); + gi->databaseSegments = NULL; + } + _setup_segments(gi); + if (gi->databaseSegments == NULL) { + DEBUG_MSGF(gi->flags, "Error reading file %s -- corrupt\n", + gi->file_path); + return; + } - gi->cache = NULL; - return -1; - } -#endif - } else if ( gi->flags & GEOIP_MEMORY_CACHE ) { - if (pread(fileno(gi->GeoIPDatabase), gi->cache, buf.st_size, 0) != (ssize_t) buf.st_size) { - fprintf(stderr,"Error reading file %s when reloading\n",gi->file_path); - return -1; - } - } - - if (gi->databaseSegments != NULL) { - free(gi->databaseSegments); - gi->databaseSegments = NULL; - } - _setup_segments(gi); - if (gi->databaseSegments == NULL) { - fprintf(stderr, "Error reading file %s -- corrupt\n", gi->file_path); - return -1; - } - - /* make sure the index is <= file size - * This test makes sense for all modes - not - * only index - */ - idx_size = _database_has_content(gi->databaseType) ? gi->databaseSegments[0] * (long)gi->record_length * 2 : buf.st_size; - if ( idx_size > buf.st_size ){ - fprintf(stderr, "Error file %s -- corrupt\n", gi->file_path); - return -1; - } - - if (gi->flags & GEOIP_INDEX_CACHE) { - gi->index_cache = (unsigned char *) realloc(gi->index_cache, sizeof(unsigned char) * idx_size ); - if (gi->index_cache != NULL) { - if (pread(fileno(gi->GeoIPDatabase), gi->index_cache, - idx_size, 0 ) != (ssize_t) idx_size) { - fprintf(stderr,"Error reading file %s where reloading\n",gi->file_path); - return -1; - } - } - } - } - } - } - return 0; -} - -#define ADDR_STR_LEN (8 * 4 + 7 + 1) -unsigned int _GeoIP_seek_record_v6_gl (GeoIP *gi, geoipv6_t ipnum, GeoIPLookup * gl) { - int depth; - char paddr[ADDR_STR_LEN]; - unsigned int x; - unsigned char stack_buffer[2 * MAX_RECORD_LENGTH]; - const unsigned char *buf = (gi->cache == NULL) ? stack_buffer : NULL; - unsigned int offset = 0; - - const unsigned char * p; - int j; - ssize_t silence _UNUSED; - int fno = fileno(gi->GeoIPDatabase); - _check_mtime(gi); - if ( GeoIP_teredo(gi) ) - __GEOIP_PREPARE_TEREDO(&ipnum); - for (depth = 127; depth >= 0; depth--) { - if (gi->cache == NULL && gi->index_cache == NULL) { - /* read from disk */ - silence = pread(fno, stack_buffer,gi->record_length * 2, (long)gi->record_length * 2 * offset ); - } else if (gi->index_cache == NULL) { - /* simply point to record in memory */ - buf = gi->cache + (long)gi->record_length * 2 *offset; - } else { - buf = gi->index_cache + (long)gi->record_length * 2 * offset; - } - - if (GEOIP_CHKBIT_V6(depth, ipnum.s6_addr )) { - /* Take the right-hand branch */ - if ( gi->record_length == 3 ) { - /* Most common case is completely unrolled and uses constants. */ - x = (buf[3*1 + 0] << (0*8)) - + (buf[3*1 + 1] << (1*8)) - + (buf[3*1 + 2] << (2*8)); - - } else { - /* General case */ - j = gi->record_length; - p = &buf[2*j]; - x = 0; - do { - x <<= 8; - x += *(--p); - } while ( --j ); - } - - } else { - /* Take the left-hand branch */ - if ( gi->record_length == 3 ) { - /* Most common case is completely unrolled and uses constants. */ - x = (buf[3*0 + 0] << (0*8)) - + (buf[3*0 + 1] << (1*8)) - + (buf[3*0 + 2] << (2*8)); - } else { - /* General case */ - j = gi->record_length; - p = &buf[1*j]; - x = 0; - do { - x <<= 8; - x += *(--p); - } while ( --j ); - } - } - - if (x >= gi->databaseSegments[0]) { - gi->netmask = gl->netmask = 128 - depth; - return x; - } - offset = x; - } - - /* shouldn't reach here */ - _GeoIP_inet_ntop(AF_INET6, &ipnum.s6_addr[0], paddr, ADDR_STR_LEN); - fprintf(stderr,"Error Traversing Database for ipnum = %s - Perhaps database is corrupt?\n", paddr); - return 0; + idx_size = get_index_size(gi, &buf); + if (idx_size < 0) { + DEBUG_MSGF(gi->flags, "Error file %s -- corrupt\n", + gi->file_path); + return; + } + + if (gi->flags & GEOIP_INDEX_CACHE) { + gi->index_cache = (unsigned char *)realloc( + gi->index_cache, sizeof(unsigned char) * idx_size ); + if (gi->index_cache != NULL) { + if (pread(fileno(gi->GeoIPDatabase), gi->index_cache, + idx_size, 0) != idx_size) { + DEBUG_MSGF( + gi->flags, + "Error reading file %s where reloading\n", + gi->file_path); + return; + } + } + } + } + } + } + return; +} + +#define ADDR_STR_LEN (8 * 4 + 7 + 1) +unsigned int _GeoIP_seek_record_v6_gl(GeoIP *gi, geoipv6_t ipnum, + GeoIPLookup * gl) +{ + int depth; + char paddr[ADDR_STR_LEN]; + unsigned int x; + unsigned char stack_buffer[2 * MAX_RECORD_LENGTH]; + const unsigned char *buf = (gi->cache == NULL) ? stack_buffer : NULL; + unsigned int offset = 0; + + const unsigned char * p; + int j; + int fno = fileno(gi->GeoIPDatabase); + + unsigned int record_pair_length = gi->record_length * 2; + + _check_mtime(gi); + if (GeoIP_teredo(gi) ) { + __GEOIP_PREPARE_TEREDO(&ipnum); + } + for (depth = 127; depth >= 0; depth--) { + unsigned int byte_offset = record_pair_length * offset; + if (byte_offset > gi->size - record_pair_length) { + /* The pointer is invalid */ + break; + } + if (gi->cache == NULL && gi->index_cache == NULL) { + /* read from disk */ + if (pread(fno, stack_buffer, record_pair_length, + (long)byte_offset) != record_pair_length) { + break; + } + } else if (gi->index_cache == NULL) { + /* simply point to record in memory */ + buf = gi->cache + (long)byte_offset; + } else { + buf = gi->index_cache + (long)byte_offset; + } + + if (GEOIP_CHKBIT_V6(depth, ipnum.s6_addr )) { + /* Take the right-hand branch */ + if (gi->record_length == 3) { + /* Most common case is completely unrolled and uses constants. */ + x = (buf[3 * 1 + 0] << (0 * 8)) + + (buf[3 * 1 + 1] << (1 * 8)) + + (buf[3 * 1 + 2] << (2 * 8)); + + } else { + /* General case */ + j = gi->record_length; + p = &buf[2 * j]; + x = 0; + do { + x <<= 8; + x += *(--p); + } while (--j); + } + + } else { + /* Take the left-hand branch */ + if (gi->record_length == 3) { + /* Most common case is completely unrolled and uses constants. */ + x = (buf[3 * 0 + 0] << (0 * 8)) + + (buf[3 * 0 + 1] << (1 * 8)) + + (buf[3 * 0 + 2] << (2 * 8)); + } else { + /* General case */ + j = gi->record_length; + p = &buf[1 * j]; + x = 0; + do { + x <<= 8; + x += *(--p); + } while (--j); + } + } + + if (x >= gi->databaseSegments[0]) { + gi->netmask = gl->netmask = 128 - depth; + return x; + } + offset = x; + } + + /* shouldn't reach here */ + _GeoIP_inet_ntop(AF_INET6, &ipnum.s6_addr[0], paddr, ADDR_STR_LEN); + DEBUG_MSGF( + gi->flags, + "Error Traversing Database for ipnum = %s - Perhaps database is corrupt?\n", + paddr); + return 0; } geoipv6_t _GeoIP_addr_to_num_v6(const char *addr) { - geoipv6_t ipnum; - if ( 1 == _GeoIP_inet_pton(AF_INET6, addr, &ipnum.s6_addr[0] ) ) - return ipnum; - return IPV6_NULL; -} - - -unsigned int _GeoIP_seek_record_gl (GeoIP *gi, unsigned long ipnum, GeoIPLookup *gl) { - int depth; - unsigned int x; - unsigned char stack_buffer[2 * MAX_RECORD_LENGTH]; - const unsigned char *buf = (gi->cache == NULL) ? stack_buffer : NULL; - unsigned int offset = 0; - ssize_t silence _UNUSED; - - const unsigned char * p; - int j; - int fno = fileno(gi->GeoIPDatabase); - _check_mtime(gi); - for (depth = 31; depth >= 0; depth--) { - if (gi->cache == NULL && gi->index_cache == NULL) { - /* read from disk */ - silence = pread(fno, stack_buffer, gi->record_length * 2, gi->record_length * 2 * offset); - } else if (gi->index_cache == NULL) { - /* simply point to record in memory */ - buf = gi->cache + (long)gi->record_length * 2 *offset; - } else { - buf = gi->index_cache + (long)gi->record_length * 2 * offset; - } - - if (ipnum & (1 << depth)) { - /* Take the right-hand branch */ - if ( gi->record_length == 3 ) { - /* Most common case is completely unrolled and uses constants. */ - x = (buf[3*1 + 0] << (0*8)) - + (buf[3*1 + 1] << (1*8)) - + (buf[3*1 + 2] << (2*8)); - - } else { - /* General case */ - j = gi->record_length; - p = &buf[2*j]; - x = 0; - do { - x <<= 8; - x += *(--p); - } while ( --j ); - } - - } else { - /* Take the left-hand branch */ - if ( gi->record_length == 3 ) { - /* Most common case is completely unrolled and uses constants. */ - x = (buf[3*0 + 0] << (0*8)) - + (buf[3*0 + 1] << (1*8)) - + (buf[3*0 + 2] << (2*8)); - } else { - /* General case */ - j = gi->record_length; - p = &buf[1*j]; - x = 0; - do { - x <<= 8; - x += *(--p); - } while ( --j ); - } - } - - if (x >= gi->databaseSegments[0]) { - gi->netmask = gl->netmask = 32 - depth; - return x; - } - offset = x; - } - /* shouldn't reach here */ - fprintf(stderr,"Error Traversing Database for ipnum = %lu - Perhaps database is corrupt?\n",ipnum); - return 0; + geoipv6_t ipnum; + if (1 == _GeoIP_inet_pton(AF_INET6, addr, &ipnum.s6_addr[0] ) ) { + return ipnum; + } + return IPV6_NULL; +} + + +unsigned int _GeoIP_seek_record_gl(GeoIP *gi, unsigned long ipnum, + GeoIPLookup *gl) +{ + int depth; + unsigned int x; + unsigned char stack_buffer[2 * MAX_RECORD_LENGTH]; + const unsigned char *buf = (gi->cache == NULL) ? stack_buffer : NULL; + unsigned int offset = 0; + + const unsigned char * p; + int j; + int fno = fileno(gi->GeoIPDatabase); + + unsigned int record_pair_length = gi->record_length * 2; + + _check_mtime(gi); + for (depth = 31; depth >= 0; depth--) { + unsigned int byte_offset = record_pair_length * offset; + if (byte_offset > gi->size - record_pair_length) { + /* The pointer is invalid */ + break; + } + if (gi->cache == NULL && gi->index_cache == NULL) { + /* read from disk */ + if (pread(fno, stack_buffer, record_pair_length, + byte_offset) != record_pair_length) { + break; + } + } else if (gi->index_cache == NULL) { + /* simply point to record in memory */ + buf = gi->cache + (long)byte_offset; + } else { + buf = gi->index_cache + (long)byte_offset; + } + + if (ipnum & (1 << depth)) { + /* Take the right-hand branch */ + if (gi->record_length == 3) { + /* Most common case is completely unrolled and uses constants. */ + x = (buf[3 * 1 + 0] << (0 * 8)) + + (buf[3 * 1 + 1] << (1 * 8)) + + (buf[3 * 1 + 2] << (2 * 8)); + + } else { + /* General case */ + j = gi->record_length; + p = &buf[2 * j]; + x = 0; + do { + x <<= 8; + x += *(--p); + } while (--j); + } + + } else { + /* Take the left-hand branch */ + if (gi->record_length == 3) { + /* Most common case is completely unrolled and uses constants. */ + x = (buf[3 * 0 + 0] << (0 * 8)) + + (buf[3 * 0 + 1] << (1 * 8)) + + (buf[3 * 0 + 2] << (2 * 8)); + } else { + /* General case */ + j = gi->record_length; + p = &buf[1 * j]; + x = 0; + do { + x <<= 8; + x += *(--p); + } while (--j); + } + } + + if (x >= gi->databaseSegments[0]) { + gi->netmask = gl->netmask = 32 - depth; + return x; + } + offset = x; + } + /* shouldn't reach here */ + DEBUG_MSGF( + gi->flags, + "Error Traversing Database for ipnum = %lu - Perhaps database is corrupt?\n", + ipnum); + return 0; } unsigned long GeoIP_addr_to_num(const char *addr) { - unsigned int c, octet, t; - unsigned long ipnum; - int i = 3; - - octet = ipnum = 0; - while ((c = *addr++)) { - if (c == '.') { - if (octet > 255) - return 0; - ipnum <<= 8; - ipnum += octet; - i--; - octet = 0; - } else { - t = octet; - octet <<= 3; - octet += t; - octet += t; - c -= '0'; - if (c > 9) - return 0; - octet += c; - } - } - if ((octet > 255) || (i != 0)) - return 0; - ipnum <<= 8; - return ipnum + octet; -} - -GeoIP* GeoIP_open_type (int type, int flags) { - GeoIP * gi; - const char * filePath; - if (type < 0 || type >= NUM_DB_TYPES) { - printf("Invalid database type %d\n", type); - return NULL; - } - _GeoIP_setup_dbfilename(); - filePath = GeoIPDBFileName[type]; - if (filePath == NULL) { - printf("Invalid database type %d\n", type); - return NULL; - } - gi = GeoIP_open (filePath, flags); - - if ( gi ){ - /* make sure this is the requested database type */ - int database_type = gi->databaseType ; - if ( database_type > 105 ) - database_type -= 105; - /* type must match, but we accept org and asnum, - * since domain and *conf database have always the wrong type - * for historical reason. Maybe we fix it at some point. - */ - if ( database_type == type - || database_type == GEOIP_ASNUM_EDITION - || database_type == GEOIP_ORG_EDITION ) - return gi; - GeoIP_delete(gi); - } - - return NULL; -} - -GeoIP* GeoIP_new (int flags) { - GeoIP * gi; - _GeoIP_setup_dbfilename(); - gi = GeoIP_open (GeoIPDBFileName[GEOIP_COUNTRY_EDITION], flags); - return gi; -} - -GeoIP* GeoIP_open (const char * filename, int flags) { - struct stat buf; - unsigned int idx_size; - GeoIP * gi; - size_t len; - - gi = (GeoIP *)malloc(sizeof(GeoIP)); - if (gi == NULL) - return NULL; - len = sizeof(char) * (strlen(filename)+1); - gi->file_path = malloc(len); - if (gi->file_path == NULL) { - free(gi); - return NULL; - } - strncpy(gi->file_path, filename, len); - gi->GeoIPDatabase = fopen(filename,"rb"); - if (gi->GeoIPDatabase == NULL) { - fprintf(stderr,"Error Opening file %s\n",filename); - free(gi->file_path); - free(gi); - return NULL; - } else { - if (fstat(fileno(gi->GeoIPDatabase), &buf) == -1) { - fprintf(stderr,"Error stating file %s\n",filename); - free(gi->file_path); - free(gi); - return NULL; - } - if (flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE) ) { - gi->mtime = buf.st_mtime; - gi->size = buf.st_size; - - /* MMAP added my Peter Shipley */ - if ( flags & GEOIP_MMAP_CACHE ) { + unsigned int c, octet, t; + unsigned long ipnum; + int i = 3; + + octet = ipnum = 0; + while ((c = *addr++)) { + if (c == '.') { + if (octet > 255) { + return 0; + } + ipnum <<= 8; + ipnum += octet; + i--; + octet = 0; + } else { + t = octet; + octet <<= 3; + octet += t; + octet += t; + c -= '0'; + if (c > 9) { + return 0; + } + octet += c; + } + } + if ((octet > 255) || (i != 0)) { + return 0; + } + ipnum <<= 8; + return ipnum + octet; +} + +GeoIP * GeoIP_open_type(int type, int flags) +{ + GeoIP * gi; + const char * filePath; + if (type < 0 || type >= NUM_DB_TYPES) { + printf("Invalid database type %d\n", type); + return NULL; + } + _GeoIP_setup_dbfilename(); + filePath = GeoIPDBFileName[type]; + if (filePath == NULL) { + printf("Invalid database type %d\n", type); + return NULL; + } + gi = GeoIP_open(filePath, flags); + + if (gi) { + /* make sure this is the requested database type */ + int database_type = gi->databaseType; + if (database_type > 105) { + database_type -= 105; + } + /* type must match, but we accept org and asnum, + * since domain and *conf database have always the wrong type + * for historical reason. Maybe we fix it at some point. + */ + if (database_type == type + || database_type == GEOIP_ASNUM_EDITION + || database_type == GEOIP_ORG_EDITION) { + return gi; + } + GeoIP_delete(gi); + } + + return NULL; +} + +GeoIP * GeoIP_new(int flags) +{ + GeoIP * gi; + _GeoIP_setup_dbfilename(); + gi = GeoIP_open(GeoIPDBFileName[GEOIP_COUNTRY_EDITION], flags); + return gi; +} + +GeoIP * GeoIP_open(const char * filename, int flags) +{ + struct stat buf; + ssize_t idx_size; + GeoIP * gi; + size_t len; + + gi = (GeoIP *)malloc(sizeof(GeoIP)); + if (gi == NULL) { + return NULL; + } + len = sizeof(char) * (strlen(filename) + 1); + gi->file_path = malloc(len); + if (gi->file_path == NULL) { + free(gi); + return NULL; + } + strncpy(gi->file_path, filename, len); + gi->GeoIPDatabase = fopen(filename, "rb"); + if (gi->GeoIPDatabase == NULL) { + DEBUG_MSGF(flags, "Error Opening file %s\n", filename); + free(gi->file_path); + free(gi); + return NULL; + } + + if (fstat(fileno(gi->GeoIPDatabase), &buf) == -1) { + DEBUG_MSGF(flags, "Error stating file %s\n", filename); + free(gi->file_path); + free(gi); + return NULL; + } + + gi->size = buf.st_size; + if (flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE) ) { + gi->mtime = buf.st_mtime; + + /* MMAP added my Peter Shipley */ + if (flags & GEOIP_MMAP_CACHE) { #if !defined(_WIN32) - gi->cache = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fileno(gi->GeoIPDatabase), 0); - if ( gi->cache == MAP_FAILED ) { - fprintf(stderr,"Error mmaping file %s\n",filename); - free(gi->file_path); - free(gi); - return NULL; - } + gi->cache = + mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fileno( + gi->GeoIPDatabase), 0); + if (gi->cache == MAP_FAILED) { + DEBUG_MSGF(flags, "Error mmaping file %s\n", filename); + free(gi->file_path); + free(gi); + return NULL; + } #endif - } else { - gi->cache = (unsigned char *) malloc(sizeof(unsigned char) * buf.st_size); - - if (gi->cache != NULL) { - if (pread(fileno(gi->GeoIPDatabase),gi->cache, buf.st_size, 0) != (ssize_t) buf.st_size) { - fprintf(stderr,"Error reading file %s\n",filename); - free(gi->cache); - free(gi->file_path); - free(gi); - return NULL; - } - } - } - } else { - if (flags & GEOIP_CHECK_CACHE) { - if (fstat(fileno(gi->GeoIPDatabase), &buf) == -1) { - fprintf(stderr,"Error stating file %s\n",filename); - free(gi->file_path); - free(gi); - return NULL; - } - gi->mtime = buf.st_mtime; - } - gi->cache = NULL; - } - gi->flags = flags; - gi->charset = GEOIP_CHARSET_ISO_8859_1; - gi->ext_flags = 1U << GEOIP_TEREDO_BIT; - _setup_segments(gi); - - idx_size = _database_has_content(gi->databaseType) ? gi->databaseSegments[0] * (long)gi->record_length * 2 : buf.st_size; - - /* make sure the index is <= file size */ - if ( idx_size > buf.st_size ){ - fprintf(stderr, "Error file %s -- corrupt\n", gi->file_path); - if (flags & GEOIP_MEMORY_CACHE) { - free(gi->cache); - } + } else { + gi->cache = (unsigned char *)malloc( + sizeof(unsigned char) * buf.st_size); + + if (gi->cache != NULL) { + if (pread(fileno(gi->GeoIPDatabase), gi->cache, buf.st_size, + 0) != (ssize_t)buf.st_size) { + DEBUG_MSGF(flags, "Error reading file %s\n", filename); + free(gi->cache); + free(gi->file_path); + free(gi); + return NULL; + } + } + } + } else { + if (flags & GEOIP_CHECK_CACHE) { + if (fstat(fileno(gi->GeoIPDatabase), &buf) == -1) { + DEBUG_MSGF(flags, "Error stating file %s\n", filename); + free(gi->file_path); + free(gi); + return NULL; + } + gi->mtime = buf.st_mtime; + } + gi->cache = NULL; + } + gi->flags = flags; + gi->charset = GEOIP_CHARSET_ISO_8859_1; + gi->ext_flags = 1U << GEOIP_TEREDO_BIT; + _setup_segments(gi); + + idx_size = get_index_size(gi, &buf); + + if (idx_size < 0) { + DEBUG_MSGF(gi->flags, "Error file %s -- corrupt\n", gi->file_path); + if (flags & GEOIP_MEMORY_CACHE) { + free(gi->cache); + } #if !defined(_WIN32) - else if ( flags & GEOIP_MMAP_CACHE) { - /* MMAP is only avail on UNIX */ - munmap(gi->cache, gi->size); - gi->cache = NULL; - } + else if (gi->cache && (flags & GEOIP_MMAP_CACHE)) { + /* MMAP is only avail on UNIX */ + munmap(gi->cache, gi->size); + gi->cache = NULL; + } #endif - free(gi->file_path); - free(gi); - return NULL; - } - - if (flags & GEOIP_INDEX_CACHE) { - gi->index_cache = (unsigned char *) malloc(sizeof(unsigned char) * idx_size); - if (gi->index_cache != NULL) { - if (pread(fileno(gi->GeoIPDatabase),gi->index_cache, idx_size, 0) != idx_size ) { - fprintf(stderr,"Error reading file %s\n",filename); - free(gi->databaseSegments); - free(gi->index_cache); - free(gi); - return NULL; - } - } - } else { - gi->index_cache = NULL; - } - return gi; - } -} - -void GeoIP_delete (GeoIP *gi) { - if (gi == NULL ) - return; - if (gi->GeoIPDatabase != NULL) - fclose(gi->GeoIPDatabase); - if (gi->cache != NULL) { - if ( gi->flags & GEOIP_MMAP_CACHE ) { + free(gi->file_path); + free(gi); + return NULL; + } + + if (flags & GEOIP_INDEX_CACHE) { + gi->index_cache = (unsigned char *)malloc( + sizeof(unsigned char) * idx_size); + if (gi->index_cache != NULL) { + if (pread(fileno(gi->GeoIPDatabase), gi->index_cache, idx_size, + 0) != idx_size) { + DEBUG_MSGF(gi->flags, "Error reading file %s\n", filename); + free(gi->databaseSegments); + free(gi->index_cache); + free(gi); + return NULL; + } + } + } else { + gi->index_cache = NULL; + } + + gi->last_mtime_check = 0; + + return gi; +} + +void GeoIP_delete(GeoIP *gi) +{ + if (gi == NULL) { + return; + } + if (gi->GeoIPDatabase != NULL) { + fclose(gi->GeoIPDatabase); + } + if (gi->cache != NULL) { + if (gi->flags & GEOIP_MMAP_CACHE) { #if !defined(_WIN32) - munmap(gi->cache, gi->size); + if (gi->cache) { + munmap(gi->cache, gi->size); + } #endif - } else { - free(gi->cache); - } - gi->cache = NULL; - } - if (gi->index_cache != NULL) - free(gi->index_cache); - if (gi->file_path != NULL) - free(gi->file_path); - if (gi->databaseSegments != NULL) - free(gi->databaseSegments); - free(gi); + } else { + free(gi->cache); + } + gi->cache = NULL; + } + if (gi->index_cache != NULL) { + free(gi->index_cache); + } + if (gi->file_path != NULL) { + free(gi->file_path); + } + if (gi->databaseSegments != NULL) { + free(gi->databaseSegments); + } + free(gi); } -const char *GeoIP_country_code_by_name_v6_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_name_v6_gl(gi, name, gl); - return (country_id > 0) ? GeoIP_country_code[country_id] : NULL; +const char *GeoIP_country_code_by_name_v6_gl(GeoIP * gi, const char *name, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_name_v6_gl(gi, name, gl); + return (country_id > 0) ? GeoIP_code_by_id(country_id) : NULL; } -const char *GeoIP_country_code_by_name_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_name_gl(gi, name, gl); - return (country_id > 0) ? GeoIP_country_code[country_id] : NULL; +const char *GeoIP_country_code_by_name_gl(GeoIP * gi, const char *name, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_name_gl(gi, name, gl); + return (country_id > 0) ? GeoIP_code_by_id(country_id) : NULL; } -const char *GeoIP_country_code3_by_name_v6_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_name_v6_gl(gi, name, gl); - return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL; +const char *GeoIP_country_code3_by_name_v6_gl(GeoIP * gi, const char *name, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_name_v6_gl(gi, name, gl); + return (country_id > 0) ? GeoIP_code3_by_id(country_id) : NULL; } -const char *GeoIP_country_code3_by_name_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_name_gl(gi, name, gl); - return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL; +const char *GeoIP_country_code3_by_name_gl(GeoIP * gi, const char *name, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_name_gl(gi, name, gl); + return (country_id > 0) ? GeoIP_code3_by_id(country_id) : NULL; } -const char *GeoIP_country_name_by_name_v6_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_name_v6_gl(gi, name, gl); - return GeoIP_country_name_by_id(gi, country_id ); +const char *GeoIP_country_name_by_name_v6_gl(GeoIP * gi, const char *name, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_name_v6_gl(gi, name, gl); + return GeoIP_country_name_by_id(gi, country_id ); } -const char *GeoIP_country_name_by_name_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_name_gl(gi, name, gl); - return GeoIP_country_name_by_id(gi, country_id ); +const char *GeoIP_country_name_by_name_gl(GeoIP * gi, const char *name, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_name_gl(gi, name, gl); + return GeoIP_country_name_by_id(gi, country_id ); } -unsigned long _GeoIP_lookupaddress (const char *host) { - unsigned long addr = inet_addr(host); - struct hostent phe2; - struct hostent * phe = &phe2; - char *buf = NULL; +unsigned long _GeoIP_lookupaddress(const char *host) +{ + unsigned long addr = inet_addr(host); + struct hostent phe2; + struct hostent * phe = &phe2; + char *buf = NULL; #ifdef HAVE_GETHOSTBYNAME_R - int buflength = 16384; - int herr = 0; + int buflength = 16384; + int herr = 0; #endif - int result = 0; + int result = 0; #ifdef HAVE_GETHOSTBYNAME_R - buf = malloc(buflength); + buf = malloc(buflength); #endif - if (addr == INADDR_NONE) { + if (addr == INADDR_NONE) { #ifdef HAVE_GETHOSTBYNAME_R - while (1) { - /* we use gethostbyname_r here because it is thread-safe and gethostbyname is not */ + while (1) { + /* we use gethostbyname_r here because it is thread-safe and gethostbyname is not */ #ifdef GETHOSTBYNAME_R_RETURNS_INT - result = gethostbyname_r(host,&phe2,buf,buflength,&phe,&herr); + result = gethostbyname_r(host, &phe2, buf, buflength, &phe, &herr); #else - phe = gethostbyname_r(host,&phe2,buf,buflength,&herr); + phe = gethostbyname_r(host, &phe2, buf, buflength, &herr); #endif - if (herr != ERANGE) - break; - if (result == 0) - break; - /* double the buffer if the buffer is too small */ - buflength = buflength * 2; - buf = realloc(buf,buflength); - } + if (herr != ERANGE) { + break; + } + if (result == 0) { + break; + } + /* double the buffer if the buffer is too small */ + buflength = buflength * 2; + buf = realloc(buf, buflength); + } #else - /* Some systems do not support gethostbyname_r, such as Mac OS X */ - phe = gethostbyname(host); + /* Some systems do not support gethostbyname_r, such as Mac OS X */ + phe = gethostbyname(host); #endif - if (!phe || result != 0) { - free(buf); - return 0; - } + if (!phe || result != 0) { + free(buf); + return 0; + } #if !defined(_WIN32) - addr = *((in_addr_t *) phe->h_addr_list[0]); + addr = *((in_addr_t *)phe->h_addr_list[0]); #else - addr = ((IN_ADDR *) phe->h_addr_list[0])->S_un.S_addr; + addr = ((IN_ADDR *)phe->h_addr_list[0])->S_un.S_addr; #endif - } + } #ifdef HAVE_GETHOSTBYNAME_R - free(buf); + free(buf); #endif - return ntohl(addr); + return ntohl(addr); } -geoipv6_t +geoipv6_t _GeoIP_lookupaddress_v6(const char *host) { - geoipv6_t ipnum; - int gaierr; - struct addrinfo hints, *aifirst; + geoipv6_t ipnum; + int gaierr; + struct addrinfo hints, *aifirst; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + /* hints.ai_flags = AI_V4MAPPED; */ + hints.ai_socktype = SOCK_STREAM; + + if ((gaierr = getaddrinfo(host, NULL, &hints, &aifirst)) != 0) { + /* DEBUG_MSGF("Err: %s (%d %s)\n", host, gaierr, gai_strerror(gaierr)); */ + return IPV6_NULL; + } + memcpy(ipnum.s6_addr, + ((struct sockaddr_in6 *)aifirst->ai_addr)->sin6_addr.s6_addr, + sizeof(geoipv6_t)); + freeaddrinfo(aifirst); + /* inet_pton(AF_INET6, host, ipnum.s6_addr); */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET6; - /* hints.ai_flags = AI_V4MAPPED; */ - hints.ai_socktype = SOCK_STREAM; + return ipnum; +} - if ((gaierr = getaddrinfo(host, NULL, &hints, &aifirst)) != 0) { - /* fprintf(stderr, "Err: %s (%d %s)\n", host, gaierr, gai_strerror(gaierr)); */ - return IPV6_NULL; - } - memcpy(ipnum.s6_addr, ((struct sockaddr_in6 *) aifirst->ai_addr)->sin6_addr.s6_addr, sizeof(geoipv6_t)); - freeaddrinfo(aifirst); - /* inet_pton(AF_INET6, host, ipnum.s6_addr); */ - - return ipnum; +int GeoIP_id_by_name_gl(GeoIP * gi, const char *name, GeoIPLookup *gl ) +{ + unsigned long ipnum; + int ret; + if (name == NULL) { + return 0; + } + if (gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION && gi->databaseType != + GEOIP_COUNTRY_EDITION && gi->databaseType != GEOIP_PROXY_EDITION && + gi->databaseType != GEOIP_NETSPEED_EDITION) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_COUNTRY_EDITION)); + return 0; + } + if (!(ipnum = _GeoIP_lookupaddress(name))) { + return 0; + } + ret = _GeoIP_seek_record_gl(gi, ipnum, gl) - gi->databaseSegments[0]; + return ret; +} + +int GeoIP_id_by_name_v6_gl(GeoIP * gi, const char *name, GeoIPLookup * gl) +{ + geoipv6_t ipnum; + int ret; + if (name == NULL) { + return 0; + } + if (gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION_V6 && + gi->databaseType != GEOIP_COUNTRY_EDITION_V6) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_COUNTRY_EDITION_V6)); + return 0; + } + ipnum = _GeoIP_lookupaddress_v6(name); + if (__GEOIP_V6_IS_NULL(ipnum)) { + return 0; + } + + ret = _GeoIP_seek_record_v6_gl(gi, ipnum, gl) - gi->databaseSegments[0]; + return ret; +} + +const char *GeoIP_country_code_by_addr_v6_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_addr_v6_gl(gi, addr, gl); + return (country_id > 0) ? GeoIP_code_by_id(country_id) : NULL; +} + + +const char *GeoIP_country_code_by_addr_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_addr_gl(gi, addr, gl); + return (country_id > 0) ? GeoIP_code_by_id(country_id) : NULL; +} +const char *GeoIP_country_code3_by_addr_v6_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_addr_v6_gl(gi, addr, gl); + return (country_id > 0) ? GeoIP_code3_by_id(country_id) : NULL; } -int GeoIP_id_by_name_gl (GeoIP* gi, const char *name, GeoIPLookup *gl ) { - unsigned long ipnum; - int ret; - if (name == NULL) { - return 0; - } - if (gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION && gi->databaseType != GEOIP_COUNTRY_EDITION && gi->databaseType != GEOIP_PROXY_EDITION && gi->databaseType != GEOIP_NETSPEED_EDITION) { - printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_COUNTRY_EDITION)); - return 0; - } - if (!(ipnum = _GeoIP_lookupaddress(name))) - return 0; - ret = _GeoIP_seek_record_gl(gi, ipnum, gl) - gi->databaseSegments[0]; - return ret; +const char *GeoIP_country_code3_by_addr_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_addr_gl(gi, addr, gl); + return (country_id > 0) ? GeoIP_code3_by_id(country_id) : NULL; } -int GeoIP_id_by_name_v6_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) { - geoipv6_t ipnum; - int ret; - if (name == NULL) { - return 0; - } - if (gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION_V6 && gi->databaseType != GEOIP_COUNTRY_EDITION_V6) { - printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_COUNTRY_EDITION_V6)); - return 0; - } - ipnum = _GeoIP_lookupaddress_v6(name); - if (__GEOIP_V6_IS_NULL(ipnum)) - return 0; +const char *GeoIP_country_name_by_addr_v6_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl ) +{ + int country_id; + country_id = GeoIP_id_by_addr_v6_gl(gi, addr, gl); + return GeoIP_country_name_by_id(gi, country_id ); +} - ret = _GeoIP_seek_record_v6_gl(gi, ipnum, gl) - gi->databaseSegments[0]; - return ret; +const char *GeoIP_country_name_by_addr_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl ) +{ + int country_id; + country_id = GeoIP_id_by_addr_gl(gi, addr, gl); + return GeoIP_country_name_by_id(gi, country_id ); +} + +const char *GeoIP_country_name_by_ipnum_gl(GeoIP * gi, unsigned long ipnum, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_ipnum_gl(gi, ipnum, gl); + return GeoIP_country_name_by_id(gi, country_id ); } -const char *GeoIP_country_code_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_addr_v6_gl(gi, addr, gl); - return (country_id > 0) ? GeoIP_country_code[country_id] : NULL; +const char *GeoIP_country_name_by_ipnum_v6_gl(GeoIP * gi, geoipv6_t ipnum, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_ipnum_v6_gl(gi, ipnum, gl); + return GeoIP_country_name_by_id(gi, country_id ); } +const char *GeoIP_country_code_by_ipnum_gl(GeoIP * gi, unsigned long ipnum, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_ipnum_gl(gi, ipnum, gl); + return (country_id > 0) ? GeoIP_code_by_id(country_id) : NULL; +} -const char *GeoIP_country_code_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_addr_gl(gi, addr, gl); - return (country_id > 0) ? GeoIP_country_code[country_id] : NULL; +const char *GeoIP_country_code_by_ipnum_v6_gl(GeoIP * gi, geoipv6_t ipnum, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_ipnum_v6_gl(gi, ipnum, gl); + return (country_id > 0) ? GeoIP_code_by_id(country_id) : NULL; } -const char *GeoIP_country_code3_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_addr_v6_gl(gi, addr, gl); - return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL; + +const char *GeoIP_country_code3_by_ipnum_gl(GeoIP * gi, unsigned long ipnum, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_ipnum_gl(gi, ipnum, gl); + return (country_id > 0) ? GeoIP_code3_by_id(country_id) : NULL; } -const char *GeoIP_country_code3_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_addr_gl(gi, addr, gl); - return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL; +const char *GeoIP_country_code3_by_ipnum_v6_gl(GeoIP * gi, geoipv6_t ipnum, + GeoIPLookup * gl) +{ + int country_id; + country_id = GeoIP_id_by_ipnum_v6_gl(gi, ipnum, gl); + return (country_id > 0) ? GeoIP_code3_by_id(country_id) : NULL; +} + +int GeoIP_country_id_by_addr_v6_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl) +{ + return GeoIP_id_by_addr_v6_gl(gi, addr, gl); +} + +int GeoIP_country_id_by_addr_gl(GeoIP * gi, const char *addr, GeoIPLookup * gl) +{ + return GeoIP_id_by_addr_gl(gi, addr, gl); +} + +int GeoIP_country_id_by_name_v6_gl(GeoIP * gi, const char *host, + GeoIPLookup * gl) +{ + return GeoIP_id_by_name_v6_gl(gi, host, gl); +} + +int GeoIP_country_id_by_name_gl(GeoIP * gi, const char *host, GeoIPLookup * gl) +{ + return GeoIP_id_by_name_gl(gi, host, gl); +} + +int GeoIP_id_by_addr_v6_gl(GeoIP * gi, const char *addr, GeoIPLookup * gl) +{ + geoipv6_t ipnum; + int ret; + if (addr == NULL) { + return 0; + } + if (gi->databaseType != GEOIP_COUNTRY_EDITION_V6 + && gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION_V6) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_COUNTRY_EDITION_V6)); + return 0; + } + ipnum = _GeoIP_addr_to_num_v6(addr); + ret = _GeoIP_seek_record_v6_gl(gi, ipnum, gl) - gi->databaseSegments[0]; + return ret; +} + + +int GeoIP_id_by_addr_gl(GeoIP * gi, const char *addr, GeoIPLookup * gl) +{ + unsigned long ipnum; + int ret; + if (addr == NULL) { + return 0; + } + if (gi->databaseType != GEOIP_COUNTRY_EDITION && + gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION && + gi->databaseType != GEOIP_PROXY_EDITION && + gi->databaseType != GEOIP_NETSPEED_EDITION) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_COUNTRY_EDITION)); + return 0; + } + ipnum = GeoIP_addr_to_num(addr); + ret = _GeoIP_seek_record_gl(gi, ipnum, gl) - gi->databaseSegments[0]; + return ret; +} + +int GeoIP_id_by_ipnum_v6_gl(GeoIP * gi, geoipv6_t ipnum, GeoIPLookup * gl) +{ + int ret; + if (gi->databaseType != GEOIP_COUNTRY_EDITION_V6 + && gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION_V6) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_COUNTRY_EDITION_V6)); + return 0; + } + ret = _GeoIP_seek_record_v6_gl(gi, ipnum, gl) - gi->databaseSegments[0]; + return ret; } -const char *GeoIP_country_name_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl ) { - int country_id; - country_id = GeoIP_id_by_addr_v6_gl(gi, addr, gl); - return GeoIP_country_name_by_id(gi, country_id ); +int GeoIP_id_by_ipnum_gl(GeoIP * gi, unsigned long ipnum, GeoIPLookup * gl) +{ + int ret; + if (ipnum == 0) { + return 0; + } + if (gi->databaseType != GEOIP_COUNTRY_EDITION && + gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION && + gi->databaseType != GEOIP_PROXY_EDITION && + gi->databaseType != GEOIP_NETSPEED_EDITION) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_COUNTRY_EDITION)); + return 0; + } + ret = _GeoIP_seek_record_gl(gi, ipnum, gl) - gi->databaseSegments[0]; + return ret; } -const char *GeoIP_country_name_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl ) { - int country_id; - country_id = GeoIP_id_by_addr_gl(gi, addr, gl); - return GeoIP_country_name_by_id(gi, country_id ); -} - -const char *GeoIP_country_name_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_ipnum_gl(gi, ipnum, gl); - return GeoIP_country_name_by_id(gi, country_id ); -} - -const char *GeoIP_country_name_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_ipnum_v6_gl(gi, ipnum, gl); - return GeoIP_country_name_by_id(gi, country_id ); -} - -const char *GeoIP_country_code_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_ipnum_gl(gi, ipnum, gl); - return (country_id > 0) ? GeoIP_country_code[country_id] : NULL; -} - -const char *GeoIP_country_code_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_ipnum_v6_gl(gi, ipnum, gl); - return (country_id > 0) ? GeoIP_country_code[country_id] : NULL; -} - -const char *GeoIP_country_code3_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_ipnum_gl(gi, ipnum, gl); - return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL; -} - -const char *GeoIP_country_code3_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) { - int country_id; - country_id = GeoIP_id_by_ipnum_v6_gl(gi, ipnum, gl); - return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL; -} - -int GeoIP_country_id_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) { - GeoIPLookup n; - return GeoIP_id_by_addr_v6_gl(gi, addr, &n); -} - -int GeoIP_country_id_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) { - return GeoIP_id_by_addr_gl(gi, addr, gl); -} - -int GeoIP_country_id_by_name_v6_gl (GeoIP* gi, const char *host, GeoIPLookup * gl) { - return GeoIP_id_by_name_v6_gl(gi, host, gl); -} - -int GeoIP_country_id_by_name_gl (GeoIP* gi, const char *host, GeoIPLookup * gl) { - return GeoIP_id_by_name_gl(gi, host, gl); -} - -int GeoIP_id_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) { - geoipv6_t ipnum; - int ret; - if (addr == NULL) { - return 0; - } - if (gi->databaseType != GEOIP_COUNTRY_EDITION_V6 - && gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION_V6) { - printf("Invalid database type %s, expected %s\n", - get_db_description(gi->databaseType), - get_db_description(GEOIP_COUNTRY_EDITION_V6)); - return 0; - } - ipnum = _GeoIP_addr_to_num_v6(addr); - ret = _GeoIP_seek_record_v6_gl(gi, ipnum, gl) - gi->databaseSegments[0]; - return ret; -} - - -int GeoIP_id_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) { - unsigned long ipnum; - int ret; - if (addr == NULL) { - return 0; - } - if (gi->databaseType != GEOIP_COUNTRY_EDITION && - gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION && - gi->databaseType != GEOIP_PROXY_EDITION && - gi->databaseType != GEOIP_NETSPEED_EDITION) { - printf("Invalid database type %s, expected %s\n", - get_db_description(gi->databaseType), - get_db_description(GEOIP_COUNTRY_EDITION)); - return 0; - } - ipnum = GeoIP_addr_to_num(addr); - ret = _GeoIP_seek_record_gl(gi, ipnum, gl) - gi->databaseSegments[0]; - return ret; -} - -int GeoIP_id_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) { - int ret; - if (gi->databaseType != GEOIP_COUNTRY_EDITION_V6 - && gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION_V6) { - printf("Invalid database type %s, expected %s\n", - get_db_description(gi->databaseType), - get_db_description(GEOIP_COUNTRY_EDITION_V6)); - return 0; - } - ret = _GeoIP_seek_record_v6_gl(gi, ipnum, gl) - gi->databaseSegments[0]; - return ret; -} - -int GeoIP_id_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) { - int ret; - if (ipnum == 0) { - return 0; - } - if (gi->databaseType != GEOIP_COUNTRY_EDITION && - gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION && - gi->databaseType != GEOIP_PROXY_EDITION && - gi->databaseType != GEOIP_NETSPEED_EDITION) { - printf("Invalid database type %s, expected %s\n", - get_db_description(gi->databaseType), - get_db_description(GEOIP_COUNTRY_EDITION)); - return 0; - } - ret = _GeoIP_seek_record_gl(gi, ipnum, gl) - gi->databaseSegments[0]; - return ret; -} - -char *GeoIP_database_info (GeoIP* gi) { - int i; - unsigned char buf[3]; - char *retval; - int hasStructureInfo = 0; - ssize_t silence _UNUSED; - int fno; - - if(gi == NULL) - return NULL; - - fno = fileno(gi->GeoIPDatabase); - - _check_mtime(gi); - lseek(fno, -3l, SEEK_END); - - /* first get past the database structure information */ - for (i = 0; i < STRUCTURE_INFO_MAX_SIZE; i++) { - silence = read(fno, buf, 3 ); - if (buf[0] == 255 && buf[1] == 255 && buf[2] == 255) { - hasStructureInfo = 1; - break; - } - lseek(fno, -4l, SEEK_CUR); - } - if (hasStructureInfo == 1) { - lseek(fno, -6l, SEEK_CUR); - } else { - /* no structure info, must be pre Sep 2002 database, go back to end */ - lseek(fno, -3l, SEEK_END); - } - - for (i = 0; i < DATABASE_INFO_MAX_SIZE; i++) { - silence = read(fno, buf, 3 ); - if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0) { - retval = malloc(sizeof(char) * (i+1)); - if (retval == NULL) { - return NULL; - } - silence = read(fno, retval, i); - retval[i] = '\0'; - return retval; - } - lseek(fno, -4l, SEEK_CUR); - } - return NULL; +char *GeoIP_database_info(GeoIP * gi) +{ + int i; + unsigned char buf[3]; + char *retval; + int has_structure_info = 0; + off_t offset = gi->size - 3; + int fno; + + if (gi == NULL) { + return NULL; + } + + fno = fileno(gi->GeoIPDatabase); + + _check_mtime(gi); + + /* first get past the database structure information */ + for (i = 0; i < STRUCTURE_INFO_MAX_SIZE; i++) { + if (pread(fno, buf, 3, offset) != 3) { + return NULL; + } + offset += 3; + if (buf[0] == 255 && buf[1] == 255 && buf[2] == 255) { + has_structure_info = 1; + break; + } + offset -= 4; + if (offset < 0) { + return NULL; + } + } + if (has_structure_info) { + offset -= 6; + if (offset < 0) { + return NULL; + } + } else { + /* no structure info, must be pre Sep 2002 database, go back to end */ + offset = gi->size - 3; + if (offset < 0) { + return NULL; + } + } + + for (i = 0; i < DATABASE_INFO_MAX_SIZE; i++) { + if (pread(fno, buf, 3, offset) != 3) { + return NULL; + } + offset += 3; + if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0) { + retval = malloc(sizeof(char) * (i + 1)); + if (retval == NULL) { + return NULL; + } + if (pread(fno, retval, i, offset) != i) { + return NULL; + } + retval[i] = '\0'; + return retval; + } + offset -= 4; + if (offset < 0) { + return NULL; + } + } + return NULL; } /* GeoIP Region Edition functions */ -void GeoIP_assign_region_by_inetaddr_gl(GeoIP* gi, unsigned long inetaddr, GeoIPRegion *region, GeoIPLookup * gl) { - unsigned int seek_region; - - /* This also writes in the terminating NULs (if you decide to - * keep them) and clear any fields that are not set. */ - memset(region, 0, sizeof(GeoIPRegion)); - - seek_region = _GeoIP_seek_record_gl(gi, ntohl(inetaddr), gl); - - if (gi->databaseType == GEOIP_REGION_EDITION_REV0) { - /* Region Edition, pre June 2003 */ - seek_region -= STATE_BEGIN_REV0; - if (seek_region >= 1000) { - region->country_code[0] = 'U'; - region->country_code[1] = 'S'; - region->region[0] = (char) ((seek_region - 1000)/26 + 65); - region->region[1] = (char) ((seek_region - 1000)%26 + 65); - } else { - memcpy(region->country_code, GeoIP_country_code[seek_region], 2); - } - } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) { - /* Region Edition, post June 2003 */ - seek_region -= STATE_BEGIN_REV1; - if (seek_region < US_OFFSET) { - /* Unknown */ - /* we don't need to do anything here b/c we memset region to 0 */ - } else if (seek_region < CANADA_OFFSET) { - /* USA State */ - region->country_code[0] = 'U'; - region->country_code[1] = 'S'; - region->region[0] = (char) ((seek_region - US_OFFSET)/26 + 65); - region->region[1] = (char) ((seek_region - US_OFFSET)%26 + 65); - } else if (seek_region < WORLD_OFFSET) { - /* Canada Province */ - region->country_code[0] = 'C'; - region->country_code[1] = 'A'; - region->region[0] = (char) ((seek_region - CANADA_OFFSET)/26 + 65); - region->region[1] = (char) ((seek_region - CANADA_OFFSET)%26 + 65); - } else { - /* Not US or Canada */ - memcpy(region->country_code, GeoIP_country_code[(seek_region - WORLD_OFFSET) / FIPS_RANGE], 2); - } - } -} - -void GeoIP_assign_region_by_inetaddr_v6_gl(GeoIP* gi, geoipv6_t inetaddr, GeoIPRegion *region, GeoIPLookup * gl) { - unsigned int seek_region; - - /* This also writes in the terminating NULs (if you decide to - * keep them) and clear any fields that are not set. */ - memset(region, 0, sizeof(GeoIPRegion)); - - seek_region = _GeoIP_seek_record_v6_gl(gi, inetaddr, gl); - - if (gi->databaseType == GEOIP_REGION_EDITION_REV0) { - /* Region Edition, pre June 2003 */ - seek_region -= STATE_BEGIN_REV0; - if (seek_region >= 1000) { - region->country_code[0] = 'U'; - region->country_code[1] = 'S'; - region->region[0] = (char) ((seek_region - 1000)/26 + 65); - region->region[1] = (char) ((seek_region - 1000)%26 + 65); - } else { - memcpy(region->country_code, GeoIP_country_code[seek_region], 2); - } - } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) { - /* Region Edition, post June 2003 */ - seek_region -= STATE_BEGIN_REV1; - if (seek_region < US_OFFSET) { - /* Unknown */ - /* we don't need to do anything here b/c we memset region to 0 */ - } else if (seek_region < CANADA_OFFSET) { - /* USA State */ - region->country_code[0] = 'U'; - region->country_code[1] = 'S'; - region->region[0] = (char) ((seek_region - US_OFFSET)/26 + 65); - region->region[1] = (char) ((seek_region - US_OFFSET)%26 + 65); - } else if (seek_region < WORLD_OFFSET) { - /* Canada Province */ - region->country_code[0] = 'C'; - region->country_code[1] = 'A'; - region->region[0] = (char) ((seek_region - CANADA_OFFSET)/26 + 65); - region->region[1] = (char) ((seek_region - CANADA_OFFSET)%26 + 65); - } else { - /* Not US or Canada */ - memcpy(region->country_code, GeoIP_country_code[(seek_region - WORLD_OFFSET) / FIPS_RANGE], 2); - } - } +void GeoIP_assign_region_by_inetaddr_gl(GeoIP * gi, unsigned long inetaddr, + GeoIPRegion *region, + GeoIPLookup * gl) +{ + unsigned int seek_region; + + /* This also writes in the terminating NULs (if you decide to + * keep them) and clear any fields that are not set. */ + memset(region, 0, sizeof(GeoIPRegion)); + + seek_region = _GeoIP_seek_record_gl(gi, ntohl(inetaddr), gl); + + if (gi->databaseType == GEOIP_REGION_EDITION_REV0) { + /* Region Edition, pre June 2003 */ + seek_region -= STATE_BEGIN_REV0; + if (seek_region >= 1000) { + region->country_code[0] = 'U'; + region->country_code[1] = 'S'; + region->region[0] = (char)((seek_region - 1000) / 26 + 65); + region->region[1] = (char)((seek_region - 1000) % 26 + 65); + } else { + const char *code = GeoIP_code_by_id(seek_region); + if (code != NULL) { + memcpy(region->country_code, code, 2); + } + } + } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) { + /* Region Edition, post June 2003 */ + seek_region -= STATE_BEGIN_REV1; + if (seek_region < US_OFFSET) { + /* Unknown */ + /* we don't need to do anything here b/c we memset region to 0 */ + } else if (seek_region < CANADA_OFFSET) { + /* USA State */ + region->country_code[0] = 'U'; + region->country_code[1] = 'S'; + region->region[0] = (char)((seek_region - US_OFFSET) / 26 + 65); + region->region[1] = (char)((seek_region - US_OFFSET) % 26 + 65); + } else if (seek_region < WORLD_OFFSET) { + /* Canada Province */ + region->country_code[0] = 'C'; + region->country_code[1] = 'A'; + region->region[0] = (char)((seek_region - CANADA_OFFSET) / 26 + 65); + region->region[1] = (char)((seek_region - CANADA_OFFSET) % 26 + 65); + } else { + /* Not US or Canada ( cc_id is always cc_id * FIPS_RANGE ) */ + const char *code = GeoIP_code_by_id( + (seek_region - WORLD_OFFSET) / FIPS_RANGE); + if (code != NULL) { + /* coverity[dont_call] */ + memcpy(region->country_code, code, 2); + } + } + } +} + +void GeoIP_assign_region_by_inetaddr_v6_gl(GeoIP * gi, geoipv6_t inetaddr, + GeoIPRegion *region, + GeoIPLookup * gl) +{ + unsigned int seek_region; + + /* This also writes in the terminating NULs (if you decide to + * keep them) and clear any fields that are not set. */ + memset(region, 0, sizeof(GeoIPRegion)); + + seek_region = _GeoIP_seek_record_v6_gl(gi, inetaddr, gl); + + if (gi->databaseType == GEOIP_REGION_EDITION_REV0) { + /* Region Edition, pre June 2003 */ + seek_region -= STATE_BEGIN_REV0; + if (seek_region >= 1000) { + region->country_code[0] = 'U'; + region->country_code[1] = 'S'; + region->region[0] = (char)((seek_region - 1000) / 26 + 65); + region->region[1] = (char)((seek_region - 1000) % 26 + 65); + } else { + const char *code = GeoIP_code_by_id(seek_region); + if (code != NULL) { + /* coverity[dont_call] */ + memcpy(region->country_code, code, 2); + } + } + } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) { + /* Region Edition, post June 2003 */ + seek_region -= STATE_BEGIN_REV1; + if (seek_region < US_OFFSET) { + /* Unknown */ + /* we don't need to do anything here b/c we memset region to 0 */ + } else if (seek_region < CANADA_OFFSET) { + /* USA State */ + region->country_code[0] = 'U'; + region->country_code[1] = 'S'; + region->region[0] = (char)((seek_region - US_OFFSET) / 26 + 65); + region->region[1] = (char)((seek_region - US_OFFSET) % 26 + 65); + } else if (seek_region < WORLD_OFFSET) { + /* Canada Province */ + region->country_code[0] = 'C'; + region->country_code[1] = 'A'; + region->region[0] = (char)((seek_region - CANADA_OFFSET) / 26 + 65); + region->region[1] = (char)((seek_region - CANADA_OFFSET) % 26 + 65); + } else { + /* Not US or Canada ( cc_id is always cc_id * FIPS_RANGE ) */ + const char *code = GeoIP_code_by_id( + (seek_region - WORLD_OFFSET) / FIPS_RANGE); + if (code != NULL) { + /* coverity[dont_call] */ + memcpy(region->country_code, code, 2); + } + } + } } static -GeoIPRegion * _get_region_gl(GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) { - GeoIPRegion * region; - - region = malloc(sizeof(GeoIPRegion)); - if (region) { - GeoIP_assign_region_by_inetaddr_gl(gi, htonl(ipnum), region, gl); - } - return region; +GeoIPRegion * _get_region_gl(GeoIP * gi, unsigned long ipnum, GeoIPLookup * gl) +{ + GeoIPRegion * region; + + region = malloc(sizeof(GeoIPRegion)); + if (region) { + GeoIP_assign_region_by_inetaddr_gl(gi, htonl(ipnum), region, gl); + } + return region; } static -GeoIPRegion * _get_region_v6_gl(GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) { - GeoIPRegion * region; - - region = malloc(sizeof(GeoIPRegion)); - if (region) { - GeoIP_assign_region_by_inetaddr_v6_gl(gi, ipnum, region, gl); - } - return region; -} - -GeoIPRegion * GeoIP_region_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) { - unsigned long ipnum; - if (addr == NULL) { - return NULL; - } - if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && - gi->databaseType != GEOIP_REGION_EDITION_REV1) { - printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_REGION_EDITION_REV1)); - return NULL; - } - ipnum = GeoIP_addr_to_num(addr); - return _get_region_gl(gi, ipnum, gl); -} - -GeoIPRegion * GeoIP_region_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) { - geoipv6_t ipnum; - if (addr == NULL) { - return NULL; - } - if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && - gi->databaseType != GEOIP_REGION_EDITION_REV1) { - printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_REGION_EDITION_REV1)); - return NULL; - } - ipnum = _GeoIP_addr_to_num_v6(addr); - return _get_region_v6_gl(gi, ipnum, gl); -} - -GeoIPRegion * GeoIP_region_by_name_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) { - unsigned long ipnum; - if (name == NULL) { - return NULL; - } - if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && - gi->databaseType != GEOIP_REGION_EDITION_REV1) { - printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_REGION_EDITION_REV1)); - return NULL; - } - if (!(ipnum = _GeoIP_lookupaddress(name))) - return NULL; - return _get_region_gl(gi, ipnum, gl); -} - -GeoIPRegion * GeoIP_region_by_name_v6_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) { - geoipv6_t ipnum; - if (name == NULL) { - return NULL; - } - if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && - gi->databaseType != GEOIP_REGION_EDITION_REV1) { - printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_REGION_EDITION_REV1)); - return NULL; - } - - ipnum = _GeoIP_lookupaddress_v6(name); - if (__GEOIP_V6_IS_NULL(ipnum)) - return NULL; - return _get_region_v6_gl(gi, ipnum, gl); -} - -GeoIPRegion * GeoIP_region_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) { - if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && - gi->databaseType != GEOIP_REGION_EDITION_REV1) { - printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_REGION_EDITION_REV1)); - return NULL; - } - return _get_region_gl(gi, ipnum, gl); -} - -GeoIPRegion * GeoIP_region_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) { - if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && - gi->databaseType != GEOIP_REGION_EDITION_REV1) { - printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType),get_db_description(GEOIP_REGION_EDITION_REV1)); - return NULL; - } - return _get_region_v6_gl(gi, ipnum, gl); -} - -void GeoIPRegion_delete (GeoIPRegion *gir) { - free(gir); +GeoIPRegion * _get_region_v6_gl(GeoIP * gi, geoipv6_t ipnum, GeoIPLookup * gl) +{ + GeoIPRegion * region; + + region = malloc(sizeof(GeoIPRegion)); + if (region) { + GeoIP_assign_region_by_inetaddr_v6_gl(gi, ipnum, region, gl); + } + return region; +} + +GeoIPRegion * GeoIP_region_by_addr_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl) +{ + unsigned long ipnum; + if (addr == NULL) { + return NULL; + } + if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && + gi->databaseType != GEOIP_REGION_EDITION_REV1) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_REGION_EDITION_REV1)); + return NULL; + } + ipnum = GeoIP_addr_to_num(addr); + return _get_region_gl(gi, ipnum, gl); +} + +GeoIPRegion * GeoIP_region_by_addr_v6_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl) +{ + geoipv6_t ipnum; + if (addr == NULL) { + return NULL; + } + if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && + gi->databaseType != GEOIP_REGION_EDITION_REV1) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_REGION_EDITION_REV1)); + return NULL; + } + ipnum = _GeoIP_addr_to_num_v6(addr); + return _get_region_v6_gl(gi, ipnum, gl); +} + +GeoIPRegion * GeoIP_region_by_name_gl(GeoIP * gi, const char *name, + GeoIPLookup * gl) +{ + unsigned long ipnum; + if (name == NULL) { + return NULL; + } + if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && + gi->databaseType != GEOIP_REGION_EDITION_REV1) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_REGION_EDITION_REV1)); + return NULL; + } + if (!(ipnum = _GeoIP_lookupaddress(name))) { + return NULL; + } + return _get_region_gl(gi, ipnum, gl); +} + +GeoIPRegion * GeoIP_region_by_name_v6_gl(GeoIP * gi, const char *name, + GeoIPLookup * gl) +{ + geoipv6_t ipnum; + if (name == NULL) { + return NULL; + } + if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && + gi->databaseType != GEOIP_REGION_EDITION_REV1) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_REGION_EDITION_REV1)); + return NULL; + } + + ipnum = _GeoIP_lookupaddress_v6(name); + if (__GEOIP_V6_IS_NULL(ipnum)) { + return NULL; + } + return _get_region_v6_gl(gi, ipnum, gl); +} + +GeoIPRegion * GeoIP_region_by_ipnum_gl(GeoIP * gi, unsigned long ipnum, + GeoIPLookup * gl) +{ + if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && + gi->databaseType != GEOIP_REGION_EDITION_REV1) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_REGION_EDITION_REV1)); + return NULL; + } + return _get_region_gl(gi, ipnum, gl); +} + +GeoIPRegion * GeoIP_region_by_ipnum_v6_gl(GeoIP * gi, geoipv6_t ipnum, + GeoIPLookup * gl) +{ + if (gi->databaseType != GEOIP_REGION_EDITION_REV0 && + gi->databaseType != GEOIP_REGION_EDITION_REV1) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_REGION_EDITION_REV1)); + return NULL; + } + return _get_region_v6_gl(gi, ipnum, gl); +} + +void GeoIPRegion_delete(GeoIPRegion *gir) +{ + free(gir); } /* GeoIP Organization, ISP and AS Number Edition private method */ static -char *_get_name_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) { - int seek_org; - char buf[MAX_ORG_RECORD_LENGTH]; - char * org_buf, * buf_pointer; - int record_pointer; - size_t len; - ssize_t silence _UNUSED; - - if (gi->databaseType != GEOIP_ORG_EDITION && - gi->databaseType != GEOIP_ISP_EDITION && - gi->databaseType != GEOIP_DOMAIN_EDITION && - gi->databaseType != GEOIP_ASNUM_EDITION && - gi->databaseType != GEOIP_ACCURACYRADIUS_EDITION && - gi->databaseType != GEOIP_NETSPEED_EDITION_REV1 && - gi->databaseType != GEOIP_USERTYPE_EDITION && - gi->databaseType != GEOIP_REGISTRAR_EDITION && - gi->databaseType != GEOIP_LOCATIONA_EDITION && - gi->databaseType != GEOIP_CITYCONF_EDITION && - gi->databaseType != GEOIP_COUNTRYCONF_EDITION && - gi->databaseType != GEOIP_REGIONCONF_EDITION && - gi->databaseType != GEOIP_POSTALCONF_EDITION - ) { - printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_ORG_EDITION)); - return NULL; - } - - seek_org = _GeoIP_seek_record_gl(gi, ipnum, gl); - if (seek_org == gi->databaseSegments[0]) - return NULL; - - record_pointer = seek_org + (2 * gi->record_length - 1) * gi->databaseSegments[0]; - - if (gi->cache == NULL) { - silence = pread(fileno(gi->GeoIPDatabase), buf, MAX_ORG_RECORD_LENGTH, record_pointer); - if ( gi->charset == GEOIP_CHARSET_UTF8 ) { - org_buf = _GeoIP_iso_8859_1__utf8( (const char * ) buf ); - } else { - len = sizeof(char) * (strlen(buf)+1); - org_buf = malloc(len); - strncpy(org_buf, buf, len); - } - } else { - buf_pointer = (char *)(gi->cache + (long)record_pointer); - if ( gi->charset == GEOIP_CHARSET_UTF8 ) { - org_buf = _GeoIP_iso_8859_1__utf8( (const char * ) buf_pointer ); - } else { - len = sizeof(char) * (strlen(buf_pointer)+1); - org_buf = malloc(len); - strncpy(org_buf, buf_pointer, len); - } - } - return org_buf; +char *_get_name_gl(GeoIP * gi, unsigned long ipnum, GeoIPLookup * gl) +{ + unsigned int seek_org; + char buf[MAX_ORG_RECORD_LENGTH]; + char * org_buf, * buf_pointer; + int record_pointer; + size_t len; + + if (gi->databaseType != GEOIP_ORG_EDITION && + gi->databaseType != GEOIP_ISP_EDITION && + gi->databaseType != GEOIP_DOMAIN_EDITION && + gi->databaseType != GEOIP_ASNUM_EDITION && + gi->databaseType != GEOIP_ACCURACYRADIUS_EDITION && + gi->databaseType != GEOIP_NETSPEED_EDITION_REV1 && + gi->databaseType != GEOIP_USERTYPE_EDITION && + gi->databaseType != GEOIP_REGISTRAR_EDITION && + gi->databaseType != GEOIP_LOCATIONA_EDITION && + gi->databaseType != GEOIP_CITYCONF_EDITION && + gi->databaseType != GEOIP_COUNTRYCONF_EDITION && + gi->databaseType != GEOIP_REGIONCONF_EDITION && + gi->databaseType != GEOIP_POSTALCONF_EDITION + ) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_ORG_EDITION)); + return NULL; + } + + seek_org = _GeoIP_seek_record_gl(gi, ipnum, gl); + if (seek_org == gi->databaseSegments[0]) { + return NULL; + } + + record_pointer = seek_org + + (2 * gi->record_length - 1) * gi->databaseSegments[0]; + + if (gi->cache == NULL) { + if (pread(fileno(gi->GeoIPDatabase), buf, MAX_ORG_RECORD_LENGTH, + record_pointer) == -1) { + return NULL; + } + if (gi->charset == GEOIP_CHARSET_UTF8) { + org_buf = _GeoIP_iso_8859_1__utf8( (const char * )buf ); + } else { + len = sizeof(char) * (strlen(buf) + 1); + org_buf = malloc(len); + strncpy(org_buf, buf, len); + } + } else { + buf_pointer = (char *)(gi->cache + (long)record_pointer); + if (gi->charset == GEOIP_CHARSET_UTF8) { + org_buf = _GeoIP_iso_8859_1__utf8( (const char * )buf_pointer ); + } else { + len = sizeof(char) * (strlen(buf_pointer) + 1); + org_buf = malloc(len); + strncpy(org_buf, buf_pointer, len); + } + } + return org_buf; } static -char *_get_name_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) { - int seek_org; - char buf[MAX_ORG_RECORD_LENGTH]; - char * org_buf, * buf_pointer; - int record_pointer; - size_t len; - ssize_t silence _UNUSED; - - if ( - gi->databaseType != GEOIP_ORG_EDITION_V6 && - gi->databaseType != GEOIP_ISP_EDITION_V6 && - gi->databaseType != GEOIP_DOMAIN_EDITION_V6 && - gi->databaseType != GEOIP_ASNUM_EDITION_V6 && - gi->databaseType != GEOIP_ACCURACYRADIUS_EDITION_V6 && - gi->databaseType != GEOIP_NETSPEED_EDITION_REV1_V6 && - gi->databaseType != GEOIP_USERTYPE_EDITION_V6 && - gi->databaseType != GEOIP_REGISTRAR_EDITION_V6 && - gi->databaseType != GEOIP_LOCATIONA_EDITION_V6 - ) { - printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_ORG_EDITION)); - return NULL; - } +char *_get_name_v6_gl(GeoIP * gi, geoipv6_t ipnum, GeoIPLookup * gl) +{ + unsigned int seek_org; + char buf[MAX_ORG_RECORD_LENGTH + 1]; + char * org_buf, * buf_pointer; + int record_pointer; + size_t len; + + if ( + gi->databaseType != GEOIP_ORG_EDITION_V6 && + gi->databaseType != GEOIP_ISP_EDITION_V6 && + gi->databaseType != GEOIP_DOMAIN_EDITION_V6 && + gi->databaseType != GEOIP_ASNUM_EDITION_V6 && + gi->databaseType != GEOIP_ACCURACYRADIUS_EDITION_V6 && + gi->databaseType != GEOIP_NETSPEED_EDITION_REV1_V6 && + gi->databaseType != GEOIP_USERTYPE_EDITION_V6 && + gi->databaseType != GEOIP_REGISTRAR_EDITION_V6 && + gi->databaseType != GEOIP_LOCATIONA_EDITION_V6 + ) { + printf("Invalid database type %s, expected %s\n", + get_db_description(gi->databaseType), + get_db_description(GEOIP_ORG_EDITION)); + return NULL; + } - seek_org = _GeoIP_seek_record_v6_gl(gi, ipnum, gl); - if (seek_org == gi->databaseSegments[0]) - return NULL; + seek_org = _GeoIP_seek_record_v6_gl(gi, ipnum, gl); + if (seek_org == gi->databaseSegments[0]) { + return NULL; + } - record_pointer = seek_org + (2 * gi->record_length - 1) * gi->databaseSegments[0]; + record_pointer = seek_org + + (2 * gi->record_length - 1) * gi->databaseSegments[0]; - if (gi->cache == NULL) { - silence = pread(fileno(gi->GeoIPDatabase), buf, MAX_ORG_RECORD_LENGTH, record_pointer); - if ( gi->charset == GEOIP_CHARSET_UTF8 ) { - org_buf = _GeoIP_iso_8859_1__utf8( (const char * ) buf ); - } else { - len = sizeof(char) * (strlen(buf)+1); - org_buf = malloc(len); - strncpy(org_buf, buf, len); - } - } else { - buf_pointer = (char *)(gi->cache + (long)record_pointer); - if ( gi->charset == GEOIP_CHARSET_UTF8 ) { - org_buf = _GeoIP_iso_8859_1__utf8( (const char * ) buf_pointer ); + if (gi->cache == NULL) { + if (pread(fileno(gi->GeoIPDatabase), buf, MAX_ORG_RECORD_LENGTH, + record_pointer) == -1) { + return NULL; + } + buf[MAX_ORG_RECORD_LENGTH] = 0; + if (gi->charset == GEOIP_CHARSET_UTF8) { + org_buf = _GeoIP_iso_8859_1__utf8( (const char * )buf ); + } else { + len = sizeof(char) * (strlen(buf) + 1); + org_buf = malloc(len); + strncpy(org_buf, buf, len); + } } else { - len = sizeof(char) * (strlen(buf_pointer)+1); - org_buf = malloc(len); - strncpy(org_buf, buf_pointer, len); - } - } - return org_buf; -} - -char * GeoIP_num_to_addr (unsigned long ipnum) { - char *ret_str; - char *cur_str; - int octet[4]; - int num_chars_written, i; - - ret_str = malloc(sizeof(char) * 16); - cur_str = ret_str; - - for (i = 0; i<4; i++) { - octet[3 - i] = ipnum % 256; - ipnum >>= 8; - } - - for (i = 0; i<4; i++) { - num_chars_written = sprintf(cur_str, "%d", octet[i]); - cur_str += num_chars_written; - - if (i < 3) { - cur_str[0] = '.'; - cur_str++; - } - } - - return ret_str; -} - -char **GeoIP_range_by_ip_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) { - unsigned long ipnum; - unsigned long left_seek; - unsigned long right_seek; - unsigned long mask; - int orig_netmask; - int target_value; - char **ret; - GeoIPLookup t; - - if (addr == NULL) { - return NULL; - } - - ret = malloc(sizeof(char *) * 2); - - ipnum = GeoIP_addr_to_num(addr); - target_value = _GeoIP_seek_record_gl(gi, ipnum, gl); - orig_netmask = gl->netmask; - mask = 0xffffffff << ( 32 - orig_netmask ); - left_seek = ipnum & mask; - right_seek = left_seek + ( 0xffffffff & ~mask ); - - while (left_seek != 0 - && target_value == _GeoIP_seek_record_gl(gi, left_seek - 1, &t) ) { - - /* Go to beginning of netblock defined by netmask */ - mask = 0xffffffff << ( 32 - t.netmask ); - left_seek = ( left_seek - 1 ) & mask; - } - ret[0] = GeoIP_num_to_addr(left_seek); - - while (right_seek != 0xffffffff - && target_value == _GeoIP_seek_record_gl(gi, right_seek + 1, &t) ) { - - /* Go to end of netblock defined by netmask */ - mask = 0xffffffff << ( 32 - t.netmask ); - right_seek = ( right_seek + 1 ) & mask; - right_seek += 0xffffffff & ~mask; - } - ret[1] = GeoIP_num_to_addr(right_seek); - - gi->netmask = orig_netmask; - - return ret; -} -void GeoIP_range_by_ip_delete( char ** ptr ){ - if ( ptr ){ - if ( ptr[0] ) - free(ptr[0]); - if ( ptr[1] ) - free(ptr[1]); - free(ptr); - } -} - -char *GeoIP_name_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) { - return _get_name_gl(gi,ipnum, gl); -} - -char *GeoIP_name_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) { - return _get_name_v6_gl(gi,ipnum, gl); -} - -char *GeoIP_name_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) { - unsigned long ipnum; - if (addr == NULL) { - return NULL; - } - ipnum = GeoIP_addr_to_num(addr); - return _get_name_gl(gi, ipnum, gl); -} - -char *GeoIP_name_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) { - geoipv6_t ipnum; - if (addr == NULL) { - return NULL; - } - ipnum = _GeoIP_addr_to_num_v6(addr); - return _get_name_v6_gl(gi, ipnum, gl); + buf_pointer = (char *)(gi->cache + (long)record_pointer); + if (gi->charset == GEOIP_CHARSET_UTF8) { + org_buf = _GeoIP_iso_8859_1__utf8( (const char * )buf_pointer ); + } else { + len = sizeof(char) * (strlen(buf_pointer) + 1); + org_buf = malloc(len); + strncpy(org_buf, buf_pointer, len); + } + } + return org_buf; } -char *GeoIP_name_by_name_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) { - unsigned long ipnum; - if (name == NULL) { - return NULL; - } - if (!(ipnum = _GeoIP_lookupaddress(name))) - return NULL; - return _get_name_gl(gi, ipnum, gl); +char * GeoIP_num_to_addr(unsigned long ipnum) +{ + char *ret_str; + char *cur_str; + int octet[4]; + int num_chars_written, i; + + ret_str = malloc(sizeof(char) * 16); + cur_str = ret_str; + + for (i = 0; i < 4; i++) { + octet[3 - i] = ipnum % 256; + ipnum >>= 8; + } + + for (i = 0; i < 4; i++) { + num_chars_written = sprintf(cur_str, "%d", octet[i]); + cur_str += num_chars_written; + + if (i < 3) { + cur_str[0] = '.'; + cur_str++; + } + } + + return ret_str; } -char *GeoIP_name_by_name_v6_gl (GeoIP* gi, const char *name, GeoIPLookup *gl) { - geoipv6_t ipnum; - if (name == NULL) { - return NULL; - } - ipnum = _GeoIP_lookupaddress_v6(name); - if (__GEOIP_V6_IS_NULL(ipnum)) - return NULL; - return _get_name_v6_gl(gi, ipnum, gl); +char **GeoIP_range_by_ip_gl(GeoIP * gi, const char *addr, GeoIPLookup * gl) +{ + unsigned long ipnum; + unsigned long left_seek; + unsigned long right_seek; + unsigned long mask; + int orig_netmask; + unsigned int target_value; + char **ret; + GeoIPLookup t; + + if (addr == NULL) { + return NULL; + } + + ret = malloc(sizeof(char *) * 2); + + ipnum = GeoIP_addr_to_num(addr); + target_value = _GeoIP_seek_record_gl(gi, ipnum, gl); + orig_netmask = gl->netmask; + mask = 0xffffffff << ( 32 - orig_netmask ); + left_seek = ipnum & mask; + right_seek = left_seek + ( 0xffffffff & ~mask ); + + while (left_seek != 0 + && target_value == _GeoIP_seek_record_gl(gi, left_seek - 1, &t) ) { + + /* Go to beginning of netblock defined by netmask */ + mask = 0xffffffff << ( 32 - t.netmask ); + left_seek = ( left_seek - 1 ) & mask; + } + ret[0] = GeoIP_num_to_addr(left_seek); + + while (right_seek != 0xffffffff + && target_value == _GeoIP_seek_record_gl(gi, right_seek + 1, &t) ) { + + /* Go to end of netblock defined by netmask */ + mask = 0xffffffff << ( 32 - t.netmask ); + right_seek = ( right_seek + 1 ) & mask; + right_seek += 0xffffffff & ~mask; + } + ret[1] = GeoIP_num_to_addr(right_seek); + + gi->netmask = orig_netmask; + + return ret; +} +void GeoIP_range_by_ip_delete( char ** ptr ) +{ + if (ptr) { + if (ptr[0]) { + free(ptr[0]); + } + if (ptr[1]) { + free(ptr[1]); + } + free(ptr); + } } -unsigned char GeoIP_database_edition (GeoIP* gi) { - return gi->databaseType; +char *GeoIP_name_by_ipnum_gl(GeoIP * gi, unsigned long ipnum, GeoIPLookup * gl) +{ + return _get_name_gl(gi, ipnum, gl); } -int GeoIP_enable_teredo(GeoIP* gi, int true_false){ - unsigned int mask = ( 1U << GEOIP_TEREDO_BIT ); - int b = ( gi->ext_flags & mask ) ? 1 : 0; - gi->ext_flags &= ~mask ; - if ( true_false ) - gi->ext_flags |= true_false; - return b; +char *GeoIP_name_by_ipnum_v6_gl(GeoIP * gi, geoipv6_t ipnum, GeoIPLookup * gl) +{ + return _get_name_v6_gl(gi, ipnum, gl); } -int GeoIP_teredo ( GeoIP* gi ){ - unsigned int mask = ( 1U << GEOIP_TEREDO_BIT ); - return ( gi->ext_flags & mask ) ? 1 : 0; +char *GeoIP_name_by_addr_gl(GeoIP * gi, const char *addr, GeoIPLookup * gl) +{ + unsigned long ipnum; + if (addr == NULL) { + return NULL; + } + ipnum = GeoIP_addr_to_num(addr); + return _get_name_gl(gi, ipnum, gl); +} + +char *GeoIP_name_by_addr_v6_gl(GeoIP * gi, const char *addr, GeoIPLookup * gl) +{ + geoipv6_t ipnum; + if (addr == NULL) { + return NULL; + } + ipnum = _GeoIP_addr_to_num_v6(addr); + return _get_name_v6_gl(gi, ipnum, gl); } -int GeoIP_charset( GeoIP* gi){ - return gi->charset; +char *GeoIP_name_by_name_gl(GeoIP * gi, const char *name, GeoIPLookup * gl) +{ + unsigned long ipnum; + if (name == NULL) { + return NULL; + } + if (!(ipnum = _GeoIP_lookupaddress(name))) { + return NULL; + } + return _get_name_gl(gi, ipnum, gl); } -int GeoIP_set_charset( GeoIP* gi, int charset ){ - int old_charset = gi->charset; - gi->charset = charset; - return old_charset; +char *GeoIP_name_by_name_v6_gl(GeoIP * gi, const char *name, GeoIPLookup *gl) +{ + geoipv6_t ipnum; + if (name == NULL) { + return NULL; + } + ipnum = _GeoIP_lookupaddress_v6(name); + if (__GEOIP_V6_IS_NULL(ipnum)) { + return NULL; + } + return _get_name_v6_gl(gi, ipnum, gl); +} + +unsigned char GeoIP_database_edition(GeoIP * gi) +{ + return gi->databaseType; +} + +int GeoIP_enable_teredo(GeoIP * gi, int true_false) +{ + unsigned int mask = ( 1U << GEOIP_TEREDO_BIT ); + int b = ( gi->ext_flags & mask ) ? 1 : 0; + gi->ext_flags &= ~mask; + if (true_false) { + gi->ext_flags |= true_false; + } + return b; +} + +int GeoIP_teredo( GeoIP * gi ) +{ + unsigned int mask = ( 1U << GEOIP_TEREDO_BIT ); + return ( gi->ext_flags & mask ) ? 1 : 0; +} + +int GeoIP_charset( GeoIP * gi) +{ + return gi->charset; +} + +int GeoIP_set_charset( GeoIP * gi, int charset ) +{ + int old_charset = gi->charset; + gi->charset = charset; + return old_charset; } /** return two letter country code */ -const char* GeoIP_code_by_id(int id) +const char * GeoIP_code_by_id(int id) { - if (id < 0 || id >= (int) num_GeoIP_countries) - return NULL; + if (id < 0 || id >= (int)num_GeoIP_countries) { + return NULL; + } - return GeoIP_country_code[id]; + return GeoIP_country_code[id]; } /** return three letter country code */ -const char* GeoIP_code3_by_id(int id) +const char * GeoIP_code3_by_id(int id) { - if (id < 0 || id >= (int) num_GeoIP_countries) - return NULL; + if (id < 0 || id >= (int)num_GeoIP_countries) { + return NULL; + } - return GeoIP_country_code3[id]; + return GeoIP_country_code3[id]; } /** return full name of country in utf8 or iso-8859-1 */ -const char* GeoIP_country_name_by_id(GeoIP * gi, int id) +const char * GeoIP_country_name_by_id(GeoIP * gi, int id) { - /* return NULL also even for index 0 for backward compatibility */ - if (id <= 0 || id >= (int) num_GeoIP_countries) - return NULL; - return ((gi->charset == GEOIP_CHARSET_UTF8) - ? GeoIP_utf8_country_name[id] - : GeoIP_country_name[id]); + /* return NULL also even for index 0 for backward compatibility */ + if (id <= 0 || id >= (int)num_GeoIP_countries) { + return NULL; + } + return (gi->charset == GEOIP_CHARSET_UTF8) + ? GeoIP_utf8_country_name[id] + : GeoIP_country_name[id]; } /** return full name of country in iso-8859-1 */ -const char* GeoIP_name_by_id(int id) +const char * GeoIP_name_by_id(int id) { - if (id < 0 || id >= (int) num_GeoIP_countries) - return NULL; + if (id < 0 || id >= (int)num_GeoIP_countries) { + return NULL; + } - return GeoIP_country_name[id]; + return GeoIP_country_name[id]; } /** return continent of country */ -const char* GeoIP_continent_by_id(int id) +const char * GeoIP_continent_by_id(int id) { - if (id < 0 || id >= (int) num_GeoIP_countries) - return NULL; + if (id < 0 || id >= (int)num_GeoIP_countries) { + return NULL; + } - return GeoIP_country_continent[id]; + return GeoIP_country_continent[id]; } /** return id by country code **/ int GeoIP_id_by_code(const char *country) { - unsigned i; + unsigned i; - for ( i = 0; i < num_GeoIP_countries; ++i) - { - if (strcmp(country, GeoIP_country_code[i]) == 0) - return i; - } + for (i = 0; i < num_GeoIP_countries; ++i) { + if (strcmp(country, GeoIP_country_code[i]) == 0) { + return i; + } + } - return 0; + return 0; } unsigned GeoIP_num_countries(void) { - return num_GeoIP_countries; + return num_GeoIP_countries; } const char * GeoIP_lib_version(void) { - return PACKAGE_VERSION; + return PACKAGE_VERSION; } int GeoIP_cleanup(void) { - int i, result = 0; - if (GeoIPDBFileName) { + int i, result = 0; + char **tmpGeoIPDBFileName = GeoIPDBFileName; + + GeoIPDBFileName = NULL; - for (i = 0; i < NUM_DB_TYPES; i++) { - if (GeoIPDBFileName[i]) free(GeoIPDBFileName[i]); - } + if (tmpGeoIPDBFileName) { + for (i = 0; i < NUM_DB_TYPES; i++) { + if (tmpGeoIPDBFileName[i]) { + free(tmpGeoIPDBFileName[i]); + } + } - free(GeoIPDBFileName); - GeoIPDBFileName = NULL; - result = 1; - } + free(tmpGeoIPDBFileName); + result = 1; + } - return result; + return result; } - diff --git a/src/mod/libGeoIP/GeoIP.h b/src/mod/libGeoIP/GeoIP.h index 24b65822..9da52507 100644 --- a/src/mod/libGeoIP/GeoIP.h +++ b/src/mod/libGeoIP/GeoIP.h @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ /* GeoIP.h * - * Copyright (C) 2006 MaxMind LLC + * Copyright (C) 2016 MaxMind, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,230 +30,309 @@ extern "C" { #include #include #include -#else /* !defined(_WIN32) */ -#include -#include -#define snprintf _snprintf -#define FILETIME_TO_USEC(ft) (((unsigned __int64) ft.dwHighDateTime << 32 | ft.dwLowDateTime) / 10) -#endif /* !defined(_WIN32) */ - -#include -#include -#include +#else /* !defined(_WIN32) */ +#include +#include +#define FILETIME_TO_USEC(ft) \ + (((unsigned __int64)ft.dwHighDateTime << 32 | \ + ft.dwLowDateTime) / 10) +#endif /* !defined(_WIN32) */ + +#include +#include +#include #include /* for fstat */ -#include /* for fstat */ +#include /* for fstat */ #define SEGMENT_RECORD_LENGTH 3 #define LARGE_SEGMENT_RECORD_LENGTH 4 #define STANDARD_RECORD_LENGTH 3 #define ORG_RECORD_LENGTH 4 #define MAX_RECORD_LENGTH 4 -#define NUM_DB_TYPES (38+1) +#define NUM_DB_TYPES (38 + 1) /* 128 bit address in network order */ typedef struct in6_addr geoipv6_t; - -#define GEOIP_CHKBIT_V6(bit,ptr) (ptr[((127UL - bit) >> 3)] & (1UL << (~(127 - bit) & 7))) + +#define GEOIP_CHKBIT_V6(bit, \ + ptr) (ptr[((127UL - \ + bit) >> 3)] & (1UL << (~(127 - bit) & 7))) typedef struct GeoIPTag { - FILE *GeoIPDatabase; - char *file_path; - unsigned char *cache; - unsigned char *index_cache; - unsigned int *databaseSegments; - char databaseType; - time_t mtime; - int flags; - off_t size; - char record_length; - int charset; /* 0 iso-8859-1 1 utf8 */ - int record_iter; /* used in GeoIP_next_record */ - int netmask; /* netmask of last lookup - set using depth in _GeoIP_seek_record */ - time_t last_mtime_check; - off_t dyn_seg_size; /* currently only used by the cityconfidence database */ - unsigned int ext_flags; /* bit 0 teredo support enabled */ + FILE *GeoIPDatabase; + char *file_path; + unsigned char *cache; + unsigned char *index_cache; + unsigned int *databaseSegments; + char databaseType; + time_t mtime; + int flags; + off_t size; + char record_length; + int charset; /* 0 iso-8859-1 1 utf8 */ + int record_iter; /* used in GeoIP_next_record */ + int netmask; /* netmask of last lookup - set using depth in _GeoIP_seek_record */ + time_t last_mtime_check; + off_t dyn_seg_size; /* currently only used by the cityconfidence database */ + unsigned int ext_flags; /* bit 0 teredo support enabled */ } GeoIP; typedef struct GeoIPLookup { - int netmask; + int netmask; } GeoIPLookup; typedef enum { - GEOIP_TEREDO_BIT = 0 + GEOIP_TEREDO_BIT = 0 } GeoIPExtFlags; typedef enum { - GEOIP_CHARSET_ISO_8859_1 = 0, - GEOIP_CHARSET_UTF8 = 1 + GEOIP_CHARSET_ISO_8859_1 = 0, + GEOIP_CHARSET_UTF8 = 1 } GeoIPCharset; typedef struct GeoIPRegionTag { - char country_code[3]; - char region[3]; + char country_code[3]; + char region[3]; } GeoIPRegion; typedef enum { - GEOIP_STANDARD = 0, - GEOIP_MEMORY_CACHE = 1, - GEOIP_CHECK_CACHE = 2, - GEOIP_INDEX_CACHE = 4, - GEOIP_MMAP_CACHE = 8, + GEOIP_STANDARD = 0, + GEOIP_MEMORY_CACHE = 1, + GEOIP_CHECK_CACHE = 2, + GEOIP_INDEX_CACHE = 4, + GEOIP_MMAP_CACHE = 8, + GEOIP_SILENCE = 16, } GeoIPOptions; typedef enum { - GEOIP_COUNTRY_EDITION = 1, - GEOIP_REGION_EDITION_REV0 = 7, - GEOIP_CITY_EDITION_REV0 = 6, - GEOIP_ORG_EDITION = 5, - GEOIP_ISP_EDITION = 4, - GEOIP_CITY_EDITION_REV1 = 2, - GEOIP_REGION_EDITION_REV1 = 3, - GEOIP_PROXY_EDITION = 8, - GEOIP_ASNUM_EDITION = 9, - GEOIP_NETSPEED_EDITION = 10, - GEOIP_DOMAIN_EDITION = 11, - GEOIP_COUNTRY_EDITION_V6 = 12, - GEOIP_LOCATIONA_EDITION = 13, - GEOIP_ACCURACYRADIUS_EDITION = 14, - GEOIP_CITYCONFIDENCE_EDITION = 15, /* unsupported */ - GEOIP_CITYCONFIDENCEDIST_EDITION = 16, /* unsupported */ - GEOIP_LARGE_COUNTRY_EDITION = 17, - GEOIP_LARGE_COUNTRY_EDITION_V6 = 18, - GEOIP_CITYCONFIDENCEDIST_ISP_ORG_EDITION = 19, /* unsued, but gaps are not allowed */ - GEOIP_CCM_COUNTRY_EDITION =20, /* unsued, but gaps are not allowed */ - GEOIP_ASNUM_EDITION_V6 = 21, - GEOIP_ISP_EDITION_V6 = 22, - GEOIP_ORG_EDITION_V6 = 23, - GEOIP_DOMAIN_EDITION_V6 = 24, - GEOIP_LOCATIONA_EDITION_V6 = 25, - GEOIP_REGISTRAR_EDITION = 26, - GEOIP_REGISTRAR_EDITION_V6 = 27, - GEOIP_USERTYPE_EDITION = 28, - GEOIP_USERTYPE_EDITION_V6 = 29, - GEOIP_CITY_EDITION_REV1_V6 = 30, - GEOIP_CITY_EDITION_REV0_V6 = 31, - GEOIP_NETSPEED_EDITION_REV1 = 32, - GEOIP_NETSPEED_EDITION_REV1_V6 = 33, - GEOIP_COUNTRYCONF_EDITION = 34, - GEOIP_CITYCONF_EDITION = 35, - GEOIP_REGIONCONF_EDITION = 36, - GEOIP_POSTALCONF_EDITION = 37, - GEOIP_ACCURACYRADIUS_EDITION_V6 = 38 + GEOIP_COUNTRY_EDITION = 1, + GEOIP_REGION_EDITION_REV0 = 7, + GEOIP_CITY_EDITION_REV0 = 6, + GEOIP_ORG_EDITION = 5, + GEOIP_ISP_EDITION = 4, + GEOIP_CITY_EDITION_REV1 = 2, + GEOIP_REGION_EDITION_REV1 = 3, + GEOIP_PROXY_EDITION = 8, + GEOIP_ASNUM_EDITION = 9, + GEOIP_NETSPEED_EDITION = 10, + GEOIP_DOMAIN_EDITION = 11, + GEOIP_COUNTRY_EDITION_V6 = 12, + GEOIP_LOCATIONA_EDITION = 13, + GEOIP_ACCURACYRADIUS_EDITION = 14, + GEOIP_CITYCONFIDENCE_EDITION = 15, /* unsupported */ + GEOIP_CITYCONFIDENCEDIST_EDITION = 16, /* unsupported */ + GEOIP_LARGE_COUNTRY_EDITION = 17, + GEOIP_LARGE_COUNTRY_EDITION_V6 = 18, + GEOIP_CITYCONFIDENCEDIST_ISP_ORG_EDITION = 19, /* unsued, but gaps are not allowed */ + GEOIP_CCM_COUNTRY_EDITION = 20, /* unsued, but gaps are not allowed */ + GEOIP_ASNUM_EDITION_V6 = 21, + GEOIP_ISP_EDITION_V6 = 22, + GEOIP_ORG_EDITION_V6 = 23, + GEOIP_DOMAIN_EDITION_V6 = 24, + GEOIP_LOCATIONA_EDITION_V6 = 25, + GEOIP_REGISTRAR_EDITION = 26, + GEOIP_REGISTRAR_EDITION_V6 = 27, + GEOIP_USERTYPE_EDITION = 28, + GEOIP_USERTYPE_EDITION_V6 = 29, + GEOIP_CITY_EDITION_REV1_V6 = 30, + GEOIP_CITY_EDITION_REV0_V6 = 31, + GEOIP_NETSPEED_EDITION_REV1 = 32, + GEOIP_NETSPEED_EDITION_REV1_V6 = 33, + GEOIP_COUNTRYCONF_EDITION = 34, + GEOIP_CITYCONF_EDITION = 35, + GEOIP_REGIONCONF_EDITION = 36, + GEOIP_POSTALCONF_EDITION = 37, + GEOIP_ACCURACYRADIUS_EDITION_V6 = 38 } GeoIPDBTypes; typedef enum { - GEOIP_ANON_PROXY = 1, - GEOIP_HTTP_X_FORWARDED_FOR_PROXY = 2, - GEOIP_HTTP_CLIENT_IP_PROXY = 3, + GEOIP_ANON_PROXY = 1, + GEOIP_HTTP_X_FORWARDED_FOR_PROXY = 2, + GEOIP_HTTP_CLIENT_IP_PROXY = 3, } GeoIPProxyTypes; typedef enum { - GEOIP_UNKNOWN_SPEED = 0, - GEOIP_DIALUP_SPEED = 1, - GEOIP_CABLEDSL_SPEED = 2, - GEOIP_CORPORATE_SPEED = 3, + GEOIP_UNKNOWN_SPEED = 0, + GEOIP_DIALUP_SPEED = 1, + GEOIP_CABLEDSL_SPEED = 2, + GEOIP_CORPORATE_SPEED = 3, } GeoIPNetspeedValues; +#if defined(_WIN32) && !defined(__MINGW32__) +#ifdef GEOIP_EXPORTS +#define GEOIP_API __declspec(dllexport) +#define GEOIP_DATA __declspec(dllexport) +#else +#define GEOIP_DATA __declspec(dllimport) +#define GEOIP_API +#endif /* GEOIP_EXPORTS */ +#else +#define GEOIP_API +#define GEOIP_DATA +#endif + extern char **GeoIPDBFileName; -extern const char * GeoIPDBDescription[NUM_DB_TYPES]; -extern const char *GeoIPCountryDBFileName; -extern const char *GeoIPRegionDBFileName; -extern const char *GeoIPCityDBFileName; -extern const char *GeoIPOrgDBFileName; -extern const char *GeoIPISPDBFileName; -extern const char *GeoIPLocationADBFileName; -extern const char *GeoIPAccuracyRadiusFileName; -extern const char *GeoIPCityConfidenceFileName; +extern GEOIP_DATA const char * GeoIPDBDescription[NUM_DB_TYPES]; +extern GEOIP_DATA const char *GeoIPCountryDBFileName; +extern GEOIP_DATA const char *GeoIPRegionDBFileName; +extern GEOIP_DATA const char *GeoIPCityDBFileName; +extern GEOIP_DATA const char *GeoIPOrgDBFileName; +extern GEOIP_DATA const char *GeoIPISPDBFileName; +extern GEOIP_DATA const char *GeoIPLocationADBFileName; +extern GEOIP_DATA const char *GeoIPAccuracyRadiusFileName; +extern GEOIP_DATA const char *GeoIPCityConfidenceFileName; extern char * GeoIP_custom_directory; /* Warning: do not use those arrays as doing so may break your * program with newer GeoIP versions */ -extern const char GeoIP_country_code[255][3]; -extern const char GeoIP_country_code3[255][4]; -extern const char * GeoIP_country_name[255]; -extern const char * GeoIP_utf8_country_name[255]; -extern const char GeoIP_country_continent[255][3]; - -#ifdef DLL -#define GEOIP_API __declspec(dllexport) -#else -#define GEOIP_API -#endif /* DLL */ +extern GEOIP_DATA const char GeoIP_country_code[256][3]; +extern GEOIP_DATA const char GeoIP_country_code3[256][4]; +extern GEOIP_DATA const char * GeoIP_country_name[256]; +extern GEOIP_DATA const char * GeoIP_utf8_country_name[256]; +extern GEOIP_DATA const char GeoIP_country_continent[256][3]; GEOIP_API void GeoIP_setup_custom_directory(char *dir); -GEOIP_API GeoIP* GeoIP_open_type (int type, int flags); -GEOIP_API GeoIP* GeoIP_new(int flags); -GEOIP_API GeoIP* GeoIP_open(const char * filename, int flags); +GEOIP_API GeoIP * GeoIP_open_type(int type, int flags); +GEOIP_API GeoIP * GeoIP_new(int flags); +GEOIP_API GeoIP * GeoIP_open(const char * filename, int flags); +/* + * WARNING: GeoIP_db_avail() checks for the existence of a database + * file but does not check that it has the requested database revision. + * For database types which have more than one revision (including Region, + * City, and Cityv6), this can lead to unexpected results. Check the + * return value of GeoIP_open_type() to find out whether a particular + * database type is really available. + */ GEOIP_API int GeoIP_db_avail(int type); -GEOIP_API void GeoIP_delete(GeoIP* gi); - -GEOIP_API const char *GeoIP_country_code_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_code_by_name_gl (GeoIP* gi, const char *host, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_code3_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_code3_by_name_gl (GeoIP* gi, const char *host, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_name_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_name_by_name_gl (GeoIP* gi, const char *host, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_name_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_code_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_code3_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl); +GEOIP_API void GeoIP_delete(GeoIP * gi); + +GEOIP_API const char *GeoIP_country_code_by_addr_gl(GeoIP * gi, + const char *addr, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_code_by_name_gl(GeoIP * gi, + const char *host, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_code3_by_addr_gl(GeoIP * gi, + const char *addr, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_code3_by_name_gl(GeoIP * gi, + const char *host, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_name_by_addr_gl(GeoIP * gi, + const char *addr, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_name_by_name_gl(GeoIP * gi, + const char *host, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_name_by_ipnum_gl(GeoIP * gi, + unsigned long ipnum, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_code_by_ipnum_gl(GeoIP * gi, + unsigned long ipnum, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_code3_by_ipnum_gl(GeoIP * gi, + unsigned long ipnum, + GeoIPLookup * gl); /* */ -GEOIP_API const char *GeoIP_country_name_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_code_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_code3_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl); - -GEOIP_API const char *GeoIP_country_code_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_code_by_name_v6_gl (GeoIP* gi, const char *host, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_code3_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_code3_by_name_v6_gl (GeoIP* gi, const char *host, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_name_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl); -GEOIP_API const char *GeoIP_country_name_by_name_v6_gl (GeoIP* gi, const char *host, GeoIPLookup * gl); - -GEOIP_API int GeoIP_id_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl); -GEOIP_API int GeoIP_id_by_name_gl (GeoIP* gi, const char *host, GeoIPLookup * gl); -GEOIP_API int GeoIP_id_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl); - -GEOIP_API int GeoIP_id_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl); -GEOIP_API int GeoIP_id_by_name_v6_gl (GeoIP* gi, const char *host, GeoIPLookup * gl); -GEOIP_API int GeoIP_id_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl); - -GEOIP_API GeoIPRegion * GeoIP_region_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl); -GEOIP_API GeoIPRegion * GeoIP_region_by_name_gl (GeoIP* gi, const char *host, GeoIPLookup * gl); -GEOIP_API GeoIPRegion * GeoIP_region_by_ipnum_gl (GeoIP *gi, unsigned long ipnum, GeoIPLookup * gl); - -GEOIP_API GeoIPRegion * GeoIP_region_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl); -GEOIP_API GeoIPRegion * GeoIP_region_by_name_v6_gl (GeoIP* gi, const char *host, GeoIPLookup * gl); -GEOIP_API GeoIPRegion * GeoIP_region_by_ipnum_v6_gl (GeoIP *gi, geoipv6_t ipnum, GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_name_by_ipnum_v6_gl(GeoIP * gi, + geoipv6_t ipnum, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_code_by_ipnum_v6_gl(GeoIP * gi, + geoipv6_t ipnum, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_code3_by_ipnum_v6_gl(GeoIP * gi, + geoipv6_t ipnum, + GeoIPLookup * gl); + +GEOIP_API const char *GeoIP_country_code_by_addr_v6_gl(GeoIP * gi, + const char *addr, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_code_by_name_v6_gl(GeoIP * gi, + const char *host, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_code3_by_addr_v6_gl(GeoIP * gi, + const char *addr, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_code3_by_name_v6_gl(GeoIP * gi, + const char *host, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_name_by_addr_v6_gl(GeoIP * gi, + const char *addr, + GeoIPLookup * gl); +GEOIP_API const char *GeoIP_country_name_by_name_v6_gl(GeoIP * gi, + const char *host, + GeoIPLookup * gl); + +GEOIP_API int GeoIP_id_by_addr_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl); +GEOIP_API int GeoIP_id_by_name_gl(GeoIP * gi, const char *host, + GeoIPLookup * gl); +GEOIP_API int GeoIP_id_by_ipnum_gl(GeoIP * gi, unsigned long ipnum, + GeoIPLookup * gl); + +GEOIP_API int GeoIP_id_by_addr_v6_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl); +GEOIP_API int GeoIP_id_by_name_v6_gl(GeoIP * gi, const char *host, + GeoIPLookup * gl); +GEOIP_API int GeoIP_id_by_ipnum_v6_gl(GeoIP * gi, geoipv6_t ipnum, + GeoIPLookup * gl); + +GEOIP_API GeoIPRegion * GeoIP_region_by_addr_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl); +GEOIP_API GeoIPRegion * GeoIP_region_by_name_gl(GeoIP * gi, const char *host, + GeoIPLookup * gl); +GEOIP_API GeoIPRegion * GeoIP_region_by_ipnum_gl(GeoIP *gi, unsigned long ipnum, + GeoIPLookup * gl); + +GEOIP_API GeoIPRegion * GeoIP_region_by_addr_v6_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl); +GEOIP_API GeoIPRegion * GeoIP_region_by_name_v6_gl(GeoIP * gi, const char *host, + GeoIPLookup * gl); +GEOIP_API GeoIPRegion * GeoIP_region_by_ipnum_v6_gl(GeoIP *gi, geoipv6_t ipnum, + GeoIPLookup * gl); /* Warning - don't call this after GeoIP_assign_region_by_inetaddr calls */ -GEOIP_API void GeoIPRegion_delete (GeoIPRegion *gir); +GEOIP_API void GeoIPRegion_delete(GeoIPRegion *gir); -GEOIP_API void GeoIP_assign_region_by_inetaddr_gl(GeoIP* gi, unsigned long inetaddr, GeoIPRegion *gir, GeoIPLookup * gl); -GEOIP_API void GeoIP_assign_region_by_inetaddr_v6_gl(GeoIP* gi, geoipv6_t inetaddr, GeoIPRegion *gir, GeoIPLookup * gl); +GEOIP_API void GeoIP_assign_region_by_inetaddr_gl(GeoIP * gi, + unsigned long inetaddr, + GeoIPRegion *gir, + GeoIPLookup * gl); +GEOIP_API void GeoIP_assign_region_by_inetaddr_v6_gl(GeoIP * gi, + geoipv6_t inetaddr, + GeoIPRegion *gir, + GeoIPLookup * gl); /* Used to query GeoIP Organization, ISP and AS Number databases */ -GEOIP_API char *GeoIP_name_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl); -GEOIP_API char *GeoIP_name_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl); -GEOIP_API char *GeoIP_name_by_name_gl (GeoIP* gi, const char *host, GeoIPLookup * gl); - -GEOIP_API char *GeoIP_name_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl); -GEOIP_API char *GeoIP_name_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl); -GEOIP_API char *GeoIP_name_by_name_v6_gl (GeoIP* gi, const char *name, GeoIPLookup * gl); +GEOIP_API char *GeoIP_name_by_ipnum_gl(GeoIP * gi, unsigned long ipnum, + GeoIPLookup * gl); +GEOIP_API char *GeoIP_name_by_addr_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl); +GEOIP_API char *GeoIP_name_by_name_gl(GeoIP * gi, const char *host, + GeoIPLookup * gl); + +GEOIP_API char *GeoIP_name_by_ipnum_v6_gl(GeoIP * gi, geoipv6_t ipnum, + GeoIPLookup * gl); +GEOIP_API char *GeoIP_name_by_addr_v6_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl); +GEOIP_API char *GeoIP_name_by_name_v6_gl(GeoIP * gi, const char *name, + GeoIPLookup * gl); /** return two letter country code */ -GEOIP_API const char* GeoIP_code_by_id(int id); +GEOIP_API const char * GeoIP_code_by_id(int id); /** return three letter country code */ -GEOIP_API const char* GeoIP_code3_by_id(int id); +GEOIP_API const char * GeoIP_code3_by_id(int id); /** return full name of country in utf8 or iso-8859-1 */ -GEOIP_API const char* GeoIP_country_name_by_id(GeoIP* gi, int id); +GEOIP_API const char * GeoIP_country_name_by_id(GeoIP * gi, int id); /** return full name of country */ -GEOIP_API const char* GeoIP_name_by_id(int id); +GEOIP_API const char * GeoIP_name_by_id(int id); /** return continent of country */ -GEOIP_API const char* GeoIP_continent_by_id(int id); +GEOIP_API const char * GeoIP_continent_by_id(int id); /** return id by country code **/ GEOIP_API int GeoIP_id_by_code(const char *country); @@ -261,22 +340,25 @@ GEOIP_API int GeoIP_id_by_code(const char *country); /** return return number of known countries */ GEOIP_API unsigned GeoIP_num_countries(void); -GEOIP_API char *GeoIP_database_info (GeoIP* gi); -GEOIP_API unsigned char GeoIP_database_edition (GeoIP* gi); +GEOIP_API char *GeoIP_database_info(GeoIP * gi); +GEOIP_API unsigned char GeoIP_database_edition(GeoIP * gi); -GEOIP_API int GeoIP_charset (GeoIP* gi); -GEOIP_API int GeoIP_set_charset (GeoIP* gi, int charset); -GEOIP_API int GeoIP_enable_teredo (GeoIP* gi, int true_false ); -GEOIP_API int GeoIP_teredo (GeoIP* gi ); +GEOIP_API int GeoIP_charset(GeoIP * gi); +GEOIP_API int GeoIP_set_charset(GeoIP * gi, int charset); +GEOIP_API int GeoIP_enable_teredo(GeoIP * gi, int true_false ); +GEOIP_API int GeoIP_teredo(GeoIP * gi ); -GEOIP_API char **GeoIP_range_by_ip_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl); +GEOIP_API char **GeoIP_range_by_ip_gl(GeoIP * gi, const char *addr, + GeoIPLookup * gl); GEOIP_API void GeoIP_range_by_ip_delete(char **ptr); /* Convert region code to region name */ -GEOIP_API const char * GeoIP_region_name_by_code(const char *country_code, const char *region_code); +GEOIP_API const char * GeoIP_region_name_by_code(const char *country_code, + const char *region_code); /* Get timezone from country and region code */ -GEOIP_API const char * GeoIP_time_zone_by_country_and_region(const char *country_code, const char *region_code); +GEOIP_API const char * GeoIP_time_zone_by_country_and_region( + const char *country_code, const char *region_code); /* some v4 helper functions as of 1.4.7 exported to the public API */ GEOIP_API unsigned long GeoIP_addr_to_num(const char *addr); @@ -285,7 +367,7 @@ GEOIP_API char * GeoIP_num_to_addr(unsigned long ipnum); /* Internal function -- convert iso to utf8; return a malloced utf8 string. */ char * _GeoIP_iso_8859_1__utf8(const char * iso); -/* Cleans up memory used to hold file name paths. Returns 1 if successful; otherwise 0. +/* Cleans up memory used to hold file name paths. Returns 1 if successful; otherwise 0. * */ GEOIP_API int GeoIP_cleanup(void); @@ -293,71 +375,87 @@ GEOIP_API int GeoIP_cleanup(void); GEOIP_API const char * GeoIP_lib_version(void); -/* depricated */ -GEOIP_API const char *GeoIP_country_code_by_addr (GeoIP* gi, const char *addr); -GEOIP_API const char *GeoIP_country_code_by_name (GeoIP* gi, const char *host); -GEOIP_API const char *GeoIP_country_code3_by_addr (GeoIP* gi, const char *addr); -GEOIP_API const char *GeoIP_country_code3_by_name (GeoIP* gi, const char *host); -GEOIP_API const char *GeoIP_country_name_by_addr (GeoIP* gi, const char *addr); -GEOIP_API const char *GeoIP_country_name_by_name (GeoIP* gi, const char *host); -GEOIP_API const char *GeoIP_country_name_by_ipnum (GeoIP* gi, unsigned long ipnum); -GEOIP_API const char *GeoIP_country_code_by_ipnum (GeoIP* gi, unsigned long ipnum); -GEOIP_API const char *GeoIP_country_code3_by_ipnum (GeoIP* gi, unsigned long ipnum); - -GEOIP_API const char *GeoIP_country_name_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum); -GEOIP_API const char *GeoIP_country_code_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum); -GEOIP_API const char *GeoIP_country_code3_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum); - -GEOIP_API const char *GeoIP_country_code_by_addr_v6 (GeoIP* gi, const char *addr); -GEOIP_API const char *GeoIP_country_code_by_name_v6 (GeoIP* gi, const char *host); -GEOIP_API const char *GeoIP_country_code3_by_addr_v6 (GeoIP* gi, const char *addr); -GEOIP_API const char *GeoIP_country_code3_by_name_v6 (GeoIP* gi, const char *host); -GEOIP_API const char *GeoIP_country_name_by_addr_v6 (GeoIP* gi, const char *addr); -GEOIP_API const char *GeoIP_country_name_by_name_v6 (GeoIP* gi, const char *host); - -GEOIP_API int GeoIP_id_by_addr (GeoIP* gi, const char *addr); -GEOIP_API int GeoIP_id_by_name (GeoIP* gi, const char *host); -GEOIP_API int GeoIP_id_by_ipnum (GeoIP* gi, unsigned long ipnum); - -GEOIP_API int GeoIP_id_by_addr_v6 (GeoIP* gi, const char *addr); -GEOIP_API int GeoIP_id_by_name_v6 (GeoIP* gi, const char *host); -GEOIP_API int GeoIP_id_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum); - -GEOIP_API GeoIPRegion * GeoIP_region_by_addr (GeoIP* gi, const char *addr); -GEOIP_API GeoIPRegion * GeoIP_region_by_name (GeoIP* gi, const char *host); -GEOIP_API GeoIPRegion * GeoIP_region_by_ipnum (GeoIP *gi, unsigned long ipnum); - -GEOIP_API GeoIPRegion * GeoIP_region_by_addr_v6 (GeoIP* gi, const char *addr); -GEOIP_API GeoIPRegion * GeoIP_region_by_name_v6 (GeoIP* gi, const char *host); -GEOIP_API GeoIPRegion * GeoIP_region_by_ipnum_v6 (GeoIP *gi, geoipv6_t ipnum); - -GEOIP_API void GeoIP_assign_region_by_inetaddr(GeoIP* gi, unsigned long inetaddr, GeoIPRegion *gir); -GEOIP_API void GeoIP_assign_region_by_inetaddr_v6(GeoIP* gi, geoipv6_t inetaddr, GeoIPRegion *gir); - -GEOIP_API char *GeoIP_name_by_ipnum (GeoIP* gi, unsigned long ipnum); -GEOIP_API char *GeoIP_name_by_addr (GeoIP* gi, const char *addr); -GEOIP_API char *GeoIP_name_by_name (GeoIP* gi, const char *host); - -GEOIP_API char *GeoIP_name_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum); -GEOIP_API char *GeoIP_name_by_addr_v6 (GeoIP* gi, const char *addr); -GEOIP_API char *GeoIP_name_by_name_v6 (GeoIP* gi, const char *name); +/* deprecated */ +GEOIP_API const char *GeoIP_country_code_by_addr(GeoIP * gi, const char *addr); +GEOIP_API const char *GeoIP_country_code_by_name(GeoIP * gi, const char *host); +GEOIP_API const char *GeoIP_country_code3_by_addr(GeoIP * gi, const char *addr); +GEOIP_API const char *GeoIP_country_code3_by_name(GeoIP * gi, const char *host); +GEOIP_API const char *GeoIP_country_name_by_addr(GeoIP * gi, const char *addr); +GEOIP_API const char *GeoIP_country_name_by_name(GeoIP * gi, const char *host); +GEOIP_API const char *GeoIP_country_name_by_ipnum(GeoIP * gi, + unsigned long ipnum); +GEOIP_API const char *GeoIP_country_code_by_ipnum(GeoIP * gi, + unsigned long ipnum); +GEOIP_API const char *GeoIP_country_code3_by_ipnum(GeoIP * gi, + unsigned long ipnum); + +GEOIP_API const char *GeoIP_country_name_by_ipnum_v6(GeoIP * gi, + geoipv6_t ipnum); +GEOIP_API const char *GeoIP_country_code_by_ipnum_v6(GeoIP * gi, + geoipv6_t ipnum); +GEOIP_API const char *GeoIP_country_code3_by_ipnum_v6(GeoIP * gi, + geoipv6_t ipnum); + +GEOIP_API const char *GeoIP_country_code_by_addr_v6(GeoIP * gi, + const char *addr); +GEOIP_API const char *GeoIP_country_code_by_name_v6(GeoIP * gi, + const char *host); +GEOIP_API const char *GeoIP_country_code3_by_addr_v6(GeoIP * gi, + const char *addr); +GEOIP_API const char *GeoIP_country_code3_by_name_v6(GeoIP * gi, + const char *host); +GEOIP_API const char *GeoIP_country_name_by_addr_v6(GeoIP * gi, + const char *addr); +GEOIP_API const char *GeoIP_country_name_by_name_v6(GeoIP * gi, + const char *host); + +GEOIP_API int GeoIP_id_by_addr(GeoIP * gi, const char *addr); +GEOIP_API int GeoIP_id_by_name(GeoIP * gi, const char *host); +GEOIP_API int GeoIP_id_by_ipnum(GeoIP * gi, unsigned long ipnum); + +GEOIP_API int GeoIP_id_by_addr_v6(GeoIP * gi, const char *addr); +GEOIP_API int GeoIP_id_by_name_v6(GeoIP * gi, const char *host); +GEOIP_API int GeoIP_id_by_ipnum_v6(GeoIP * gi, geoipv6_t ipnum); + +GEOIP_API GeoIPRegion * GeoIP_region_by_addr(GeoIP * gi, const char *addr); +GEOIP_API GeoIPRegion * GeoIP_region_by_name(GeoIP * gi, const char *host); +GEOIP_API GeoIPRegion * GeoIP_region_by_ipnum(GeoIP *gi, unsigned long ipnum); + +GEOIP_API GeoIPRegion * GeoIP_region_by_addr_v6(GeoIP * gi, const char *addr); +GEOIP_API GeoIPRegion * GeoIP_region_by_name_v6(GeoIP * gi, const char *host); +GEOIP_API GeoIPRegion * GeoIP_region_by_ipnum_v6(GeoIP *gi, geoipv6_t ipnum); + +GEOIP_API void GeoIP_assign_region_by_inetaddr(GeoIP * gi, + unsigned long inetaddr, + GeoIPRegion *gir); +GEOIP_API void GeoIP_assign_region_by_inetaddr_v6(GeoIP * gi, + geoipv6_t inetaddr, + GeoIPRegion *gir); + +GEOIP_API char *GeoIP_name_by_ipnum(GeoIP * gi, unsigned long ipnum); +GEOIP_API char *GeoIP_name_by_addr(GeoIP * gi, const char *addr); +GEOIP_API char *GeoIP_name_by_name(GeoIP * gi, const char *host); + +GEOIP_API char *GeoIP_name_by_ipnum_v6(GeoIP * gi, geoipv6_t ipnum); +GEOIP_API char *GeoIP_name_by_addr_v6(GeoIP * gi, const char *addr); +GEOIP_API char *GeoIP_name_by_name_v6(GeoIP * gi, const char *name); /** GeoIP_last_netmask is deprecated - it is not thread safe */ -GEOIP_API int GeoIP_last_netmask (GeoIP* gi); -GEOIP_API char **GeoIP_range_by_ip (GeoIP* gi, const char *addr); +GEOIP_API int GeoIP_last_netmask(GeoIP * gi); +GEOIP_API char **GeoIP_range_by_ip(GeoIP * gi, const char *addr); /* Deprecated - for backwards compatibility only */ -GEOIP_API int GeoIP_country_id_by_addr (GeoIP* gi, const char *addr); -GEOIP_API int GeoIP_country_id_by_name (GeoIP* gi, const char *host); -GEOIP_API char *GeoIP_org_by_addr (GeoIP* gi, const char *addr); -GEOIP_API char *GeoIP_org_by_name (GeoIP* gi, const char *host); -GEOIP_API char *GeoIP_org_by_ipnum (GeoIP* gi, unsigned long ipnum); - -GEOIP_API int GeoIP_country_id_by_addr_v6 (GeoIP* gi, const char *addr); -GEOIP_API char *GeoIP_org_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum); -GEOIP_API char *GeoIP_org_by_addr_v6 (GeoIP* gi, const char *addr); -GEOIP_API char *GeoIP_org_by_name_v6 (GeoIP* gi, const char *name); +GEOIP_API int GeoIP_country_id_by_addr(GeoIP * gi, const char *addr); +GEOIP_API int GeoIP_country_id_by_name(GeoIP * gi, const char *host); +GEOIP_API char *GeoIP_org_by_addr(GeoIP * gi, const char *addr); +GEOIP_API char *GeoIP_org_by_name(GeoIP * gi, const char *host); +GEOIP_API char *GeoIP_org_by_ipnum(GeoIP * gi, unsigned long ipnum); + +GEOIP_API int GeoIP_country_id_by_addr_v6(GeoIP * gi, const char *addr); +GEOIP_API char *GeoIP_org_by_ipnum_v6(GeoIP * gi, geoipv6_t ipnum); +GEOIP_API char *GeoIP_org_by_addr_v6(GeoIP * gi, const char *addr); +GEOIP_API char *GeoIP_org_by_name_v6(GeoIP * gi, const char *name); /* End deprecated */ diff --git a/src/mod/libGeoIP/GeoIPCity.c b/src/mod/libGeoIP/GeoIPCity.c index ae377750..88912fc9 100644 --- a/src/mod/libGeoIP/GeoIPCity.c +++ b/src/mod/libGeoIP/GeoIPCity.c @@ -2,7 +2,7 @@ /* * GeoIPCity.c * - * Copyright (C) 2006 MaxMind LLC + * Copyright (C) 2016 MaxMind, Inc. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the @@ -25,307 +25,343 @@ #if !defined(_WIN32) #include #include -#include /* For ntohl */ +#include /* For ntohl */ #else #include #include + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VS 2005+ deprecates fileno, lseek and read +# define fileno _fileno +# define read _read +# define lseek _lseek +#endif #endif -#include /* For uint32_t */ +#include /* For uint32_t */ #ifdef HAVE_STDINT_H -#include /* For uint32_t */ +#include /* For uint32_t */ +#endif + +#if defined(_WIN32) && !defined(__MINGW32__) +#include "pread.h" #endif #ifndef HAVE_PREAD -#define pread(fd, buf, count, offset) \ - ( \ +#define pread(fd, buf, count, offset) \ + ( \ lseek(fd, offset, SEEK_SET) == offset ? \ - read(fd, buf, count) : \ - -1 \ - ) + read(fd, buf, count) : \ + -1 \ + ) #endif /* HAVE_PREAD */ static -const int FULL_RECORD_LENGTH = 50; +const int FULL_RECORD_LENGTH = 50; static -GeoIPRecord * +GeoIPRecord * _extract_record(GeoIP * gi, unsigned int seek_record, int *next_record_ptr) { - int record_pointer; - unsigned char *record_buf = NULL; - unsigned char *begin_record_buf = NULL; - GeoIPRecord *record; - int str_length = 0; - int j; - double latitude = 0, longitude = 0; - int metroarea_combo = 0; - int bytes_read = 0; - if (seek_record == gi->databaseSegments[0]) - return NULL; - - record = malloc(sizeof(GeoIPRecord)); - memset(record, 0, sizeof(GeoIPRecord)); - record->charset = gi->charset; - - record_pointer = seek_record + (2 * gi->record_length - 1) * gi->databaseSegments[0]; + int record_pointer; + unsigned char *record_buf = NULL; + unsigned char *begin_record_buf = NULL; + GeoIPRecord *record; + int str_length = 0; + int j; + double latitude = 0, longitude = 0; + int metroarea_combo = 0; + int bytes_read = 0; + if (seek_record == gi->databaseSegments[0]) { + return NULL; + } + + record = malloc(sizeof(GeoIPRecord)); + memset(record, 0, sizeof(GeoIPRecord)); + record->charset = gi->charset; + + record_pointer = seek_record + + (2 * gi->record_length - 1) * gi->databaseSegments[0]; if (gi->cache == NULL) { - begin_record_buf = record_buf = malloc(sizeof(char) * FULL_RECORD_LENGTH); - bytes_read = pread(fileno(gi->GeoIPDatabase), record_buf, FULL_RECORD_LENGTH, record_pointer); - if (bytes_read == 0) { - /* eof or other error */ - free(begin_record_buf); - free(record); - return NULL; - } + begin_record_buf = record_buf = malloc( + sizeof(unsigned char) * FULL_RECORD_LENGTH); + bytes_read = pread(fileno( + gi->GeoIPDatabase), record_buf, + FULL_RECORD_LENGTH, record_pointer); + if (bytes_read <= 0) { + /* eof or other error */ + free(begin_record_buf); + free(record); + return NULL; + } + }else { + if (gi->size <= record_pointer) { + /* such record does not exists in the cache */ + free(record); + return NULL; + } + record_buf = gi->cache + (long)record_pointer; + } + + /* get country */ + record->continent_code = (char *)GeoIP_country_continent[record_buf[0]]; + record->country_code = (char *)GeoIP_country_code[record_buf[0]]; + record->country_code3 = (char *)GeoIP_country_code3[record_buf[0]]; + record->country_name = (char *)GeoIP_country_name_by_id(gi, record_buf[0]); + record_buf++; + + /* get region */ + while (record_buf[str_length] != '\0') { + str_length++; + } + if (str_length > 0) { + record->region = malloc(str_length + 1); + strncpy(record->region, (char *)record_buf, str_length + 1); } - else { - record_buf = gi->cache + (long) record_pointer; + record_buf += str_length + 1; + str_length = 0; + + /* get city */ + while (record_buf[str_length] != '\0') { + str_length++; + } + if (str_length > 0) { + if (gi->charset == GEOIP_CHARSET_UTF8) { + record->city = _GeoIP_iso_8859_1__utf8((const char *)record_buf); + }else { + record->city = malloc(str_length + 1); + strncpy(record->city, (const char *)record_buf, str_length + 1); + } } + record_buf += (str_length + 1); + str_length = 0; - /* get country */ - record->continent_code = (char *) GeoIP_country_continent[record_buf[0]]; - record->country_code = (char *) GeoIP_country_code[record_buf[0]]; - record->country_code3 = (char *) GeoIP_country_code3[record_buf[0]]; - record->country_name = (char *) GeoIP_country_name_by_id(gi, record_buf[0]); - record_buf++; - - /* get region */ - while (record_buf[str_length] != '\0') - str_length++; - if (str_length > 0) { - record->region = malloc(str_length + 1); - strncpy(record->region, (char *) record_buf, str_length + 1); - } - record_buf += str_length + 1; - str_length = 0; - - /* get city */ - while (record_buf[str_length] != '\0') - str_length++; - if (str_length > 0) { - if (gi->charset == GEOIP_CHARSET_UTF8) { - record->city = _GeoIP_iso_8859_1__utf8((const char *) record_buf); + /* get postal code */ + while (record_buf[str_length] != '\0') { + str_length++; } - else { - record->city = malloc(str_length + 1); - strncpy(record->city, (const char *) record_buf, str_length + 1); + if (str_length > 0) { + record->postal_code = malloc(str_length + 1); + strncpy(record->postal_code, (char *)record_buf, str_length + 1); } - } - record_buf += (str_length + 1); - str_length = 0; - - /* get postal code */ - while (record_buf[str_length] != '\0') - str_length++; - if (str_length > 0) { - record->postal_code = malloc(str_length + 1); - strncpy(record->postal_code, (char *) record_buf, str_length + 1); - } - record_buf += (str_length + 1); - - /* get latitude */ - for (j = 0; j < 3; ++j) - latitude += (record_buf[j] << (j * 8)); - record->latitude = latitude / 10000 - 180; - record_buf += 3; - - /* get longitude */ - for (j = 0; j < 3; ++j) - longitude += (record_buf[j] << (j * 8)); - record->longitude = longitude / 10000 - 180; - - /* - * get area code and metro code for post April 2002 databases and for US - * locations - */ - if (GEOIP_CITY_EDITION_REV1 == gi->databaseType) { - if (!strcmp(record->country_code, "US")) { - record_buf += 3; - for (j = 0; j < 3; ++j) - metroarea_combo += (record_buf[j] << (j * 8)); - record->metro_code = metroarea_combo / 1000; - record->area_code = metroarea_combo % 1000; + record_buf += (str_length + 1); + + /* get latitude */ + for (j = 0; j < 3; ++j) { + latitude += (record_buf[j] << (j * 8)); } - } + record->latitude = (float)(latitude / 10000 - 180); + record_buf += 3; - if (gi->cache == NULL) - free(begin_record_buf); + /* get longitude */ + for (j = 0; j < 3; ++j) { + longitude += (record_buf[j] << (j * 8)); + } + record->longitude = (float)(longitude / 10000 - 180); + + /* + * get area code and metro code for post April 2002 databases and for US + * locations + */ + if (GEOIP_CITY_EDITION_REV1 == gi->databaseType) { + if (!strcmp(record->country_code, "US")) { + record_buf += 3; + for (j = 0; j < 3; ++j) { + metroarea_combo += (record_buf[j] << (j * 8)); + } + record->metro_code = metroarea_combo / 1000; + record->area_code = metroarea_combo % 1000; + } + } - /* Used for GeoIP_next_record */ - if (next_record_ptr != NULL) - *next_record_ptr = seek_record + record_buf - begin_record_buf + 3; + if (begin_record_buf != NULL) { + free(begin_record_buf); + } - return record; + /* Used for GeoIP_next_record */ + if (next_record_ptr != NULL) { + *next_record_ptr = seek_record + record_buf - begin_record_buf + 3; + } + + return record; } static -GeoIPRecord * +GeoIPRecord * _get_record_gl(GeoIP * gi, unsigned long ipnum, GeoIPLookup * gl) { - unsigned int seek_record; - GeoIPRecord * r; - if (gi->databaseType != GEOIP_CITY_EDITION_REV0 - && gi->databaseType != GEOIP_CITY_EDITION_REV1) { - printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int) gi->databaseType], GeoIPDBDescription[GEOIP_CITY_EDITION_REV1]); - return NULL; - } - - seek_record = _GeoIP_seek_record_gl(gi, ipnum, gl); - r = _extract_record(gi, seek_record, NULL); - if ( r ) - r->netmask = gl->netmask; - return r; + unsigned int seek_record; + GeoIPRecord * r; + if (gi->databaseType != GEOIP_CITY_EDITION_REV0 + && gi->databaseType != GEOIP_CITY_EDITION_REV1) { + printf("Invalid database type %s, expected %s\n", + GeoIPDBDescription[(int)gi->databaseType], + GeoIPDBDescription[GEOIP_CITY_EDITION_REV1]); + return NULL; + } + + seek_record = _GeoIP_seek_record_gl(gi, ipnum, gl); + r = _extract_record(gi, seek_record, NULL); + if (r) { + r->netmask = gl->netmask; + } + return r; } static -GeoIPRecord * +GeoIPRecord * _get_record(GeoIP * gi, unsigned long ipnum) { - GeoIPLookup gl; - return _get_record_gl(gi, ipnum, &gl); + GeoIPLookup gl; + return _get_record_gl(gi, ipnum, &gl); } static -GeoIPRecord * +GeoIPRecord * _get_record_v6_gl(GeoIP * gi, geoipv6_t ipnum, GeoIPLookup * gl) { - GeoIPRecord * r; - unsigned int seek_record; - if (gi->databaseType != GEOIP_CITY_EDITION_REV0_V6 && - gi->databaseType != GEOIP_CITY_EDITION_REV1_V6) { - printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int) gi->databaseType], GeoIPDBDescription[GEOIP_CITY_EDITION_REV1_V6]); - return NULL; - } - - seek_record = _GeoIP_seek_record_v6_gl(gi, ipnum, gl); - r = _extract_record(gi, seek_record, NULL); - if ( r ) - r->netmask = gl->netmask; - return r; + GeoIPRecord * r; + unsigned int seek_record; + if (gi->databaseType != GEOIP_CITY_EDITION_REV0_V6 && + gi->databaseType != GEOIP_CITY_EDITION_REV1_V6) { + printf("Invalid database type %s, expected %s\n", + GeoIPDBDescription[(int)gi->databaseType], + GeoIPDBDescription[GEOIP_CITY_EDITION_REV1_V6]); + return NULL; + } + + seek_record = _GeoIP_seek_record_v6_gl(gi, ipnum, gl); + r = _extract_record(gi, seek_record, NULL); + if (r) { + r->netmask = gl->netmask; + } + return r; } static -GeoIPRecord * +GeoIPRecord * _get_record_v6(GeoIP * gi, geoipv6_t ipnum) { - GeoIPLookup gl; - return _get_record_v6_gl(gi, ipnum, &gl); + GeoIPLookup gl; + return _get_record_v6_gl(gi, ipnum, &gl); } -GeoIPRecord * +GeoIPRecord * GeoIP_record_by_ipnum(GeoIP * gi, unsigned long ipnum) { - return _get_record(gi, ipnum); + return _get_record(gi, ipnum); } -GeoIPRecord * +GeoIPRecord * GeoIP_record_by_ipnum_v6(GeoIP * gi, geoipv6_t ipnum) { - return _get_record_v6(gi, ipnum); + return _get_record_v6(gi, ipnum); } -GeoIPRecord * +GeoIPRecord * GeoIP_record_by_addr(GeoIP * gi, const char *addr) { - unsigned long ipnum; - GeoIPLookup gl; - if (addr == NULL) { - return 0; - } - ipnum = GeoIP_addr_to_num(addr); - return _get_record_gl(gi, ipnum, &gl); + unsigned long ipnum; + GeoIPLookup gl; + if (addr == NULL) { + return 0; + } + ipnum = GeoIP_addr_to_num(addr); + return _get_record_gl(gi, ipnum, &gl); } -GeoIPRecord * +GeoIPRecord * GeoIP_record_by_addr_v6(GeoIP * gi, const char *addr) { - geoipv6_t ipnum; - if (addr == NULL) { - return 0; - } - ipnum = _GeoIP_addr_to_num_v6(addr); - return _get_record_v6(gi, ipnum); + geoipv6_t ipnum; + if (addr == NULL) { + return 0; + } + ipnum = _GeoIP_addr_to_num_v6(addr); + return _get_record_v6(gi, ipnum); } -GeoIPRecord * +GeoIPRecord * GeoIP_record_by_name(GeoIP * gi, const char *name) { - unsigned long ipnum; - if (name == NULL) { - return 0; - } - ipnum = _GeoIP_lookupaddress(name); - return _get_record(gi, ipnum); + unsigned long ipnum; + if (name == NULL) { + return 0; + } + ipnum = _GeoIP_lookupaddress(name); + return _get_record(gi, ipnum); } -GeoIPRecord * +GeoIPRecord * GeoIP_record_by_name_v6(GeoIP * gi, const char *name) { - geoipv6_t ipnum; - if (name == NULL) { - return 0; - } - ipnum = _GeoIP_lookupaddress_v6(name); - return _get_record_v6(gi, ipnum); + geoipv6_t ipnum; + if (name == NULL) { + return 0; + } + ipnum = _GeoIP_lookupaddress_v6(name); + return _get_record_v6(gi, ipnum); } int GeoIP_record_id_by_addr(GeoIP * gi, const char *addr) { - unsigned long ipnum; - if (gi->databaseType != GEOIP_CITY_EDITION_REV0 && - gi->databaseType != GEOIP_CITY_EDITION_REV1) { - printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int) gi->databaseType], GeoIPDBDescription[GEOIP_CITY_EDITION_REV1]); - return 0; - } - if (addr == NULL) { - return 0; - } - ipnum = GeoIP_addr_to_num(addr); - return _GeoIP_seek_record(gi, ipnum); + unsigned long ipnum; + if (gi->databaseType != GEOIP_CITY_EDITION_REV0 && + gi->databaseType != GEOIP_CITY_EDITION_REV1) { + printf("Invalid database type %s, expected %s\n", + GeoIPDBDescription[(int)gi->databaseType], + GeoIPDBDescription[GEOIP_CITY_EDITION_REV1]); + return 0; + } + if (addr == NULL) { + return 0; + } + ipnum = GeoIP_addr_to_num(addr); + return _GeoIP_seek_record(gi, ipnum); } int GeoIP_record_id_by_addr_v6(GeoIP * gi, const char *addr) { - geoipv6_t ipnum; - if (gi->databaseType != GEOIP_CITY_EDITION_REV0_V6 && - gi->databaseType != GEOIP_CITY_EDITION_REV1_V6) { - printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int) gi->databaseType], GeoIPDBDescription[GEOIP_CITY_EDITION_REV1]); - return 0; - } - if (addr == NULL) { - return 0; - } - ipnum = _GeoIP_addr_to_num_v6(addr); - return _GeoIP_seek_record_v6(gi, ipnum); + geoipv6_t ipnum; + if (gi->databaseType != GEOIP_CITY_EDITION_REV0_V6 && + gi->databaseType != GEOIP_CITY_EDITION_REV1_V6) { + printf("Invalid database type %s, expected %s\n", + GeoIPDBDescription[(int)gi->databaseType], + GeoIPDBDescription[GEOIP_CITY_EDITION_REV1]); + return 0; + } + if (addr == NULL) { + return 0; + } + ipnum = _GeoIP_addr_to_num_v6(addr); + return _GeoIP_seek_record_v6(gi, ipnum); } int GeoIP_init_record_iter(GeoIP * gi) { - return gi->databaseSegments[0] + 1; + return gi->databaseSegments[0] + 1; } int GeoIP_next_record(GeoIP * gi, GeoIPRecord ** gir, int *record_iter) { - if (gi->cache != NULL) { - printf("GeoIP_next_record not supported in memory cache mode\n"); - return 1; - } - *gir = _extract_record(gi, *record_iter, record_iter); - return 0; + if (gi->cache != NULL) { + printf("GeoIP_next_record not supported in memory cache mode\n"); + return 1; + } + *gir = _extract_record(gi, *record_iter, record_iter); + return 0; } void GeoIPRecord_delete(GeoIPRecord * gir) { - free(gir->region); - free(gir->city); - free(gir->postal_code); - free(gir); + free(gir->region); + free(gir->city); + free(gir->postal_code); + free(gir); } diff --git a/src/mod/libGeoIP/GeoIPCity.h b/src/mod/libGeoIP/GeoIPCity.h index c91acb83..9dbd60d4 100644 --- a/src/mod/libGeoIP/GeoIPCity.h +++ b/src/mod/libGeoIP/GeoIPCity.h @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ /* GeoIPCity.h * - * Copyright (C) 2006 MaxMind LLC + * Copyright (C) 2016 MaxMind, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,40 +30,41 @@ extern "C" { #define GEOIP_UNKNOWN_CONF ( 0x7f ) typedef struct GeoIPRecordTag { - char *country_code; - char *country_code3; - char *country_name; - char *region; - char *city; - char *postal_code; - float latitude; - float longitude; - union { - int metro_code; /* metro_code is a alias for dma_code */ - int dma_code; - }; - int area_code; - int charset; - char *continent_code; - int netmask; + char *country_code; + char *country_code3; + char *country_name; + char *region; + char *city; + char *postal_code; + float latitude; + float longitude; + union { + int metro_code; /* metro_code is a alias for dma_code */ + int dma_code; + }; + int area_code; + int charset; + char *continent_code; + int netmask; } GeoIPRecord; -GeoIPRecord * GeoIP_record_by_ipnum (GeoIP* gi, unsigned long ipnum); -GeoIPRecord * GeoIP_record_by_addr (GeoIP* gi, const char *addr); -GeoIPRecord * GeoIP_record_by_name (GeoIP* gi, const char *host); +GEOIP_API GeoIPRecord * GeoIP_record_by_ipnum(GeoIP * gi, unsigned long ipnum); +GEOIP_API GeoIPRecord * GeoIP_record_by_addr(GeoIP * gi, const char *addr); +GEOIP_API GeoIPRecord * GeoIP_record_by_name(GeoIP * gi, const char *host); -GeoIPRecord * GeoIP_record_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum); -GeoIPRecord * GeoIP_record_by_addr_v6 (GeoIP* gi, const char *addr); -GeoIPRecord * GeoIP_record_by_name_v6 (GeoIP* gi, const char *host); +GEOIP_API GeoIPRecord * GeoIP_record_by_ipnum_v6(GeoIP * gi, geoipv6_t ipnum); +GEOIP_API GeoIPRecord * GeoIP_record_by_addr_v6(GeoIP * gi, const char *addr); +GEOIP_API GeoIPRecord * GeoIP_record_by_name_v6(GeoIP * gi, const char *host); -int GeoIP_record_id_by_addr (GeoIP* gi, const char *addr); -int GeoIP_record_id_by_addr_v6 (GeoIP* gi, const char *addr); +GEOIP_API int GeoIP_record_id_by_addr(GeoIP * gi, const char *addr); +GEOIP_API int GeoIP_record_id_by_addr_v6(GeoIP * gi, const char *addr); -int GeoIP_init_record_iter (GeoIP* gi); +GEOIP_API int GeoIP_init_record_iter(GeoIP * gi); /* returns 0 on success, 1 on failure */ -int GeoIP_next_record (GeoIP* gi, GeoIPRecord **gir, int *record_iter); +GEOIP_API int GeoIP_next_record(GeoIP * gi, GeoIPRecord **gir, + int *record_iter); -void GeoIPRecord_delete (GeoIPRecord *gir); +GEOIP_API void GeoIPRecord_delete(GeoIPRecord *gir); /* NULL on failure otherwise a malloced string in utf8 */ /* char * GeoIP_iso_8859_1__utf8(const char *); */ diff --git a/src/mod/libGeoIP/GeoIP_deprecated.c b/src/mod/libGeoIP/GeoIP_deprecated.c new file mode 100644 index 00000000..561d55e3 --- /dev/null +++ b/src/mod/libGeoIP/GeoIP_deprecated.c @@ -0,0 +1,354 @@ + +#include "GeoIP_internal.h" + +char * +GeoIP_org_by_ipnum(GeoIP * gi, unsigned long ipnum) +{ + GeoIPLookup gl; + return GeoIP_name_by_ipnum_gl(gi, ipnum, &gl); +} + +char * +GeoIP_org_by_ipnum_v6(GeoIP * gi, geoipv6_t ipnum) +{ + GeoIPLookup gl; + return GeoIP_name_by_ipnum_v6_gl(gi, ipnum, &gl); +} + +char * +GeoIP_org_by_addr(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_name_by_addr_gl(gi, addr, &gl); +} + +char * +GeoIP_org_by_addr_v6(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_name_by_addr_v6_gl(gi, addr, &gl); +} + +char * +GeoIP_org_by_name(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_name_by_name_gl(gi, name, &gl); +} + +char * +GeoIP_org_by_name_v6(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_name_by_name_v6_gl(gi, name, &gl); +} + +int +GeoIP_last_netmask(GeoIP * gi) +{ + return gi->netmask; +} + +unsigned int +_GeoIP_seek_record_v6(GeoIP * gi, geoipv6_t ipnum) +{ + GeoIPLookup gl; + return _GeoIP_seek_record_v6_gl(gi, ipnum, &gl); +} + +unsigned int +_GeoIP_seek_record(GeoIP * gi, unsigned long ipnum) +{ + GeoIPLookup gl; + return _GeoIP_seek_record_gl(gi, ipnum, &gl); +} + +const char * +GeoIP_country_code_by_name_v6(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_country_code_by_name_v6_gl(gi, name, &gl); +} + +const char * +GeoIP_country_code_by_name(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_country_code_by_name_gl(gi, name, &gl); +} + +const char * +GeoIP_country_code3_by_name_v6(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_country_code3_by_name_v6_gl(gi, name, &gl); +} + +const char * +GeoIP_country_code3_by_name(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_country_code3_by_name_gl(gi, name, &gl); +} + +const char * +GeoIP_country_name_by_name_v6(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_country_name_by_name_v6_gl(gi, name, &gl); +} + +const char * +GeoIP_country_name_by_name(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_country_name_by_name_gl(gi, name, &gl); +} + +int +GeoIP_id_by_name(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_id_by_name_gl(gi, name, &gl); +} +int +GeoIP_id_by_name_v6(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_id_by_name_v6_gl(gi, name, &gl); +} + +const char * +GeoIP_country_code_by_addr_v6(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_country_code_by_addr_v6_gl(gi, addr, &gl); +} +const char * +GeoIP_country_code_by_addr(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_country_code_by_addr_gl(gi, addr, &gl); +} + +const char * +GeoIP_country_code3_by_addr_v6(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_country_code3_by_addr_v6_gl(gi, addr, &gl); +} + +const char * +GeoIP_country_code3_by_addr(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_country_code3_by_addr_gl(gi, addr, &gl); +} + +const char * +GeoIP_country_name_by_addr_v6(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_country_name_by_addr_v6_gl(gi, addr, &gl); +} +const char * +GeoIP_country_name_by_addr(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_country_name_by_addr_gl(gi, addr, &gl); +} + +const char * +GeoIP_country_name_by_ipnum(GeoIP * gi, unsigned long ipnum) +{ + GeoIPLookup gl; + return GeoIP_country_name_by_ipnum_gl(gi, ipnum, &gl); +} + +const char * +GeoIP_country_name_by_ipnum_v6(GeoIP * gi, geoipv6_t ipnum) +{ + GeoIPLookup gl; + return GeoIP_country_name_by_ipnum_v6_gl(gi, ipnum, &gl); +} + +const char * +GeoIP_country_code_by_ipnum_v6(GeoIP * gi, geoipv6_t ipnum) +{ + GeoIPLookup gl; + return GeoIP_country_code_by_ipnum_v6_gl(gi, ipnum, &gl); +} + + +const char * +GeoIP_country_code_by_ipnum(GeoIP * gi, unsigned long ipnum) +{ + GeoIPLookup gl; + return GeoIP_country_code_by_ipnum_gl(gi, ipnum, &gl); +} + +const char * +GeoIP_country_code3_by_ipnum(GeoIP * gi, unsigned long ipnum) +{ + GeoIPLookup gl; + return GeoIP_country_code3_by_ipnum_gl(gi, ipnum, &gl); +} + +const char * +GeoIP_country_code3_by_ipnum_v6(GeoIP * gi, geoipv6_t ipnum) +{ + GeoIPLookup gl; + return GeoIP_country_code3_by_ipnum_v6_gl(gi, ipnum, &gl); +} + +int +GeoIP_country_id_by_addr_v6(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_id_by_addr_v6_gl(gi, addr, &gl); +} + +int +GeoIP_country_id_by_addr(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_id_by_addr_gl(gi, addr, &gl); +} +int +GeoIP_country_id_by_name_v6(GeoIP * gi, const char *host) +{ + GeoIPLookup gl; + return GeoIP_id_by_name_v6_gl(gi, host, &gl); +} +int +GeoIP_country_id_by_name(GeoIP * gi, const char *host) +{ + GeoIPLookup gl; + return GeoIP_id_by_name_gl(gi, host, &gl); +} +int +GeoIP_id_by_addr_v6(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_id_by_addr_v6_gl(gi, addr, &gl); +} +int +GeoIP_id_by_addr(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_id_by_addr_gl(gi, addr, &gl); +} + +int +GeoIP_id_by_ipnum_v6(GeoIP * gi, geoipv6_t ipnum) +{ + GeoIPLookup gl; + return GeoIP_id_by_ipnum_v6_gl(gi, ipnum, &gl); +} +int +GeoIP_id_by_ipnum(GeoIP * gi, unsigned long ipnum) +{ + GeoIPLookup gl; + return GeoIP_id_by_ipnum_gl(gi, ipnum, &gl); +} +void +GeoIP_assign_region_by_inetaddr(GeoIP * gi, unsigned long inetaddr, + GeoIPRegion * region) +{ + GeoIPLookup gl; + GeoIP_assign_region_by_inetaddr_gl(gi, inetaddr, region, &gl); +} + +void +GeoIP_assign_region_by_inetaddr_v6(GeoIP * gi, geoipv6_t inetaddr, + GeoIPRegion * region) +{ + GeoIPLookup gl; + GeoIP_assign_region_by_inetaddr_v6_gl(gi, inetaddr, region, &gl); +} + + +GeoIPRegion * +GeoIP_region_by_addr(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_region_by_addr_gl(gi, addr, &gl); +} +GeoIPRegion * +GeoIP_region_by_addr_v6(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_region_by_addr_v6_gl(gi, addr, &gl); +} + +GeoIPRegion * +GeoIP_region_by_name(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_region_by_name_gl(gi, name, &gl); +} +GeoIPRegion * +GeoIP_region_by_name_v6(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_region_by_name_v6_gl(gi, name, &gl); +} + +GeoIPRegion * +GeoIP_region_by_ipnum(GeoIP * gi, unsigned long ipnum) +{ + GeoIPLookup gl; + return GeoIP_region_by_ipnum_gl(gi, ipnum, &gl); +} +GeoIPRegion * +GeoIP_region_by_ipnum_v6(GeoIP * gi, geoipv6_t ipnum) +{ + GeoIPLookup gl; + return GeoIP_region_by_ipnum_v6_gl(gi, ipnum, &gl); +} + +char ** +GeoIP_range_by_ip(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_range_by_ip_gl(gi, addr, &gl); +} + +char * +GeoIP_name_by_ipnum(GeoIP * gi, unsigned long ipnum) +{ + GeoIPLookup gl; + return GeoIP_name_by_ipnum_gl(gi, ipnum, &gl); +} +char * +GeoIP_name_by_ipnum_v6(GeoIP * gi, geoipv6_t ipnum) +{ + GeoIPLookup gl; + return GeoIP_name_by_ipnum_v6_gl(gi, ipnum, &gl); +} +char * +GeoIP_name_by_addr(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_name_by_addr_gl(gi, addr, &gl); +} +char * +GeoIP_name_by_addr_v6(GeoIP * gi, const char *addr) +{ + GeoIPLookup gl; + return GeoIP_name_by_addr_v6_gl(gi, addr, &gl); +} + +char * +GeoIP_name_by_name(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_name_by_name_gl(gi, name, &gl); +} + +char * +GeoIP_name_by_name_v6(GeoIP * gi, const char *name) +{ + GeoIPLookup gl; + return GeoIP_name_by_name_v6_gl(gi, name, &gl); +} diff --git a/src/mod/libGeoIP/GeoIP_internal.h b/src/mod/libGeoIP/GeoIP_internal.h index fc801e57..9a409b45 100644 --- a/src/mod/libGeoIP/GeoIP_internal.h +++ b/src/mod/libGeoIP/GeoIP_internal.h @@ -3,19 +3,21 @@ #include "GeoIP.h" -GEOIP_API unsigned int _GeoIP_seek_record_gl (GeoIP *gi, unsigned long ipnum, GeoIPLookup * gl); -GEOIP_API unsigned int _GeoIP_seek_record_v6_gl (GeoIP *gi, geoipv6_t ipnum, GeoIPLookup * gl); -GEOIP_API geoipv6_t _GeoIP_addr_to_num_v6 (const char *addr); +GEOIP_API unsigned int _GeoIP_seek_record_gl(GeoIP *gi, unsigned long ipnum, + GeoIPLookup * gl); +GEOIP_API unsigned int _GeoIP_seek_record_v6_gl(GeoIP *gi, geoipv6_t ipnum, + GeoIPLookup * gl); +GEOIP_API geoipv6_t _GeoIP_addr_to_num_v6(const char *addr); -GEOIP_API unsigned long _GeoIP_lookupaddress (const char *host); -GEOIP_API geoipv6_t _GeoIP_lookupaddress_v6 (const char *host); +GEOIP_API unsigned long _GeoIP_lookupaddress(const char *host); +GEOIP_API geoipv6_t _GeoIP_lookupaddress_v6(const char *host); GEOIP_API int __GEOIP_V6_IS_NULL(geoipv6_t v6); GEOIP_API void _GeoIP_setup_dbfilename(); GEOIP_API char *_GeoIP_full_path_to(const char *file_name); /* deprecated */ -GEOIP_API unsigned int _GeoIP_seek_record (GeoIP *gi, unsigned long ipnum); -GEOIP_API unsigned int _GeoIP_seek_record_v6 (GeoIP *gi, geoipv6_t ipnum); +GEOIP_API unsigned int _GeoIP_seek_record(GeoIP *gi, unsigned long ipnum); +GEOIP_API unsigned int _GeoIP_seek_record_v6(GeoIP *gi, geoipv6_t ipnum); #endif diff --git a/src/mod/libGeoIP/pread.h b/src/mod/libGeoIP/pread.h new file mode 100644 index 00000000..4e48949e --- /dev/null +++ b/src/mod/libGeoIP/pread.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef _WIN64 +typedef __int64 ssize_t; + +int pread(int fd, void *buf, unsigned int nbyte, __int64 offset); +#else +typedef int ssize_t; + +int pread(int fd, void *buf, unsigned int nbyte, long offset); +#endif + +#define HAVE_PREAD diff --git a/src/mod/sqlite3/sqlite3.c b/src/mod/sqlite3/sqlite3.c index 3b9d703f..aaab2008 100644 --- a/src/mod/sqlite3/sqlite3.c +++ b/src/mod/sqlite3/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.12.1. By combining all the individual C code files into this +** version 3.15.2. 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 @@ -9,7 +9,7 @@ ** ** This file is all you need to compile SQLite. To use SQLite in other ** programs, you need this file and the "sqlite3.h" header file that defines -** the programming interface to the SQLite library. (If you do not have +** the programming interface to the SQLite library. (If you do not have ** the "sqlite3.h" header file at hand, you will find a copy embedded within ** the text of this file. Search for "Begin file sqlite3.h" to find the start ** of the embedded sqlite3.h header file.) Additional code files may be needed @@ -37,8 +37,43 @@ ** Internal interface definitions for SQLite. ** */ -#ifndef _SQLITEINT_H_ -#define _SQLITEINT_H_ +#ifndef SQLITEINT_H +#define SQLITEINT_H + +/* Special Comments: +** +** Some comments have special meaning to the tools that measure test +** coverage: +** +** NO_TEST - The branches on this line are not +** measured by branch coverage. This is +** used on lines of code that actually +** implement parts of coverage testing. +** +** OPTIMIZATION-IF-TRUE - This branch is allowed to alway be false +** and the correct answer is still obtained, +** though perhaps more slowly. +** +** OPTIMIZATION-IF-FALSE - This branch is allowed to alway be true +** and the correct answer is still obtained, +** though perhaps more slowly. +** +** PREVENTS-HARMLESS-OVERREAD - This branch prevents a buffer overread +** that would be harmless and undetectable +** if it did occur. +** +** In all cases, the special comment must be enclosed in the usual +** slash-asterisk...asterisk-slash comment marks, with no spaces between the +** asterisks and the comment text. +*/ + +/* +** Make sure the Tcl calling convention macro is defined. This macro is +** only used by test code and Tcl integration code. +*/ +#ifndef SQLITE_TCLAPI +# define SQLITE_TCLAPI +#endif /* ** Make sure that rand_s() is available on Windows systems with MSVC 2005 @@ -70,8 +105,8 @@ ** ** This file contains code that is specific to MSVC. */ -#ifndef _MSVC_H_ -#define _MSVC_H_ +#ifndef SQLITE_MSVC_H +#define SQLITE_MSVC_H #if defined(_MSC_VER) #pragma warning(disable : 4054) @@ -91,7 +126,7 @@ #pragma warning(disable : 4706) #endif /* defined(_MSC_VER) */ -#endif /* _MSVC_H_ */ +#endif /* SQLITE_MSVC_H */ /************** End of msvc.h ************************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -255,8 +290,8 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. */ -#ifndef _SQLITE3_H_ -#define _SQLITE3_H_ +#ifndef SQLITE3_H +#define SQLITE3_H #include /* Needed for the definition of va_list */ /* @@ -279,8 +314,17 @@ extern "C" { #ifndef SQLITE_CDECL # define SQLITE_CDECL #endif +#ifndef SQLITE_APICALL +# define SQLITE_APICALL +#endif #ifndef SQLITE_STDCALL -# define SQLITE_STDCALL +# define SQLITE_STDCALL SQLITE_APICALL +#endif +#ifndef SQLITE_CALLBACK +# define SQLITE_CALLBACK +#endif +#ifndef SQLITE_SYSAPI +# define SQLITE_SYSAPI #endif /* @@ -324,7 +368,8 @@ extern "C" { ** be held constant and Z will be incremented or else Y will be incremented ** and Z will be reset to zero. ** -** Since version 3.6.18, SQLite source code has been stored in the +** Since [version 3.6.18] ([dateof:3.6.18]), +** SQLite source code has been stored in the ** Fossil configuration management ** system. ^The SQLITE_SOURCE_ID macro evaluates to ** a string which identifies a particular check-in of SQLite @@ -336,9 +381,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.12.1" -#define SQLITE_VERSION_NUMBER 3012001 -#define SQLITE_SOURCE_ID "2016-04-08 15:09:49 fe7d3b75fe1bde41511b323925af8ae1b910bc4d" +#define SQLITE_VERSION "3.15.2" +#define SQLITE_VERSION_NUMBER 3015002 +#define SQLITE_SOURCE_ID "2016-11-28 19:13:37 bbd85d235f7037c6a033a9690534391ffeacecc8" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -371,9 +416,9 @@ extern "C" { ** See also: [sqlite_version()] and [sqlite_source_id()]. */ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; -SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void); -SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void); -SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void); +SQLITE_API const char *sqlite3_libversion(void); +SQLITE_API const char *sqlite3_sourceid(void); +SQLITE_API int sqlite3_libversion_number(void); /* ** CAPI3REF: Run-Time Library Compilation Options Diagnostics @@ -398,8 +443,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void); ** [sqlite_compileoption_get()] and the [compile_options pragma]. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName); -SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N); +SQLITE_API int sqlite3_compileoption_used(const char *zOptName); +SQLITE_API const char *sqlite3_compileoption_get(int N); #endif /* @@ -438,7 +483,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N); ** ** See the [threading mode] documentation for additional information. */ -SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void); +SQLITE_API int sqlite3_threadsafe(void); /* ** CAPI3REF: Database Connection Handle @@ -535,8 +580,8 @@ typedef sqlite_uint64 sqlite3_uint64; ** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer ** argument is a harmless no-op. */ -SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3*); -SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3*); +SQLITE_API int sqlite3_close(sqlite3*); +SQLITE_API int sqlite3_close_v2(sqlite3*); /* ** The type for a callback function. @@ -607,7 +652,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. ** */ -SQLITE_API int SQLITE_STDCALL sqlite3_exec( +SQLITE_API int sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ int (*callback)(void*,int,char**,char**), /* Callback function */ @@ -668,7 +713,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec( ** [result codes]. However, experience has shown that many of ** these result codes are too coarse-grained. They do not provide as ** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 and later) include +** address this, newer versions of SQLite (version 3.3.8 [dateof:3.3.8] +** and later) include ** support for additional result codes that provide more detailed information ** about errors. These [extended result codes] are enabled or disabled ** on a per database connection basis using the @@ -731,6 +777,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec( #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) +#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8)) /* ** CAPI3REF: Flags For File Open Operations @@ -1191,6 +1238,12 @@ struct sqlite3_io_methods { ** on whether or not the file has been renamed, moved, or deleted since it ** was first opened. ** +**
  • [[SQLITE_FCNTL_WIN32_GET_HANDLE]] +** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the +** underlying native file handle associated with a file handle. This file +** control interprets its argument as a pointer to a native file handle and +** writes the resulting value there. +** **
  • [[SQLITE_FCNTL_WIN32_SET_HANDLE]] ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This ** opcode causes the xFileControl method to swap the file handle with the one @@ -1241,6 +1294,7 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_RBU 26 #define SQLITE_FCNTL_VFS_POINTER 27 #define SQLITE_FCNTL_JOURNAL_POINTER 28 +#define SQLITE_FCNTL_WIN32_GET_HANDLE 29 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE @@ -1260,6 +1314,16 @@ struct sqlite3_io_methods { */ typedef struct sqlite3_mutex sqlite3_mutex; +/* +** CAPI3REF: Loadable Extension Thunk +** +** A pointer to the opaque sqlite3_api_routines structure is passed as +** the third parameter to entry points of [loadable extensions]. This +** structure must be typedefed in order to work around compiler warnings +** on some platforms. +*/ +typedef struct sqlite3_api_routines sqlite3_api_routines; + /* ** CAPI3REF: OS Interface Object ** @@ -1595,10 +1659,10 @@ struct sqlite3_vfs { ** must return [SQLITE_OK] on success and some other [error code] upon ** failure. */ -SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void); -SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void); -SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void); -SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); +SQLITE_API int sqlite3_initialize(void); +SQLITE_API int sqlite3_shutdown(void); +SQLITE_API int sqlite3_os_init(void); +SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library @@ -1631,7 +1695,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code]. */ -SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...); +SQLITE_API int sqlite3_config(int, ...); /* ** CAPI3REF: Configure database connections @@ -1650,7 +1714,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...); ** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if ** the call is considered successful. */ -SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3*, int op, ...); +SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); /* ** CAPI3REF: Memory Allocation Routines @@ -2157,12 +2221,40 @@ struct sqlite3_mem_methods { ** following this call. The second parameter may be a NULL pointer, in ** which case the new setting is not reported back. ** +**
    SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
    +**
    ^This option is used to enable or disable the [sqlite3_load_extension()] +** interface independently of the [load_extension()] SQL function. +** The [sqlite3_enable_load_extension()] API enables or disables both the +** C-API [sqlite3_load_extension()] and the SQL function [load_extension()]. +** There should be two additional arguments. +** When the first argument to this interface is 1, then only the C-API is +** enabled and the SQL function remains disabled. If the first argument to +** this interface is 0, then both the C-API and the SQL function are disabled. +** If the first argument is -1, then no changes are made to state of either the +** C-API or the SQL function. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface +** is disabled or enabled following this call. The second parameter may +** be a NULL pointer, in which case the new setting is not reported back. +**
    +** +**
    SQLITE_DBCONFIG_MAINDBNAME
    +**
    ^This option is used to change the name of the "main" database +** schema. ^The sole argument is a pointer to a constant UTF8 string +** which will become the new schema name in place of "main". ^SQLite +** does not make a copy of the new main schema name string, so the application +** must ensure that the argument passed into this DBCONFIG option is unchanged +** until after the database connection closes. +**
    +** ** */ +#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #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* */ /* @@ -2173,7 +2265,7 @@ struct sqlite3_mem_methods { ** [extended result codes] feature of SQLite. ^The extended result ** codes are disabled by default for historical compatibility. */ -SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff); +SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); /* ** CAPI3REF: Last Insert Rowid @@ -2225,7 +2317,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff) ** unpredictable and might not equal either the old or the new ** last insert [rowid]. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*); +SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); /* ** CAPI3REF: Count The Number Of Rows Modified @@ -2278,7 +2370,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*); ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. */ -SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*); +SQLITE_API int sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified @@ -2302,7 +2394,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*); ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. */ -SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*); +SQLITE_API int sqlite3_total_changes(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query @@ -2342,7 +2434,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*); ** If the database connection closes while [sqlite3_interrupt()] ** is running then bad things will likely happen. */ -SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*); +SQLITE_API void sqlite3_interrupt(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete @@ -2377,8 +2469,8 @@ SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*); ** The input to [sqlite3_complete16()] must be a zero-terminated ** UTF-16 string in native byte order. */ -SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *sql); -SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql); +SQLITE_API int sqlite3_complete(const char *sql); +SQLITE_API int sqlite3_complete16(const void *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors @@ -2439,7 +2531,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql); ** A busy handler must not close the database connection ** or [prepared statement] that invoked the busy handler. */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); +SQLITE_API int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*); /* ** CAPI3REF: Set A Busy Timeout @@ -2462,7 +2554,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*, int(*)(void*,int), ** ** See also: [PRAGMA busy_timeout] */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms); +SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); /* ** CAPI3REF: Convenience Routines For Running Queries @@ -2537,7 +2629,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms); ** reflected in subsequent calls to [sqlite3_errcode()] or ** [sqlite3_errmsg()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_table( +SQLITE_API int sqlite3_get_table( sqlite3 *db, /* An open database */ const char *zSql, /* SQL to be evaluated */ char ***pazResult, /* Results of the query */ @@ -2545,7 +2637,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_table( int *pnColumn, /* Number of result columns written here */ char **pzErrmsg /* Error msg written here */ ); -SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); +SQLITE_API void sqlite3_free_table(char **result); /* ** CAPI3REF: Formatted String Printing Functions @@ -2651,10 +2743,10 @@ SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); ** addition that after the string has been read and copied into ** the result, [sqlite3_free()] is called on the input string.)^ */ -SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char*,...); -SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char*, va_list); -SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int,char*,const char*, ...); -SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list); +SQLITE_API char *sqlite3_mprintf(const char*,...); +SQLITE_API char *sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); +SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); /* ** CAPI3REF: Memory Allocation Subsystem @@ -2744,12 +2836,12 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list ** a block of memory after it has been released using ** [sqlite3_free()] or [sqlite3_realloc()]. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int); -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64); -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void*, int); -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void*, sqlite3_uint64); -SQLITE_API void SQLITE_STDCALL sqlite3_free(void*); -SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*); +SQLITE_API void *sqlite3_malloc(int); +SQLITE_API void *sqlite3_malloc64(sqlite3_uint64); +SQLITE_API void *sqlite3_realloc(void*, int); +SQLITE_API void *sqlite3_realloc64(void*, sqlite3_uint64); +SQLITE_API void sqlite3_free(void*); +SQLITE_API sqlite3_uint64 sqlite3_msize(void*); /* ** CAPI3REF: Memory Allocator Statistics @@ -2774,8 +2866,8 @@ SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*); ** by [sqlite3_memory_highwater(1)] is the high-water mark ** prior to the reset. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag); +SQLITE_API sqlite3_int64 sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); /* ** CAPI3REF: Pseudo-Random Number Generator @@ -2798,7 +2890,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag); ** internally and without recourse to the [sqlite3_vfs] xRandomness ** method. */ -SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P); +SQLITE_API void sqlite3_randomness(int N, void *P); /* ** CAPI3REF: Compile-Time Authorization Callbacks @@ -2881,7 +2973,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P); ** as stated in the previous paragraph, sqlite3_step() invokes ** sqlite3_prepare_v2() to reprepare a statement after a schema change. */ -SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( +SQLITE_API int sqlite3_set_authorizer( sqlite3*, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pUserData @@ -2961,6 +3053,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( ** CAPI3REF: Tracing And Profiling Functions ** METHOD: sqlite3 ** +** These routines are deprecated. Use the [sqlite3_trace_v2()] interface +** instead of the routines described here. +** ** These routines register callback functions that can be used for ** tracing and profiling the execution of SQL statements. ** @@ -2986,10 +3081,104 @@ SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( ** sqlite3_profile() function is considered experimental and is ** subject to change in future versions of SQLite. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_profile(sqlite3*, +SQLITE_API SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*, + void(*xTrace)(void*,const char*), void*); +SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, void(*xProfile)(void*,const char*,sqlite3_uint64), void*); +/* +** CAPI3REF: SQL Trace Event Codes +** KEYWORDS: SQLITE_TRACE +** +** These constants identify classes of events that can be monitored +** using the [sqlite3_trace_v2()] tracing logic. The third argument +** to [sqlite3_trace_v2()] is an OR-ed combination of one or more of +** the following constants. ^The first argument to the trace callback +** is one of the following constants. +** +** New tracing constants may be added in future releases. +** +** ^A trace callback has four arguments: xCallback(T,C,P,X). +** ^The T argument is one of the integer type codes above. +** ^The C argument is a copy of the context pointer passed in as the +** fourth argument to [sqlite3_trace_v2()]. +** The P and X arguments are pointers whose meanings depend on T. +** +**
    +** [[SQLITE_TRACE_STMT]]
    SQLITE_TRACE_STMT
    +**
    ^An SQLITE_TRACE_STMT callback is invoked when a prepared statement +** first begins running and possibly at other times during the +** execution of the prepared statement, such as at the start of each +** trigger subprogram. ^The P argument is a pointer to the +** [prepared statement]. ^The X argument is a pointer to a string which +** is the unexpanded SQL text of the prepared statement or an SQL comment +** that indicates the invocation of a trigger. ^The callback can compute +** the same text that would have been returned by the legacy [sqlite3_trace()] +** interface by using the X argument when X begins with "--" and invoking +** [sqlite3_expanded_sql(P)] otherwise. +** +** [[SQLITE_TRACE_PROFILE]]
    SQLITE_TRACE_PROFILE
    +**
    ^An SQLITE_TRACE_PROFILE callback provides approximately the same +** information as is provided by the [sqlite3_profile()] callback. +** ^The P argument is a pointer to the [prepared statement] and the +** X argument points to a 64-bit integer which is the estimated of +** the number of nanosecond that the prepared statement took to run. +** ^The SQLITE_TRACE_PROFILE callback is invoked when the statement finishes. +** +** [[SQLITE_TRACE_ROW]]
    SQLITE_TRACE_ROW
    +**
    ^An SQLITE_TRACE_ROW callback is invoked whenever a prepared +** statement generates a single row of result. +** ^The P argument is a pointer to the [prepared statement] and the +** X argument is unused. +** +** [[SQLITE_TRACE_CLOSE]]
    SQLITE_TRACE_CLOSE
    +**
    ^An SQLITE_TRACE_CLOSE callback is invoked when a database +** connection closes. +** ^The P argument is a pointer to the [database connection] object +** and the X argument is unused. +**
    +*/ +#define SQLITE_TRACE_STMT 0x01 +#define SQLITE_TRACE_PROFILE 0x02 +#define SQLITE_TRACE_ROW 0x04 +#define SQLITE_TRACE_CLOSE 0x08 + +/* +** CAPI3REF: SQL Trace Hook +** METHOD: sqlite3 +** +** ^The sqlite3_trace_v2(D,M,X,P) interface registers a trace callback +** function X against [database connection] D, using property mask M +** and context pointer P. ^If the X callback is +** NULL or if the M mask is zero, then tracing is disabled. The +** M argument should be the bitwise OR-ed combination of +** zero or more [SQLITE_TRACE] constants. +** +** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides +** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2(). +** +** ^The X callback is invoked whenever any of the events identified by +** mask M occur. ^The integer return value from the callback is currently +** ignored, though this may change in future releases. Callback +** implementations should return zero to ensure future compatibility. +** +** ^A trace callback is invoked with four arguments: callback(T,C,P,X). +** ^The T argument is one of the [SQLITE_TRACE] +** constants to indicate why the callback was invoked. +** ^The C argument is a copy of the context pointer. +** The P and X arguments are pointers whose meanings depend on T. +** +** The sqlite3_trace_v2() interface is intended to replace the legacy +** interfaces [sqlite3_trace()] and [sqlite3_profile()], both of which +** are deprecated. +*/ +SQLITE_API int sqlite3_trace_v2( + sqlite3*, + unsigned uMask, + int(*xCallback)(unsigned,void*,void*,void*), + void *pCtx +); + /* ** CAPI3REF: Query Progress Callbacks ** METHOD: sqlite3 @@ -3022,7 +3211,7 @@ SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_profile(sqlite3*, ** database connections for the meaning of "modify" in this paragraph. ** */ -SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); +SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); /* ** CAPI3REF: Opening A New Database Connection @@ -3251,15 +3440,15 @@ SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(vo ** ** See also: [sqlite3_temp_directory] */ -SQLITE_API int SQLITE_STDCALL sqlite3_open( +SQLITE_API int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_open16( +SQLITE_API int sqlite3_open16( const void *filename, /* Database filename (UTF-16) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( +SQLITE_API int sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ @@ -3305,9 +3494,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( ** VFS method, then the behavior of this routine is undefined and probably ** undesirable. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam); -SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const char*, sqlite3_int64); +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); /* @@ -3351,11 +3540,11 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const cha ** was invoked incorrectly by the application. In that case, the ** error code and message may or may not be set. */ -SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db); -SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db); -SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3*); -SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int); +SQLITE_API int sqlite3_errcode(sqlite3 *db); +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *sqlite3_errmsg(sqlite3*); +SQLITE_API const void *sqlite3_errmsg16(sqlite3*); +SQLITE_API const char *sqlite3_errstr(int); /* ** CAPI3REF: Prepared Statement Object @@ -3423,7 +3612,7 @@ typedef struct sqlite3_stmt sqlite3_stmt; ** ** New run-time limit categories may be added in future releases. */ -SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); +SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Run-Time Limit Categories @@ -3575,28 +3764,28 @@ SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); **
  • ** */ -SQLITE_API int SQLITE_STDCALL sqlite3_prepare( +SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2( +SQLITE_API int sqlite3_prepare_v2( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( +SQLITE_API int sqlite3_prepare16( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( +SQLITE_API int sqlite3_prepare16_v2( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ @@ -3608,11 +3797,35 @@ SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( ** CAPI3REF: Retrieving Statement SQL ** METHOD: sqlite3_stmt ** -** ^This interface can be used to retrieve a saved copy of the original -** SQL text used to create a [prepared statement] if that statement was -** compiled using either [sqlite3_prepare_v2()] or [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()]. +** ^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. +** +** ^(For example, if a prepared statement is created using the SQL +** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 +** and parameter :xyz is unbound, then sqlite3_sql() will return +** the original string, "SELECT $abc,:xyz" but sqlite3_expanded_sql() +** will return "SELECT 2345,NULL".)^ +** +** ^The sqlite3_expanded_sql() interface returns NULL if insufficient memory +** is available to hold the result, or if the result would exceed the +** the maximum string length determined by the [SQLITE_LIMIT_LENGTH]. +** +** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of +** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time +** option causes sqlite3_expanded_sql() to always return NULL. +** +** ^The string returned by sqlite3_sql(P) is managed by SQLite and is +** automatically freed when the prepared statement is finalized. +** ^The string returned by sqlite3_expanded_sql(P), on the other hand, +** is obtained from [sqlite3_malloc()] and must be free by the application +** by passing it to [sqlite3_free()]. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt); +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); +SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database @@ -3644,7 +3857,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt); ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset @@ -3665,7 +3878,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt); ** for example, in diagnostic routines to search for prepared ** statements that are holding a transaction open. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt*); +SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); /* ** CAPI3REF: Dynamically Typed Value Object @@ -3829,20 +4042,20 @@ typedef struct sqlite3_context sqlite3_context; ** See also: [sqlite3_bind_parameter_count()], ** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, +SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt*, int, double); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt*, int, int); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, +SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); +SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, void(*)(void*), unsigned char encoding); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); +SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); +SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); /* ** CAPI3REF: Number Of SQL Parameters @@ -3863,7 +4076,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite ** [sqlite3_bind_parameter_name()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*); +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); /* ** CAPI3REF: Name Of A Host Parameter @@ -3891,7 +4104,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*); ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, int); +SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); /* ** CAPI3REF: Index Of A Parameter With A Given Name @@ -3908,7 +4121,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_name()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); /* ** CAPI3REF: Reset All Bindings On A Prepared Statement @@ -3918,7 +4131,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const ** the [sqlite3_bind_blob | bindings] on a [prepared statement]. ** ^Use this routine to reset all host parameters to NULL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*); +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); /* ** CAPI3REF: Number Of Columns In A Result Set @@ -3930,7 +4143,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*); ** ** See also: [sqlite3_data_count()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Column Names In A Result Set @@ -3959,8 +4172,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt); ** then the name of the column is unspecified and may change from ** one release of SQLite to the next. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt*, int N); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N); +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); /* ** CAPI3REF: Source Of Data In A Query Result @@ -4008,12 +4221,12 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N ** for the same [prepared statement] and result column ** at the same time then the results are undefined. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt*,int); -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt*,int); -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); /* ** CAPI3REF: Declared Datatype Of A Query Result @@ -4045,8 +4258,8 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt* ** is associated with individual values, not with the containers ** used to hold those values. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); /* ** CAPI3REF: Evaluate An SQL Statement @@ -4107,7 +4320,8 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,in ** 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, sqlite3_step() began +** 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 ** break because any application that ever receives an SQLITE_MISUSE error @@ -4126,7 +4340,7 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,in ** then the more specific [error codes] are returned directly ** by sqlite3_step(). The use of the "v2" interface is recommended. */ -SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*); +SQLITE_API int sqlite3_step(sqlite3_stmt*); /* ** CAPI3REF: Number of columns in a result set @@ -4147,7 +4361,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*); ** ** See also: [sqlite3_column_count()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Fundamental Datatypes @@ -4337,16 +4551,16 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); ** pointer. Subsequent calls to [sqlite3_errcode()] will return ** [SQLITE_NOMEM].)^ */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt*, int iCol); -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*, int iCol); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int iCol); +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); /* ** CAPI3REF: Destroy A Prepared Statement Object @@ -4374,7 +4588,7 @@ SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int ** statement after it has been finalized can result in undefined and ** undesirable behavior such as segfaults and heap corruption. */ -SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); /* ** CAPI3REF: Reset A Prepared Statement Object @@ -4401,7 +4615,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt); ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ -SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); /* ** CAPI3REF: Create Or Redefine SQL Functions @@ -4501,7 +4715,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt); ** close the database connection nor finalize or reset the prepared ** statement in which the function is running. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_function( +SQLITE_API int sqlite3_create_function( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4511,7 +4725,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( +SQLITE_API int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, @@ -4521,7 +4735,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( +SQLITE_API int sqlite3_create_function_v2( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4567,12 +4781,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( ** these functions, we will not explain what they do. */ #ifndef SQLITE_OMIT_DEPRECATED -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_global_recover(void); -SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_thread_cleanup(void); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), +SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), void*,sqlite3_int64); #endif @@ -4622,18 +4836,18 @@ SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(voi ** These routines must be called from the same thread as ** the SQL function that supplied the [sqlite3_value*] parameters. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value*); -SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value*); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value*); -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*); +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 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_type(sqlite3_value*); +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Finding The Subtype Of SQL Values @@ -4649,7 +4863,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*); ** from the result of one [application-defined SQL function] into the ** input of another. */ -SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value*); +SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); /* ** CAPI3REF: Copy And Free SQL Values @@ -4665,8 +4879,8 @@ SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value*); ** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer ** then sqlite3_value_free(V) is a harmless no-op. */ -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value*); -SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*); +SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value*); +SQLITE_API void sqlite3_value_free(sqlite3_value*); /* ** CAPI3REF: Obtain Aggregate Function Context @@ -4711,7 +4925,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*); ** This routine must be called from the same thread in which ** the aggregate SQL function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int nBytes); +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* ** CAPI3REF: User Data For Functions @@ -4726,7 +4940,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int ** This routine must be called from the same thread in which ** the application-defined function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*); +SQLITE_API void *sqlite3_user_data(sqlite3_context*); /* ** CAPI3REF: Database Connection For Functions @@ -4738,7 +4952,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*); ** and [sqlite3_create_function16()] routines that originally ** registered the application defined function. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); /* ** CAPI3REF: Function Auxiliary Data @@ -4770,12 +4984,13 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); ** SQLite will invoke the destructor function X with parameter P exactly ** once, when the metadata is discarded. ** SQLite is free to discard the metadata at any time, including:
      -**
    • when the corresponding function parameter changes, or -**
    • when [sqlite3_reset()] or [sqlite3_finalize()] is called for the -** SQL statement, or -**
    • when sqlite3_set_auxdata() is invoked again on the same parameter, or -**
    • during the original sqlite3_set_auxdata() call when a memory -** allocation error occurs.
    )^ +**
  • ^(when the corresponding function parameter changes)^, or +**
  • ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the +** SQL statement)^, or +**
  • ^(when sqlite3_set_auxdata() is invoked again on the same +** parameter)^, or +**
  • ^(during the original sqlite3_set_auxdata() call when a memory +** allocation error occurs.)^ ** ** Note the last bullet in particular. The destructor X in ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the @@ -4791,8 +5006,8 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); ** These routines must be called from the same thread in which ** the SQL function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context*, int N); -SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); /* @@ -4928,27 +5143,27 @@ typedef void (*sqlite3_destructor_type)(void*); ** than the one containing the application-defined function that received ** the [sqlite3_context] pointer, the results are undefined. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64(sqlite3_context*,const void*, +SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*, sqlite3_uint64,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context*, double); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context*, const char*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context*, const void*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, +SQLITE_API void sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void sqlite3_result_null(sqlite3_context*); +SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n); -SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); +SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(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_zeroblob(sqlite3_context*, int n); +SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); /* @@ -4963,7 +5178,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context*,unsigned int); +SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); /* ** CAPI3REF: Define New Collating Sequences @@ -5045,14 +5260,14 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context*,unsigned ** ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation( +SQLITE_API int sqlite3_create_collation( sqlite3*, const char *zName, int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( +SQLITE_API int sqlite3_create_collation_v2( sqlite3*, const char *zName, int eTextRep, @@ -5060,7 +5275,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( int(*xCompare)(void*,int,const void*,int,const void*), void(*xDestroy)(void*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( +SQLITE_API int sqlite3_create_collation16( sqlite3*, const void *zName, int eTextRep, @@ -5095,12 +5310,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( ** [sqlite3_create_collation()], [sqlite3_create_collation16()], or ** [sqlite3_create_collation_v2()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( +SQLITE_API int sqlite3_collation_needed( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const char*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( +SQLITE_API int sqlite3_collation_needed16( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) @@ -5114,11 +5329,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int SQLITE_STDCALL sqlite3_key( +SQLITE_API int sqlite3_key( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The key */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_key_v2( +SQLITE_API int sqlite3_key_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The key */ @@ -5132,11 +5347,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_key_v2( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int SQLITE_STDCALL sqlite3_rekey( +SQLITE_API int sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2( +SQLITE_API int sqlite3_rekey_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The new key */ @@ -5146,7 +5361,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2( ** Specify the activation key for a SEE database. Unless ** activated, none of the SEE routines will work. */ -SQLITE_API void SQLITE_STDCALL sqlite3_activate_see( +SQLITE_API void sqlite3_activate_see( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -5156,7 +5371,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_activate_see( ** Specify the activation key for a CEROD database. Unless ** activated, none of the CEROD routines will work. */ -SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod( +SQLITE_API void sqlite3_activate_cerod( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -5178,7 +5393,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod( ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. */ -SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int); +SQLITE_API int sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files @@ -5297,7 +5512,7 @@ SQLITE_API char *sqlite3_data_directory; ** connection while this routine is running, then the return value ** is undefined. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*); +SQLITE_API int sqlite3_get_autocommit(sqlite3*); /* ** CAPI3REF: Find The Database Handle Of A Prepared Statement @@ -5310,7 +5525,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*); ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*); +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Filename For A Database Connection @@ -5327,7 +5542,7 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*); ** will be an absolute pathname, even if the filename used ** to open the database originally was a URI or relative pathname. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName); +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only @@ -5337,7 +5552,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const cha ** of connection D is read-only, 0 if it is read/write, or -1 if N is not ** the name of a database on connection D. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName); +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Find the next prepared statement @@ -5353,7 +5568,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbNa ** [sqlite3_next_stmt(D,S)] must refer to an open database ** connection and in particular must not be a NULL pointer. */ -SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); /* ** CAPI3REF: Commit And Rollback Notification Callbacks @@ -5402,8 +5617,8 @@ SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_ ** ** See also the [sqlite3_update_hook()] interface. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); +SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* ** CAPI3REF: Data Change Notification Callbacks @@ -5412,7 +5627,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), ** ^The sqlite3_update_hook() interface registers a callback function ** with the [database connection] identified by the first argument ** to be invoked whenever a row is updated, inserted or deleted in -** a rowid table. +** a [rowid table]. ** ^Any callback set by a previous call to this function ** for the same database connection is overridden. ** @@ -5451,10 +5666,10 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), ** on the same [database connection] D, or NULL for ** the first call on D. ** -** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] -** interfaces. +** See also the [sqlite3_commit_hook()], [sqlite3_rollback_hook()], +** and [sqlite3_preupdate_hook()] interfaces. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( +SQLITE_API void *sqlite3_update_hook( sqlite3*, void(*)(void *,int ,char const *,char const *,sqlite3_int64), void* @@ -5469,7 +5684,8 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( ** and disabled if the argument is false.)^ ** ** ^Cache sharing is enabled and disabled for an entire process. -** This is a change as of SQLite version 3.5.0. In prior versions of SQLite, +** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). +** In prior versions of SQLite, ** sharing was enabled or disabled for each thread separately. ** ** ^(The cache sharing mode set by this interface effects all subsequent @@ -5494,7 +5710,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( ** ** See Also: [SQLite Shared-Cache Mode] */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int); +SQLITE_API int sqlite3_enable_shared_cache(int); /* ** CAPI3REF: Attempt To Free Heap Memory @@ -5510,7 +5726,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int); ** ** See also: [sqlite3_db_release_memory()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int); +SQLITE_API int sqlite3_release_memory(int); /* ** CAPI3REF: Free Memory Used By A Database Connection @@ -5524,7 +5740,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int); ** ** See also: [sqlite3_release_memory()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); +SQLITE_API int sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size @@ -5563,7 +5779,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); ** from the heap. ** )^ ** -** Beginning with SQLite version 3.7.3, the soft heap limit is enforced +** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]), +** the soft heap limit is enforced ** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] ** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], ** the soft heap limit is enforced on every memory allocation. Without @@ -5576,7 +5793,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); ** The circumstances under which SQLite will enforce the soft heap limit may ** changes in future releases of SQLite. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 N); +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface @@ -5587,7 +5804,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 ** only. All new applications should use the ** [sqlite3_soft_heap_limit64()] interface rather than this one. */ -SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); +SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); /* @@ -5602,7 +5819,7 @@ SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); ** column exists. ^The sqlite3_table_column_metadata() interface returns ** SQLITE_ERROR and if the specified column does not exist. ** ^If the column-name parameter to sqlite3_table_column_metadata() is a -** NULL pointer, then this routine simply checks for the existance of the +** 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. ** @@ -5657,7 +5874,7 @@ SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); ** parsed, if that has not already been done, and returns an error if ** any errors are encountered while loading the schema. */ -SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( +SQLITE_API int sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ @@ -5699,12 +5916,21 @@ SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( ** should free this memory by calling [sqlite3_free()]. ** ** ^Extension loading must be enabled using -** [sqlite3_enable_load_extension()] prior to calling this API, +** [sqlite3_enable_load_extension()] or +** [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],1,NULL) +** prior to calling this API, ** otherwise an error will be returned. ** +** Security warning: It is recommended that the +** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this +** interface. The use of the [sqlite3_enable_load_extension()] interface +** should be avoided. This will keep the SQL function [load_extension()] +** disabled and prevent SQL injections from giving attackers +** access to extension loading capabilities. +** ** See also the [load_extension() SQL function]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( +SQLITE_API int sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Derived from zFile if 0 */ @@ -5724,8 +5950,19 @@ SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( ** ^Call the sqlite3_enable_load_extension() routine with onoff==1 ** to turn extension loading on and call it with onoff==0 to turn ** it back off again. +** +** ^This interface enables or disables both the C-API +** [sqlite3_load_extension()] and the SQL function [load_extension()]. +** ^(Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..) +** to enable or disable only the C-API.)^ +** +** Security warning: It is recommended that extension loading +** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method +** rather than this interface, so the [load_extension()] SQL function +** remains disabled. This will prevent SQL injections from giving attackers +** access to extension loading capabilities. */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff); +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ** CAPI3REF: Automatically Load Statically Linked Extensions @@ -5737,7 +5974,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int ono ** ** ^(Even though the function prototype shows that xEntryPoint() takes ** no arguments and returns void, SQLite invokes xEntryPoint() with three -** arguments and expects and integer result as if the signature of the +** arguments and expects an integer result as if the signature of the ** entry point where as follows: ** **
    @@ -5763,7 +6000,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int ono
     ** See also: [sqlite3_reset_auto_extension()]
     ** and [sqlite3_cancel_auto_extension()]
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xEntryPoint)(void));
    +SQLITE_API int sqlite3_auto_extension(void(*xEntryPoint)(void));
     
     /*
     ** CAPI3REF: Cancel Automatic Extension Loading
    @@ -5775,7 +6012,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xEntryPoint)(void));
     ** unregistered and it returns 0 if X was not on the list of initialization
     ** routines.
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
    +SQLITE_API int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void));
     
     /*
     ** CAPI3REF: Reset Automatic Extension Loading
    @@ -5783,7 +6020,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xEntryPoint)(
     ** ^This interface disables all automatic extensions previously
     ** registered using [sqlite3_auto_extension()].
     */
    -SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void);
    +SQLITE_API void sqlite3_reset_auto_extension(void);
     
     /*
     ** The interface to the virtual-table mechanism is currently considered
    @@ -5937,13 +6174,15 @@ struct sqlite3_module {
     ** the xUpdate method are automatically rolled back by SQLite.
     **
     ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
    -** structure for SQLite version 3.8.2. If a virtual table extension is
    +** structure for SQLite [version 3.8.2] ([dateof:3.8.2]). 
    +** If a virtual table extension is
     ** used with an SQLite version earlier than 3.8.2, the results of attempting 
     ** to read or write the estimatedRows field are undefined (but are likely 
     ** to included crashing the application). The estimatedRows field should
     ** therefore only be used if [sqlite3_libversion_number()] returns a
     ** value greater than or equal to 3008002. Similarly, the idxFlags field
    -** was added for version 3.9.0. It may therefore only be used if
    +** was added for [version 3.9.0] ([dateof:3.9.0]). 
    +** It may therefore only be used if
     ** sqlite3_libversion_number() returns a value greater than or equal to
     ** 3009000.
     */
    @@ -6028,13 +6267,13 @@ struct sqlite3_index_info {
     ** interface is equivalent to sqlite3_create_module_v2() with a NULL
     ** destructor.
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_create_module(
    +SQLITE_API int sqlite3_create_module(
       sqlite3 *db,               /* SQLite connection to register module with */
       const char *zName,         /* Name of the module */
       const sqlite3_module *p,   /* Methods for the module */
       void *pClientData          /* Client data for xCreate/xConnect */
     );
    -SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2(
    +SQLITE_API int sqlite3_create_module_v2(
       sqlite3 *db,               /* SQLite connection to register module with */
       const char *zName,         /* Name of the module */
       const sqlite3_module *p,   /* Methods for the module */
    @@ -6097,7 +6336,7 @@ struct sqlite3_vtab_cursor {
     ** to declare the format (the names and datatypes of the columns) of
     ** the virtual tables they implement.
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL);
    +SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
     
     /*
     ** CAPI3REF: Overload A Function For A Virtual Table
    @@ -6116,7 +6355,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL);
     ** purpose is to be a placeholder function that can be overloaded
     ** by a [virtual table].
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
    +SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
     
     /*
     ** The interface to the virtual-table mechanism defined above (back up
    @@ -6215,7 +6454,7 @@ 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()].
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_blob_open(
    +SQLITE_API int sqlite3_blob_open(
       sqlite3*,
       const char *zDb,
       const char *zTable,
    @@ -6248,7 +6487,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open(
     **
     ** ^This function sets the database handle error code and message.
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
    +SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
     
     /*
     ** CAPI3REF: Close A BLOB Handle
    @@ -6271,7 +6510,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64)
     ** is passed a valid open blob handle, the values returned by the 
     ** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning.
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *);
    +SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
     
     /*
     ** CAPI3REF: Return The Size Of An Open BLOB
    @@ -6287,7 +6526,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *);
     ** been closed by [sqlite3_blob_close()].  Passing any other pointer in
     ** to this routine results in undefined and probably undesirable behavior.
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *);
    +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *);
     
     /*
     ** CAPI3REF: Read Data From A BLOB Incrementally
    @@ -6316,7 +6555,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *);
     **
     ** See also: [sqlite3_blob_write()].
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
    +SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
     
     /*
     ** CAPI3REF: Write Data Into A BLOB Incrementally
    @@ -6358,7 +6597,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N,
     **
     ** See also: [sqlite3_blob_read()].
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
    +SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
     
     /*
     ** CAPI3REF: Virtual File System Objects
    @@ -6389,9 +6628,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z,
     ** ^(If the default VFS is unregistered, another VFS is chosen as
     ** the default.  The choice for the new VFS is arbitrary.)^
     */
    -SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfsName);
    -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
    -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*);
    +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
    +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
    +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
     
     /*
     ** CAPI3REF: Mutexes
    @@ -6507,11 +6746,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*);
     **
     ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
     */
    -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int);
    -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex*);
    -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex*);
    -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex*);
    -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex*);
    +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int);
    +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*);
    +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*);
    +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*);
    +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
     
     /*
     ** CAPI3REF: Mutex Methods Object
    @@ -6621,8 +6860,8 @@ struct sqlite3_mutex_methods {
     ** interface should also return 1 when given a NULL pointer.
     */
     #ifndef NDEBUG
    -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex*);
    -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*);
    +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
    +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
     #endif
     
     /*
    @@ -6641,7 +6880,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*);
     #define SQLITE_MUTEX_STATIC_MEM       3  /* sqlite3_malloc() */
     #define SQLITE_MUTEX_STATIC_MEM2      4  /* NOT USED */
     #define SQLITE_MUTEX_STATIC_OPEN      4  /* sqlite3BtreeOpen() */
    -#define SQLITE_MUTEX_STATIC_PRNG      5  /* sqlite3_random() */
    +#define SQLITE_MUTEX_STATIC_PRNG      5  /* sqlite3_randomness() */
     #define SQLITE_MUTEX_STATIC_LRU       6  /* lru page list */
     #define SQLITE_MUTEX_STATIC_LRU2      7  /* NOT USED */
     #define SQLITE_MUTEX_STATIC_PMEM      7  /* sqlite3PageMalloc() */
    @@ -6662,7 +6901,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*);
     ** ^If the [threading mode] is Single-thread or Multi-thread then this
     ** routine returns a NULL pointer.
     */
    -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*);
    +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
     
     /*
     ** CAPI3REF: Low-Level Control Of Database Files
    @@ -6697,7 +6936,7 @@ SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*);
     **
     ** See also: [SQLITE_FCNTL_LOCKSTATE]
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
    +SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
     
     /*
     ** CAPI3REF: Testing Interface
    @@ -6716,7 +6955,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName
     ** Unlike most of the SQLite API, this function is not guaranteed to
     ** operate consistently from one release to the next.
     */
    -SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...);
    +SQLITE_API int sqlite3_test_control(int op, ...);
     
     /*
     ** CAPI3REF: Testing Interface Operation Codes
    @@ -6745,6 +6984,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...);
     #define SQLITE_TESTCTRL_SCRATCHMALLOC           17
     #define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
     #define SQLITE_TESTCTRL_EXPLAIN_STMT            19  /* NOT USED */
    +#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD    19
     #define SQLITE_TESTCTRL_NEVER_CORRUPT           20
     #define SQLITE_TESTCTRL_VDBE_COVERAGE           21
     #define SQLITE_TESTCTRL_BYTEORDER               22
    @@ -6779,8 +7019,8 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...);
     **
     ** See also: [sqlite3_db_status()]
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
    -SQLITE_API int SQLITE_STDCALL sqlite3_status64(
    +SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
    +SQLITE_API int sqlite3_status64(
       int op,
       sqlite3_int64 *pCurrent,
       sqlite3_int64 *pHighwater,
    @@ -6905,7 +7145,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status64(
     **
     ** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
    +SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
     
     /*
     ** CAPI3REF: Status Parameters for database connections
    @@ -6951,6 +7191,18 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int
     ** memory used by all pager caches associated with the database connection.)^
     ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
     **
    +** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]] 
    +** ^(
    SQLITE_DBSTATUS_CACHE_USED_SHARED
    +**
    This parameter is similar to DBSTATUS_CACHE_USED, except that if a +** pager cache is shared between two or more connections the bytes of heap +** memory used by that pager cache is divided evenly between the attached +** connections.)^ In other words, if none of the pager caches associated +** with the database connection are shared, this request returns the same +** value as DBSTATUS_CACHE_USED. Or, if one or more or the pager caches are +** shared, the value returned by this call will be smaller than that returned +** by DBSTATUS_CACHE_USED. ^The highwater mark associated with +** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0. +** ** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(
    SQLITE_DBSTATUS_SCHEMA_USED
    **
    This parameter returns the approximate number of bytes of heap ** memory used to store the schema for all databases associated @@ -7008,7 +7260,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_CACHE_WRITE 9 #define SQLITE_DBSTATUS_DEFERRED_FKS 10 -#define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 +#define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */ /* @@ -7035,7 +7288,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int ** ** See also: [sqlite3_status()] and [sqlite3_db_status()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); +SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); /* ** CAPI3REF: Status Parameters for prepared statements @@ -7362,7 +7615,7 @@ typedef struct sqlite3_backup sqlite3_backup; ** must be different or else sqlite3_backup_init(D,N,S,M) will fail with ** an error. ** -** ^A call to sqlite3_backup_init() will fail, returning SQLITE_ERROR, if +** ^A call to sqlite3_backup_init() will fail, returning NULL, if ** there is already a read or read-write transaction open on the ** destination database. ** @@ -7504,16 +7757,16 @@ typedef struct sqlite3_backup sqlite3_backup; ** same time as another thread is invoking sqlite3_backup_step() it is ** possible that they return invalid values. */ -SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( +SQLITE_API sqlite3_backup *sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ const char *zSourceName /* Source database name */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); /* ** CAPI3REF: Unlock Notification @@ -7630,7 +7883,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p); ** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE_LOCKED.)^ */ -SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( +SQLITE_API int sqlite3_unlock_notify( sqlite3 *pBlocked, /* Waiting connection */ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ void *pNotifyArg /* Argument to pass to xNotify */ @@ -7645,8 +7898,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( ** strings in a case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *, const char *); -SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int); +SQLITE_API int sqlite3_stricmp(const char *, const char *); +SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* ** CAPI3REF: String Globbing @@ -7663,7 +7916,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int); ** ** See also: [sqlite3_strlike()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zStr); +SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); /* ** CAPI3REF: String LIKE Matching @@ -7686,7 +7939,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zSt ** ** See also: [sqlite3_strglob()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc); +SQLITE_API int sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc); /* ** CAPI3REF: Error Logging Interface @@ -7709,7 +7962,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zGlob, const char *zSt ** a few hundred characters, it will be truncated to the length of the ** buffer. */ -SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...); +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); /* ** CAPI3REF: Write-Ahead Log Commit Hook @@ -7745,7 +7998,7 @@ SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...) ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** overwrite any prior [sqlite3_wal_hook()] settings. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( +SQLITE_API void *sqlite3_wal_hook( sqlite3*, int(*)(void *,sqlite3*,const char*,int), void* @@ -7780,7 +8033,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( ** is only necessary if the default setting is found to be suboptimal ** for a particular application. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N); +SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); /* ** CAPI3REF: Checkpoint a database @@ -7802,7 +8055,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N); ** start a callback but which do not need the full power (and corresponding ** complication) of [sqlite3_wal_checkpoint_v2()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); +SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Checkpoint a database @@ -7896,7 +8149,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zD ** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface ** from SQL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( +SQLITE_API int sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of attached database (or NULL) */ int eMode, /* SQLITE_CHECKPOINT_* value */ @@ -7932,7 +8185,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( ** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options ** may be added in the future. */ -SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...); +SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); /* ** CAPI3REF: Virtual Table Configuration Options @@ -7985,7 +8238,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...); ** of the SQL statement that triggered the call to the [xUpdate] method of the ** [virtual table]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *); +SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); /* ** CAPI3REF: Conflict resolution modes @@ -8090,7 +8343,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *); ** ** See also: [sqlite3_stmt_scanstatus_reset()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( +SQLITE_API int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ @@ -8106,7 +8359,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ -SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); +SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** CAPI3REF: Flush caches to disk mid-transaction @@ -8138,19 +8391,115 @@ SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); ** ^This function does not set the database handle error code or message ** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3*); +SQLITE_API int sqlite3_db_cacheflush(sqlite3*); + +/* +** CAPI3REF: The pre-update hook. +** +** ^These interfaces are only available if SQLite is compiled using the +** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option. +** +** ^The [sqlite3_preupdate_hook()] interface registers a callback function +** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation +** on a [rowid 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. +** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()] +** with a NULL pointer as the second parameter. +** ^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 second parameter to the preupdate callback is a pointer to +** the [database connection] that registered the preupdate hook. +** ^The third parameter to the preupdate callback is one of the constants +** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to identify the +** kind of update operation that is about to occur. +** ^(The fourth parameter to the preupdate callback is the name of the +** database within the database connection that is being modified. This +** will be "main" for the main database or "temp" for TEMP tables or +** the name given after the AS keyword in the [ATTACH] statement for attached +** 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. +** +** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()], +** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces +** provide additional information about a preupdate event. These routines +** may only be called from within a preupdate callback. Invoking any of +** these routines from outside of a preupdate callback or with a +** [database connection] pointer that is different from the one supplied +** to the preupdate callback results in undefined and probably undesirable +** behavior. +** +** ^The [sqlite3_preupdate_count(D)] interface returns the number of columns +** in the row that is being inserted, updated, or deleted. +** +** ^The [sqlite3_preupdate_old(D,N,P)] interface writes into P a pointer to +** a [protected sqlite3_value] that contains the value of the Nth column of +** the table row before it is updated. The N parameter must be between 0 +** and one less than the number of columns or the behavior will be +** undefined. This must only be used within SQLITE_UPDATE and SQLITE_DELETE +** preupdate callbacks; if it is used by an SQLITE_INSERT callback then the +** behavior is undefined. The [sqlite3_value] that P points to +** will be destroyed when the preupdate callback returns. +** +** ^The [sqlite3_preupdate_new(D,N,P)] interface writes into P a pointer to +** a [protected sqlite3_value] that contains the value of the Nth column of +** the table row after it is updated. The N parameter must be between 0 +** and one less than the number of columns or the behavior will be +** undefined. This must only be used within SQLITE_INSERT and SQLITE_UPDATE +** preupdate callbacks; if it is used by an SQLITE_DELETE callback then the +** behavior is undefined. The [sqlite3_value] that P points to +** will be destroyed when the preupdate callback returns. +** +** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate +** callback was invoked as a result of a direct insert, update, or delete +** operation; or 1 for inserts, updates, or deletes invoked by top-level +** triggers; or 2 for changes resulting from triggers called by top-level +** triggers; and so forth. +** +** See also: [sqlite3_update_hook()] +*/ +SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook( + sqlite3 *db, + void(*xPreUpdate)( + void *pCtx, /* Copy of third arg to preupdate_hook() */ + sqlite3 *db, /* Database handle */ + int op, /* SQLITE_UPDATE, DELETE or INSERT */ + char const *zDb, /* Database name */ + char const *zName, /* Table name */ + sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ + sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ + ), + 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 **); /* ** CAPI3REF: Low-level system error code ** ** ^Attempt to return the underlying operating system error code or error -** number that caused the most reason I/O error or failure to open a file. +** number that caused the most recent I/O error or failure to open a file. ** The return value is OS-dependent. For example, on unix systems, after ** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be ** called to get back the underlying "errno" that caused the problem, such ** as ENOSPC, EAUTH, EISDIR, and so forth. */ -SQLITE_API int SQLITE_STDCALL sqlite3_system_errno(sqlite3*); +SQLITE_API int sqlite3_system_errno(sqlite3*); /* ** CAPI3REF: Database Snapshot @@ -8200,7 +8549,7 @@ typedef struct sqlite3_snapshot sqlite3_snapshot; ** The [sqlite3_snapshot_get()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_get( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( sqlite3 *db, const char *zSchema, sqlite3_snapshot **ppSnapshot @@ -8210,26 +8559,35 @@ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_get( ** CAPI3REF: Start a read transaction on an historical snapshot ** EXPERIMENTAL ** -** ^The [sqlite3_snapshot_open(D,S,P)] interface attempts to move the -** read transaction that is currently open on schema S of -** [database connection] D so that it refers to historical [snapshot] P. +** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a +** read transaction for schema S of +** [database connection] D such that the read transaction +** refers to historical [snapshot] P, rather than the most +** recent change to the database. ** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success ** or an appropriate [error code] if it fails. ** ** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be -** the first operation, apart from other sqlite3_snapshot_open() calls, -** following the [BEGIN] that starts a new read transaction. -** ^A [snapshot] will fail to open if it has been overwritten by a +** the first operation following the [BEGIN] that takes the schema S +** out of [autocommit mode]. +** ^In other words, schema S must not currently be in +** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the +** database connection D must be out of [autocommit mode]. +** ^A [snapshot] will fail to open if it has been overwritten by a ** [checkpoint]. -** ^A [snapshot] will fail to open if the database connection D has not -** previously completed at least one read operation against the database -** file. (Hint: Run "[PRAGMA application_id]" against a newly opened +** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the +** database connection D does not know that the database file for +** schema S is in [WAL mode]. A database connection might not know +** that the database file is in [WAL mode] if there has been no prior +** I/O on that database connection, or if the database entered [WAL mode] +** after the most recent I/O on the database connection.)^ +** (Hint: Run "[PRAGMA application_id]" against a newly opened ** database connection in order to make it ready to use snapshots.) ** ** The [sqlite3_snapshot_open()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_open( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( sqlite3 *db, const char *zSchema, sqlite3_snapshot *pSnapshot @@ -8246,7 +8604,34 @@ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_open( ** The [sqlite3_snapshot_free()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ -SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3_snapshot*); +SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); + +/* +** CAPI3REF: Compare the ages of two snapshot handles. +** EXPERIMENTAL +** +** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages +** of two valid snapshot handles. +** +** If the two snapshot handles are not associated with the same database +** file, the result of the comparison is undefined. +** +** Additionally, the result of the comparison is only valid if both of the +** snapshot handles were obtained by calling sqlite3_snapshot_get() since the +** last time the wal file was deleted. The wal file is deleted when the +** database is changed back to rollback mode or when the number of database +** clients drops to zero. If either snapshot handle was obtained before the +** wal file was last deleted, the value returned by this function +** is undefined. +** +** Otherwise, this API returns a negative value if P1 refers to an older +** snapshot than P2, zero if the two handles refer to the same database +** snapshot, and a positive value if P1 is a newer snapshot than P2. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( + sqlite3_snapshot *p1, + sqlite3_snapshot *p2 +); /* ** Undo the hack that converts floating point types to integer for @@ -8259,8 +8644,9 @@ SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3 #if 0 } /* End of the 'extern "C"' block */ #endif -#endif /* _SQLITE3_H_ */ +#endif /* SQLITE3_H */ +/******** Begin file sqlite3rtree.h *********/ /* ** 2010 August 30 ** @@ -8300,7 +8686,7 @@ typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info; ** ** SELECT ... FROM WHERE MATCH $zGeom(... params ...) */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( +SQLITE_API int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), @@ -8326,7 +8712,7 @@ struct sqlite3_rtree_geometry { ** ** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( +SQLITE_API int sqlite3_rtree_query_callback( sqlite3 *db, const char *zQueryFunc, int (*xQueryFunc)(sqlite3_rtree_query_info*), @@ -8378,6 +8764,1291 @@ struct sqlite3_rtree_query_info { #endif /* ifndef _SQLITE3RTREE_H_ */ +/******** End of sqlite3rtree.h *********/ +/******** Begin file sqlite3session.h *********/ + +#if !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) +#define __SQLITESESSION_H_ 1 + +/* +** Make sure we can call this stuff from C++. +*/ +#if 0 +extern "C" { +#endif + + +/* +** CAPI3REF: Session Object Handle +*/ +typedef struct sqlite3_session sqlite3_session; + +/* +** CAPI3REF: Changeset Iterator Handle +*/ +typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; + +/* +** CAPI3REF: Create A New Session Object +** +** Create a new session object attached to database handle db. If successful, +** a pointer to the new object is written to *ppSession and SQLITE_OK is +** returned. If an error occurs, *ppSession is set to NULL and an SQLite +** error code (e.g. SQLITE_NOMEM) is returned. +** +** It is possible to create multiple session objects attached to a single +** database handle. +** +** Session objects created using this function should be deleted using the +** [sqlite3session_delete()] function before the database handle that they +** are attached to is itself closed. If the database handle is closed before +** the session object is deleted, then the results of calling any session +** module function, including [sqlite3session_delete()] on the session object +** are undefined. +** +** Because the session module uses the [sqlite3_preupdate_hook()] API, it +** is not possible for an application to register a pre-update hook on a +** database handle that has one or more session objects attached. Nor is +** it possible to create a session object attached to a database handle for +** which a pre-update hook is already defined. The results of attempting +** either of these things are undefined. +** +** The session object will be used to create changesets for tables in +** database zDb, where zDb is either "main", or "temp", or the name of an +** 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( + sqlite3 *db, /* Database handle */ + const char *zDb, /* Name of db (e.g. "main") */ + sqlite3_session **ppSession /* OUT: New session object */ +); + +/* +** CAPI3REF: Delete A Session Object +** +** Delete a session object previously allocated using +** [sqlite3session_create()]. Once a session object has been deleted, the +** results of attempting to use pSession with any other session module +** function are undefined. +** +** Session objects must be deleted before the database handle to which they +** are attached is closed. Refer to the documentation for +** [sqlite3session_create()] for details. +*/ +void sqlite3session_delete(sqlite3_session *pSession); + + +/* +** CAPI3REF: Enable Or Disable A Session Object +** +** Enable or disable the recording of changes by a session object. When +** enabled, a session object records changes made to the database. When +** disabled - it does not. A newly created session object is enabled. +** Refer to the documentation for [sqlite3session_changeset()] for further +** details regarding how enabling and disabling a session object affects +** the eventual changesets. +** +** Passing zero to this function disables the session. Passing a value +** greater than zero enables it. Passing a value less than zero is a +** no-op, and may be used to query the current state of the session. +** +** 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); + +/* +** CAPI3REF: Set Or Clear the Indirect Change Flag +** +** Each change recorded by a session object is marked as either direct or +** indirect. A change is marked as indirect if either: +** +**
      +**
    • The session object "indirect" flag is set when the change is +** made, or +**
    • The change is made by an SQL trigger or foreign key action +** instead of directly as a result of a users SQL statement. +**
    +** +** If a single row is affected by more than one operation within a session, +** then the change is considered indirect if all operations meet the criteria +** for an indirect change above, or direct otherwise. +** +** This function is used to set, clear or query the session object indirect +** flag. If the second argument passed to this function is zero, then the +** indirect flag is cleared. If it is greater than zero, the indirect flag +** is set. Passing a value less than zero does not modify the current value +** of the indirect flag, and may be used to query the current state of the +** indirect flag for the specified session object. +** +** 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); + +/* +** CAPI3REF: Attach A Table To A Session Object +** +** If argument zTab is not NULL, then it is the name of a table to attach +** to the session object passed as the first argument. All subsequent changes +** made to the table while the session object is enabled will be recorded. See +** documentation for [sqlite3session_changeset()] for further details. +** +** Or, if argument zTab is NULL, then changes are recorded for all tables +** in the database. If additional tables are added to the database (by +** executing "CREATE TABLE" statements) after this call is made, changes for +** the new tables are also recorded. +** +** Changes can only be recorded for tables that have a PRIMARY KEY explicitly +** defined as part of their CREATE TABLE statement. It does not matter if the +** PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) or not. The PRIMARY +** KEY may consist of a single column, or may be a composite key. +** +** It is not an error if the named table does not exist in the database. Nor +** is it an error if the named table does not have a PRIMARY KEY. However, +** no changes will be recorded in either of these scenarios. +** +** Changes are not recorded for individual rows that have NULL values stored +** in one or more of their PRIMARY KEY columns. +** +** 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( + sqlite3_session *pSession, /* Session object */ + const char *zTab /* Table name */ +); + +/* +** CAPI3REF: Set a table filter on a Session Object. +** +** The second argument (xFilter) is the "filter callback". For changes to rows +** in tables that are not attached to the Session object, the filter is called +** to determine whether changes to the table's rows should be tracked or not. +** 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( + sqlite3_session *pSession, /* Session object */ + int(*xFilter)( + void *pCtx, /* Copy of third arg to _filter_table() */ + const char *zTab /* Table name */ + ), + void *pCtx /* First argument passed to xFilter */ +); + +/* +** CAPI3REF: Generate A Changeset From A Session Object +** +** Obtain a changeset containing changes to the tables attached to the +** session object passed as the first argument. If successful, +** set *ppChangeset to point to a buffer containing the changeset +** and *pnChangeset to the size of the changeset in bytes before returning +** SQLITE_OK. If an error occurs, set both *ppChangeset and *pnChangeset to +** zero and return an SQLite error code. +** +** A changeset consists of zero or more INSERT, UPDATE and/or DELETE changes, +** each representing a change to a single row of an attached table. An INSERT +** change contains the values of each field of a new database row. A DELETE +** contains the original values of each field of a deleted database row. An +** UPDATE change contains the original values of each field of an updated +** database row along with the updated values for each updated non-primary-key +** column. It is not possible for an UPDATE change to represent a change that +** modifies the values of primary key columns. If such a change is made, it +** is represented in a changeset as a DELETE followed by an INSERT. +** +** Changes are not recorded for rows that have NULL values stored in one or +** more of their PRIMARY KEY columns. If such a row is inserted or deleted, +** no corresponding change is present in the changesets returned by this +** function. If an existing row with one or more NULL values stored in +** PRIMARY KEY columns is updated so that all PRIMARY KEY columns are non-NULL, +** only an INSERT is appears in the changeset. Similarly, if an existing row +** with non-NULL PRIMARY KEY values is updated so that one or more of its +** PRIMARY KEY columns are set to NULL, the resulting changeset contains a +** DELETE change only. +** +** The contents of a changeset may be traversed using an iterator created +** using the [sqlite3changeset_start()] API. A changeset may be applied to +** a database with a compatible schema using the [sqlite3changeset_apply()] +** API. +** +** Within a changeset generated by this function, all changes related to a +** single table are grouped together. In other words, when iterating through +** a changeset or when applying a changeset to a database, all changes related +** to a single table are processed before moving on to the next table. Tables +** are sorted in the same order in which they were attached (or auto-attached) +** to the sqlite3_session object. The order in which the changes related to +** a single table are stored is undefined. +** +** Following a successful call to this function, it is the responsibility of +** the caller to eventually free the buffer that *ppChangeset points to using +** [sqlite3_free()]. +** +**

    Changeset Generation

    +** +** Once a table has been attached to a session object, the session object +** records the primary key values of all new rows inserted into the table. +** It also records the original primary key and other column values of any +** deleted or updated rows. For each unique primary key value, data is only +** recorded once - the first time a row with said primary key is inserted, +** updated or deleted in the lifetime of the session. +** +** There is one exception to the previous paragraph: when a row is inserted, +** updated or deleted, if one or more of its primary key columns contain a +** NULL value, no record of the change is made. +** +** The session object therefore accumulates two types of records - those +** that consist of primary key values only (created when the user inserts +** a new record) and those that consist of the primary key values and the +** original values of other table columns (created when the users deletes +** or updates a record). +** +** When this function is called, the requested changeset is created using +** both the accumulated records and the current contents of the database +** file. Specifically: +** +**
      +**
    • For each record generated by an insert, the database is queried +** for a row with a matching primary key. If one is found, an INSERT +** change is added to the changeset. If no such row is found, no change +** is added to the changeset. +** +**
    • For each record generated by an update or delete, the database is +** queried for a row with a matching primary key. If such a row is +** found and one or more of the non-primary key fields have been +** modified from their original values, an UPDATE change is added to +** the changeset. Or, if no such row is found in the table, a DELETE +** change is added to the changeset. If there is a row with a matching +** primary key in the database, but all fields contain their original +** values, no change is added to the changeset. +**
    +** +** This means, amongst other things, that if a row is inserted and then later +** deleted while a session object is active, neither the insert nor the delete +** will be present in the changeset. Or if a row is deleted and then later a +** row with the same primary key values inserted while a session object is +** active, the resulting changeset will contain an UPDATE change instead of +** a DELETE and an INSERT. +** +** When a session object is disabled (see the [sqlite3session_enable()] API), +** it does not accumulate records when rows are inserted, updated or deleted. +** This may appear to have some counter-intuitive effects if a single row +** is written to more than once during a session. For example, if a row +** is inserted while a session object is enabled, then later deleted while +** the same session object is disabled, no INSERT record will appear in the +** changeset, even though the delete took place while the session was disabled. +** Or, if one field of a row is updated while a session is disabled, and +** 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( + sqlite3_session *pSession, /* Session object */ + int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ + void **ppChangeset /* OUT: Buffer containing changeset */ +); + +/* +** CAPI3REF: Load The Difference Between Tables Into A Session +** +** If it is not already attached to the session object passed as the first +** argument, this function attaches table zTbl in the same manner as the +** [sqlite3session_attach()] function. If zTbl does not exist, or if it +** does not have a primary key, this function is a no-op (but does not return +** an error). +** +** Argument zFromDb must be the name of a database ("main", "temp" etc.) +** attached to the same database handle as the session object that contains +** a table compatible with the table attached to the session by this function. +** A table is considered compatible if it: +** +**
      +**
    • Has the same name, +**
    • Has the same set of columns declared in the same order, and +**
    • Has the same PRIMARY KEY definition. +**
    +** +** If the tables are not compatible, SQLITE_SCHEMA is returned. If the tables +** are compatible but do not have any PRIMARY KEY columns, it is not an error +** but no changes are added to the session object. As with other session +** APIs, tables without PRIMARY KEYs are simply ignored. +** +** This function adds a set of changes to the session object that could be +** used to update the table in database zFrom (call this the "from-table") +** so that its content is the same as the table attached to the session +** object (call this the "to-table"). Specifically: +** +**
      +**
    • For each row (primary key) that exists in the to-table but not in +** the from-table, an INSERT record is added to the session object. +** +**
    • For each row (primary key) that exists in the to-table but not in +** 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. +**
    +** +** To clarify, if this function is called and then a changeset constructed +** using [sqlite3session_changeset()], then after applying that changeset to +** database zFrom the contents of the two compatible tables would be +** identical. +** +** It an error if database zFrom does not exist or does not contain the +** required compatible table. +** +** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite +** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg +** may be set to point to a buffer containing an English language error +** message. It is the responsibility of the caller to free this buffer using +** sqlite3_free(). +*/ +int sqlite3session_diff( + sqlite3_session *pSession, + const char *zFromDb, + const char *zTbl, + char **pzErrMsg +); + + +/* +** CAPI3REF: Generate A Patchset From A Session Object +** +** The differences between a patchset and a changeset are that: +** +**
      +**
    • DELETE records consist of the primary key fields only. The +** original values of other fields are omitted. +**
    • The original values of any modified fields are omitted from +** UPDATE records. +**
    +** +** A patchset blob may be used with up to date versions of all +** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(), +** which returns SQLITE_CORRUPT if it is passed a patchset. Similarly, +** attempting to use a patchset blob with old versions of the +** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error. +** +** Because the non-primary key "old.*" fields are omitted, no +** SQLITE_CHANGESET_DATA conflicts can be detected or reported if a patchset +** is passed to the sqlite3changeset_apply() API. Other conflict types work +** in the same way as for changesets. +** +** Changes within a patchset are ordered in the same way as for changesets +** generated by the sqlite3session_changeset() function (i.e. all changes for +** a single table are grouped together, tables appear in the order in which +** they were attached to the session object). +*/ +int sqlite3session_patchset( + sqlite3_session *pSession, /* Session object */ + int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ + void **ppPatchset /* OUT: Buffer containing changeset */ +); + +/* +** CAPI3REF: Test if a changeset has recorded any changes. +** +** Return non-zero if no changes to attached tables have been recorded by +** the session object passed as the first argument. Otherwise, if one or +** more changes have been recorded, return zero. +** +** Even if this function returns zero, it is possible that calling +** [sqlite3session_changeset()] on the session handle may still return a +** changeset that contains no changes. This can happen when a row in +** an attached table is modified and then later on the original values +** are restored. However, if this function returns non-zero, then it is +** guaranteed that a call to sqlite3session_changeset() will return a +** changeset containing zero changes. +*/ +int sqlite3session_isempty(sqlite3_session *pSession); + +/* +** CAPI3REF: Create An Iterator To Traverse A Changeset +** +** Create an iterator used to iterate through the contents of a changeset. +** If successful, *pp is set to point to the iterator handle and SQLITE_OK +** is returned. Otherwise, if an error occurs, *pp is set to zero and an +** SQLite error code is returned. +** +** The following functions can be used to advance and query a changeset +** iterator created by this function: +** +**
      +**
    • [sqlite3changeset_next()] +**
    • [sqlite3changeset_op()] +**
    • [sqlite3changeset_new()] +**
    • [sqlite3changeset_old()] +**
    +** +** It is the responsibility of the caller to eventually destroy the iterator +** by passing it to [sqlite3changeset_finalize()]. The buffer containing the +** changeset (pChangeset) must remain valid until after the iterator is +** destroyed. +** +** Assuming the changeset blob was created by one of the +** [sqlite3session_changeset()], [sqlite3changeset_concat()] or +** [sqlite3changeset_invert()] functions, all changes within the changeset +** that apply to a single table are grouped together. This means that when +** an application iterates through a changeset using an iterator created by +** this function, all changes that relate to a single table are visited +** consecutively. There is no chance that the iterator will visit a change +** the applies to table X, then one for table Y, and then later on visit +** another change for table X. +*/ +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 */ +); + + +/* +** CAPI3REF: Advance A Changeset Iterator +** +** This function may only be used with iterators created by function +** [sqlite3changeset_start()]. If it is called on an iterator passed to +** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE +** is returned and the call has no effect. +** +** Immediately after an iterator is created by sqlite3changeset_start(), it +** does not point to any change in the changeset. Assuming the changeset +** is not empty, the first call to this function advances the iterator to +** point to the first change in the changeset. Each subsequent call advances +** the iterator to point to the next change in the changeset (if any). If +** no error occurs and the iterator points to a valid change after a call +** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned. +** Otherwise, if all changes in the changeset have already been visited, +** SQLITE_DONE is returned. +** +** If an error occurs, an SQLite error code is returned. Possible error +** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or +** SQLITE_NOMEM. +*/ +int sqlite3changeset_next(sqlite3_changeset_iter *pIter); + +/* +** CAPI3REF: Obtain The Current Operation From A Changeset Iterator +** +** The pIter argument passed to this function may either be an iterator +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +** created by [sqlite3changeset_start()]. In the latter case, the most recent +** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this +** is not the case, this function returns [SQLITE_MISUSE]. +** +** If argument pzTab is not NULL, then *pzTab is set to point to a +** nul-terminated utf-8 encoded string containing the name of the table +** affected by the current change. The buffer remains valid until either +** sqlite3changeset_next() is called on the iterator or until the +** conflict-handler function returns. If pnCol is not NULL, then *pnCol is +** set to the number of columns in the table affected by the change. If +** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change +** is an indirect change, or false (0) otherwise. See the documentation for +** [sqlite3session_indirect()] for a description of direct and indirect +** changes. Finally, if pOp is not NULL, then *pOp is set to one of +** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the +** type of change that the iterator currently points to. +** +** If no error occurs, SQLITE_OK is returned. If an error does occur, an +** SQLite error code is returned. The values of the output variables may not +** be trusted in this case. +*/ +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 */ + int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */ + int *pbIndirect /* OUT: True for an 'indirect' change */ +); + +/* +** CAPI3REF: Obtain The Primary Key Definition Of A Table +** +** For each modified table, a changeset includes the following: +** +**
      +**
    • The number of columns in the table, and +**
    • Which of those columns make up the tables PRIMARY KEY. +**
    +** +** This function is used to find which columns comprise the PRIMARY KEY of +** the table modified by the change that iterator pIter currently points to. +** If successful, *pabPK is set to point to an array of nCol entries, where +** nCol is the number of columns in the table. Elements of *pabPK are set to +** 0x01 if the corresponding column is part of the tables primary key, or +** 0x00 if it is not. +** +** If argument pnCol is not NULL, then *pnCol is set to the number of columns +** in the table. +** +** If this function is called when the iterator does not point to a valid +** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, +** SQLITE_OK is returned and the output variables populated as described +** above. +*/ +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 */ +); + +/* +** CAPI3REF: Obtain old.* Values From A Changeset Iterator +** +** The pIter argument passed to this function may either be an iterator +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +** created by [sqlite3changeset_start()]. In the latter case, the most recent +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. +** Furthermore, it may only be called if the type of change that the iterator +** currently points to is either [SQLITE_DELETE] or [SQLITE_UPDATE]. Otherwise, +** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. +** +** Argument iVal must be greater than or equal to 0, and less than the number +** of columns in the table affected by the current change. Otherwise, +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. +** +** If successful, this function sets *ppValue to point to a protected +** sqlite3_value object containing the iVal'th value from the vector of +** original row values stored as part of the UPDATE or DELETE change and +** returns SQLITE_OK. The name of the function comes from the fact that this +** is similar to the "old.*" columns available to update or delete triggers. +** +** 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( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ +); + +/* +** CAPI3REF: Obtain new.* Values From A Changeset Iterator +** +** The pIter argument passed to this function may either be an iterator +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +** created by [sqlite3changeset_start()]. In the latter case, the most recent +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. +** Furthermore, it may only be called if the type of change that the iterator +** currently points to is either [SQLITE_UPDATE] or [SQLITE_INSERT]. Otherwise, +** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. +** +** Argument iVal must be greater than or equal to 0, and less than the number +** of columns in the table affected by the current change. Otherwise, +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. +** +** If successful, this function sets *ppValue to point to a protected +** sqlite3_value object containing the iVal'th value from the vector of +** new row values stored as part of the UPDATE or INSERT change and +** returns SQLITE_OK. If the change is an UPDATE and does not include +** a new value for the requested column, *ppValue is set to NULL and +** SQLITE_OK returned. The name of the function comes from the fact that +** this is similar to the "new.*" columns available to update or delete +** triggers. +** +** 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( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ +); + +/* +** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator +** +** This function should only be used with iterator objects passed to a +** conflict-handler callback by [sqlite3changeset_apply()] with either +** [SQLITE_CHANGESET_DATA] or [SQLITE_CHANGESET_CONFLICT]. If this function +** is called on any other iterator, [SQLITE_MISUSE] is returned and *ppValue +** is set to NULL. +** +** Argument iVal must be greater than or equal to 0, and less than the number +** of columns in the table affected by the current change. Otherwise, +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. +** +** If successful, this function sets *ppValue to point to a protected +** sqlite3_value object containing the iVal'th value from the +** "conflicting row" associated with the current conflict-handler callback +** and returns SQLITE_OK. +** +** 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( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: Value from conflicting row */ +); + +/* +** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations +** +** This function may only be called with an iterator passed to an +** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case +** it sets the output variable to the total number of known foreign key +** violations in the destination database and returns SQLITE_OK. +** +** In all other cases this function returns SQLITE_MISUSE. +*/ +int sqlite3changeset_fk_conflicts( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int *pnOut /* OUT: Number of FK violations */ +); + + +/* +** CAPI3REF: Finalize A Changeset Iterator +** +** This function is used to finalize an iterator allocated with +** [sqlite3changeset_start()]. +** +** This function should only be called on iterators created using the +** [sqlite3changeset_start()] function. If an application calls this +** function with an iterator passed to a conflict-handler by +** [sqlite3changeset_apply()], [SQLITE_MISUSE] is immediately returned and the +** call has no effect. +** +** If an error was encountered within a call to an sqlite3changeset_xxx() +** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an +** [SQLITE_NOMEM] in [sqlite3changeset_new()]) then an error code corresponding +** to that error is returned by this function. Otherwise, SQLITE_OK is +** returned. This is to allow the following pattern (pseudo-code): +** +** sqlite3changeset_start(); +** while( SQLITE_ROW==sqlite3changeset_next() ){ +** // Do something with change. +** } +** rc = sqlite3changeset_finalize(); +** if( rc!=SQLITE_OK ){ +** // An error has occurred +** } +*/ +int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); + +/* +** CAPI3REF: Invert A Changeset +** +** This function is used to "invert" a changeset object. Applying an inverted +** changeset to a database reverses the effects of applying the uninverted +** changeset. Specifically: +** +**
      +**
    • Each DELETE change is changed to an INSERT, and +**
    • Each INSERT change is changed to a DELETE, and +**
    • For each UPDATE change, the old.* and new.* values are exchanged. +**
    +** +** This function does not change the order in which changes appear within +** the changeset. It merely reverses the sense of each individual change. +** +** If successful, a pointer to a buffer containing the inverted changeset +** is stored in *ppOut, the size of the same buffer is stored in *pnOut, and +** SQLITE_OK is returned. If an error occurs, both *pnOut and *ppOut are +** zeroed and an SQLite error code returned. +** +** It is the responsibility of the caller to eventually call sqlite3_free() +** on the *ppOut pointer to free the buffer allocation following a successful +** call to this function. +** +** WARNING/TODO: This function currently assumes that the input is a valid +** changeset. If it is not, the results are undefined. +*/ +int sqlite3changeset_invert( + int nIn, const void *pIn, /* Input changeset */ + int *pnOut, void **ppOut /* OUT: Inverse of input */ +); + +/* +** CAPI3REF: Concatenate Two Changeset Objects +** +** This function is used to concatenate two changesets, A and B, into a +** single changeset. The result is a changeset equivalent to applying +** changeset A followed by changeset B. +** +** This function combines the two input changesets using an +** sqlite3_changegroup object. Calling it produces similar results as the +** following code fragment: +** +** sqlite3_changegroup *pGrp; +** rc = sqlite3_changegroup_new(&pGrp); +** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA); +** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nB, pB); +** if( rc==SQLITE_OK ){ +** rc = sqlite3changegroup_output(pGrp, pnOut, ppOut); +** }else{ +** *ppOut = 0; +** *pnOut = 0; +** } +** +** Refer to the sqlite3_changegroup documentation below for details. +*/ +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 */ + void *pB, /* Pointer to buffer containing changeset B */ + int *pnOut, /* OUT: Number of bytes in output changeset */ + void **ppOut /* OUT: Buffer containing output changeset */ +); + + +/* +** CAPI3REF: Changegroup Handle +*/ +typedef struct sqlite3_changegroup sqlite3_changegroup; + +/* +** CAPI3REF: Create A New Changegroup Object +** +** An sqlite3_changegroup object is used to combine two or more changesets +** (or patchsets) into a single changeset (or patchset). A single changegroup +** object may combine changesets or patchsets, but not both. The output is +** always in the same format as the input. +** +** If successful, this function returns SQLITE_OK and populates (*pp) with +** a pointer to a new sqlite3_changegroup object before returning. The caller +** should eventually free the returned object using a call to +** sqlite3changegroup_delete(). If an error occurs, an SQLite error code +** (i.e. SQLITE_NOMEM) is returned and *pp is set to NULL. +** +** The usual usage pattern for an sqlite3_changegroup object is as follows: +** +**
      +**
    • It is created using a call to sqlite3changegroup_new(). +** +**
    • Zero or more changesets (or patchsets) are added to the object +** by calling sqlite3changegroup_add(). +** +**
    • The result of combining all input changesets together is obtained +** by the application via a call to sqlite3changegroup_output(). +** +**
    • The object is deleted using a call to sqlite3changegroup_delete(). +**
    +** +** Any number of calls to add() and output() may be made between the calls to +** new() and delete(), and in any order. +** +** As well as the regular sqlite3changegroup_add() and +** sqlite3changegroup_output() functions, also available are the streaming +** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm(). +*/ +int sqlite3changegroup_new(sqlite3_changegroup **pp); + +/* +** CAPI3REF: Add A Changeset To A Changegroup +** +** Add all changes within the changeset (or patchset) in buffer pData (size +** nData bytes) to the changegroup. +** +** If the buffer contains a patchset, then all prior calls to this function +** on the same changegroup object must also have specified patchsets. Or, if +** the buffer contains a changeset, so must have the earlier calls to this +** function. Otherwise, SQLITE_ERROR is returned and no changes are added +** to the changegroup. +** +** Rows within the changeset and changegroup are identified by the values in +** their PRIMARY KEY columns. A change in the changeset is considered to +** apply to the same row as a change already present in the changegroup if +** the two rows have the same primary key. +** +** Changes to rows that do not already appear in the changegroup are +** simply copied into it. Or, if both the new changeset and the changegroup +** contain changes that apply to a single row, the final contents of the +** changegroup depends on the type of each change, as follows: +** +** +** +** +**
    Existing Change New Change Output Change +**
    INSERT INSERT +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    INSERT UPDATE +** The INSERT change remains in the changegroup. The values in the +** INSERT change are modified as if the row was inserted by the +** existing change and then updated according to the new change. +**
    INSERT DELETE +** The existing INSERT is removed from the changegroup. The DELETE is +** not added. +**
    UPDATE INSERT +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    UPDATE UPDATE +** The existing UPDATE remains within the changegroup. It is amended +** so that the accompanying values are as if the row was updated once +** by the existing change and then again by the new change. +**
    UPDATE DELETE +** The existing UPDATE is replaced by the new DELETE within the +** changegroup. +**
    DELETE INSERT +** If one or more of the column values in the row inserted by the +** new change differ from those in the row deleted by the existing +** change, the existing DELETE is replaced by an UPDATE within the +** changegroup. Otherwise, if the inserted row is exactly the same +** as the deleted row, the existing DELETE is simply discarded. +**
    DELETE UPDATE +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    DELETE DELETE +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    +** +** If the new changeset contains changes to a table that is already present +** in the changegroup, then the number of columns and the position of the +** primary key columns for the table must be consistent. If this is not the +** case, this function fails with SQLITE_SCHEMA. If the input changeset +** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is +** returned. Or, if an out-of-memory condition occurs during processing, this +** function returns SQLITE_NOMEM. In all cases, if an error occurs the +** final contents of the changegroup is undefined. +** +** If no error occurs, SQLITE_OK is returned. +*/ +int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); + +/* +** CAPI3REF: Obtain A Composite Changeset From A Changegroup +** +** Obtain a buffer containing a changeset (or patchset) representing the +** current contents of the changegroup. If the inputs to the changegroup +** were themselves changesets, the output is a changeset. Or, if the +** inputs were patchsets, the output is also a patchset. +** +** As with the output of the sqlite3session_changeset() and +** sqlite3session_patchset() functions, all changes related to a single +** table are grouped together in the output of this function. Tables appear +** in the same order as for the very first changeset added to the changegroup. +** If the second or subsequent changesets added to the changegroup contain +** changes for tables that do not appear in the first changeset, they are +** appended onto the end of the output changeset, again in the order in +** which they are first encountered. +** +** If an error occurs, an SQLite error code is returned and the output +** variables (*pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK +** is returned and the output variables are set to the size of and a +** pointer to the output buffer, respectively. In this case it is the +** responsibility of the caller to eventually free the buffer using a +** call to sqlite3_free(). +*/ +int sqlite3changegroup_output( + sqlite3_changegroup*, + int *pnData, /* OUT: Size of output buffer in bytes */ + void **ppData /* OUT: Pointer to output buffer */ +); + +/* +** CAPI3REF: Delete A Changegroup Object +*/ +void sqlite3changegroup_delete(sqlite3_changegroup*); + +/* +** CAPI3REF: Apply A Changeset To A Database +** +** Apply a changeset to a database. This function attempts to update the +** "main" database attached to handle db with the changes found in the +** changeset passed via the second and third arguments. +** +** The fourth argument (xFilter) passed to this function is the "filter +** callback". If it is not NULL, then for each table affected by at least one +** change in the changeset, the filter callback is invoked with +** the table name as the second argument, and a copy of the context pointer +** passed as the sixth argument to this function as the first. If the "filter +** callback" returns zero, then no attempt is made to apply any changes to +** the table. Otherwise, if the return value is non-zero or the xFilter +** argument to this function is NULL, all changes related to the table are +** attempted. +** +** For each table that is not excluded by the filter callback, this function +** tests that the target database contains a compatible table. A table is +** considered compatible if all of the following are true: +** +**
      +**
    • 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 +** changeset, and +**
    • The table has primary key columns in the same position as +** recorded in the changeset. +**
    +** +** If there is no compatible table, it is not an error, but none of the +** changes associated with the table are applied. A warning message is issued +** via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most +** one such warning is issued for each table in the changeset. +** +** For each change for which there is a compatible table, an attempt is made +** to modify the table contents according to the UPDATE, INSERT or DELETE +** change. If a change cannot be applied cleanly, the conflict handler +** function passed as the fifth argument to sqlite3changeset_apply() may be +** invoked. A description of exactly when the conflict handler is invoked for +** each type of change is below. +** +** Unlike the xFilter argument, xConflict may not be passed NULL. The results +** of passing anything other than a valid function pointer as the xConflict +** argument are undefined. +** +** Each time the conflict handler function is invoked, it must return one +** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or +** [SQLITE_CHANGESET_REPLACE]. SQLITE_CHANGESET_REPLACE may only be returned +** if the second argument passed to the conflict handler is either +** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If the conflict-handler +** returns an illegal value, any changes already made are rolled back and +** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different +** actions are taken by sqlite3changeset_apply() depending on the value +** returned by each invocation of the conflict-handler function. Refer to +** the documentation for the three +** [SQLITE_CHANGESET_OMIT|available return values] for details. +** +**
    +**
    DELETE Changes
    +** For each DELETE 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 deleted from 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 the original +** row value stored in the changeset, the conflict-handler function is +** invoked with [SQLITE_CHANGESET_DATA] as the second argument. +** +** If no row with matching primary key values is found in the database, +** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] +** passed as the second argument. +** +** If the DELETE operation is attempted, but SQLite returns SQLITE_CONSTRAINT +** (which can only happen if a foreign key constraint is violated), the +** conflict-handler function is invoked with [SQLITE_CHANGESET_CONSTRAINT] +** passed as the second argument. This includes the case where the DELETE +** operation is attempted because an earlier call to the conflict handler +** function returned [SQLITE_CHANGESET_REPLACE]. +** +**
    INSERT Changes
    +** For each INSERT change, an attempt is made to insert the new row into +** the database. +** +** If the attempt to insert the row fails because the database already +** contains a row with the same primary key values, the conflict handler +** function is invoked with the second argument set to +** [SQLITE_CHANGESET_CONFLICT]. +** +** If the attempt to insert the row fails because of some other constraint +** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is +** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT]. +** This includes the case where the INSERT operation is re-attempted because +** an earlier call to the conflict handler function returned +** [SQLITE_CHANGESET_REPLACE]. +** +**
    UPDATE Changes
    +** 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. +** +** 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 +** 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. +** +** If no row with matching primary key values is found in the database, +** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] +** passed as the second argument. +** +** If the UPDATE operation is attempted, but SQLite returns +** SQLITE_CONSTRAINT, the conflict-handler function is invoked with +** [SQLITE_CHANGESET_CONSTRAINT] passed as the second argument. +** This includes the case where the UPDATE operation is attempted after +** an earlier call to the conflict handler function returned +** [SQLITE_CHANGESET_REPLACE]. +**
    +** +** It is safe to execute SQL statements, including those that write to the +** table that the callback related to, from within the xConflict callback. +** This can be used to further customize the applications conflict +** resolution strategy. +** +** All changes made by this function are enclosed in a savepoint transaction. +** If any other error (aside from a constraint failure when attempting to +** write to the target database) occurs, then the savepoint transaction is +** rolled back, restoring the target database to its original state, and an +** SQLite error code returned. +*/ +int sqlite3changeset_apply( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx /* First argument passed to xConflict */ +); + +/* +** CAPI3REF: Constants Passed To The Conflict Handler +** +** Values that may be passed as the second argument to a conflict-handler. +** +**
    +**
    SQLITE_CHANGESET_DATA
    +** The conflict handler is invoked with CHANGESET_DATA as the second argument +** when processing a DELETE or UPDATE change if a row with the required +** PRIMARY KEY fields is present in the database, but one or more other +** (non primary-key) fields modified by the update do not contain the +** expected "before" values. +** +** The conflicting row, in this case, is the database row with the matching +** primary key. +** +**
    SQLITE_CHANGESET_NOTFOUND
    +** The conflict handler is invoked with CHANGESET_NOTFOUND as the second +** argument when processing a DELETE or UPDATE change if a row with the +** required PRIMARY KEY fields is not present in the database. +** +** There is no conflicting row in this case. The results of invoking the +** sqlite3changeset_conflict() API are undefined. +** +**
    SQLITE_CHANGESET_CONFLICT
    +** CHANGESET_CONFLICT is passed as the second argument to the conflict +** handler while processing an INSERT change if the operation would result +** in duplicate primary key values. +** +** The conflicting row in this case is the database row with the matching +** primary key. +** +**
    SQLITE_CHANGESET_FOREIGN_KEY
    +** If foreign key handling is enabled, and applying a changeset leaves the +** database in a state containing foreign key violations, the conflict +** handler is invoked with CHANGESET_FOREIGN_KEY as the second argument +** exactly once before the changeset is committed. If the conflict handler +** returns CHANGESET_OMIT, the changes, including those that caused the +** foreign key constraint violation, are committed. Or, if it returns +** CHANGESET_ABORT, the changeset is rolled back. +** +** No current or conflicting row information is provided. The only function +** it is possible to call on the supplied sqlite3_changeset_iter handle +** is sqlite3changeset_fk_conflicts(). +** +**
    SQLITE_CHANGESET_CONSTRAINT
    +** If any other constraint violation occurs while applying a change (i.e. +** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is +** invoked with CHANGESET_CONSTRAINT as the second argument. +** +** There is no conflicting row in this case. The results of invoking the +** sqlite3changeset_conflict() API are undefined. +** +**
    +*/ +#define SQLITE_CHANGESET_DATA 1 +#define SQLITE_CHANGESET_NOTFOUND 2 +#define SQLITE_CHANGESET_CONFLICT 3 +#define SQLITE_CHANGESET_CONSTRAINT 4 +#define SQLITE_CHANGESET_FOREIGN_KEY 5 + +/* +** CAPI3REF: Constants Returned By The Conflict Handler +** +** A conflict handler callback must return one of the following three values. +** +**
    +**
    SQLITE_CHANGESET_OMIT
    +** If a conflict handler returns this value no special action is taken. The +** change that caused the conflict is not applied. The session module +** continues to the next change in the changeset. +** +**
    SQLITE_CHANGESET_REPLACE
    +** This value may only be returned if the second argument to the conflict +** handler was SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this +** is not the case, any changes applied so far are rolled back and the +** call to sqlite3changeset_apply() returns SQLITE_MISUSE. +** +** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_DATA conflict +** handler, then the conflicting row is either updated or deleted, depending +** on the type of change. +** +** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_CONFLICT conflict +** handler, then the conflicting row is removed from the database and a +** second attempt to apply the change is made. If this second attempt fails, +** the original row is restored to the database before continuing. +** +**
    SQLITE_CHANGESET_ABORT
    +** If this value is returned, any changes applied so far are rolled back +** and the call to sqlite3changeset_apply() returns SQLITE_ABORT. +**
    +*/ +#define SQLITE_CHANGESET_OMIT 0 +#define SQLITE_CHANGESET_REPLACE 1 +#define SQLITE_CHANGESET_ABORT 2 + +/* +** CAPI3REF: Streaming Versions of API functions. +** +** The six streaming API xxx_strm() functions serve similar purposes to the +** corresponding non-streaming API functions: +** +** +** +**
    Streaming functionNon-streaming equivalent
    sqlite3changeset_apply_str[sqlite3changeset_apply] +**
    sqlite3changeset_concat_str[sqlite3changeset_concat] +**
    sqlite3changeset_invert_str[sqlite3changeset_invert] +**
    sqlite3changeset_start_str[sqlite3changeset_start] +**
    sqlite3session_changeset_str[sqlite3session_changeset] +**
    sqlite3session_patchset_str[sqlite3session_patchset] +**
    +** +** Non-streaming functions that accept changesets (or patchsets) as input +** require that the entire changeset be stored in a single buffer in memory. +** Similarly, those that return a changeset or patchset do so by returning +** a pointer to a single large buffer allocated using sqlite3_malloc(). +** Normally this is convenient. However, if an application running in a +** low-memory environment is required to handle very large changesets, the +** large contiguous memory allocations required can become onerous. +** +** In order to avoid this problem, instead of a single large buffer, input +** is passed to a streaming API functions by way of a callback function that +** the sessions module invokes to incrementally request input data as it is +** required. In all cases, a pair of API function parameters such as +** +**
    +**        int nChangeset,
    +**        void *pChangeset,
    +**  
    +** +** Is replaced by: +** +**
    +**        int (*xInput)(void *pIn, void *pData, int *pnData),
    +**        void *pIn,
    +**  
    +** +** Each time the xInput callback is invoked by the sessions module, the first +** argument passed is a copy of the supplied pIn context pointer. The second +** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no +** error occurs the xInput method should copy up to (*pnData) bytes of data +** into the buffer and set (*pnData) to the actual number of bytes copied +** before returning SQLITE_OK. If the input is completely exhausted, (*pnData) +** should be set to zero to indicate this. Or, if an error occurs, an SQLite +** error code should be returned. In all cases, if an xInput callback returns +** an error, all processing is abandoned and the streaming API function +** returns a copy of the error code to the caller. +** +** In the case of sqlite3changeset_start_strm(), the xInput callback may be +** invoked by the sessions module at any point during the lifetime of the +** iterator. If such an xInput callback returns an error, the iterator enters +** an error state, whereby all subsequent calls to iterator functions +** immediately fail with the same error code as returned by xInput. +** +** Similarly, streaming API functions that return changesets (or patchsets) +** return them in chunks by way of a callback function instead of via a +** pointer to a single large buffer. In this case, a pair of parameters such +** as: +** +**
    +**        int *pnChangeset,
    +**        void **ppChangeset,
    +**  
    +** +** Is replaced by: +** +**
    +**        int (*xOutput)(void *pOut, const void *pData, int nData),
    +**        void *pOut
    +**  
    +** +** The xOutput callback is invoked zero or more times to return data to +** the application. The first parameter passed to each call is a copy of the +** pOut pointer supplied by the application. The second parameter, pData, +** points to a buffer nData bytes in size containing the chunk of output +** data being returned. If the xOutput callback successfully processes the +** supplied data, it should return SQLITE_OK to indicate success. Otherwise, +** it should return some other SQLite error code. In this case processing +** is immediately abandoned and the streaming API function returns a copy +** of the xOutput error code to the application. +** +** The sessions module never invokes an xOutput callback with the third +** 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( + 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 */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx /* First argument passed to xConflict */ +); +int sqlite3changeset_concat_strm( + int (*xInputA)(void *pIn, void *pData, int *pnData), + void *pInA, + int (*xInputB)(void *pIn, void *pData, int *pnData), + void *pInB, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +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( + sqlite3_changeset_iter **pp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn +); +int sqlite3session_changeset_strm( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +int sqlite3session_patchset_strm( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +int sqlite3changegroup_add_strm(sqlite3_changegroup*, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn +); +int sqlite3changegroup_output_strm(sqlite3_changegroup*, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); + + +/* +** Make sure we can call this stuff from C++. +*/ +#if 0 +} +#endif + +#endif /* !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) */ + +/******** End of sqlite3session.h *********/ +/******** Begin file fts5.h *********/ /* ** 2014 May 31 ** @@ -8522,11 +10193,13 @@ struct Fts5PhraseIter { ** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid ** ** with $p set to a phrase equivalent to the phrase iPhrase of the -** current query is executed. For each row visited, the callback function -** passed as the fourth argument is invoked. The context and API objects -** passed to the callback function may be used to access the properties of -** each matched row. Invoking Api.xUserData() returns a copy of the pointer -** passed as the third argument to pUserData. +** current query is executed. Any column filter that applies to +** phrase iPhrase of the current query is included in $p. For each +** row visited, the callback function passed as the fourth argument +** is invoked. The context and API objects passed to the callback +** function may be used to access the properties of each matched row. +** Invoking Api.xUserData() returns a copy of the pointer passed as +** the third argument to pUserData. ** ** If the callback function returns any value other than SQLITE_OK, the ** query is abandoned and the xQueryPhrase function returns immediately. @@ -8695,7 +10368,7 @@ struct Fts5ExtensionApi { ** behaviour. The structure methods are expected to function as follows: ** ** xCreate: -** This function is used to allocate and inititalize a tokenizer instance. +** This function is used to allocate and initialize a tokenizer instance. ** A tokenizer instance is required to actually tokenize text. ** ** The first argument passed to this function is a copy of the (void*) @@ -8955,7 +10628,7 @@ struct fts5_api { #endif /* _FTS5_H */ - +/******** End of fts5.h *********/ /************** End of sqlite3.h *********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -9252,7 +10925,7 @@ struct fts5_api { ** the SQLITE_DISABLE_INTRINSIC define. */ #if !defined(SQLITE_DISABLE_INTRINSIC) -# if defined(_MSC_VER) && _MSC_VER>=1300 +# if defined(_MSC_VER) && _MSC_VER>=1400 # if !defined(_WIN32_WCE) # include # pragma intrinsic(_byteswap_ushort) @@ -9437,7 +11110,7 @@ SQLITE_PRIVATE void sqlite3Coverage(int); ** be true and false so that the unreachable code they specify will ** not be counted as untested code. */ -#if defined(SQLITE_COVERAGE_TEST) +#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) # define ALWAYS(X) (1) # define NEVER(X) (0) #elif !defined(NDEBUG) @@ -9529,8 +11202,8 @@ SQLITE_PRIVATE void sqlite3Coverage(int); ** This is the header file for the generic hash-table implementation ** used in SQLite. */ -#ifndef _SQLITE_HASH_H_ -#define _SQLITE_HASH_H_ +#ifndef SQLITE_HASH_H +#define SQLITE_HASH_H /* Forward declarations of structures. */ typedef struct Hash Hash; @@ -9610,7 +11283,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); */ /* #define sqliteHashCount(H) ((H)->count) // NOT USED */ -#endif /* _SQLITE_HASH_H_ */ +#endif /* SQLITE_HASH_H */ /************** End of hash.h ************************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -9642,76 +11315,76 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_AS 24 #define TK_WITHOUT 25 #define TK_COMMA 26 -#define TK_ID 27 -#define TK_INDEXED 28 -#define TK_ABORT 29 -#define TK_ACTION 30 -#define TK_AFTER 31 -#define TK_ANALYZE 32 -#define TK_ASC 33 -#define TK_ATTACH 34 -#define TK_BEFORE 35 -#define TK_BY 36 -#define TK_CASCADE 37 -#define TK_CAST 38 -#define TK_COLUMNKW 39 -#define TK_CONFLICT 40 -#define TK_DATABASE 41 -#define TK_DESC 42 -#define TK_DETACH 43 -#define TK_EACH 44 -#define TK_FAIL 45 -#define TK_FOR 46 -#define TK_IGNORE 47 -#define TK_INITIALLY 48 -#define TK_INSTEAD 49 -#define TK_LIKE_KW 50 -#define TK_MATCH 51 -#define TK_NO 52 -#define TK_KEY 53 -#define TK_OF 54 -#define TK_OFFSET 55 -#define TK_PRAGMA 56 -#define TK_RAISE 57 -#define TK_RECURSIVE 58 -#define TK_REPLACE 59 -#define TK_RESTRICT 60 -#define TK_ROW 61 -#define TK_TRIGGER 62 -#define TK_VACUUM 63 -#define TK_VIEW 64 -#define TK_VIRTUAL 65 -#define TK_WITH 66 -#define TK_REINDEX 67 -#define TK_RENAME 68 -#define TK_CTIME_KW 69 -#define TK_ANY 70 -#define TK_OR 71 -#define TK_AND 72 -#define TK_IS 73 -#define TK_BETWEEN 74 -#define TK_IN 75 -#define TK_ISNULL 76 -#define TK_NOTNULL 77 -#define TK_NE 78 -#define TK_EQ 79 -#define TK_GT 80 -#define TK_LE 81 -#define TK_LT 82 -#define TK_GE 83 -#define TK_ESCAPE 84 -#define TK_BITAND 85 -#define TK_BITOR 86 -#define TK_LSHIFT 87 -#define TK_RSHIFT 88 -#define TK_PLUS 89 -#define TK_MINUS 90 -#define TK_STAR 91 -#define TK_SLASH 92 -#define TK_REM 93 -#define TK_CONCAT 94 -#define TK_COLLATE 95 -#define TK_BITNOT 96 +#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_STRING 97 #define TK_JOIN_KW 98 #define TK_CONSTRAINT 99 @@ -9747,9 +11420,9 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_LIMIT 129 #define TK_WHERE 130 #define TK_INTO 131 -#define TK_INTEGER 132 -#define TK_FLOAT 133 -#define TK_BLOB 134 +#define TK_FLOAT 132 +#define TK_BLOB 133 +#define TK_INTEGER 134 #define TK_VARIABLE 135 #define TK_CASE 136 #define TK_WHEN 137 @@ -9773,10 +11446,12 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_UMINUS 155 #define TK_UPLUS 156 #define TK_REGISTER 157 -#define TK_ASTERISK 158 -#define TK_SPAN 159 -#define TK_SPACE 160 -#define TK_ILLEGAL 161 +#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 /* The token codes above must all fit in 8 bits */ #define TKFLG_MASK 0xff @@ -10258,8 +11933,8 @@ struct BusyHandler { #define SQLITE_WSD const #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v))) #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config) -SQLITE_API int SQLITE_STDCALL sqlite3_wsd_init(int N, int J); -SQLITE_API void *SQLITE_STDCALL sqlite3_wsd_find(void *K, int L); +SQLITE_API int sqlite3_wsd_init(int N, int J); +SQLITE_API void *sqlite3_wsd_find(void *K, int L); #else #define SQLITE_WSD #define GLOBAL(t,v) v @@ -10313,6 +11988,7 @@ typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; typedef struct Parse Parse; +typedef struct PreUpdate PreUpdate; typedef struct PrintfArguments PrintfArguments; typedef struct RowSet RowSet; typedef struct Savepoint Savepoint; @@ -10357,8 +12033,8 @@ typedef struct With With; ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. */ -#ifndef _BTREE_H_ -#define _BTREE_H_ +#ifndef SQLITE_BTREE_H +#define SQLITE_BTREE_H /* TODO: This definition is just included so other modules compile. It ** needs to be revisited. @@ -10383,6 +12059,7 @@ typedef struct With With; typedef struct Btree Btree; typedef struct BtCursor BtCursor; typedef struct BtShared BtShared; +typedef struct BtreePayload BtreePayload; SQLITE_PRIVATE int sqlite3BtreeOpen( @@ -10433,7 +12110,9 @@ SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*); SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree); +#ifndef SQLITE_OMIT_SHARED_CACHE SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock); +#endif SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int); SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); @@ -10594,26 +12273,52 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags); #define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */ #define BTREE_AUXDELETE 0x04 /* not the primary delete operation */ -SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, - const void *pData, int nData, - int nZero, int bias, int seekResult); +/* An instance of the BtreePayload object describes the content of a single +** entry in either an index or table btree. +** +** Index btrees (used for indexes and also WITHOUT ROWID tables) contain +** an arbitrary key and no data. These btrees have pKey,nKey set to their +** key and pData,nData,nZero set to zero. +** +** Table btrees (used for rowid tables) contain an integer rowid used as +** the key and passed in the nKey field. The pKey field is zero. +** pData,nData hold the content of the new entry. nZero extra zero bytes +** are appended to the end of the content when constructing the entry. +** +** This object is used to pass information into sqlite3BtreeInsert(). The +** same information used to be passed as five separate parameters. But placing +** the information into this object helps to keep the interface more +** organized and understandable, and it also helps the resulting code to +** run a little faster by using fewer registers for parameter passing. +*/ +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 */ + 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); SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes); -SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor*, i64 *pSize); +SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); -SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, u32 *pAmt); -SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, u32 *pAmt); -SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); +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*); +#ifndef SQLITE_OMIT_INCRBLOB SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *); +#endif SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *); SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask); @@ -10647,11 +12352,13 @@ SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*); SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*); SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*); SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree*); #else # define sqlite3BtreeEnter(X) # define sqlite3BtreeEnterAll(X) # define sqlite3BtreeSharable(X) 0 # define sqlite3BtreeEnterCursor(X) +# define sqlite3BtreeConnectionCount(X) 1 #endif #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE @@ -10676,7 +12383,7 @@ SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*); #endif -#endif /* _BTREE_H_ */ +#endif /* SQLITE_BTREE_H */ /************** End of btree.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -10699,8 +12406,8 @@ SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*); ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. */ -#ifndef _SQLITE_VDBE_H_ -#define _SQLITE_VDBE_H_ +#ifndef SQLITE_VDBE_H +#define SQLITE_VDBE_H /* #include */ /* @@ -10725,7 +12432,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 opflags; /* Mask of the OPFLG_* flags in opcodes.h */ + u8 notUsed1; u8 p5; /* Fifth parameter is an unsigned character */ int p1; /* First operand */ int p2; /* Second parameter (often the jump destination) */ @@ -10744,6 +12451,7 @@ struct VdbeOp { KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ int *ai; /* Used when p4type is P4_INTARRAY */ SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ + Table *pTab; /* Used when p4type is P4_TABLE */ #ifdef SQLITE_ENABLE_CURSOR_HINTS Expr *pExpr; /* Used when p4type is P4_EXPR */ #endif @@ -10771,7 +12479,6 @@ struct SubProgram { int nOp; /* Elements in aOp[] */ int nMem; /* Number of memory cells required */ int nCsr; /* Number of cursors required */ - int nOnce; /* Number of OP_Once instructions */ void *token; /* id that may be used to recursive triggers */ SubProgram *pNext; /* Next sub-program already visited */ }; @@ -10808,7 +12515,8 @@ typedef struct VdbeOpList VdbeOpList; #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_FUNCCTX (-20) /* P4 is a pointer to an sqlite3_context object */ +#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 */ /* Error message codes for OP_Halt */ #define P5_ConstraintNotNull 1 @@ -10866,153 +12574,154 @@ typedef struct VdbeOpList VdbeOpList; #define OP_VUpdate 12 /* synopsis: data=r[P3@P2] */ #define OP_Goto 13 #define OP_Gosub 14 -#define OP_Return 15 -#define OP_InitCoroutine 16 -#define OP_EndCoroutine 17 -#define OP_Yield 18 +#define OP_InitCoroutine 15 +#define OP_Yield 16 +#define OP_MustBeInt 17 +#define OP_Jump 18 #define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ -#define OP_HaltIfNull 20 /* synopsis: if r[P3]=null halt */ -#define OP_Halt 21 -#define OP_Integer 22 /* synopsis: r[P2]=P1 */ -#define OP_Int64 23 /* synopsis: r[P2]=P4 */ -#define OP_String 24 /* synopsis: r[P2]='P4' (len=P1) */ -#define OP_Null 25 /* synopsis: r[P2..P3]=NULL */ -#define OP_SoftNull 26 /* synopsis: r[P1]=NULL */ -#define OP_Blob 27 /* synopsis: r[P2]=P4 (len=P1) */ -#define OP_Variable 28 /* synopsis: r[P2]=parameter(P1,P4) */ -#define OP_Move 29 /* synopsis: r[P2@P3]=r[P1@P3] */ -#define OP_Copy 30 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ -#define OP_SCopy 31 /* synopsis: r[P2]=r[P1] */ -#define OP_IntCopy 32 /* synopsis: r[P2]=r[P1] */ -#define OP_ResultRow 33 /* synopsis: output=r[P1@P2] */ -#define OP_CollSeq 34 -#define OP_Function0 35 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_Function 36 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_AddImm 37 /* synopsis: r[P1]=r[P1]+P2 */ -#define OP_MustBeInt 38 -#define OP_RealAffinity 39 -#define OP_Cast 40 /* synopsis: affinity(r[P1]) */ -#define OP_Permutation 41 -#define OP_Compare 42 /* synopsis: r[P1@P3] <-> r[P2@P3] */ -#define OP_Jump 43 -#define OP_Once 44 -#define OP_If 45 -#define OP_IfNot 46 -#define OP_Column 47 /* synopsis: r[P3]=PX */ -#define OP_Affinity 48 /* synopsis: affinity(r[P1@P2]) */ -#define OP_MakeRecord 49 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ -#define OP_Count 50 /* synopsis: r[P2]=count() */ -#define OP_ReadCookie 51 -#define OP_SetCookie 52 -#define OP_ReopenIdx 53 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenRead 54 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenWrite 55 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenAutoindex 56 /* synopsis: nColumn=P2 */ -#define OP_OpenEphemeral 57 /* synopsis: nColumn=P2 */ -#define OP_SorterOpen 58 -#define OP_SequenceTest 59 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ -#define OP_OpenPseudo 60 /* synopsis: P3 columns in r[P2] */ -#define OP_Close 61 -#define OP_ColumnsUsed 62 -#define OP_SeekLT 63 /* synopsis: key=r[P3@P4] */ -#define OP_SeekLE 64 /* synopsis: key=r[P3@P4] */ -#define OP_SeekGE 65 /* synopsis: key=r[P3@P4] */ -#define OP_SeekGT 66 /* synopsis: key=r[P3@P4] */ -#define OP_NoConflict 67 /* synopsis: key=r[P3@P4] */ -#define OP_NotFound 68 /* synopsis: key=r[P3@P4] */ -#define OP_Found 69 /* synopsis: key=r[P3@P4] */ -#define OP_NotExists 70 /* synopsis: intkey=r[P3] */ -#define OP_Or 71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ -#define OP_And 72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ -#define OP_Sequence 73 /* synopsis: r[P2]=cursor[P1].ctr++ */ -#define OP_NewRowid 74 /* synopsis: r[P2]=rowid */ -#define OP_Insert 75 /* synopsis: intkey=r[P3] data=r[P2] */ -#define OP_IsNull 76 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ -#define OP_NotNull 77 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ -#define OP_Ne 78 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */ -#define OP_Eq 79 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */ -#define OP_Gt 80 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */ -#define OP_Le 81 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */ -#define OP_Lt 82 /* same as TK_LT, synopsis: if r[P1]=r[P3] goto P2 */ -#define OP_InsertInt 84 /* synopsis: intkey=P3 data=r[P2] */ -#define OP_BitAnd 85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ -#define OP_BitOr 86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ -#define OP_ShiftLeft 87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */ -#define OP_Add 89 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ -#define OP_Subtract 90 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ -#define OP_Multiply 91 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ -#define OP_Divide 92 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ -#define OP_Remainder 93 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ -#define OP_Concat 94 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ -#define OP_Delete 95 -#define OP_BitNot 96 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ +#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_Column 96 /* synopsis: r[P3]=PX */ #define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ -#define OP_ResetCount 98 -#define OP_SorterCompare 99 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ -#define OP_SorterData 100 /* synopsis: r[P2]=data */ -#define OP_RowKey 101 /* synopsis: r[P2]=key */ -#define OP_RowData 102 /* synopsis: r[P2]=data */ -#define OP_Rowid 103 /* synopsis: r[P2]=rowid */ -#define OP_NullRow 104 -#define OP_Last 105 -#define OP_SorterSort 106 -#define OP_Sort 107 -#define OP_Rewind 108 -#define OP_SorterInsert 109 -#define OP_IdxInsert 110 /* synopsis: key=r[P2] */ -#define OP_IdxDelete 111 /* synopsis: key=r[P2@P3] */ -#define OP_Seek 112 /* synopsis: Move P3 to P1.rowid */ -#define OP_IdxRowid 113 /* synopsis: r[P2]=rowid */ -#define OP_IdxLE 114 /* synopsis: key=r[P3@P4] */ -#define OP_IdxGT 115 /* synopsis: key=r[P3@P4] */ -#define OP_IdxLT 116 /* synopsis: key=r[P3@P4] */ -#define OP_IdxGE 117 /* synopsis: key=r[P3@P4] */ -#define OP_Destroy 118 -#define OP_Clear 119 -#define OP_ResetSorter 120 -#define OP_CreateIndex 121 /* synopsis: r[P2]=root iDb=P1 */ -#define OP_CreateTable 122 /* synopsis: r[P2]=root iDb=P1 */ -#define OP_ParseSchema 123 -#define OP_LoadAnalysis 124 -#define OP_DropTable 125 -#define OP_DropIndex 126 -#define OP_DropTrigger 127 -#define OP_IntegrityCk 128 -#define OP_RowSetAdd 129 /* synopsis: rowset(P1)=r[P2] */ -#define OP_RowSetRead 130 /* synopsis: r[P3]=rowset(P1) */ -#define OP_RowSetTest 131 /* synopsis: if r[P3] in rowset(P1) goto P2 */ -#define OP_Program 132 -#define OP_Real 133 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ -#define OP_Param 134 -#define OP_FkCounter 135 /* synopsis: fkctr[P1]+=P2 */ -#define OP_FkIfZero 136 /* synopsis: if fkctr[P1]==0 goto P2 */ -#define OP_MemMax 137 /* synopsis: r[P1]=max(r[P1],r[P2]) */ -#define OP_IfPos 138 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ -#define OP_OffsetLimit 139 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ -#define OP_IfNotZero 140 /* synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 */ -#define OP_DecrJumpZero 141 /* synopsis: if (--r[P1])==0 goto P2 */ -#define OP_JumpZeroIncr 142 /* synopsis: if (r[P1]++)==0 ) goto P2 */ -#define OP_AggStep0 143 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggStep 144 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggFinal 145 /* synopsis: accum=r[P1] N=P2 */ -#define OP_IncrVacuum 146 -#define OP_Expire 147 -#define OP_TableLock 148 /* synopsis: iDb=P1 root=P2 write=P3 */ -#define OP_VBegin 149 -#define OP_VCreate 150 -#define OP_VDestroy 151 -#define OP_VOpen 152 -#define OP_VColumn 153 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VNext 154 -#define OP_VRename 155 -#define OP_Pagecount 156 -#define OP_MaxPgcnt 157 -#define OP_Init 158 /* synopsis: Start at P2 */ -#define OP_CursorHint 159 -#define OP_Noop 160 -#define OP_Explain 161 +#define OP_Affinity 98 /* synopsis: affinity(r[P1@P2]) */ +#define OP_MakeRecord 99 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +#define OP_Count 100 /* synopsis: r[P2]=count() */ +#define OP_ReadCookie 101 +#define OP_SetCookie 102 +#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_RowData 122 /* synopsis: r[P2]=data */ +#define OP_Rowid 123 /* synopsis: r[P2]=rowid */ +#define OP_NullRow 124 +#define OP_SorterInsert 125 +#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_IdxRowid 129 /* synopsis: r[P2]=rowid */ +#define OP_Destroy 130 +#define OP_Clear 131 +#define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ +#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 /* Properties such as "out2" or "jump" that are specified in ** comments following the "case" for each opcode in the vdbe.c @@ -11026,26 +12735,34 @@ typedef struct VdbeOpList VdbeOpList; #define OPFLG_OUT3 0x20 /* out3: P3 is an output */ #define OPFLG_INITIALIZER {\ /* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,\ -/* 8 */ 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x02,\ -/* 16 */ 0x01, 0x02, 0x03, 0x12, 0x08, 0x00, 0x10, 0x10,\ -/* 24 */ 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,\ -/* 32 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x02,\ -/* 40 */ 0x02, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x00,\ -/* 48 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\ -/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,\ -/* 64 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x26,\ -/* 72 */ 0x26, 0x10, 0x10, 0x00, 0x03, 0x03, 0x0b, 0x0b,\ -/* 80 */ 0x0b, 0x0b, 0x0b, 0x0b, 0x00, 0x26, 0x26, 0x26,\ -/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00,\ -/* 96 */ 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ -/* 104 */ 0x00, 0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x00,\ -/* 112 */ 0x00, 0x10, 0x01, 0x01, 0x01, 0x01, 0x10, 0x00,\ -/* 120 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 128 */ 0x00, 0x06, 0x23, 0x0b, 0x01, 0x10, 0x10, 0x00,\ -/* 136 */ 0x01, 0x04, 0x03, 0x1a, 0x03, 0x03, 0x03, 0x00,\ -/* 144 */ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 152 */ 0x00, 0x00, 0x01, 0x00, 0x10, 0x10, 0x01, 0x00,\ -/* 160 */ 0x00, 0x00,} +/* 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,\ +/* 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,\ +/* 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,} + +/* The sqlite3P2Values() routine is able to run faster if it knows +** the value of the largest JUMP opcode. The smaller the maximum +** JUMP opcode the better, so the mkopcodeh.tcl script that +** 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 */ /************** End of opcodes.h *********************************************/ /************** Continuing where we left off in vdbe.h ***********************/ @@ -11192,7 +12909,7 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const ch # define sqlite3VdbeScanStatus(a,b,c,d,e) #endif -#endif +#endif /* SQLITE_VDBE_H */ /************** End of vdbe.h ************************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -11214,8 +12931,8 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const ch ** at a time and provides a journal for rollback. */ -#ifndef _PAGER_H_ -#define _PAGER_H_ +#ifndef SQLITE_PAGER_H +#define SQLITE_PAGER_H /* ** Default maximum size for persistent journal files. A negative @@ -11268,7 +12985,11 @@ typedef struct PgHdr DbPage; #define PAGER_LOCKINGMODE_EXCLUSIVE 1 /* -** Numeric constants that encode the journalmode. +** Numeric constants that encode the journalmode. +** +** The numeric values encoded here (other than PAGER_JOURNALMODE_QUERY) +** are exposed in the API via the "PRAGMA journal_mode" command and +** therefore cannot be changed without a compatibility break. */ #define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */ #define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */ @@ -11286,6 +13007,11 @@ typedef struct PgHdr DbPage; /* ** Flags for sqlite3PagerSetFlags() +** +** Value constraints (enforced via assert()): +** PAGER_FULLFSYNC == SQLITE_FullFSync +** PAGER_CKPT_FULLFSYNC == SQLITE_CkptFullFSync +** PAGER_CACHE_SPILL == SQLITE_CacheSpill */ #define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */ #define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */ @@ -11369,10 +13095,13 @@ 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); # ifdef SQLITE_ENABLE_SNAPSHOT SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); # endif +#else +# define sqlite3PagerUseWal(x) 0 #endif #ifdef SQLITE_ENABLE_ZIPVFS @@ -11394,7 +13123,7 @@ SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*); SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *); -SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *); +SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*); SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); /* Functions used to truncate the database file. */ @@ -11421,7 +13150,7 @@ SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*); # define enable_simulated_io_errors() #endif -#endif /* _PAGER_H_ */ +#endif /* SQLITE_PAGER_H */ /************** End of pager.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -11455,7 +13184,7 @@ struct PgHdr { sqlite3_pcache_page *pPage; /* Pcache object page handle */ void *pData; /* Page data */ void *pExtra; /* Extra content */ - PgHdr *pDirty; /* Transient list of dirty pages */ + 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 */ #ifdef SQLITE_CHECK_PAGES @@ -11480,11 +13209,10 @@ struct PgHdr { #define PGHDR_WRITEABLE 0x004 /* Journaled and ready to modify */ #define PGHDR_NEED_SYNC 0x008 /* Fsync the rollback journal before ** writing this page to the database */ -#define PGHDR_NEED_READ 0x010 /* Content is unread */ -#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ -#define PGHDR_MMAP 0x040 /* This is an mmap page object */ +#define PGHDR_DONT_WRITE 0x010 /* Do not write content to disk */ +#define PGHDR_MMAP 0x020 /* This is an mmap page object */ -#define PGHDR_WAL_APPEND 0x080 /* Appended to wal file */ +#define PGHDR_WAL_APPEND 0x040 /* Appended to wal file */ /* Initialize and shutdown the page cache subsystem */ SQLITE_PRIVATE int sqlite3PcacheInitialize(void); @@ -11528,6 +13256,7 @@ SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */ SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */ SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */ +SQLITE_PRIVATE void sqlite3PcacheClearWritable(PCache*); /* Change a page number. Used by incr-vacuum. */ SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr*, Pgno); @@ -11566,6 +13295,11 @@ SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*); SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)); #endif +#if defined(SQLITE_DEBUG) +/* Check invariants on a PgHdr object */ +SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr*); +#endif + /* Set and get the suggested cache-size for the specified pager-cache. ** ** If no global maximum is configured, then the system attempts to limit @@ -11602,6 +13336,9 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void); SQLITE_PRIVATE int sqlite3HeaderSizePcache(void); SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void); +/* Number of dirty pages as a percentage of the configured cache size */ +SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*); + #endif /* _PCACHE_H_ */ /************** End of pcache.h **********************************************/ @@ -11651,8 +13388,8 @@ SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void); ** This file contains pre-processor directives related to operating system ** detection and/or setup. */ -#ifndef _OS_SETUP_H_ -#define _OS_SETUP_H_ +#ifndef SQLITE_OS_SETUP_H +#define SQLITE_OS_SETUP_H /* ** Figure out if we are dealing with Unix, Windows, or some other operating @@ -11692,7 +13429,7 @@ SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void); # endif #endif -#endif /* _OS_SETUP_H_ */ +#endif /* SQLITE_OS_SETUP_H */ /************** End of os_setup.h ********************************************/ /************** Continuing where we left off in os.h *************************/ @@ -11831,7 +13568,7 @@ SQLITE_PRIVATE int sqlite3OsInit(void); /* ** Functions for accessing sqlite3_file methods */ -SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file*); +SQLITE_PRIVATE void sqlite3OsClose(sqlite3_file*); SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset); SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset); SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size); @@ -11876,7 +13613,7 @@ SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*); ** sqlite3_malloc() to obtain space for the file-handle structure. */ SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*); -SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *); +SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *); #endif /* _SQLITE_OS_H_ */ @@ -11997,7 +13734,7 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *); ** databases may be attached. */ struct Db { - char *zName; /* Name of this database */ + char *zDbSName; /* Name of this database. (schema name, not filename) */ Btree *pBt; /* The B*Tree structure for this database file */ u8 safety_level; /* How aggressive at syncing data to disk */ u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */ @@ -12149,6 +13886,15 @@ SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**); const char*); #endif +#ifndef SQLITE_OMIT_DEPRECATED +/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing +** in the style of sqlite3_trace() +*/ +#define SQLITE_TRACE_LEGACY 0x80 +#else +#define SQLITE_TRACE_LEGACY 0 +#endif /* SQLITE_OMIT_DEPRECATED */ + /* ** Each database connection is an instance of the following structure. @@ -12178,6 +13924,7 @@ struct sqlite3 { u8 suppressErr; /* Do not issue error messages if true */ 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 */ int nextPagesize; /* Pagesize after VACUUM if >0 */ u32 magic; /* Magic number for detect library misuse */ int nChange; /* Value returned by sqlite3_changes() */ @@ -12198,7 +13945,7 @@ struct sqlite3 { int nVDestroy; /* Number of active OP_VDestroy operations */ int nExtension; /* Number of loaded extensions */ void **aExtension; /* Array of shared library handles */ - void (*xTrace)(void*,const char*); /* Trace function */ + int (*xTrace)(u32,void*,void*,void*); /* Trace function */ void *pTraceArg; /* Argument to the trace function */ void (*xProfile)(void*,const char*,u64); /* Profiling function */ void *pProfileArg; /* Argument to profile function */ @@ -12208,6 +13955,13 @@ struct sqlite3 { void (*xRollbackCallback)(void*); /* Invoked at every commit. */ void *pUpdateArg; void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + void *pPreUpdateArg; /* First argument to xPreUpdateCallback */ + void (*xPreUpdateCallback)( /* Registered using sqlite3_preupdate_hook() */ + void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64 + ); + PreUpdate *pPreUpdate; /* Context for active pre-update callback */ +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ #ifndef SQLITE_OMIT_WAL int (*xWalCallback)(void *, sqlite3 *, const char *, int); void *pWalArg; @@ -12278,6 +14032,11 @@ struct sqlite3 { /* ** Possible values for the sqlite3.flags. +** +** Value constraints (enforced via assert()): +** SQLITE_FullFSync == PAGER_FULLFSYNC +** 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 */ @@ -12305,13 +14064,14 @@ struct sqlite3 { #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_EnableTrigger 0x00800000 /* True to enable triggers */ -#define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */ -#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */ -#define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */ -#define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */ -#define SQLITE_CellSizeCk 0x10000000 /* Check btree cell sizes on load */ -#define SQLITE_Fts3Tokenizer 0x20000000 /* Enable fts3_tokenizer(2) */ +#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) */ /* @@ -12412,6 +14172,13 @@ struct FuncDestructor { ** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And ** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There ** are assert() statements in the code to verify this. +** +** Value constraints (enforced via assert()): +** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg +** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG +** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG +** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API +** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API */ #define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ #define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */ @@ -12603,6 +14370,7 @@ struct CollSeq { ** operator is NULL. It is added to certain comparison operators to ** prove that the operands are always NOT NULL. */ +#define SQLITE_KEEPNULL 0x08 /* Used by vector == or <> */ #define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */ #define SQLITE_STOREP2 0x20 /* Store result in reg[P2] rather than jump */ #define SQLITE_NULLEQ 0x80 /* NULL=NULL */ @@ -13167,9 +14935,11 @@ struct Expr { int iTable; /* TK_COLUMN: cursor number of table holding column ** TK_REGISTER: register number ** TK_TRIGGER: 1 -> new, 0 -> old - ** EP_Unlikely: 134217728 times likelihood */ + ** EP_Unlikely: 134217728 times likelihood + ** TK_SELECT: 1st register of result vector */ ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. - ** TK_VARIABLE: variable number (always >= 1). */ + ** TK_VARIABLE: variable number (always >= 1). + ** TK_SELECT_COLUMN: column of the result vector */ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ u8 op2; /* TK_REGISTER: original value of Expr.op @@ -13205,6 +14975,7 @@ struct Expr { #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ #define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ #define EP_Alias 0x400000 /* Is an alias for a result set column */ +#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ /* ** Combinations of two or more EP_* flags @@ -13373,7 +15144,7 @@ struct SrcList { int regReturn; /* Register holding return address of addrFillSub */ int regResult; /* Registers holding results of a co-routine */ struct { - u8 jointype; /* Type of join between this able and the previous */ + u8 jointype; /* Type of join between this table and the previous */ unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */ unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */ unsigned isTabFunc :1; /* True if table-valued-function syntax */ @@ -13411,23 +15182,28 @@ struct SrcList { /* ** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin() ** and the WhereInfo.wctrlFlags member. +** +** Value constraints (enforced via assert()): +** WHERE_USE_LIMIT == SF_FixedLimit */ #define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */ #define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */ #define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */ #define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */ -#define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */ -#define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */ -#define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */ -#define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */ -#define WHERE_NO_AUTOINDEX 0x0080 /* Disallow automatic indexes */ -#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */ -#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */ -#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */ -#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */ -#define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */ -#define WHERE_ONEPASS_MULTIROW 0x2000 /* ONEPASS is ok with multiple rows */ -#define WHERE_USE_LIMIT 0x4000 /* There is a constant LIMIT clause */ +#define WHERE_ONEPASS_MULTIROW 0x0008 /* ONEPASS is ok with multiple rows */ +#define WHERE_DUPLICATES_OK 0x0010 /* Ok to return a row more than once */ +#define WHERE_OR_SUBCLAUSE 0x0020 /* Processing a sub-WHERE as part of + ** the OR optimization */ +#define WHERE_GROUPBY 0x0040 /* pOrderBy is really a GROUP BY */ +#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */ +#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */ +#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 */ + /* 0x2000 not currently used */ +#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */ + /* 0x8000 not currently used */ /* Allowed return values from sqlite3WhereIsDistinct() */ @@ -13471,16 +15247,18 @@ struct NameContext { /* ** Allowed values for the NameContext, ncFlags field. ** -** Note: NC_MinMaxAgg must have the same value as SF_MinMaxAgg and -** SQLITE_FUNC_MINMAX. +** Value constraints (all checked via assert()): +** NC_HasAgg == SF_HasAgg +** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX ** */ #define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */ -#define NC_HasAgg 0x0002 /* One or more aggregate functions seen */ +#define NC_PartIdx 0x0002 /* True if resolving a partial index WHERE */ #define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */ #define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */ -#define NC_PartIdx 0x0010 /* True if resolving a partial index WHERE */ +#define NC_HasAgg 0x0010 /* One or more aggregate functions seen */ #define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */ +#define NC_VarSelect 0x0040 /* A correlated subquery has been seen */ #define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */ /* @@ -13528,24 +15306,30 @@ struct Select { /* ** Allowed values for Select.selFlags. The "SF" prefix stands for ** "Select Flag". +** +** Value constraints (all checked via assert()) +** SF_HasAgg == NC_HasAgg +** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX +** SF_FixedLimit == WHERE_USE_LIMIT */ #define SF_Distinct 0x00001 /* Output should be DISTINCT */ #define SF_All 0x00002 /* Includes the ALL keyword */ #define SF_Resolved 0x00004 /* Identifiers have been resolved */ -#define SF_Aggregate 0x00008 /* Contains aggregate functions */ -#define SF_UsesEphemeral 0x00010 /* Uses the OpenEphemeral opcode */ -#define SF_Expanded 0x00020 /* sqlite3SelectExpand() called on this */ -#define SF_HasTypeInfo 0x00040 /* FROM subqueries have Table metadata */ -#define SF_Compound 0x00080 /* Part of a compound query */ -#define SF_Values 0x00100 /* Synthesized from VALUES clause */ -#define SF_MultiValue 0x00200 /* Single VALUES term with multiple rows */ -#define SF_NestedFrom 0x00400 /* Part of a parenthesized FROM clause */ -#define SF_MaybeConvert 0x00800 /* Need convertCompoundSelectToSubquery() */ +#define SF_Aggregate 0x00008 /* Contains agg functions or a GROUP BY */ +#define SF_HasAgg 0x00010 /* Contains aggregate functions */ +#define SF_UsesEphemeral 0x00020 /* Uses the OpenEphemeral opcode */ +#define SF_Expanded 0x00040 /* sqlite3SelectExpand() called on this */ +#define SF_HasTypeInfo 0x00080 /* FROM subqueries have Table metadata */ +#define SF_Compound 0x00100 /* Part of a compound query */ +#define SF_Values 0x00200 /* Synthesized from VALUES clause */ +#define SF_MultiValue 0x00400 /* Single VALUES term with multiple rows */ +#define SF_NestedFrom 0x00800 /* Part of a parenthesized FROM clause */ #define SF_MinMaxAgg 0x01000 /* Aggregate containing min() or max() */ #define SF_Recursive 0x02000 /* The recursive part of a recursive CTE */ #define SF_FixedLimit 0x04000 /* nSelectRow set by a constant LIMIT */ -#define SF_Converted 0x08000 /* By convertCompoundSelectToSubquery() */ -#define SF_IncludeHidden 0x10000 /* Include hidden columns in output */ +#define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */ +#define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */ +#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */ /* @@ -13637,7 +15421,7 @@ struct Select { */ struct SelectDest { u8 eDest; /* How to dispose of the results. On of SRT_* above. */ - char affSdst; /* Affinity used when eDest==SRT_Set */ + 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 */ @@ -13742,36 +15526,24 @@ struct Parse { u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ u8 okConstFactor; /* OK to factor out constants */ u8 disableLookaside; /* Number of times lookaside has been disabled */ - int aTempReg[8]; /* Holding area for temporary registers */ + u8 nColCache; /* Number of entries in aColCache[] */ int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ - int nSet; /* Number of sets used so far */ - int nOnce; /* Number of OP_Once instructions so far */ int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ - int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */ int ckBase; /* Base register of data during check constraints */ int iSelfTab; /* Table of an index whose exprs are being coded */ int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ int iCacheCnt; /* Counter used to generate aColCache[].lru values */ int nLabel; /* Number of labels used */ int *aLabel; /* Space to hold the labels */ - struct yColCache { - int iTable; /* Table cursor number */ - i16 iColumn; /* Table column number */ - u8 tempReg; /* iReg is a temp register that needs to be freed */ - int iLevel; /* Nesting level */ - int iReg; /* Reg with value of this column. 0 means none. */ - int lru; /* Least recently used entry has the smallest value */ - } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ ExprList *pConstExpr;/* Constant expressions */ Token constraintName;/* Name of the constraint currently being parsed */ yDbMask writeMask; /* Start a write transaction on these databases */ yDbMask cookieMask; /* Bitmask of schema verified databases */ - int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ int regRowid; /* Register holding rowid of CREATE TABLE entry */ int regRoot; /* Register holding root page number for new objects */ int nMaxArg; /* Max args passed to user function by sub-program */ @@ -13784,8 +15556,6 @@ struct Parse { TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ - - /* Information used while coding trigger programs. */ Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */ @@ -13796,13 +15566,32 @@ struct Parse { u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ u8 disableTriggers; /* True to disable triggers */ + /************************************************************************** + ** Fields above must be initialized to zero. The fields that follow, + ** down to the beginning of the recursive section, do not need to be + ** initialized as they will be set before being used. The boundary is + ** determined by offsetof(Parse,aColCache). + **************************************************************************/ + + struct yColCache { + int iTable; /* Table cursor number */ + i16 iColumn; /* Table column number */ + u8 tempReg; /* iReg is a temp register that needs to be freed */ + int iLevel; /* Nesting level */ + int iReg; /* Reg with value of this column. 0 means none. */ + int lru; /* Least recently used entry has the smallest value */ + } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ + int aTempReg[8]; /* Holding area for temporary registers */ + Token sNameToken; /* Token with unqualified schema object name */ + /************************************************************************ ** Above is constant between recursions. Below is reset before and after ** each recursion. The boundary between these two regions is determined - ** using offsetof(Parse,nVar) so the nVar field must be the first field - ** in the recursive region. + ** using offsetof(Parse,sLastToken) so the sLastToken field must be the + ** first field in the recursive region. ************************************************************************/ + 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 */ @@ -13811,7 +15600,6 @@ struct Parse { u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ int nVtabLock; /* Number of virtual tables to lock */ #endif - int nAlias; /* Number of aliased result set columns */ int nHeight; /* Expression tree height of current sub-select */ #ifndef SQLITE_OMIT_EXPLAIN int iSelectId; /* ID of current select for EXPLAIN output */ @@ -13823,8 +15611,6 @@ struct Parse { Table *pNewTable; /* A table being constructed by CREATE TABLE */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ - Token sNameToken; /* Token with unqualified schema object name */ - Token sLastToken; /* The last token parsed */ #ifndef SQLITE_OMIT_VIRTUALTABLE Token sArg; /* Complete text of a module argument */ Table **apVtabLock; /* Pointer to virtual tables needing locking */ @@ -13835,6 +15621,14 @@ struct Parse { With *pWithToFree; /* Free this WITH object at the end of the parse */ }; +/* +** Sizes and pointers of various parts of the Parse object. +*/ +#define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/ +#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */ +#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ +#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */ + /* ** Return true if currently inside an sqlite3_declare_vtab() call. */ @@ -13855,6 +15649,15 @@ struct AuthContext { /* ** Bitfield flags for P5 value in various opcodes. +** +** Value constraints (enforced via assert()): +** OPFLAG_LENGTHARG == SQLITE_FUNC_LENGTH +** OPFLAG_TYPEOFARG == SQLITE_FUNC_TYPEOF +** OPFLAG_BULKCSR == BTREE_BULKLOAD +** OPFLAG_SEEKEQ == BTREE_SEEK_EQ +** OPFLAG_FORDELETE == BTREE_FORDELETE +** OPFLAG_SAVEPOSITION == BTREE_SAVEPOSITION +** OPFLAG_AUXDELETE == BTREE_AUXDELETE */ #define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */ /* Also used in P2 (not P5) of OP_Delete */ @@ -13863,6 +15666,9 @@ struct AuthContext { #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 */ @@ -14071,6 +15877,7 @@ struct Sqlite3Config { int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif int bLocaltimeFault; /* True to fail localtime() calls */ + int iOnceResetThreshold; /* When to reset OP_Once counters */ }; /* @@ -14109,6 +15916,7 @@ struct Walker { 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 */ } u; }; @@ -14226,6 +16034,7 @@ SQLITE_PRIVATE int sqlite3IoerrnomemError(int); # define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04) # define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08) # define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)]) +# define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80) #else # define sqlite3Toupper(x) toupper((unsigned char)(x)) # define sqlite3Isspace(x) isspace((unsigned char)(x)) @@ -14234,6 +16043,7 @@ SQLITE_PRIVATE int sqlite3IoerrnomemError(int); # define sqlite3Isdigit(x) isdigit((unsigned char)(x)) # define sqlite3Isxdigit(x) isxdigit((unsigned char)(x)) # define sqlite3Tolower(x) tolower((unsigned char)(x)) +# define sqlite3Isquote(x) ((x)=='"'||(x)=='\''||(x)=='['||(x)=='`') #endif #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS SQLITE_PRIVATE int sqlite3IsIdChar(u8); @@ -14290,11 +16100,15 @@ SQLITE_PRIVATE int sqlite3HeapNearlyFull(void); # define sqlite3StackFree(D,P) sqlite3DbFree(D,P) #endif -#ifdef SQLITE_ENABLE_MEMSYS3 -SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void); -#endif +/* Do not allow both MEMSYS5 and MEMSYS3 to be defined together. If they +** are, disable MEMSYS3 +*/ #ifdef SQLITE_ENABLE_MEMSYS5 SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void); +#undef SQLITE_ENABLE_MEMSYS3 +#endif +#ifdef SQLITE_ENABLE_MEMSYS3 +SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void); #endif @@ -14349,6 +16163,7 @@ SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); #if defined(SQLITE_DEBUG) SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); +SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*); SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8); SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8); @@ -14357,7 +16172,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8); SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); -SQLITE_PRIVATE int sqlite3Dequote(char*); +SQLITE_PRIVATE void sqlite3Dequote(char*); SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*); SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); @@ -14374,11 +16189,13 @@ 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 void sqlite3PExprAddSelect(Parse*, Expr*, Select*); SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); -SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*); +SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); +SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int); SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); @@ -14414,7 +16231,6 @@ SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*, sqlite3_vfs**,char**,char **); SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*); -SQLITE_PRIVATE int sqlite3CodeOnce(Parse *); #ifdef SQLITE_OMIT_BUILTIN_TEST # define sqlite3FaultSim(X) SQLITE_OK @@ -14476,8 +16292,8 @@ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*); SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*); SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*); SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**); -SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, - Expr*, int, int); +SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, + Expr*, int, int, u8); SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, @@ -14496,6 +16312,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*); +SQLITE_PRIVATE int sqlite3WhereOrderedInnerLoop(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*); @@ -14529,19 +16346,22 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int); SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*); -SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*); -SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *); +#define LOCATE_VIEW 0x01 +#define LOCATE_NOERR 0x02 +SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*); +SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_item *); SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); -SQLITE_PRIVATE void sqlite3Vacuum(Parse*); -SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*); +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 sqlite3ExprListCompare(ExprList*, ExprList*, int); SQLITE_PRIVATE int sqlite3ExprImpliesExpr(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 @@ -14710,6 +16530,7 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3*, Index*); SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int); SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2); SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); +SQLITE_PRIVATE char sqlite3TableColumnAffinity(Table*,int); SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr); SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8); SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*); @@ -14775,7 +16596,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); -SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); +SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr *, int, int); SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p); SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*); @@ -14830,12 +16651,20 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int); SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *); SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *); +#ifndef SQLITE_OMIT_SUBQUERY +SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse*, Expr*); +#else +# define sqlite3ExprCheckIN(x,y) SQLITE_OK +#endif + #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void); -SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(Parse*,Index*,UnpackedRecord**,Expr*,u8,int,int*); +SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue( + Parse*,Index*,UnpackedRecord**,Expr*,int,int,int*); SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**); SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord*); SQLITE_PRIVATE int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**); +SQLITE_PRIVATE char sqlite3IndexColumnAffinity(sqlite3*, Index*, int); #endif /* @@ -14988,7 +16817,7 @@ SQLITE_PRIVATE void sqlite3EndBenignMalloc(void); #define IN_INDEX_NOOP_OK 0x0001 /* OK to return IN_INDEX_NOOP */ #define IN_INDEX_MEMBERSHIP 0x0002 /* IN operator used for membership test */ #define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */ -SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*); +SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*); SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *); @@ -15093,7 +16922,12 @@ SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread*, void**); SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3*); #endif -#endif /* _SQLITEINT_H_ */ +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); + +#endif /* SQLITEINT_H */ /************** End of sqliteInt.h *******************************************/ /************** Begin file global.c ******************************************/ @@ -15169,6 +17003,7 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = { ** isxdigit() 0x08 ** toupper() 0x20 ** SQLite identifier character 0x40 +** Quote character 0x80 ** ** Bit 0x20 is set if the mapped character requires translation to upper ** case. i.e. if the character is a lower-case ASCII character. @@ -15177,16 +17012,13 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = { ** ** (x & ~(map[x]&0x20)) ** -** Standard function tolower() is implemented using the sqlite3UpperToLower[] +** The equivalent of tolower() is implemented using the sqlite3UpperToLower[] ** array. tolower() is used more often than toupper() by SQLite. ** -** Bit 0x40 is set if the character non-alphanumeric and can be used in an +** Bit 0x40 is set if the character is non-alphanumeric and can be used in an ** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any ** non-ASCII UTF character. Hence the test for whether or not a character is ** part of an identifier is 0x46. -** -** SQLite's versions are identical to the standard versions assuming a -** locale of "C". They are implemented as macros in sqliteInt.h. */ #ifdef SQLITE_ASCII SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = { @@ -15194,7 +17026,7 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17 ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f ........ */ - 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, /* 20..27 !"#$%&' */ + 0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x80, /* 20..27 !"#$%&' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f ()*+,-./ */ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37 01234567 */ 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f 89:;<=>? */ @@ -15202,8 +17034,8 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = { 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47 @ABCDEFG */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f HIJKLMNO */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57 PQRSTUVW */ - 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, /* 58..5f XYZ[\]^_ */ - 0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67 `abcdefg */ + 0x02, 0x02, 0x02, 0x80, 0x00, 0x00, 0x00, 0x40, /* 58..5f XYZ[\]^_ */ + 0x80, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67 `abcdefg */ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f hijklmno */ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77 pqrstuvw */ 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f xyz{|}~. */ @@ -15259,7 +17091,7 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = { #endif /* Statement journals spill to disk when their size exceeds the following -** threashold (in bytes). 0 means that statement journals are created and +** threshold (in bytes). 0 means that statement journals are created and ** written to disk immediately (the default behavior for SQLite versions ** before 3.12.0). -1 means always keep the entire statement journal in ** memory. (The statement journal is also always held entirely in memory @@ -15323,7 +17155,8 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { #ifndef SQLITE_OMIT_BUILTIN_TEST 0, /* xTestCallback */ #endif - 0 /* bLocaltimeFault */ + 0, /* bLocaltimeFault */ + 0x7ffffffe /* iOnceResetThreshold */ }; /* @@ -15346,7 +17179,7 @@ SQLITE_PRIVATE const Token sqlite3IntTokens[] = { ** The value of the "pending" byte must be 0x40000000 (1 byte past the ** 1-gibabyte boundary) in a compatible database. SQLite never uses ** the database page that contains the pending byte. It never attempts -** to read or write that page. The pending byte page is set assign +** to read or write that page. The pending byte page is set aside ** for use by the VFS layers as space for managing file locks. ** ** During testing, it is often desirable to move the pending byte to @@ -15427,6 +17260,15 @@ static const char * const azCompileOpt[] = { #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 @@ -15446,7 +17288,7 @@ static const char * const azCompileOpt[] = { "DISABLE_LFS", #endif #if SQLITE_ENABLE_8_3_NAMES - "ENABLE_8_3_NAMES", + "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES), #endif #if SQLITE_ENABLE_API_ARMOR "ENABLE_API_ARMOR", @@ -15786,7 +17628,7 @@ static const char * const azCompileOpt[] = { ** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix ** is not required for a match. */ -SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName){ +SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ int i, n; #if SQLITE_ENABLE_API_ARMOR @@ -15814,7 +17656,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName){ ** Return the N-th compile-time option string. If N is out of range, ** return a NULL pointer. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N){ +SQLITE_API const char *sqlite3_compileoption_get(int N){ if( N>=0 && NaDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ - int iStatement; /* Statement number (or 0 if has not opened stmt) */ u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */ -#ifndef SQLITE_OMIT_TRACE - i64 startTime; /* Time when query started - used for profiling */ -#endif - i64 iCurrentTime; /* Value of julianday('now') for this statement */ - i64 nFkConstraint; /* Number of imm. FK constraints this VM */ - i64 nStmtDefCons; /* Number of def. constraints when stmt started */ - i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ char *zSql; /* Text of the SQL statement that generated this */ void *pFree; /* Free this when deleting the vdbe */ VdbeFrame *pFrame; /* Parent frame */ @@ -16255,8 +18085,6 @@ struct Vdbe { int nFrame; /* Number of frames in pFrame list */ u32 expmask; /* Binding to these vars invalidates VM */ SubProgram *pProgram; /* Linked list of all sub-programs used by VM */ - int nOnceFlag; /* Size of array aOnceFlag[] */ - u8 *aOnceFlag; /* Flags for OP_Once */ AuxData *pAuxData; /* Linked list of auxdata allocations */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS i64 *anExec; /* Number of times each op has been executed */ @@ -16268,10 +18096,30 @@ struct Vdbe { /* ** The following are allowed values for Vdbe.magic */ -#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ -#define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ -#define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */ -#define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ +#define VDBE_MAGIC_INIT 0x16bceaa5 /* Building a VDBE program */ +#define VDBE_MAGIC_RUN 0x2df20da3 /* VDBE is ready to execute */ +#define VDBE_MAGIC_HALT 0x319c2973 /* VDBE has completed execution */ +#define VDBE_MAGIC_RESET 0x48fa9f76 /* Reset and ready to run again */ +#define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */ + +/* +** Structure used to store the context required by the +** sqlite3_preupdate_*() API functions. +*/ +struct PreUpdate { + Vdbe *v; + VdbeCursor *pCsr; /* Cursor to read old values from */ + int op; /* One of SQLITE_INSERT, UPDATE, DELETE */ + u8 *aRecord; /* old.* database record */ + KeyInfo keyinfo; + UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ + UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ + int iNewReg; /* Register for new.* values */ + i64 iKey1; /* First key value passed to hook */ + i64 iKey2; /* Second key value passed to hook */ + Mem *aNew; /* Array of new.* values */ + Table *pTab; /* Schema object being upated */ +}; /* ** Function prototypes @@ -16332,6 +18180,9 @@ SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *); +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK +SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int); +#endif SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p); SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *); @@ -16381,7 +18232,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *); #define ExpandBlob(P) SQLITE_OK #endif -#endif /* !defined(_VDBEINT_H_) */ +#endif /* !defined(SQLITE_VDBEINT_H) */ /************** End of vdbeInt.h *********************************************/ /************** Continuing where we left off in status.c *********************/ @@ -16502,7 +18353,7 @@ SQLITE_PRIVATE void sqlite3StatusHighwater(int op, int X){ /* ** Query status information. */ -SQLITE_API int SQLITE_STDCALL sqlite3_status64( +SQLITE_API int sqlite3_status64( int op, sqlite3_int64 *pCurrent, sqlite3_int64 *pHighwater, @@ -16527,8 +18378,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status64( (void)pMutex; /* Prevent warning when SQLITE_THREADSAFE=0 */ return SQLITE_OK; } -SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ - sqlite3_int64 iCur, iHwtr; +SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ + sqlite3_int64 iCur = 0, iHwtr = 0; int rc; #ifdef SQLITE_ENABLE_API_ARMOR if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; @@ -16544,7 +18395,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwa /* ** Query status information for a single database connection */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_status( +SQLITE_API int sqlite3_db_status( sqlite3 *db, /* The database connection whose status is desired */ int op, /* Status verb */ int *pCurrent, /* Write current value here */ @@ -16589,6 +18440,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status( ** by all pagers associated with the given database connection. The ** highwater mark is meaningless and is returned as zero. */ + case SQLITE_DBSTATUS_CACHE_USED_SHARED: case SQLITE_DBSTATUS_CACHE_USED: { int totalUsed = 0; int i; @@ -16597,7 +18449,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status( Btree *pBt = db->aDb[i].pBt; if( pBt ){ Pager *pPager = sqlite3BtreePager(pBt); - totalUsed += sqlite3PagerMemUsed(pPager); + int nByte = sqlite3PagerMemUsed(pPager); + if( op==SQLITE_DBSTATUS_CACHE_USED_SHARED ){ + nByte = nByte / sqlite3BtreeConnectionCount(pBt); + } + totalUsed += nByte; } } sqlite3BtreeLeaveAll(db); @@ -16769,6 +18625,15 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status( #ifndef SQLITE_OMIT_DATETIME_FUNCS +/* +** The MSVC CRT on Windows CE may not have a localtime() function. +** So declare a substitute. The substitute function itself is +** defined in "os_win.c". +*/ +#if !defined(SQLITE_OMIT_LOCALTIME) && defined(_WIN32_WCE) && \ + (!defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API) +struct tm *__cdecl localtime(const time_t *); +#endif /* ** A structure for holding a single date and time. @@ -17137,6 +19002,7 @@ static void clearYMD_HMS_TZ(DateTime *p){ p->validTZ = 0; } +#ifndef SQLITE_OMIT_LOCALTIME /* ** On recent Windows platforms, the localtime_s() function is available ** as part of the "Secure CRT". It is essentially equivalent to @@ -17155,7 +19021,6 @@ static void clearYMD_HMS_TZ(DateTime *p){ #define HAVE_LOCALTIME_S 1 #endif -#ifndef SQLITE_OMIT_LOCALTIME /* ** The following routine implements the rough equivalent of localtime_r() ** using whatever operating-system specific localtime facility that @@ -17822,7 +19687,6 @@ static void currentTimeFunc( ){ time_t t; char *zFormat = (char *)sqlite3_user_data(context); - sqlite3 *db; sqlite3_int64 iT; struct tm *pTm; struct tm sNow; @@ -17891,9 +19755,7 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ ** This file contains OS interface code that is common to all ** architectures. */ -#define _SQLITE_OS_C_ 1 /* #include "sqliteInt.h" */ -#undef _SQLITE_OS_C_ /* ** If we compile with the SQLITE_TEST macro set, then the following block @@ -17959,13 +19821,11 @@ SQLITE_API int sqlite3_memdebug_vfs_oom_test = 1; ** of this would be completely automatic if SQLite were coded using ** C++ instead of plain old C. */ -SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file *pId){ - int rc = SQLITE_OK; +SQLITE_PRIVATE void sqlite3OsClose(sqlite3_file *pId){ if( pId->pMethods ){ - rc = pId->pMethods->xClose(pId); + pId->pMethods->xClose(pId); pId->pMethods = 0; } - return rc; } SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){ DO_OS_MALLOC_TEST(id); @@ -18183,12 +20043,10 @@ SQLITE_PRIVATE int sqlite3OsOpenMalloc( } return rc; } -SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *pFile){ - int rc = SQLITE_OK; +SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *pFile){ assert( pFile ); - rc = sqlite3OsClose(pFile); + sqlite3OsClose(pFile); sqlite3_free(pFile); - return rc; } /* @@ -18214,7 +20072,7 @@ static sqlite3_vfs * SQLITE_WSD vfsList = 0; ** Locate a VFS by name. If no name is given, simply return the ** first VFS on the list. */ -SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfs){ +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){ sqlite3_vfs *pVfs = 0; #if SQLITE_THREADSAFE sqlite3_mutex *mutex; @@ -18260,7 +20118,7 @@ static void vfsUnlink(sqlite3_vfs *pVfs){ ** VFS multiple times. The new VFS becomes the default if makeDflt is ** true. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ MUTEX_LOGIC(sqlite3_mutex *mutex;) #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); @@ -18288,7 +20146,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDf /* ** Unregister a VFS so that it is no longer accessible. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ #if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif @@ -20639,7 +22497,7 @@ SQLITE_PRIVATE int sqlite3MutexEnd(void){ /* ** Retrieve a pointer to a static mutex or allocate a new dynamic one. */ -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int id){ +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){ #ifndef SQLITE_OMIT_AUTOINIT if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0; if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0; @@ -20660,7 +22518,7 @@ SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){ /* ** Free a dynamic mutex. */ -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex *p){ +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){ if( p ){ assert( sqlite3GlobalConfig.mutex.xMutexFree ); sqlite3GlobalConfig.mutex.xMutexFree(p); @@ -20671,7 +22529,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex *p){ ** Obtain the mutex p. If some other thread already has the mutex, block ** until it can be obtained. */ -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex *p){ +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){ if( p ){ assert( sqlite3GlobalConfig.mutex.xMutexEnter ); sqlite3GlobalConfig.mutex.xMutexEnter(p); @@ -20682,7 +22540,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex *p){ ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. */ -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex *p){ +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){ int rc = SQLITE_OK; if( p ){ assert( sqlite3GlobalConfig.mutex.xMutexTry ); @@ -20697,7 +22555,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex *p){ ** is not currently entered. If a NULL pointer is passed as an argument ** this function is a no-op. */ -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex *p){ +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){ if( p ){ assert( sqlite3GlobalConfig.mutex.xMutexLeave ); sqlite3GlobalConfig.mutex.xMutexLeave(p); @@ -20709,11 +22567,11 @@ SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex *p){ ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are ** intended for use inside assert() statements. */ -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex *p){ +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){ assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld ); return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p); } -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex *p){ +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld ); return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p); } @@ -21410,8 +23268,8 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ ** This file contains inline asm code for retrieving "high-performance" ** counters for x86 class CPUs. */ -#ifndef _HWTIME_H_ -#define _HWTIME_H_ +#ifndef SQLITE_HWTIME_H +#define SQLITE_HWTIME_H /* ** The following routine only works on pentium-class (or newer) processors. @@ -21479,7 +23337,7 @@ SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } #endif -#endif /* !defined(_HWTIME_H_) */ +#endif /* !defined(SQLITE_HWTIME_H) */ /************** End of hwtime.h **********************************************/ /************** Continuing where we left off in os_common.h ******************/ @@ -21569,8 +23427,8 @@ SQLITE_API extern int sqlite3_open_file_count; ** ** This file contains code that is specific to Windows. */ -#ifndef _OS_WIN_H_ -#define _OS_WIN_H_ +#ifndef SQLITE_OS_WIN_H +#define SQLITE_OS_WIN_H /* ** Include the primary Windows SDK header file. @@ -21642,7 +23500,7 @@ SQLITE_API extern int sqlite3_open_file_count; # define SQLITE_OS_WIN_THREADS 0 #endif -#endif /* _OS_WIN_H_ */ +#endif /* SQLITE_OS_WIN_H */ /************** End of os_win.h **********************************************/ /************** Continuing where we left off in mutex_w32.c ******************/ @@ -21745,8 +23603,8 @@ static int winMutex_isNt = -1; /* <0 means "need to query" */ */ static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0; -SQLITE_API int SQLITE_STDCALL sqlite3_win32_is_nt(void); /* os_win.c */ -SQLITE_API void SQLITE_STDCALL sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ +SQLITE_API int sqlite3_win32_is_nt(void); /* os_win.c */ +SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ static int winMutexInit(void){ /* The first to increment to 1 does actual initialization */ @@ -22046,7 +23904,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ ** held by SQLite. An example of non-essential memory is memory used to ** cache database pages that are not currently in use. */ -SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int n){ +SQLITE_API int sqlite3_release_memory(int n){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT return sqlite3PcacheReleaseMemory(n); #else @@ -22105,7 +23963,7 @@ SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void){ ** that was invoked when memory usage grew too large. Now it is a ** no-op. */ -SQLITE_API int SQLITE_STDCALL sqlite3_memory_alarm( +SQLITE_API int sqlite3_memory_alarm( void(*xCallback)(void *pArg, sqlite3_int64 used,int N), void *pArg, sqlite3_int64 iThreshold @@ -22121,7 +23979,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_memory_alarm( ** Set the soft heap-size limit for the library. Passing a zero or ** negative value indicates no limit. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 n){ +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){ sqlite3_int64 priorLimit; sqlite3_int64 excess; sqlite3_int64 nUsed; @@ -22143,7 +24001,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff)); return priorLimit; } -SQLITE_API void SQLITE_STDCALL sqlite3_soft_heap_limit(int n){ +SQLITE_API void sqlite3_soft_heap_limit(int n){ if( n<0 ) n = 0; sqlite3_soft_heap_limit64(n); } @@ -22212,7 +24070,7 @@ SQLITE_PRIVATE void sqlite3MallocEnd(void){ /* ** Return the amount of memory currently checked out. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void){ +SQLITE_API sqlite3_int64 sqlite3_memory_used(void){ sqlite3_int64 res, mx; sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, 0); return res; @@ -22223,7 +24081,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void){ ** checked out since either the beginning of this process ** or since the most recent reset. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag){ +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ sqlite3_int64 res, mx; sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, resetFlag); return mx; @@ -22303,13 +24161,13 @@ SQLITE_PRIVATE void *sqlite3Malloc(u64 n){ ** First make sure the memory subsystem is initialized, then do the ** allocation. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int n){ +SQLITE_API void *sqlite3_malloc(int n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif return n<=0 ? 0 : sqlite3Malloc(n); } -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64 n){ +SQLITE_API void *sqlite3_malloc64(sqlite3_uint64 n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif @@ -22452,7 +24310,7 @@ SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){ return db->lookaside.sz; } } -SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void *p){ +SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){ assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); return p ? sqlite3GlobalConfig.m.xSize(p) : 0; @@ -22461,7 +24319,7 @@ SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void *p){ /* ** Free memory previously obtained from sqlite3Malloc(). */ -SQLITE_API void SQLITE_STDCALL sqlite3_free(void *p){ +SQLITE_API void sqlite3_free(void *p){ if( p==0 ) return; /* IMP: R-49053-54554 */ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); @@ -22570,14 +24428,14 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){ ** The public interface to sqlite3Realloc. Make sure that the memory ** subsystem is initialized prior to invoking sqliteRealloc. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void *pOld, int n){ +SQLITE_API void *sqlite3_realloc(void *pOld, int n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif if( n<0 ) n = 0; /* IMP: R-26507-47431 */ return sqlite3Realloc(pOld, n); } -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void *pOld, sqlite3_uint64 n){ +SQLITE_API void *sqlite3_realloc64(void *pOld, sqlite3_uint64 n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif @@ -22868,26 +24726,26 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){ ** Conversion types fall into various categories as defined by the ** following enumeration. */ -#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */ -#define etFLOAT 2 /* Floating point. %f */ -#define etEXP 3 /* Exponentional notation. %e and %E */ -#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */ -#define etSIZE 5 /* Return number of characters processed so far. %n */ -#define etSTRING 6 /* Strings. %s */ -#define etDYNSTRING 7 /* Dynamically allocated strings. %z */ -#define etPERCENT 8 /* Percent symbol. %% */ -#define etCHARX 9 /* Characters. %c */ +#define etRADIX 0 /* Integer types. %d, %x, %o, and so forth */ +#define etFLOAT 1 /* Floating point. %f */ +#define etEXP 2 /* Exponentional notation. %e and %E */ +#define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */ +#define etSIZE 4 /* Return number of characters processed so far. %n */ +#define etSTRING 5 /* Strings. %s */ +#define etDYNSTRING 6 /* Dynamically allocated strings. %z */ +#define etPERCENT 7 /* Percent symbol. %% */ +#define etCHARX 8 /* Characters. %c */ /* The rest are extensions, not normally found in printf() */ -#define etSQLESCAPE 10 /* Strings with '\'' doubled. %q */ -#define etSQLESCAPE2 11 /* Strings with '\'' doubled and enclosed in '', +#define etSQLESCAPE 9 /* Strings with '\'' doubled. %q */ +#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '', NULL pointers replaced by SQL NULL. %Q */ -#define etTOKEN 12 /* a pointer to a Token structure */ -#define etSRCLIST 13 /* a pointer to a SrcList */ -#define etPOINTER 14 /* The %p conversion */ -#define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */ -#define etORDINAL 16 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ +#define etTOKEN 11 /* a pointer to a Token structure */ +#define etSRCLIST 12 /* a pointer to a SrcList */ +#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 etINVALID 0 /* Any unrecognized conversion type */ +#define etINVALID 16 /* Any unrecognized conversion type */ /* @@ -23042,7 +24900,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( etByte flag_long; /* True if "l" flag is present */ etByte flag_longlong; /* True if the "ll" flag is present */ etByte done; /* Loop termination flag */ - etByte xtype = 0; /* Conversion paradigm */ + 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'. */ @@ -23804,7 +25662,7 @@ SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){ ** Print into memory obtained from sqlite3_malloc(). Omit the internal ** %-conversion extensions. */ -SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char *zFormat, va_list ap){ +SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){ char *z; char zBase[SQLITE_PRINT_BUF_SIZE]; StrAccum acc; @@ -23828,7 +25686,7 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char *zFormat, va_list ap ** Print into memory obtained from sqlite3_malloc()(). Omit the internal ** %-conversion extensions. */ -SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char *zFormat, ...){ +SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){ va_list ap; char *z; #ifndef SQLITE_OMIT_AUTOINIT @@ -23853,7 +25711,7 @@ SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char *zFormat, ...){ ** ** sqlite3_vsnprintf() is the varargs version. */ -SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ +SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ StrAccum acc; if( n<=0 ) return zBuf; #ifdef SQLITE_ENABLE_API_ARMOR @@ -23867,7 +25725,7 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int n, char *zBuf, const char sqlite3VXPrintf(&acc, zFormat, ap); return sqlite3StrAccumFinish(&acc); } -SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ +SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ char *z; va_list ap; va_start(ap,zFormat); @@ -23903,7 +25761,7 @@ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ /* ** Format and write a message to the log if logging is enabled. */ -SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...){ +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){ va_list ap; /* Vararg list */ if( sqlite3GlobalConfig.xLog ){ va_start(ap, zFormat); @@ -24068,7 +25926,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m /* -** Generate a human-readable description of a the Select object. +** Generate a human-readable description of a Select object. */ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ int n = 0; @@ -24393,6 +26251,21 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m break; } #endif + case TK_MATCH: { + sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s", + pExpr->iTable, pExpr->iColumn, zFlgs); + sqlite3TreeViewExpr(pView, pExpr->pRight, 0); + break; + } + case TK_VECTOR: { + sqlite3TreeViewBareExprList(pView, pExpr->x.pList, "VECTOR"); + break; + } + case TK_SELECT_COLUMN: { + sqlite3TreeViewLine(pView, "SELECT-COLUMN %d", pExpr->iColumn); + sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0); + break; + } default: { sqlite3TreeViewLine(pView, "op=%d", pExpr->op); break; @@ -24409,21 +26282,20 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m sqlite3TreeViewPop(pView); } + /* ** Generate a human-readable explanation of an expression list. */ -SQLITE_PRIVATE void sqlite3TreeViewExprList( +SQLITE_PRIVATE void sqlite3TreeViewBareExprList( TreeView *pView, const ExprList *pList, - u8 moreToFollow, const char *zLabel ){ - int i; - pView = sqlite3TreeViewPush(pView, moreToFollow); if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST"; if( pList==0 ){ sqlite3TreeViewLine(pView, "%s (empty)", zLabel); }else{ + int i; sqlite3TreeViewLine(pView, "%s", zLabel); for(i=0; inExpr; i++){ int j = pList->a[i].u.x.iOrderByCol; @@ -24435,6 +26307,15 @@ SQLITE_PRIVATE void sqlite3TreeViewExprList( if( j ) sqlite3TreeViewPop(pView); } } +} +SQLITE_PRIVATE void sqlite3TreeViewExprList( + TreeView *pView, + const ExprList *pList, + u8 moreToFollow, + const char *zLabel +){ + pView = sqlite3TreeViewPush(pView, moreToFollow); + sqlite3TreeViewBareExprList(pView, pList, zLabel); sqlite3TreeViewPop(pView); } @@ -24474,7 +26355,7 @@ static SQLITE_WSD struct sqlite3PrngType { /* ** Return N random bytes. */ -SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *pBuf){ +SQLITE_API void sqlite3_randomness(int N, void *pBuf){ unsigned char t; unsigned char *zBuf = pBuf; @@ -25633,18 +27514,13 @@ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ ** brackets from around identifiers. For example: "[a-b-c]" becomes ** "a-b-c". */ -SQLITE_PRIVATE int sqlite3Dequote(char *z){ +SQLITE_PRIVATE void sqlite3Dequote(char *z){ char quote; int i, j; - if( z==0 ) return -1; + if( z==0 ) return; quote = z[0]; - switch( quote ){ - case '\'': break; - case '"': break; - case '`': break; /* For MySQL compatibility */ - case '[': quote = ']'; break; /* For MS SqlServer compatibility */ - default: return -1; - } + if( !sqlite3Isquote(quote) ) return; + if( quote=='[' ) quote = ']'; for(i=1, j=0;; i++){ assert( z[i] ); if( z[i]==quote ){ @@ -25659,7 +27535,6 @@ SQLITE_PRIVATE int sqlite3Dequote(char *z){ } } z[j] = 0; - return j; } /* @@ -25683,7 +27558,7 @@ SQLITE_PRIVATE void sqlite3TokenInit(Token *p, char *z){ ** case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *zLeft, const char *zRight){ +SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){ if( zLeft==0 ){ return zRight ? -1 : 0; }else if( zRight==0 ){ @@ -25704,7 +27579,7 @@ SQLITE_PRIVATE int sqlite3StrICmp(const char *zLeft, const char *zRight){ } return c; } -SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ +SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ register unsigned char *a, *b; if( zLeft==0 ){ return zRight ? -1 : 0; @@ -25752,7 +27627,7 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en int eValid = 1; /* True exponent is either not used or is well-formed */ double result; int nDigits = 0; - int nonNum = 0; + int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); *pResult = 0.0; /* Default return value, in case of an error */ @@ -25765,7 +27640,7 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); for(i=3-enc; i=zEnd ) goto do_atof_calc; @@ -25813,7 +27686,12 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en if( *z=='e' || *z=='E' ){ z+=incr; eValid = 0; - if( z>=zEnd ) goto do_atof_calc; + + /* This branch is needed to avoid a (harmless) buffer overread. The + ** special comment alerts the mutation tester that the correct answer + ** is obtained even if the branch is omitted */ + if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/ + /* get sign of exponent */ if( *z=='-' ){ esign = -1; @@ -25830,9 +27708,7 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en } /* skip trailing spaces */ - if( nDigits && eValid ){ - while( z0 ){ - while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10; - }else{ - while( !(s%10) && e>0 ) e--,s/=10; + /* Attempt to reduce exponent. + ** + ** Branches that are not required for the correct answer but which only + ** help to obtain the correct answer faster are marked with special + ** comments, as a hint to the mutation tester. + */ + while( e>0 ){ /*OPTIMIZATION-IF-TRUE*/ + if( esign>0 ){ + if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/ + s *= 10; + }else{ + if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/ + s /= 10; + } + e--; } /* adjust the sign of significand */ s = sign<0 ? -s : s; - /* if exponent, scale significand as appropriate - ** and store in result. */ - if( e ){ + if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/ + result = (double)s; + }else{ LONGDOUBLE_TYPE scale = 1.0; /* attempt to handle extremely small/large numbers better */ - if( e>307 && e<342 ){ - while( e%308 ) { scale *= 1.0e+1; e -= 1; } - if( esign<0 ){ - result = s / scale; - result /= 1.0e+308; - }else{ - result = s * scale; - result *= 1.0e+308; - } - }else if( e>=342 ){ - if( esign<0 ){ - result = 0.0*s; - }else{ - result = 1e308*1e308*s; /* Infinity */ + if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/ + if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/ + while( e%308 ) { scale *= 1.0e+1; e -= 1; } + if( esign<0 ){ + result = s / scale; + result /= 1.0e+308; + }else{ + result = s * scale; + result *= 1.0e+308; + } + }else{ assert( e>=342 ); + if( esign<0 ){ + result = 0.0*s; + }else{ + result = 1e308*1e308*s; /* Infinity */ + } } }else{ /* 1.0e+22 is the largest power of 10 than can be @@ -25891,8 +27777,6 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en result = s * scale; } } - } else { - result = (double)s; } } @@ -25900,7 +27784,7 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en *pResult = result; /* return true if number and no extra non-whitespace chracters after */ - return z>=zEnd && nDigits>0 && eValid && nonNum==0; + return z==zEnd && nDigits>0 && eValid && nonNum==0; #else return !sqlite3Atoi64(z, pResult, length, enc); #endif /* SQLITE_OMIT_FLOATING_POINT */ @@ -25962,7 +27846,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc int neg = 0; /* assume positive */ int i; int c = 0; - int nonNum = 0; + int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */ const char *zStart; const char *zEnd = zNum + length; assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); @@ -25973,7 +27857,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); for(i=3-enc; i19*incr || nonNum ){ + if( &zNum[i]19*incr /* Too many digits */ + || nonNum /* UTF16 with high-order bytes non-zero */ + ){ /* zNum is empty or contains non-numeric text or is longer ** than 19 digits (thus guaranteeing that it is too large) */ return 1; @@ -26043,7 +27930,6 @@ SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){ #ifndef SQLITE_OMIT_HEX_INTEGER if( z[0]=='0' && (z[1]=='x' || z[1]=='X') - && sqlite3Isxdigit(z[2]) ){ u64 u = 0; int i, k; @@ -26691,36 +28577,21 @@ SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){ return sqlite3AddInt64(pA, -iB); } } -#define TWOPOWER32 (((i64)1)<<32) -#define TWOPOWER31 (((i64)1)<<31) SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){ i64 iA = *pA; - i64 iA1, iA0, iB1, iB0, r; - - iA1 = iA/TWOPOWER32; - iA0 = iA % TWOPOWER32; - iB1 = iB/TWOPOWER32; - iB0 = iB % TWOPOWER32; - if( iA1==0 ){ - if( iB1==0 ){ - *pA *= iB; - return 0; - } - r = iA0*iB1; - }else if( iB1==0 ){ - r = iA1*iB0; - }else{ - /* If both iA1 and iB1 are non-zero, overflow will result */ - return 1; - } - testcase( r==(-TWOPOWER31)-1 ); - testcase( r==(-TWOPOWER31) ); - testcase( r==TWOPOWER31 ); - testcase( r==TWOPOWER31-1 ); - if( r<(-TWOPOWER31) || r>=TWOPOWER31 ) return 1; - r *= TWOPOWER32; - if( sqlite3AddInt64(&r, iA0*iB0) ) return 1; - *pA = r; + if( iB>0 ){ + if( iA>LARGEST_INT64/iB ) return 1; + if( iA0 ){ + if( iBLARGEST_INT64/-iB ) return 1; + } + } + *pA = iA*iB; return 0; } @@ -26805,7 +28676,7 @@ SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){ if( x<2 ) return 0; while( x<8 ){ y -= 10; x <<= 1; } }else{ - while( x>255 ){ y += 40; x >>= 4; } + while( x>255 ){ y += 40; x >>= 4; } /*OPTIMIZATION-IF-TRUE*/ while( x>15 ){ y += 10; x >>= 1; } } return a[x&7] + y - 10; @@ -26839,7 +28710,6 @@ SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){ */ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){ u64 n; - if( x<10 ) return 1; n = x%10; x /= 10; if( n>=5 ) n -= 2; @@ -26915,8 +28785,12 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){ static unsigned int strHash(const char *z){ unsigned int h = 0; unsigned char c; - while( (c = (unsigned char)*z++)!=0 ){ - h = (h<<3) ^ h ^ sqlite3UpperToLower[c]; + while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/ + /* Knuth multiplicative hashing. (Sorting & Searching, p. 510). + ** 0x9e3779b1 is 2654435761 which is the closest prime number to + ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */ + h += sqlite3UpperToLower[c]; + h *= 0x9e3779b1; } return h; } @@ -27008,7 +28882,7 @@ static HashElem *findElementWithHash( int count; /* Number of elements left to test */ unsigned int h; /* The computed hash */ - if( pH->ht ){ + if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/ struct _ht *pEntry; h = strHash(pKey) % pH->htsize; pEntry = &pH->ht[h]; @@ -27155,153 +29029,154 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 12 */ "VUpdate" OpHelp("data=r[P3@P2]"), /* 13 */ "Goto" OpHelp(""), /* 14 */ "Gosub" OpHelp(""), - /* 15 */ "Return" OpHelp(""), - /* 16 */ "InitCoroutine" OpHelp(""), - /* 17 */ "EndCoroutine" OpHelp(""), - /* 18 */ "Yield" OpHelp(""), + /* 15 */ "InitCoroutine" OpHelp(""), + /* 16 */ "Yield" OpHelp(""), + /* 17 */ "MustBeInt" OpHelp(""), + /* 18 */ "Jump" OpHelp(""), /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), - /* 20 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), - /* 21 */ "Halt" OpHelp(""), - /* 22 */ "Integer" OpHelp("r[P2]=P1"), - /* 23 */ "Int64" OpHelp("r[P2]=P4"), - /* 24 */ "String" OpHelp("r[P2]='P4' (len=P1)"), - /* 25 */ "Null" OpHelp("r[P2..P3]=NULL"), - /* 26 */ "SoftNull" OpHelp("r[P1]=NULL"), - /* 27 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), - /* 28 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), - /* 29 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), - /* 30 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), - /* 31 */ "SCopy" OpHelp("r[P2]=r[P1]"), - /* 32 */ "IntCopy" OpHelp("r[P2]=r[P1]"), - /* 33 */ "ResultRow" OpHelp("output=r[P1@P2]"), - /* 34 */ "CollSeq" OpHelp(""), - /* 35 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), - /* 36 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), - /* 37 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), - /* 38 */ "MustBeInt" OpHelp(""), - /* 39 */ "RealAffinity" OpHelp(""), - /* 40 */ "Cast" OpHelp("affinity(r[P1])"), - /* 41 */ "Permutation" OpHelp(""), - /* 42 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), - /* 43 */ "Jump" OpHelp(""), - /* 44 */ "Once" OpHelp(""), - /* 45 */ "If" OpHelp(""), - /* 46 */ "IfNot" OpHelp(""), - /* 47 */ "Column" OpHelp("r[P3]=PX"), - /* 48 */ "Affinity" OpHelp("affinity(r[P1@P2])"), - /* 49 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), - /* 50 */ "Count" OpHelp("r[P2]=count()"), - /* 51 */ "ReadCookie" OpHelp(""), - /* 52 */ "SetCookie" OpHelp(""), - /* 53 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), - /* 54 */ "OpenRead" OpHelp("root=P2 iDb=P3"), - /* 55 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), - /* 56 */ "OpenAutoindex" OpHelp("nColumn=P2"), - /* 57 */ "OpenEphemeral" OpHelp("nColumn=P2"), - /* 58 */ "SorterOpen" OpHelp(""), - /* 59 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), - /* 60 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), - /* 61 */ "Close" OpHelp(""), - /* 62 */ "ColumnsUsed" OpHelp(""), - /* 63 */ "SeekLT" OpHelp("key=r[P3@P4]"), - /* 64 */ "SeekLE" OpHelp("key=r[P3@P4]"), - /* 65 */ "SeekGE" OpHelp("key=r[P3@P4]"), - /* 66 */ "SeekGT" OpHelp("key=r[P3@P4]"), - /* 67 */ "NoConflict" OpHelp("key=r[P3@P4]"), - /* 68 */ "NotFound" OpHelp("key=r[P3@P4]"), - /* 69 */ "Found" OpHelp("key=r[P3@P4]"), - /* 70 */ "NotExists" OpHelp("intkey=r[P3]"), - /* 71 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), - /* 72 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), - /* 73 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), - /* 74 */ "NewRowid" OpHelp("r[P2]=rowid"), - /* 75 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), - /* 76 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), - /* 77 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), - /* 78 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"), - /* 79 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"), - /* 80 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"), - /* 81 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"), - /* 82 */ "Lt" OpHelp("if r[P1]=r[P3] goto P2"), - /* 84 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), - /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), - /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), - /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), - /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), - /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), - /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), - /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), - /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), - /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), - /* 95 */ "Delete" OpHelp(""), - /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), + /* 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]"), + /* 96 */ "Column" OpHelp("r[P3]=PX"), /* 97 */ "String8" OpHelp("r[P2]='P4'"), - /* 98 */ "ResetCount" OpHelp(""), - /* 99 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), - /* 100 */ "SorterData" OpHelp("r[P2]=data"), - /* 101 */ "RowKey" OpHelp("r[P2]=key"), - /* 102 */ "RowData" OpHelp("r[P2]=data"), - /* 103 */ "Rowid" OpHelp("r[P2]=rowid"), - /* 104 */ "NullRow" OpHelp(""), - /* 105 */ "Last" OpHelp(""), - /* 106 */ "SorterSort" OpHelp(""), - /* 107 */ "Sort" OpHelp(""), - /* 108 */ "Rewind" OpHelp(""), - /* 109 */ "SorterInsert" OpHelp(""), - /* 110 */ "IdxInsert" OpHelp("key=r[P2]"), - /* 111 */ "IdxDelete" OpHelp("key=r[P2@P3]"), - /* 112 */ "Seek" OpHelp("Move P3 to P1.rowid"), - /* 113 */ "IdxRowid" OpHelp("r[P2]=rowid"), - /* 114 */ "IdxLE" OpHelp("key=r[P3@P4]"), - /* 115 */ "IdxGT" OpHelp("key=r[P3@P4]"), - /* 116 */ "IdxLT" OpHelp("key=r[P3@P4]"), - /* 117 */ "IdxGE" OpHelp("key=r[P3@P4]"), - /* 118 */ "Destroy" OpHelp(""), - /* 119 */ "Clear" OpHelp(""), - /* 120 */ "ResetSorter" OpHelp(""), - /* 121 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), - /* 122 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), - /* 123 */ "ParseSchema" OpHelp(""), - /* 124 */ "LoadAnalysis" OpHelp(""), - /* 125 */ "DropTable" OpHelp(""), - /* 126 */ "DropIndex" OpHelp(""), - /* 127 */ "DropTrigger" OpHelp(""), - /* 128 */ "IntegrityCk" OpHelp(""), - /* 129 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), - /* 130 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), - /* 131 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), - /* 132 */ "Program" OpHelp(""), - /* 133 */ "Real" OpHelp("r[P2]=P4"), - /* 134 */ "Param" OpHelp(""), - /* 135 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), - /* 136 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), - /* 137 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), - /* 138 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), - /* 139 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), - /* 140 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]-=P3, goto P2"), - /* 141 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), - /* 142 */ "JumpZeroIncr" OpHelp("if (r[P1]++)==0 ) goto P2"), - /* 143 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 144 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 145 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), - /* 146 */ "IncrVacuum" OpHelp(""), - /* 147 */ "Expire" OpHelp(""), - /* 148 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), - /* 149 */ "VBegin" OpHelp(""), - /* 150 */ "VCreate" OpHelp(""), - /* 151 */ "VDestroy" OpHelp(""), - /* 152 */ "VOpen" OpHelp(""), - /* 153 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 154 */ "VNext" OpHelp(""), - /* 155 */ "VRename" OpHelp(""), - /* 156 */ "Pagecount" OpHelp(""), - /* 157 */ "MaxPgcnt" OpHelp(""), - /* 158 */ "Init" OpHelp("Start at P2"), - /* 159 */ "CursorHint" OpHelp(""), - /* 160 */ "Noop" OpHelp(""), - /* 161 */ "Explain" OpHelp(""), + /* 98 */ "Affinity" OpHelp("affinity(r[P1@P2])"), + /* 99 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), + /* 100 */ "Count" OpHelp("r[P2]=count()"), + /* 101 */ "ReadCookie" OpHelp(""), + /* 102 */ "SetCookie" OpHelp(""), + /* 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"), + /* 122 */ "RowData" OpHelp("r[P2]=data"), + /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), + /* 124 */ "NullRow" OpHelp(""), + /* 125 */ "SorterInsert" OpHelp(""), + /* 126 */ "IdxInsert" OpHelp("key=r[P2]"), + /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"), + /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"), + /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"), + /* 130 */ "Destroy" OpHelp(""), + /* 131 */ "Clear" OpHelp(""), + /* 132 */ "Real" OpHelp("r[P2]=P4"), + /* 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(""), }; return azName[i]; } @@ -27651,8 +29526,8 @@ static pid_t randomnessPid = 0; ** This file contains inline asm code for retrieving "high-performance" ** counters for x86 class CPUs. */ -#ifndef _HWTIME_H_ -#define _HWTIME_H_ +#ifndef SQLITE_HWTIME_H +#define SQLITE_HWTIME_H /* ** The following routine only works on pentium-class (or newer) processors. @@ -27720,7 +29595,7 @@ SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } #endif -#endif /* !defined(_HWTIME_H_) */ +#endif /* !defined(SQLITE_HWTIME_H) */ /************** End of hwtime.h **********************************************/ /************** Continuing where we left off in os_common.h ******************/ @@ -27914,7 +29789,7 @@ static struct unix_syscall { #else { "pread64", (sqlite3_syscall_ptr)0, 0 }, #endif -#define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent) +#define osPread64 ((ssize_t(*)(int,void*,size_t,off64_t))aSyscall[10].pCurrent) { "write", (sqlite3_syscall_ptr)write, 0 }, #define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent) @@ -27932,7 +29807,7 @@ static struct unix_syscall { #else { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, #endif -#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\ +#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off64_t))\ aSyscall[13].pCurrent) { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, @@ -29011,7 +30886,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ ** lock transitions in terms of the POSIX advisory shared and exclusive ** lock primitives (called read-locks and write-locks below, to avoid ** confusion with SQLite lock names). The algorithms are complicated - ** slightly in order to be compatible with windows systems simultaneously + ** slightly in order to be compatible with Windows95 systems simultaneously ** accessing the same database file, in case that is ever required. ** ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved @@ -29019,8 +30894,14 @@ static int unixLock(sqlite3_file *id, int eFileLock){ ** range', a range of 510 bytes at a well known offset. ** ** To obtain a SHARED lock, a read-lock is obtained on the 'pending - ** byte'. If this is successful, a random byte from the 'shared byte - ** range' is read-locked and the lock on the 'pending byte' released. + ** byte'. If this is successful, 'shared byte range' is read-locked + ** and the lock on the 'pending byte' released. (Legacy note: When + ** SQLite was first developed, Windows95 systems were still very common, + ** and Widnows95 lacks a shared-lock capability. So on Windows95, a + ** single randomly selected by from the 'shared byte range' is locked. + ** Windows95 is now pretty much extinct, but this work-around for the + ** lack of shared-locks on Windows95 lives on, for backwards + ** compatibility.) ** ** A process may only obtain a RESERVED lock after it has a SHARED lock. ** A RESERVED lock is implemented by grabbing a write-lock on the @@ -29039,11 +30920,6 @@ static int unixLock(sqlite3_file *id, int eFileLock){ ** range'. Since all other locks require a read-lock on one of the bytes ** within this range, this ensures that no other locks are held on the ** database. - ** - ** The reason a single byte cannot be used instead of the 'shared byte - ** range' is that some versions of windows do not support read-locks. By - ** locking a random byte from a range, concurrent SHARED locks may exist - ** even if the locking primitive used is always a write-lock. */ int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; @@ -31796,10 +33672,12 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ pShmNode->h = -1; pDbFd->pInode->pShmNode = pShmNode; pShmNode->pInode = pDbFd->pInode; - pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( pShmNode->mutex==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto shm_open_err; + if( sqlite3GlobalConfig.bCoreMutex ){ + pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + if( pShmNode->mutex==0 ){ + rc = SQLITE_NOMEM_BKPT; + goto shm_open_err; + } } if( pInode->bProcessLock==0 ){ @@ -32918,20 +34796,24 @@ static const char *unixTempFileDir(void){ "/tmp", "." }; - unsigned int i; + unsigned int i = 0; struct stat buf; const char *zDir = sqlite3_temp_directory; if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR"); if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR"); - for(i=0; i=sizeof(azDirs)/sizeof(azDirs[0]) ) break; + zDir = azDirs[i++]; } - return zDir; + return 0; } /* @@ -32947,9 +34829,11 @@ static int unixGetTempname(int nBuf, char *zBuf){ ** using the io-error infrastructure to test that SQLite handles this ** function failing. */ + zBuf[0] = 0; SimulateIOError( return SQLITE_IOERR ); zDir = unixTempFileDir(); + if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH; do{ u64 r; sqlite3_randomness(sizeof(r), &r); @@ -33029,6 +34913,27 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ return pUnused; } +/* +** Find the mode, uid and gid of file zFile. +*/ +static int getFileMode( + const char *zFile, /* File name */ + mode_t *pMode, /* OUT: Permissions of zFile */ + uid_t *pUid, /* OUT: uid of zFile. */ + gid_t *pGid /* OUT: gid of zFile. */ +){ + struct stat sStat; /* Output of stat() on database file */ + int rc = SQLITE_OK; + if( 0==osStat(zFile, &sStat) ){ + *pMode = sStat.st_mode & 0777; + *pUid = sStat.st_uid; + *pGid = sStat.st_gid; + }else{ + rc = SQLITE_IOERR_FSTAT; + } + return rc; +} + /* ** This function is called by unixOpen() to determine the unix permissions ** to create new files with. If no error occurs, then SQLITE_OK is returned @@ -33064,7 +34969,6 @@ static int findCreateFileMode( if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ char zDb[MAX_PATHNAME+1]; /* Database file path */ int nDb; /* Number of valid bytes in zDb */ - struct stat sStat; /* Output of stat() on database file */ /* zPath is a path to a WAL or journal file. The following block derives ** the path to the associated database file from zPath. This block handles @@ -33095,15 +34999,18 @@ static int findCreateFileMode( memcpy(zDb, zPath, nDb); zDb[nDb] = '\0'; - if( 0==osStat(zDb, &sStat) ){ - *pMode = sStat.st_mode & 0777; - *pUid = sStat.st_uid; - *pGid = sStat.st_gid; - }else{ - rc = SQLITE_IOERR_FSTAT; - } + rc = getFileMode(zDb, pMode, pUid, pGid); }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){ *pMode = 0600; + }else if( flags & SQLITE_OPEN_URI ){ + /* If this is a main database file and the file was opened using a URI + ** filename, check for the "modeof" parameter. If present, interpret + ** its value as a filename and try to copy the mode, uid and gid from + ** that file. */ + const char *z = sqlite3_uri_parameter(zPath, "modeof"); + if( z ){ + rc = getFileMode(z, pMode, pUid, pGid); + } } return rc; } @@ -34984,7 +36891,7 @@ static int proxyClose(sqlite3_file *id) { ** necessarily been initialized when this routine is called, and so they ** should not be used. */ -SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ +SQLITE_API int sqlite3_os_init(void){ /* ** The following macro defines an initializer for an sqlite3_vfs object. ** The name of the VFS is NAME. The pAppData is a pointer to a pointer @@ -35083,7 +36990,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ ** to release dynamically allocated objects. But not on unix. ** This routine is a no-op for unix. */ -SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ +SQLITE_API int sqlite3_os_end(void){ return SQLITE_OK; } @@ -35171,8 +37078,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ ** This file contains inline asm code for retrieving "high-performance" ** counters for x86 class CPUs. */ -#ifndef _HWTIME_H_ -#define _HWTIME_H_ +#ifndef SQLITE_HWTIME_H +#define SQLITE_HWTIME_H /* ** The following routine only works on pentium-class (or newer) processors. @@ -35240,7 +37147,7 @@ SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } #endif -#endif /* !defined(_HWTIME_H_) */ +#endif /* !defined(SQLITE_HWTIME_H) */ /************** End of hwtime.h **********************************************/ /************** Continuing where we left off in os_common.h ******************/ @@ -35581,6 +37488,17 @@ struct winFile { #endif }; +/* +** The winVfsAppData structure is used for the pAppData member for all of the +** Win32 VFS variants. +*/ +typedef struct winVfsAppData winVfsAppData; +struct winVfsAppData { + const sqlite3_io_methods *pMethod; /* The file I/O methods to use. */ + void *pAppData; /* The extra pAppData, if any. */ + BOOL bNoLock; /* Non-zero if locking is disabled. */ +}; + /* ** Allowed values for winFile.ctrlFlags */ @@ -36507,7 +38425,7 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){ ** "pnLargest" argument, if non-zero, will be used to return the size of the ** largest committed free block in the heap, in bytes. */ -SQLITE_API int SQLITE_STDCALL sqlite3_win32_compact_heap(LPUINT pnLargest){ +SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){ int rc = SQLITE_OK; UINT nLargest = 0; HANDLE hHeap; @@ -36547,12 +38465,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_win32_compact_heap(LPUINT pnLargest){ ** the sqlite3_memory_used() function does not return zero, SQLITE_BUSY will ** be returned and no changes will be made to the Win32 native heap. */ -SQLITE_API int SQLITE_STDCALL sqlite3_win32_reset_heap(){ +SQLITE_API int sqlite3_win32_reset_heap(){ int rc; MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */ - MUTEX_LOGIC( pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); ) - MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); ) + MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) + MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); ) sqlite3_mutex_enter(pMaster); sqlite3_mutex_enter(pMem); winMemAssertMagic(); @@ -36592,11 +38510,17 @@ SQLITE_API int SQLITE_STDCALL sqlite3_win32_reset_heap(){ ** (if available). */ -SQLITE_API void SQLITE_STDCALL sqlite3_win32_write_debug(const char *zBuf, int nBuf){ +SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){ char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE]; int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */ if( nMin<-1 ) nMin = -1; /* all negative values become -1. */ assert( nMin==-1 || nMin==0 || nMin0 ){ memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); @@ -36632,7 +38556,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_win32_write_debug(const char *zBuf, int n static HANDLE sleepObj = NULL; #endif -SQLITE_API void SQLITE_STDCALL sqlite3_win32_sleep(DWORD milliseconds){ +SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){ #if SQLITE_OS_WINRT if ( sleepObj==NULL ){ sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET, @@ -36681,7 +38605,7 @@ SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){ ** This function determines if the machine is running a version of Windows ** based on the NT kernel. */ -SQLITE_API int SQLITE_STDCALL sqlite3_win32_is_nt(void){ +SQLITE_API int sqlite3_win32_is_nt(void){ #if SQLITE_OS_WINRT /* ** NOTE: The WinRT sub-platform is always assumed to be based on the NT @@ -36922,147 +38846,244 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){ #endif /* SQLITE_WIN32_MALLOC */ /* -** Convert a UTF-8 string to Microsoft Unicode (UTF-16?). +** Convert a UTF-8 string to Microsoft Unicode. ** -** Space to hold the returned string is obtained from malloc. +** Space to hold the returned string is obtained from sqlite3_malloc(). */ -static LPWSTR winUtf8ToUnicode(const char *zFilename){ +static LPWSTR winUtf8ToUnicode(const char *zText){ int nChar; - LPWSTR zWideFilename; + LPWSTR zWideText; - nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); + nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0); if( nChar==0 ){ return 0; } - zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) ); - if( zWideFilename==0 ){ + zWideText = sqlite3MallocZero( nChar*sizeof(WCHAR) ); + if( zWideText==0 ){ return 0; } - nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, + nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText, nChar); if( nChar==0 ){ - sqlite3_free(zWideFilename); - zWideFilename = 0; + sqlite3_free(zWideText); + zWideText = 0; } - return zWideFilename; + return zWideText; } /* -** Convert Microsoft Unicode to UTF-8. Space to hold the returned string is -** obtained from sqlite3_malloc(). +** Convert a Microsoft Unicode string to UTF-8. +** +** Space to hold the returned string is obtained from sqlite3_malloc(). */ -static char *winUnicodeToUtf8(LPCWSTR zWideFilename){ +static char *winUnicodeToUtf8(LPCWSTR zWideText){ int nByte; - char *zFilename; + char *zText; - nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); + nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0); if( nByte == 0 ){ return 0; } - zFilename = sqlite3MallocZero( nByte ); - if( zFilename==0 ){ + zText = sqlite3MallocZero( nByte ); + if( zText==0 ){ return 0; } - nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, + nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte, 0, 0); if( nByte == 0 ){ - sqlite3_free(zFilename); - zFilename = 0; + sqlite3_free(zText); + zText = 0; } - return zFilename; + return zText; } /* -** Convert an ANSI string to Microsoft Unicode, based on the -** current codepage settings for file apis. +** Convert an ANSI string to Microsoft Unicode, using the ANSI or OEM +** code page. ** -** Space to hold the returned string is obtained -** from sqlite3_malloc. +** Space to hold the returned string is obtained from sqlite3_malloc(). */ -static LPWSTR winMbcsToUnicode(const char *zFilename){ +static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){ int nByte; - LPWSTR zMbcsFilename; - int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; + LPWSTR zMbcsText; + int codepage = useAnsi ? CP_ACP : CP_OEMCP; - nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL, + nByte = osMultiByteToWideChar(codepage, 0, zText, -1, NULL, 0)*sizeof(WCHAR); if( nByte==0 ){ return 0; } - zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) ); - if( zMbcsFilename==0 ){ + zMbcsText = sqlite3MallocZero( nByte*sizeof(WCHAR) ); + if( zMbcsText==0 ){ return 0; } - nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, + nByte = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText, nByte); if( nByte==0 ){ - sqlite3_free(zMbcsFilename); - zMbcsFilename = 0; + sqlite3_free(zMbcsText); + zMbcsText = 0; } - return zMbcsFilename; + return zMbcsText; } /* -** Convert Microsoft Unicode to multi-byte character string, based on the -** user's ANSI codepage. +** Convert a Microsoft Unicode string to a multi-byte character string, +** using the ANSI or OEM code page. ** -** Space to hold the returned string is obtained from -** sqlite3_malloc(). +** Space to hold the returned string is obtained from sqlite3_malloc(). */ -static char *winUnicodeToMbcs(LPCWSTR zWideFilename){ +static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi){ int nByte; - char *zFilename; - int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; + char *zText; + int codepage = useAnsi ? CP_ACP : CP_OEMCP; - nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); + nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, 0, 0, 0, 0); if( nByte == 0 ){ return 0; } - zFilename = sqlite3MallocZero( nByte ); - if( zFilename==0 ){ + zText = sqlite3MallocZero( nByte ); + if( zText==0 ){ return 0; } - nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, + nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, zText, nByte, 0, 0); if( nByte == 0 ){ - sqlite3_free(zFilename); - zFilename = 0; + sqlite3_free(zText); + zText = 0; } - return zFilename; + return zText; } /* -** Convert multibyte character string to UTF-8. Space to hold the -** returned string is obtained from sqlite3_malloc(). +** Convert a multi-byte character string to UTF-8. +** +** Space to hold the returned string is obtained from sqlite3_malloc(). */ -SQLITE_API char *SQLITE_STDCALL sqlite3_win32_mbcs_to_utf8(const char *zFilename){ - char *zFilenameUtf8; +static char *winMbcsToUtf8(const char *zText, int useAnsi){ + char *zTextUtf8; LPWSTR zTmpWide; - zTmpWide = winMbcsToUnicode(zFilename); + zTmpWide = winMbcsToUnicode(zText, useAnsi); if( zTmpWide==0 ){ return 0; } - zFilenameUtf8 = winUnicodeToUtf8(zTmpWide); + zTextUtf8 = winUnicodeToUtf8(zTmpWide); sqlite3_free(zTmpWide); - return zFilenameUtf8; + return zTextUtf8; } /* -** Convert UTF-8 to multibyte character string. Space to hold the -** returned string is obtained from sqlite3_malloc(). +** Convert a UTF-8 string to a multi-byte character string. +** +** Space to hold the returned string is obtained from sqlite3_malloc(). */ -SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs(const char *zFilename){ - char *zFilenameMbcs; +static char *winUtf8ToMbcs(const char *zText, int useAnsi){ + char *zTextMbcs; LPWSTR zTmpWide; - zTmpWide = winUtf8ToUnicode(zFilename); + zTmpWide = winUtf8ToUnicode(zText); if( zTmpWide==0 ){ return 0; } - zFilenameMbcs = winUnicodeToMbcs(zTmpWide); + zTextMbcs = winUnicodeToMbcs(zTmpWide, useAnsi); sqlite3_free(zTmpWide); - return zFilenameMbcs; + return zTextMbcs; +} + +/* +** This is a public wrapper for the winUtf8ToUnicode() function. +*/ +SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !zText ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return winUtf8ToUnicode(zText); +} + +/* +** This is a public wrapper for the winUnicodeToUtf8() function. +*/ +SQLITE_API char *sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !zWideText ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return winUnicodeToUtf8(zWideText); +} + +/* +** This is a public wrapper for the winMbcsToUtf8() function. +*/ +SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zText){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !zText ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return winMbcsToUtf8(zText, osAreFileApisANSI()); +} + +/* +** This is a public wrapper for the winMbcsToUtf8() function. +*/ +SQLITE_API char *sqlite3_win32_mbcs_to_utf8_v2(const char *zText, int useAnsi){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !zText ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return winMbcsToUtf8(zText, useAnsi); +} + +/* +** This is a public wrapper for the winUtf8ToMbcs() function. +*/ +SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zText){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !zText ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return winUtf8ToMbcs(zText, osAreFileApisANSI()); +} + +/* +** This is a public wrapper for the winUtf8ToMbcs() function. +*/ +SQLITE_API char *sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !zText ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return winUtf8ToMbcs(zText, useAnsi); } /* @@ -37072,7 +39093,7 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs(const char *zFilename ** argument is the name of the directory to use. The return value will be ** SQLITE_OK if successful. */ -SQLITE_API int SQLITE_STDCALL sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ +SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ char **ppDirectory = 0; #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); @@ -37164,7 +39185,7 @@ static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){ if( dwLen > 0 ){ /* allocate a buffer and convert to UTF8 */ sqlite3BeginBenignMalloc(); - zOut = sqlite3_win32_mbcs_to_utf8(zTemp); + zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI()); sqlite3EndBenignMalloc(); /* free the system buffer allocated by FormatMessage */ osLocalFree(zTemp); @@ -37306,16 +39327,17 @@ static void winLogIoerr(int nRetry, int lineno){ } } -#if SQLITE_OS_WINCE -/************************************************************************* -** This section contains code for WinCE only. +/* +** This #if does not rely on the SQLITE_OS_WINCE define because the +** corresponding section in "date.c" cannot use it. */ -#if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API +#if !defined(SQLITE_OMIT_LOCALTIME) && defined(_WIN32_WCE) && \ + (!defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API) /* -** The MSVC CRT on Windows CE may not have a localtime() function. So -** create a substitute. +** The MSVC CRT on Windows CE may not have a localtime() function. +** So define a substitute. */ -/* #include */ +/* # include */ struct tm *__cdecl localtime(const time_t *t) { static struct tm y; @@ -37339,6 +39361,10 @@ struct tm *__cdecl localtime(const time_t *t) } #endif +#if SQLITE_OS_WINCE +/************************************************************************* +** This section contains code for WinCE only. +*/ #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)] /* @@ -37794,7 +39820,12 @@ static int winClose(sqlite3_file *id){ }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) ); #if SQLITE_OS_WINCE #define WINCE_DELETION_ATTEMPTS 3 - winceDestroyLock(pFile); + { + winVfsAppData *pAppData = (winVfsAppData*)pFile->pVfs->pAppData; + if( pAppData==NULL || !pAppData->bNoLock ){ + winceDestroyLock(pFile); + } + } if( pFile->zDeleteOnClose ){ int cnt = 0; while( @@ -38352,9 +40383,8 @@ static int winLock(sqlite3_file *id, int locktype){ ** the PENDING_LOCK byte is temporary. */ newLocktype = pFile->locktype; - if( (pFile->locktype==NO_LOCK) - || ( (locktype==EXCLUSIVE_LOCK) - && (pFile->locktype==RESERVED_LOCK)) + if( pFile->locktype==NO_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktype<=RESERVED_LOCK) ){ int cnt = 3; while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, @@ -38527,6 +40557,44 @@ static int winUnlock(sqlite3_file *id, int locktype){ return rc; } +/****************************************************************************** +****************************** No-op Locking ********************************** +** +** Of the various locking implementations available, this is by far the +** simplest: locking is ignored. No attempt is made to lock the database +** file for reading or writing. +** +** This locking mode is appropriate for use on read-only databases +** (ex: databases that are burned into CD-ROM, for example.) It can +** also be used if the application employs some external mechanism to +** prevent simultaneous access of the same database by two or more +** database connections. But there is a serious risk of database +** corruption if this locking mode is used in situations where multiple +** database connections are accessing the same database file at the same +** time and one or more of those connections are writing. +*/ + +static int winNolockLock(sqlite3_file *id, int locktype){ + UNUSED_PARAMETER(id); + UNUSED_PARAMETER(locktype); + return SQLITE_OK; +} + +static int winNolockCheckReservedLock(sqlite3_file *id, int *pResOut){ + UNUSED_PARAMETER(id); + UNUSED_PARAMETER(pResOut); + return SQLITE_OK; +} + +static int winNolockUnlock(sqlite3_file *id, int locktype){ + UNUSED_PARAMETER(id); + UNUSED_PARAMETER(locktype); + return SQLITE_OK; +} + +/******************* End of the no-op lock implementation ********************* +******************************************************************************/ + /* ** If *pArg is initially negative then this is a query. Set *pArg to ** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set. @@ -38618,6 +40686,12 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } + case SQLITE_FCNTL_WIN32_GET_HANDLE: { + LPHANDLE phFile = (LPHANDLE)pArg; + *phFile = pFile->h; + OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; + } #ifdef SQLITE_TEST case SQLITE_FCNTL_WIN32_SET_HANDLE: { LPHANDLE phFile = (LPHANDLE)pArg; @@ -38805,12 +40879,12 @@ struct winShm { /* ** Apply advisory locks for all n bytes beginning at ofst. */ -#define _SHM_UNLCK 1 -#define _SHM_RDLCK 2 -#define _SHM_WRLCK 3 +#define WINSHM_UNLCK 1 +#define WINSHM_RDLCK 2 +#define WINSHM_WRLCK 3 static int winShmSystemLock( winShmNode *pFile, /* Apply locks to this open shared-memory segment */ - int lockType, /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */ + int lockType, /* WINSHM_UNLCK, WINSHM_RDLCK, or WINSHM_WRLCK */ int ofst, /* Offset to first byte to be locked/unlocked */ int nByte /* Number of bytes to lock or unlock */ ){ @@ -38823,12 +40897,12 @@ static int winShmSystemLock( pFile->hFile.h, lockType, ofst, nByte)); /* Release/Acquire the system-level lock */ - if( lockType==_SHM_UNLCK ){ + if( lockType==WINSHM_UNLCK ){ rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0); }else{ /* Initialize the locking parameters */ DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY; - if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; + if( lockType == WINSHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0); } @@ -38840,7 +40914,7 @@ static int winShmSystemLock( } OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n", - pFile->hFile.h, (lockType == _SHM_UNLCK) ? "winUnlockFile" : + pFile->hFile.h, (lockType == WINSHM_UNLCK) ? "winUnlockFile" : "winLockFile", pFile->lastErrno, sqlite3ErrName(rc))); return rc; @@ -38948,10 +41022,12 @@ static int winOpenSharedMemory(winFile *pDbFd){ pShmNode->pNext = winShmNodeList; winShmNodeList = pShmNode; - pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( pShmNode->mutex==0 ){ - rc = SQLITE_IOERR_NOMEM_BKPT; - goto shm_open_err; + if( sqlite3GlobalConfig.bCoreMutex ){ + pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + if( pShmNode->mutex==0 ){ + rc = SQLITE_IOERR_NOMEM_BKPT; + goto shm_open_err; + } } rc = winOpen(pDbFd->pVfs, @@ -38966,7 +41042,7 @@ static int winOpenSharedMemory(winFile *pDbFd){ /* Check to see if another process is holding the dead-man switch. ** If not, truncate the file to zero length. */ - if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){ + if( winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){ rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0); if( rc!=SQLITE_OK ){ rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(), @@ -38974,8 +41050,8 @@ static int winOpenSharedMemory(winFile *pDbFd){ } } if( rc==SQLITE_OK ){ - winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); - rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1); + winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); + rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1); } if( rc ) goto shm_open_err; } @@ -39004,7 +41080,7 @@ static int winOpenSharedMemory(winFile *pDbFd){ /* Jump here on any error */ shm_open_err: - winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); + winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */ sqlite3_free(p); sqlite3_free(pNew); @@ -39093,7 +41169,7 @@ static int winShmLock( /* Unlock the system-level locks */ if( (mask & allMask)==0 ){ - rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n); + rc = winShmSystemLock(pShmNode, WINSHM_UNLCK, ofst+WIN_SHM_BASE, n); }else{ rc = SQLITE_OK; } @@ -39121,7 +41197,7 @@ static int winShmLock( /* Get shared locks at the system level, if necessary */ if( rc==SQLITE_OK ){ if( (allShared & mask)==0 ){ - rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n); + rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, ofst+WIN_SHM_BASE, n); }else{ rc = SQLITE_OK; } @@ -39146,7 +41222,7 @@ static int winShmLock( ** also mark the local connection as being locked. */ if( rc==SQLITE_OK ){ - rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n); + rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, ofst+WIN_SHM_BASE, n); if( rc==SQLITE_OK ){ assert( (p->sharedMask & mask)==0 ); p->exclMask |= mask; @@ -39589,6 +41665,44 @@ static const sqlite3_io_methods winIoMethod = { winUnfetch /* xUnfetch */ }; +/* +** This vector defines all the methods that can operate on an +** sqlite3_file for win32 without performing any locking. +*/ +static const sqlite3_io_methods winIoNolockMethod = { + 3, /* iVersion */ + winClose, /* xClose */ + winRead, /* xRead */ + winWrite, /* xWrite */ + winTruncate, /* xTruncate */ + winSync, /* xSync */ + winFileSize, /* xFileSize */ + winNolockLock, /* xLock */ + winNolockUnlock, /* xUnlock */ + winNolockCheckReservedLock, /* xCheckReservedLock */ + winFileControl, /* xFileControl */ + winSectorSize, /* xSectorSize */ + winDeviceCharacteristics, /* xDeviceCharacteristics */ + winShmMap, /* xShmMap */ + winShmLock, /* xShmLock */ + winShmBarrier, /* xShmBarrier */ + winShmUnmap, /* xShmUnmap */ + winFetch, /* xFetch */ + winUnfetch /* xUnfetch */ +}; + +static winVfsAppData winAppData = { + &winIoMethod, /* pMethod */ + 0, /* pAppData */ + 0 /* bNoLock */ +}; + +static winVfsAppData winNolockAppData = { + &winIoNolockMethod, /* pMethod */ + 0, /* pAppData */ + 1 /* bNoLock */ +}; + /**************************************************************************** **************************** sqlite3_vfs methods **************************** ** @@ -39609,7 +41723,7 @@ static char *winConvertToUtf8Filename(const void *zFilename){ } #ifdef SQLITE_WIN32_HAS_ANSI else{ - zConverted = sqlite3_win32_mbcs_to_utf8(zFilename); + zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI()); } #endif /* caller will handle out of memory */ @@ -39630,7 +41744,7 @@ static void *winConvertFromUtf8Filename(const char *zFilename){ } #ifdef SQLITE_WIN32_HAS_ANSI else{ - zConverted = sqlite3_win32_utf8_to_mbcs(zFilename); + zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI()); } #endif /* caller will handle out of memory */ @@ -39831,7 +41945,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(), "winGetTempname3", 0); } - zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath); + zUtf8 = winMbcsToUtf8(zMbcsPath, osAreFileApisANSI()); if( zUtf8 ){ sqlite3_snprintf(nMax, zBuf, "%s", zUtf8); sqlite3_free(zUtf8); @@ -39921,7 +42035,7 @@ static int winIsDir(const void *zConverted){ ** Open a file. */ static int winOpen( - sqlite3_vfs *pVfs, /* Used to get maximum path name length */ + sqlite3_vfs *pVfs, /* Used to get maximum path length and AppData */ const char *zName, /* Name of the file (UTF-8) */ sqlite3_file *id, /* Write the SQLite file handle here */ int flags, /* Open mode flags */ @@ -39936,6 +42050,7 @@ static int winOpen( #if SQLITE_OS_WINCE int isTemp = 0; #endif + winVfsAppData *pAppData; winFile *pFile = (winFile*)id; void *zConverted; /* Filename in OS encoding */ const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ @@ -40157,15 +42272,20 @@ static int winOpen( "rc=%s\n", h, zUtf8Name, dwDesiredAccess, pOutFlags, pOutFlags ? *pOutFlags : 0, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); + pAppData = (winVfsAppData*)pVfs->pAppData; + #if SQLITE_OS_WINCE - if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB - && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK - ){ - osCloseHandle(h); - sqlite3_free(zConverted); - sqlite3_free(zTmpname); - OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc))); - return rc; + { + if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB + && ((pAppData==NULL) || !pAppData->bNoLock) + && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK + ){ + osCloseHandle(h); + sqlite3_free(zConverted); + sqlite3_free(zTmpname); + OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc))); + return rc; + } } if( isTemp ){ pFile->zDeleteOnClose = zConverted; @@ -40176,7 +42296,7 @@ static int winOpen( } sqlite3_free(zTmpname); - pFile->pMethod = &winIoMethod; + pFile->pMethod = pAppData ? pAppData->pMethod : &winIoMethod; pFile->pVfs = pVfs; pFile->h = h; if( isReadonly ){ @@ -40451,6 +42571,18 @@ static int winFullPathname( int nFull, /* Size of output buffer in bytes */ char *zFull /* Output buffer */ ){ +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__) + DWORD nByte; + void *zConverted; + char *zOut; +#endif + + /* If this path name begins with "/X:", where "X" is any alphabetic + ** character, discard the initial "/" from the pathname. + */ + if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){ + zRelative++; + } #if defined(__CYGWIN__) SimulateIOError( return SQLITE_ERROR ); @@ -40529,17 +42661,6 @@ static int winFullPathname( #endif #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__) - DWORD nByte; - void *zConverted; - char *zOut; - - /* If this path name begins with "/X:", where "X" is any alphabetic - ** character, discard the initial "/" from the pathname. - */ - if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){ - zRelative++; - } - /* It's odd to simulate an io-error here, but really this is just ** using the io-error infrastructure to test that SQLite handles this ** function failing. This function could fail if, for example, the @@ -40609,7 +42730,7 @@ static int winFullPathname( "winFullPathname4", zRelative); } sqlite3_free(zConverted); - zOut = sqlite3_win32_mbcs_to_utf8(zTemp); + zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI()); sqlite3_free(zTemp); } #endif @@ -40896,55 +43017,105 @@ static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ /* ** Initialize and deinitialize the operating system interface. */ -SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ +SQLITE_API int sqlite3_os_init(void){ static sqlite3_vfs winVfs = { - 3, /* iVersion */ - sizeof(winFile), /* szOsFile */ + 3, /* iVersion */ + sizeof(winFile), /* szOsFile */ SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */ - 0, /* pNext */ - "win32", /* zName */ - 0, /* pAppData */ - winOpen, /* xOpen */ - winDelete, /* xDelete */ - winAccess, /* xAccess */ - winFullPathname, /* xFullPathname */ - winDlOpen, /* xDlOpen */ - winDlError, /* xDlError */ - winDlSym, /* xDlSym */ - winDlClose, /* xDlClose */ - winRandomness, /* xRandomness */ - winSleep, /* xSleep */ - winCurrentTime, /* xCurrentTime */ - winGetLastError, /* xGetLastError */ - winCurrentTimeInt64, /* xCurrentTimeInt64 */ - winSetSystemCall, /* xSetSystemCall */ - winGetSystemCall, /* xGetSystemCall */ - winNextSystemCall, /* xNextSystemCall */ + 0, /* pNext */ + "win32", /* zName */ + &winAppData, /* pAppData */ + winOpen, /* xOpen */ + winDelete, /* xDelete */ + winAccess, /* xAccess */ + winFullPathname, /* xFullPathname */ + winDlOpen, /* xDlOpen */ + winDlError, /* xDlError */ + winDlSym, /* xDlSym */ + winDlClose, /* xDlClose */ + winRandomness, /* xRandomness */ + winSleep, /* xSleep */ + winCurrentTime, /* xCurrentTime */ + winGetLastError, /* xGetLastError */ + winCurrentTimeInt64, /* xCurrentTimeInt64 */ + winSetSystemCall, /* xSetSystemCall */ + winGetSystemCall, /* xGetSystemCall */ + winNextSystemCall, /* xNextSystemCall */ }; #if defined(SQLITE_WIN32_HAS_WIDE) static sqlite3_vfs winLongPathVfs = { - 3, /* iVersion */ - sizeof(winFile), /* szOsFile */ + 3, /* iVersion */ + sizeof(winFile), /* szOsFile */ + SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */ + 0, /* pNext */ + "win32-longpath", /* zName */ + &winAppData, /* pAppData */ + winOpen, /* xOpen */ + winDelete, /* xDelete */ + winAccess, /* xAccess */ + winFullPathname, /* xFullPathname */ + winDlOpen, /* xDlOpen */ + winDlError, /* xDlError */ + winDlSym, /* xDlSym */ + winDlClose, /* xDlClose */ + winRandomness, /* xRandomness */ + winSleep, /* xSleep */ + winCurrentTime, /* xCurrentTime */ + winGetLastError, /* xGetLastError */ + winCurrentTimeInt64, /* xCurrentTimeInt64 */ + winSetSystemCall, /* xSetSystemCall */ + winGetSystemCall, /* xGetSystemCall */ + winNextSystemCall, /* xNextSystemCall */ + }; +#endif + static sqlite3_vfs winNolockVfs = { + 3, /* iVersion */ + sizeof(winFile), /* szOsFile */ + SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */ + 0, /* pNext */ + "win32-none", /* zName */ + &winNolockAppData, /* pAppData */ + winOpen, /* xOpen */ + winDelete, /* xDelete */ + winAccess, /* xAccess */ + winFullPathname, /* xFullPathname */ + winDlOpen, /* xDlOpen */ + winDlError, /* xDlError */ + winDlSym, /* xDlSym */ + winDlClose, /* xDlClose */ + winRandomness, /* xRandomness */ + winSleep, /* xSleep */ + winCurrentTime, /* xCurrentTime */ + winGetLastError, /* xGetLastError */ + winCurrentTimeInt64, /* xCurrentTimeInt64 */ + winSetSystemCall, /* xSetSystemCall */ + winGetSystemCall, /* xGetSystemCall */ + winNextSystemCall, /* xNextSystemCall */ + }; +#if defined(SQLITE_WIN32_HAS_WIDE) + static sqlite3_vfs winLongPathNolockVfs = { + 3, /* iVersion */ + sizeof(winFile), /* szOsFile */ SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */ - 0, /* pNext */ - "win32-longpath", /* zName */ - 0, /* pAppData */ - winOpen, /* xOpen */ - winDelete, /* xDelete */ - winAccess, /* xAccess */ - winFullPathname, /* xFullPathname */ - winDlOpen, /* xDlOpen */ - winDlError, /* xDlError */ - winDlSym, /* xDlSym */ - winDlClose, /* xDlClose */ - winRandomness, /* xRandomness */ - winSleep, /* xSleep */ - winCurrentTime, /* xCurrentTime */ - winGetLastError, /* xGetLastError */ - winCurrentTimeInt64, /* xCurrentTimeInt64 */ - winSetSystemCall, /* xSetSystemCall */ - winGetSystemCall, /* xGetSystemCall */ - winNextSystemCall, /* xNextSystemCall */ + 0, /* pNext */ + "win32-longpath-none", /* zName */ + &winNolockAppData, /* pAppData */ + winOpen, /* xOpen */ + winDelete, /* xDelete */ + winAccess, /* xAccess */ + winFullPathname, /* xFullPathname */ + winDlOpen, /* xDlOpen */ + winDlError, /* xDlError */ + winDlSym, /* xDlSym */ + winDlClose, /* xDlClose */ + winRandomness, /* xRandomness */ + winSleep, /* xSleep */ + winCurrentTime, /* xCurrentTime */ + winGetLastError, /* xGetLastError */ + winCurrentTimeInt64, /* xCurrentTimeInt64 */ + winSetSystemCall, /* xSetSystemCall */ + winGetSystemCall, /* xGetSystemCall */ + winNextSystemCall, /* xNextSystemCall */ }; #endif @@ -40968,10 +43139,16 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ sqlite3_vfs_register(&winLongPathVfs, 0); #endif + sqlite3_vfs_register(&winNolockVfs, 0); + +#if defined(SQLITE_WIN32_HAS_WIDE) + sqlite3_vfs_register(&winLongPathNolockVfs, 0); +#endif + return SQLITE_OK; } -SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ +SQLITE_API int sqlite3_os_end(void){ #if SQLITE_OS_WINRT if( sleepObj!=NULL ){ osCloseHandle(sleepObj); @@ -41415,7 +43592,29 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ /* #include "sqliteInt.h" */ /* -** A complete page cache is an instance of this structure. +** A complete page cache is an instance of this structure. Every +** entry in the cache holds a single page of the database file. The +** btree layer only operates on the cached copy of the database pages. +** +** A page cache entry is "clean" if it exactly matches what is currently +** on disk. A page is "dirty" if it has been modified and needs to be +** persisted to disk. +** +** pDirty, pDirtyTail, pSynced: +** All dirty pages are linked into the doubly linked list using +** PgHdr.pDirtyNext and pDirtyPrev. The list is maintained in LRU order +** such that p was added to the list more recently than p->pDirtyNext. +** PCache.pDirty points to the first (newest) element in the list and +** pDirtyTail to the last (oldest). +** +** The PCache.pSynced variable is used to optimize searching for a dirty +** page to eject from the cache mid-transaction. It is better to eject +** a page that does not require a journal sync than one that does. +** Therefore, pSynced is maintained to that it *almost* always points +** to either the oldest page in the pDirty/pDirtyTail list that has a +** clear PGHDR_NEED_SYNC flag or to a page that is older than this one +** (so that the right page to eject can be found by following pDirtyPrev +** pointers). */ struct PCache { PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ @@ -41432,6 +43631,95 @@ struct PCache { sqlite3_pcache *pCache; /* Pluggable cache module */ }; +/********************************** Test and Debug Logic **********************/ +/* +** Debug tracing macros. Enable by by changing the "0" to "1" and +** recompiling. +** +** When sqlite3PcacheTrace is 1, single line trace messages are issued. +** When sqlite3PcacheTrace is 2, a dump of the pcache showing all cache entries +** is displayed for many operations, resulting in a lot of output. +*/ +#if defined(SQLITE_DEBUG) && 0 + int sqlite3PcacheTrace = 2; /* 0: off 1: simple 2: cache dumps */ + int sqlite3PcacheMxDump = 9999; /* Max cache entries for pcacheDump() */ +# define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;} + void pcacheDump(PCache *pCache){ + int N; + int i, j; + sqlite3_pcache_page *pLower; + PgHdr *pPg; + unsigned char *a; + + if( sqlite3PcacheTrace<2 ) return; + if( pCache->pCache==0 ) return; + N = sqlite3PcachePagecount(pCache); + if( N>sqlite3PcacheMxDump ) N = sqlite3PcacheMxDump; + for(i=1; i<=N; i++){ + pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0); + if( pLower==0 ) continue; + pPg = (PgHdr*)pLower->pExtra; + printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags); + a = (unsigned char *)pLower->pBuf; + for(j=0; j<12; j++) printf("%02x", a[j]); + printf("\n"); + if( pPg->pPage==0 ){ + sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0); + } + } + } + #else +# define pcacheTrace(X) +# define pcacheDump(X) +#endif + +/* +** Check invariants on a PgHdr entry. Return true if everything is OK. +** Return false if any invariant is violated. +** +** This routine is for use inside of assert() statements only. For +** example: +** +** assert( sqlite3PcachePageSanity(pPg) ); +*/ +#if SQLITE_DEBUG +SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr *pPg){ + PCache *pCache; + assert( pPg!=0 ); + assert( pPg->pgno>0 ); /* Page number is 1 or more */ + pCache = pPg->pCache; + assert( pCache!=0 ); /* Every page has an associated PCache */ + if( pPg->flags & PGHDR_CLEAN ){ + assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */ + assert( pCache->pDirty!=pPg ); /* CLEAN pages not on dirty list */ + assert( pCache->pDirtyTail!=pPg ); + } + /* WRITEABLE pages must also be DIRTY */ + if( pPg->flags & PGHDR_WRITEABLE ){ + assert( pPg->flags & PGHDR_DIRTY ); /* WRITEABLE implies DIRTY */ + } + /* NEED_SYNC can be set independently of WRITEABLE. This can happen, + ** for example, when using the sqlite3PagerDontWrite() optimization: + ** (1) Page X is journalled, and gets WRITEABLE and NEED_SEEK. + ** (2) Page X moved to freelist, WRITEABLE is cleared + ** (3) Page X reused, WRITEABLE is set again + ** If NEED_SYNC had been cleared in step 2, then it would not be reset + ** in step 3, and page might be written into the database without first + ** syncing the rollback journal, which might cause corruption on a power + ** loss. + ** + ** Another example is when the database page size is smaller than the + ** disk sector size. When any page of a sector is journalled, all pages + ** in that sector are marked NEED_SYNC even if they are still CLEAN, just + ** in case they are later modified, since all pages in the same sector + ** must be journalled and synced before any of those pages can be safely + ** written. + */ + return 1; +} +#endif /* SQLITE_DEBUG */ + + /********************************** Linked List Management ********************/ /* Allowed values for second argument to pcacheManageDirtyList() */ @@ -41448,17 +43736,16 @@ struct PCache { static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){ PCache *p = pPage->pCache; + pcacheTrace(("%p.DIRTYLIST.%s %d\n", p, + addRemove==1 ? "REMOVE" : addRemove==2 ? "ADD" : "FRONT", + pPage->pgno)); if( addRemove & PCACHE_DIRTYLIST_REMOVE ){ assert( pPage->pDirtyNext || pPage==p->pDirtyTail ); assert( pPage->pDirtyPrev || pPage==p->pDirty ); /* Update the PCache1.pSynced variable if necessary. */ if( p->pSynced==pPage ){ - PgHdr *pSynced = pPage->pDirtyPrev; - while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){ - pSynced = pSynced->pDirtyPrev; - } - p->pSynced = pSynced; + p->pSynced = pPage->pDirtyPrev; } if( pPage->pDirtyNext ){ @@ -41470,10 +43757,15 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){ if( pPage->pDirtyPrev ){ pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext; }else{ + /* If there are now no dirty pages in the cache, set eCreate to 2. + ** This is an optimization that allows sqlite3PcacheFetch() to skip + ** searching for a dirty page to eject from the cache when it might + ** otherwise have to. */ assert( pPage==p->pDirty ); p->pDirty = pPage->pDirtyNext; - if( p->pDirty==0 && p->bPurgeable ){ - assert( p->eCreate==1 ); + assert( p->bPurgeable || p->eCreate==2 ); + if( p->pDirty==0 ){ /*OPTIMIZATION-IF-TRUE*/ + assert( p->bPurgeable==0 || p->eCreate==1 ); p->eCreate = 2; } } @@ -41495,10 +43787,19 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){ } } p->pDirty = pPage; - if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){ + + /* If pSynced is NULL and this page has a clear NEED_SYNC flag, set + ** pSynced to point to it. Checking the NEED_SYNC flag is an + ** optimization, as if pSynced points to a page with the NEED_SYNC + ** flag set sqlite3PcacheFetchStress() searches through all newer + ** entries of the dirty-list for a page with NEED_SYNC clear anyway. */ + if( !p->pSynced + && 0==(pPage->flags&PGHDR_NEED_SYNC) /*OPTIMIZATION-IF-FALSE*/ + ){ p->pSynced = pPage; } } + pcacheDump(p); } /* @@ -41507,7 +43808,9 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){ */ static void pcacheUnpin(PgHdr *p){ if( p->pCache->bPurgeable ){ + pcacheTrace(("%p.UNPIN %d\n", p->pCache, p->pgno)); sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0); + pcacheDump(p->pCache); } } @@ -41577,6 +43880,7 @@ SQLITE_PRIVATE int sqlite3PcacheOpen( p->pStress = pStress; p->szCache = 100; p->szSpill = 1; + pcacheTrace(("%p.OPEN szPage %d bPurgeable %d\n",p,szPage,bPurgeable)); return sqlite3PcacheSetPageSize(p, szPage); } @@ -41599,6 +43903,7 @@ SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ } pCache->pCache = pNew; pCache->szPage = szPage; + pcacheTrace(("%p.PAGESIZE %d\n",pCache,szPage)); } return SQLITE_OK; } @@ -41633,11 +43938,13 @@ SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch( int createFlag /* If true, create page if it does not exist already */ ){ int eCreate; + sqlite3_pcache_page *pRes; 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. ** 0 Do not allocate a new page. (createFlag==0) @@ -41650,12 +43957,15 @@ SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch( assert( eCreate==0 || eCreate==1 || eCreate==2 ); assert( createFlag==0 || pCache->eCreate==eCreate ); assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) ); - return sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate); + pRes = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate); + pcacheTrace(("%p.FETCH %d%s (result: %p)\n",pCache,pgno, + createFlag?" create":"",pRes)); + return pRes; } /* ** If the sqlite3PcacheFetch() routine is unable to allocate a new -** page because new clean pages are available for reuse and the cache +** page because no clean pages are available for reuse and the cache ** size limit has been reached, then this routine can be invoked to ** try harder to allocate a page. This routine might invoke the stress ** callback to spill dirty pages to the journal. It will then try to @@ -41677,7 +43987,11 @@ SQLITE_PRIVATE int sqlite3PcacheFetchStress( ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC ** cleared), but if that is not possible settle for any other ** unreferenced dirty page. - */ + ** + ** If the LRU page in the dirty list that has a clear PGHDR_NEED_SYNC + ** flag is currently referenced, then the following may leave pSynced + ** set incorrectly (pointing to other than the LRU page with NEED_SYNC + ** cleared). This is Ok, as pSynced is just an optimization. */ for(pPg=pCache->pSynced; pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); pPg=pPg->pDirtyPrev @@ -41695,7 +44009,9 @@ SQLITE_PRIVATE int sqlite3PcacheFetchStress( sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache), numberOfCachePages(pCache)); #endif + pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno)); rc = pCache->xStress(pCache->pStress, pPg); + pcacheDump(pCache); if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ return rc; } @@ -41723,7 +44039,7 @@ static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit( assert( pPage!=0 ); pPgHdr = (PgHdr*)pPage->pExtra; assert( pPgHdr->pPage==0 ); - memset(pPgHdr, 0, sizeof(PgHdr)); + memset(&pPgHdr->pDirty, 0, sizeof(PgHdr) - offsetof(PgHdr,pDirty)); pPgHdr->pPage = pPage; pPgHdr->pData = pPage->pBuf; pPgHdr->pExtra = (void *)&pPgHdr[1]; @@ -41755,6 +44071,7 @@ SQLITE_PRIVATE PgHdr *sqlite3PcacheFetchFinish( } pCache->nRefSum++; pPgHdr->nRef++; + assert( sqlite3PcachePageSanity(pPgHdr) ); return pPgHdr; } @@ -41768,8 +44085,11 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){ if( (--p->nRef)==0 ){ if( p->flags&PGHDR_CLEAN ){ pcacheUnpin(p); - }else if( p->pDirtyPrev!=0 ){ - /* Move the page to the head of the dirty list. */ + }else if( p->pDirtyPrev!=0 ){ /*OPTIMIZATION-IF-FALSE*/ + /* Move the page to the head of the dirty list. If p->pDirtyPrev==0, + ** then page p is already at the head of the dirty list and the + ** following call would be a no-op. Hence the OPTIMIZATION-IF-FALSE + ** tag above. */ pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); } } @@ -41780,6 +44100,7 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){ */ SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){ assert(p->nRef>0); + assert( sqlite3PcachePageSanity(p) ); p->nRef++; p->pCache->nRefSum++; } @@ -41791,6 +44112,7 @@ SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){ */ SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){ assert( p->nRef==1 ); + assert( sqlite3PcachePageSanity(p) ); if( p->flags&PGHDR_DIRTY ){ pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); } @@ -41804,13 +44126,16 @@ SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){ */ SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){ assert( p->nRef>0 ); - if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){ + assert( sqlite3PcachePageSanity(p) ); + if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){ /*OPTIMIZATION-IF-FALSE*/ p->flags &= ~PGHDR_DONT_WRITE; if( p->flags & PGHDR_CLEAN ){ p->flags ^= (PGHDR_DIRTY|PGHDR_CLEAN); + pcacheTrace(("%p.DIRTY %d\n",p->pCache,p->pgno)); assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY ); pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD); } + assert( sqlite3PcachePageSanity(p) ); } } @@ -41819,11 +44144,14 @@ SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){ ** make it so. */ SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){ - if( (p->flags & PGHDR_DIRTY) ){ + assert( sqlite3PcachePageSanity(p) ); + if( ALWAYS((p->flags & PGHDR_DIRTY)!=0) ){ assert( (p->flags & PGHDR_CLEAN)==0 ); pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE); p->flags |= PGHDR_CLEAN; + pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno)); + assert( sqlite3PcachePageSanity(p) ); if( p->nRef==0 ){ pcacheUnpin(p); } @@ -41835,11 +44163,24 @@ SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){ */ SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){ PgHdr *p; + pcacheTrace(("%p.CLEAN-ALL\n",pCache)); while( (p = pCache->pDirty)!=0 ){ sqlite3PcacheMakeClean(p); } } +/* +** Clear the PGHDR_NEED_SYNC and PGHDR_WRITEABLE flag from all dirty pages. +*/ +SQLITE_PRIVATE void sqlite3PcacheClearWritable(PCache *pCache){ + PgHdr *p; + pcacheTrace(("%p.CLEAR-WRITEABLE\n",pCache)); + for(p=pCache->pDirty; p; p=p->pDirtyNext){ + p->flags &= ~(PGHDR_NEED_SYNC|PGHDR_WRITEABLE); + } + pCache->pSynced = pCache->pDirtyTail; +} + /* ** Clear the PGHDR_NEED_SYNC flag from all dirty pages. */ @@ -41858,6 +44199,8 @@ SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ PCache *pCache = p->pCache; assert( p->nRef>0 ); assert( newPgno>0 ); + assert( sqlite3PcachePageSanity(p) ); + pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno)); sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno); p->pgno = newPgno; if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){ @@ -41878,6 +44221,7 @@ SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){ if( pCache->pCache ){ PgHdr *p; PgHdr *pNext; + pcacheTrace(("%p.TRUNCATE %d\n",pCache,pgno)); for(p=pCache->pDirty; p; p=pNext){ pNext = p->pDirtyNext; /* This routine never gets call with a positive pgno except right @@ -41885,7 +44229,7 @@ SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){ ** it must be that pgno==0. */ assert( p->pgno>0 ); - if( ALWAYS(p->pgno>pgno) ){ + if( p->pgno>pgno ){ assert( p->flags&PGHDR_DIRTY ); sqlite3PcacheMakeClean(p); } @@ -41908,6 +44252,7 @@ SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){ */ SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){ assert( pCache->pCache!=0 ); + pcacheTrace(("%p.CLOSE\n",pCache)); sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); } @@ -41920,29 +44265,31 @@ SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){ /* ** Merge two lists of pages connected by pDirty and in pgno order. -** Do not both fixing the pDirtyPrev pointers. +** Do not bother fixing the pDirtyPrev pointers. */ static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){ PgHdr result, *pTail; pTail = &result; - while( pA && pB ){ + assert( pA!=0 && pB!=0 ); + for(;;){ if( pA->pgnopgno ){ pTail->pDirty = pA; pTail = pA; pA = pA->pDirty; + if( pA==0 ){ + pTail->pDirty = pB; + break; + } }else{ pTail->pDirty = pB; pTail = pB; pB = pB->pDirty; + if( pB==0 ){ + pTail->pDirty = pA; + break; + } } } - if( pA ){ - pTail->pDirty = pA; - }else if( pB ){ - pTail->pDirty = pB; - }else{ - pTail->pDirty = 0; - } return result.pDirty; } @@ -41983,7 +44330,8 @@ static PgHdr *pcacheSortDirtyList(PgHdr *pIn){ } p = a[0]; for(i=1; ipDirty; pDirty; pDirty=pDirty->pDirtyNext) nDirty++; + return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0; +} #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) /* @@ -42374,7 +44733,7 @@ static int pcache1InitBulk(PCache1 *pCache){ szBulk = -1024 * (i64)pcache1.nInitPage; } if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ - szBulk = pCache->szAlloc*pCache->nMax; + szBulk = pCache->szAlloc*(i64)pCache->nMax; } zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); sqlite3EndBenignMalloc(); @@ -42727,12 +45086,30 @@ static void pcache1TruncateUnsafe( PCache1 *pCache, /* The cache to truncate */ unsigned int iLimit /* Drop pages with this pgno or larger */ ){ - TESTONLY( unsigned int nPage = 0; ) /* To assert pCache->nPage is correct */ - unsigned int h; + TESTONLY( int nPage = 0; ) /* To assert pCache->nPage is correct */ + unsigned int h, iStop; assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); - for(h=0; hnHash; h++){ - PgHdr1 **pp = &pCache->apHash[h]; + assert( pCache->iMaxKey >= iLimit ); + assert( pCache->nHash > 0 ); + if( pCache->iMaxKey - iLimit < pCache->nHash ){ + /* If we are just shaving the last few pages off the end of the + ** cache, then there is no point in scanning the entire hash table. + ** Only scan those hash slots that might contain pages that need to + ** be removed. */ + h = iLimit % pCache->nHash; + iStop = pCache->iMaxKey % pCache->nHash; + TESTONLY( nPage = -10; ) /* Disable the pCache->nPage validity check */ + }else{ + /* This is the general case where many pages are being removed. + ** It is necessary to scan the entire hash table */ + h = pCache->nHash/2; + iStop = h - 1; + } + for(;;){ + PgHdr1 **pp; PgHdr1 *pPage; + assert( hnHash ); + pp = &pCache->apHash[h]; while( (pPage = *pp)!=0 ){ if( pPage->iKey>=iLimit ){ pCache->nPage--; @@ -42741,11 +45118,13 @@ static void pcache1TruncateUnsafe( pcache1FreePage(pPage); }else{ pp = &pPage->pNext; - TESTONLY( nPage++; ) + TESTONLY( if( nPage>=0 ) nPage++; ) } } + if( h==iStop ) break; + h = (h+1) % pCache->nHash; } - assert( pCache->nPage==nPage ); + assert( nPage<0 || pCache->nPage==(unsigned)nPage ); } /******************************************************************************/ @@ -42785,8 +45164,8 @@ static int pcache1Init(void *NotUsed){ #if SQLITE_THREADSAFE if( sqlite3GlobalConfig.bCoreMutex ){ - pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU); - pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM); + pcache1.grp.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU); + pcache1.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PMEM); } #endif if( pcache1.separateCache @@ -43222,7 +45601,7 @@ static void pcache1Destroy(sqlite3_pcache *p){ PGroup *pGroup = pCache->pGroup; assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) ); pcache1EnterMutex(pGroup); - pcache1TruncateUnsafe(pCache, 0); + if( pCache->nPage ) pcache1TruncateUnsafe(pCache, 0); assert( pGroup->nMaxPage >= pCache->nMax ); pGroup->nMaxPage -= pCache->nMax; assert( pGroup->nMinPage >= pCache->nMin ); @@ -43392,8 +45771,9 @@ SQLITE_PRIVATE void sqlite3PcacheStats( ** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST ** primitives are constant time. The cost of DESTROY is O(N). ** -** There is an added cost of O(N) when switching between TEST and -** SMALLEST primitives. +** TEST and SMALLEST may not be used by the same RowSet. This used to +** be possible, but the feature was not used, so it was removed in order +** to simplify the code. */ /* #include "sqliteInt.h" */ @@ -43514,7 +45894,9 @@ SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){ */ static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ assert( p!=0 ); - if( p->nFresh==0 ){ + if( p->nFresh==0 ){ /*OPTIMIZATION-IF-FALSE*/ + /* We could allocate a fresh RowSetEntry each time one is needed, but it + ** is more efficient to pull a preallocated entry from the pool */ struct RowSetChunk *pNew; pNew = sqlite3DbMallocRawNN(p->db, sizeof(*pNew)); if( pNew==0 ){ @@ -43548,7 +45930,9 @@ SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){ pEntry->pRight = 0; pLast = p->pLast; if( pLast ){ - if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){ + if( rowid<=pLast->v ){ /*OPTIMIZATION-IF-FALSE*/ + /* Avoid unnecessary sorts by preserving the ROWSET_SORTED flags + ** where possible */ p->rsFlags &= ~ROWSET_SORTED; } pLast->pRight = pEntry; @@ -43572,28 +45956,26 @@ static struct RowSetEntry *rowSetEntryMerge( struct RowSetEntry *pTail; pTail = &head; - while( pA && pB ){ + assert( pA!=0 && pB!=0 ); + for(;;){ assert( pA->pRight==0 || pA->v<=pA->pRight->v ); assert( pB->pRight==0 || pB->v<=pB->pRight->v ); - if( pA->vv ){ - pTail->pRight = pA; + if( pA->v<=pB->v ){ + if( pA->vv ) pTail = pTail->pRight = pA; pA = pA->pRight; - pTail = pTail->pRight; - }else if( pB->vv ){ - pTail->pRight = pB; - pB = pB->pRight; - pTail = pTail->pRight; + if( pA==0 ){ + pTail->pRight = pB; + break; + } }else{ - pA = pA->pRight; + pTail = pTail->pRight = pB; + pB = pB->pRight; + if( pB==0 ){ + pTail->pRight = pA; + break; + } } } - if( pA ){ - assert( pA->pRight==0 || pA->v<=pA->pRight->v ); - pTail->pRight = pA; - }else{ - assert( pB==0 || pB->pRight==0 || pB->v<=pB->pRight->v ); - pTail->pRight = pB; - } return head.pRight; } @@ -43616,9 +45998,10 @@ static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){ aBucket[i] = pIn; pIn = pNext; } - pIn = 0; - for(i=0; i1 ){ /*OPTIMIZATION-IF-TRUE*/ + /* This branch causes a *balanced* tree to be generated. A valid tree + ** is still generated without this branch, but the tree is wildly + ** unbalanced and inefficient. */ + pLeft = rowSetNDeepTree(ppList, iDepth-1); + p = *ppList; + if( p==0 ){ /*OPTIMIZATION-IF-FALSE*/ + /* It is safe to always return here, but the resulting tree + ** would be unbalanced */ + return pLeft; + } + p->pLeft = pLeft; + *ppList = p->pRight; + p->pRight = rowSetNDeepTree(ppList, iDepth-1); + }else{ p = *ppList; *ppList = p->pRight; p->pLeft = p->pRight = 0; - return p; - } - pLeft = rowSetNDeepTree(ppList, iDepth-1); - p = *ppList; - if( p==0 ){ - return pLeft; } - p->pLeft = pLeft; - *ppList = p->pRight; - p->pRight = rowSetNDeepTree(ppList, iDepth-1); return p; } @@ -43713,59 +46102,37 @@ static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){ return p; } -/* -** Take all the entries on p->pEntry and on the trees in p->pForest and -** sort them all together into one big ordered list on p->pEntry. -** -** This routine should only be called once in the life of a RowSet. -*/ -static void rowSetToList(RowSet *p){ - - /* This routine is called only once */ - assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); - - if( (p->rsFlags & ROWSET_SORTED)==0 ){ - p->pEntry = rowSetEntrySort(p->pEntry); - } - - /* While this module could theoretically support it, sqlite3RowSetNext() - ** is never called after sqlite3RowSetText() for the same RowSet. So - ** there is never a forest to deal with. Should this change, simply - ** remove the assert() and the #if 0. */ - assert( p->pForest==0 ); -#if 0 - while( p->pForest ){ - struct RowSetEntry *pTree = p->pForest->pLeft; - if( pTree ){ - struct RowSetEntry *pHead, *pTail; - rowSetTreeToList(pTree, &pHead, &pTail); - p->pEntry = rowSetEntryMerge(p->pEntry, pHead); - } - p->pForest = p->pForest->pRight; - } -#endif - p->rsFlags |= ROWSET_NEXT; /* Verify this routine is never called again */ -} - /* ** Extract the smallest element from the RowSet. ** Write the element into *pRowid. Return 1 on success. Return ** 0 if the RowSet is already empty. ** ** After this routine has been called, the sqlite3RowSetInsert() -** routine may not be called again. +** routine may not be called again. +** +** This routine may not be called after sqlite3RowSetTest() has +** been used. Older versions of RowSet allowed that, but as the +** capability was not used by the code generator, it was removed +** for code economy. */ SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ assert( p!=0 ); + assert( p->pForest==0 ); /* Cannot be used with sqlite3RowSetText() */ /* Merge the forest into a single sorted list on first call */ - if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p); + if( (p->rsFlags & ROWSET_NEXT)==0 ){ /*OPTIMIZATION-IF-FALSE*/ + if( (p->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/ + p->pEntry = rowSetEntrySort(p->pEntry); + } + p->rsFlags |= ROWSET_SORTED|ROWSET_NEXT; + } /* Return the next entry on the list */ if( p->pEntry ){ *pRowid = p->pEntry->v; p->pEntry = p->pEntry->pRight; - if( p->pEntry==0 ){ + if( p->pEntry==0 ){ /*OPTIMIZATION-IF-TRUE*/ + /* Free memory immediately, rather than waiting on sqlite3_finalize() */ sqlite3RowSetClear(p); } return 1; @@ -43788,13 +46155,15 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 /* This routine is never called after sqlite3RowSetNext() */ assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 ); - /* Sort entries into the forest on the first test of a new batch + /* Sort entries into the forest on the first test of a new batch. + ** To save unnecessary work, only do this when the batch number changes. */ - if( iBatch!=pRowSet->iBatch ){ + if( iBatch!=pRowSet->iBatch ){ /*OPTIMIZATION-IF-FALSE*/ p = pRowSet->pEntry; if( p ){ struct RowSetEntry **ppPrevTree = &pRowSet->pForest; - if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ + if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/ + /* Only sort the current set of entiries if they need it */ p = rowSetEntrySort(p); } for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ @@ -43884,8 +46253,8 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 ** the implementation of each function in log.c for further details. */ -#ifndef _WAL_H_ -#define _WAL_H_ +#ifndef SQLITE_WAL_H +#define SQLITE_WAL_H /* #include "sqliteInt.h" */ @@ -44013,7 +46382,7 @@ SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal); SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal); #endif /* ifndef SQLITE_OMIT_WAL */ -#endif /* _WAL_H_ */ +#endif /* SQLITE_WAL_H */ /************** End of wal.h *************************************************/ /************** Continuing where we left off in pager.c **********************/ @@ -44813,9 +47182,10 @@ static const unsigned char aJournalMagic[] = { ** rollback journal. Otherwise false. */ #ifndef SQLITE_OMIT_WAL -static int pagerUseWal(Pager *pPager){ +SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager){ return (pPager->pWal!=0); } +# define pagerUseWal(x) sqlite3PagerUseWal(x) #else # define pagerUseWal(x) 0 # define pagerRollbackWal(x) 0 @@ -44868,6 +47238,7 @@ static int assert_pager_state(Pager *p){ ** state. */ if( MEMDB ){ + assert( !isOpen(p->fd) ); assert( p->noSync ); assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_MEMORY @@ -44954,7 +47325,7 @@ static int assert_pager_state(Pager *p){ ** back to OPEN state. */ assert( pPager->errCode!=SQLITE_OK ); - assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); + assert( sqlite3PcacheRefCount(pPager->pPCache)>0 || pPager->tempFile ); break; } @@ -45166,6 +47537,8 @@ static int jrnlBufferSize(Pager *pPager){ return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager); } +#else +# define jrnlBufferSize(x) 0 #endif /* @@ -45814,13 +48187,17 @@ static void pager_unlock(Pager *pPager){ ** it can safely move back to PAGER_OPEN state. This happens in both ** normal and exclusive-locking mode. */ + assert( pPager->errCode==SQLITE_OK || !MEMDB ); if( pPager->errCode ){ - assert( !MEMDB ); - pager_reset(pPager); - pPager->changeCountDone = pPager->tempFile; - pPager->eState = PAGER_OPEN; - pPager->errCode = SQLITE_OK; + if( pPager->tempFile==0 ){ + pager_reset(pPager); + pPager->changeCountDone = 0; + pPager->eState = PAGER_OPEN; + }else{ + pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER); + } if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0); + pPager->errCode = SQLITE_OK; } pPager->journalOff = 0; @@ -45864,6 +48241,29 @@ static int pager_error(Pager *pPager, int rc){ static int pager_truncate(Pager *pPager, Pgno nPage); +/* +** The write transaction open on pPager is being committed (bCommit==1) +** or rolled back (bCommit==0). +** +** Return TRUE if and only if all dirty pages should be flushed to disk. +** +** Rules: +** +** * For non-TEMP databases, always sync to disk. This is necessary +** for transactions to be durable. +** +** * Sync TEMP database only on a COMMIT (not a ROLLBACK) when the backing +** file has been created already (via a spill on pagerStress()) and +** when the number of dirty pages in memory exceeds 25% of the total +** cache size. +*/ +static int pagerFlushOnCommit(Pager *pPager, int bCommit){ + if( pPager->tempFile==0 ) return 1; + if( !bCommit ) return 0; + if( !isOpen(pPager->fd) ) return 0; + return (sqlite3PCachePercentDirty(pPager->pPCache)>=25); +} + /* ** This routine ends a transaction. A transaction is usually ended by ** either a COMMIT or a ROLLBACK operation. This routine may be called @@ -45967,7 +48367,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL) ){ - rc = zeroJournalHdr(pPager, hasMaster); + rc = zeroJournalHdr(pPager, hasMaster||pPager->tempFile); pPager->journalOff = 0; }else{ /* This branch may be executed with Pager.journalMode==MEMORY if @@ -46002,8 +48402,14 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; pPager->nRec = 0; - sqlite3PcacheCleanAll(pPager->pPCache); - sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); + if( rc==SQLITE_OK ){ + if( pagerFlushOnCommit(pPager, bCommit) ){ + sqlite3PcacheCleanAll(pPager->pPCache); + }else{ + sqlite3PcacheClearWritable(pPager->pPCache); + } + sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); + } if( pagerUseWal(pPager) ){ /* Drop the WAL write-lock, if any. Also, if the connection was in @@ -46287,7 +48693,7 @@ static int pager_playback_one_page( pPg = sqlite3PagerLookup(pPager, pgno); } assert( pPg || !MEMDB ); - assert( pPager->eState!=PAGER_OPEN || pPg==0 ); + assert( pPager->eState!=PAGER_OPEN || pPg==0 || pPager->tempFile ); PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n", PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData), (isMainJrnl?"main-journal":"sub-journal") @@ -46337,7 +48743,6 @@ static int pager_playback_one_page( assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 ); pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK; if( rc!=SQLITE_OK ) return rc; - pPg->flags &= ~PGHDR_NEED_READ; sqlite3PcacheMakeDirty(pPg); } if( pPg ){ @@ -46351,29 +48756,10 @@ static int pager_playback_one_page( pData = pPg->pData; memcpy(pData, (u8*)aData, pPager->pageSize); pPager->xReiniter(pPg); - if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){ - /* If the contents of this page were just restored from the main - ** journal file, then its content must be as they were when the - ** transaction was first opened. In this case we can mark the page - ** as clean, since there will be no need to write it out to the - ** database. - ** - ** There is one exception to this rule. If the page is being rolled - ** back as part of a savepoint (or statement) rollback from an - ** unsynced portion of the main journal file, then it is not safe - ** to mark the page as clean. This is because marking the page as - ** clean will clear the PGHDR_NEED_SYNC flag. Since the page is - ** already in the journal file (recorded in Pager.pInJournal) and - ** the PGHDR_NEED_SYNC flag is cleared, if the page is written to - ** again within this transaction, it will be marked as dirty but - ** the PGHDR_NEED_SYNC flag will not be set. It could then potentially - ** be written out into the database file before its journal file - ** segment is synced. If a crash occurs during or following this, - ** database corruption may ensue. - */ - assert( !pagerUseWal(pPager) ); - sqlite3PcacheMakeClean(pPg); - } + /* It used to be that sqlite3PcacheMakeClean(pPg) was called here. But + ** that call was dangerous and had no detectable benefit since the cache + ** is normally cleaned by sqlite3PcacheCleanAll() after rollback and so + ** has been removed. */ pager_set_pagehash(pPg); /* If this was page 1, then restore the value of Pager.dbFileVers. @@ -47164,6 +49550,8 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ */ assert( pPager->eState==PAGER_OPEN ); assert( pPager->eLock>=SHARED_LOCK ); + assert( isOpen(pPager->fd) ); + assert( pPager->tempFile==0 ); nPage = sqlite3WalDbsize(pPager->pWal); /* If the number of pages in the database is not available from the @@ -47171,14 +49559,11 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ ** the database file. If the size of the database file is not an ** integer multiple of the page-size, round up the result. */ - if( nPage==0 ){ + if( nPage==0 && ALWAYS(isOpen(pPager->fd)) ){ i64 n = 0; /* Size of db file in bytes */ - assert( isOpen(pPager->fd) || pPager->tempFile ); - if( isOpen(pPager->fd) ){ - int rc = sqlite3OsFileSize(pPager->fd, &n); - if( rc!=SQLITE_OK ){ - return rc; - } + int rc = sqlite3OsFileSize(pPager->fd, &n); + if( rc!=SQLITE_OK ){ + return rc; } nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize); } @@ -48254,8 +50639,9 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){ /* This function is only called for rollback pagers in WRITER_DBMOD state. */ assert( !pagerUseWal(pPager) ); - assert( pPager->eState==PAGER_WRITER_DBMOD ); + assert( pPager->tempFile || pPager->eState==PAGER_WRITER_DBMOD ); assert( pPager->eLock==EXCLUSIVE_LOCK ); + assert( isOpen(pPager->fd) || pList->pDirty==0 ); /* If the file is a temp-file has not yet been opened, open it now. It ** is not possible for rc to be other than SQLITE_OK if this branch @@ -48923,6 +51309,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){ if( rc==SQLITE_OK && !locked ){ Pgno nPage; /* Number of pages in database file */ + assert( pPager->tempFile==0 ); rc = pagerPagecount(pPager, &nPage); if( rc==SQLITE_OK ){ /* If the database is zero pages in size, that means that either (1) the @@ -49015,17 +51402,17 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ /* This routine is only called from b-tree and only when there are no ** outstanding pages. This implies that the pager state should either ** be OPEN or READER. READER is only possible if the pager is or was in - ** exclusive access mode. - */ + ** exclusive access mode. */ assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); assert( assert_pager_state(pPager) ); assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER ); - if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; } + assert( pPager->errCode==SQLITE_OK ); if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){ int bHotJournal = 1; /* True if there exists a hot journal-file */ assert( !MEMDB ); + assert( pPager->tempFile==0 || pPager->eLock==EXCLUSIVE_LOCK ); rc = pager_wait_on_lock(pPager, SHARED_LOCK); if( rc!=SQLITE_OK ){ @@ -49111,7 +51498,7 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ assert( rc==SQLITE_OK ); rc = pagerSyncHotJournal(pPager); if( rc==SQLITE_OK ){ - rc = pager_playback(pPager, 1); + rc = pager_playback(pPager, !pPager->tempFile); pPager->eState = PAGER_OPEN; } }else if( !pPager->exclusiveMode ){ @@ -49207,7 +51594,7 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ rc = pagerBeginReadTransaction(pPager); } - if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){ + if( pPager->tempFile==0 && pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){ rc = pagerPagecount(pPager, &pPager->dbSize); } @@ -49340,7 +51727,7 @@ SQLITE_PRIVATE int sqlite3PagerGet( ); if( rc==SQLITE_OK && pData ){ - if( pPager->eState>PAGER_READER ){ + if( pPager->eState>PAGER_READER || pPager->tempFile ){ pPg = sqlite3PagerLookup(pPager, pgno); } if( pPg==0 ){ @@ -49407,7 +51794,8 @@ SQLITE_PRIVATE int sqlite3PagerGet( goto pager_acquire_err; } - if( MEMDB || pPager->dbSizefd) ){ + assert( !isOpen(pPager->fd) || !MEMDB ); + if( !isOpen(pPager->fd) || pPager->dbSizepPager->mxPgno ){ rc = SQLITE_FULL; goto pager_acquire_err; @@ -49549,24 +51937,24 @@ static int pager_open_journal(Pager *pPager){ if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ sqlite3MemJournalOpen(pPager->jfd); }else{ - const int flags = /* VFS flags to open journal file */ - SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| - (pPager->tempFile ? - (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL): - (SQLITE_OPEN_MAIN_JOURNAL) - ); + int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; + int nSpill; + if( pPager->tempFile ){ + flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL); + nSpill = sqlite3Config.nStmtSpill; + }else{ + flags |= SQLITE_OPEN_MAIN_JOURNAL; + nSpill = jrnlBufferSize(pPager); + } + /* Verify that the database still has the same name as it did when ** it was originally opened. */ rc = databaseIsUnmoved(pPager); if( rc==SQLITE_OK ){ -#ifdef SQLITE_ENABLE_ATOMIC_WRITE - rc = sqlite3JournalOpen( - pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager) + rc = sqlite3JournalOpen ( + pVfs, pPager->zJournal, pPager->jfd, flags, nSpill ); -#else - rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); -#endif } } assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); @@ -49937,6 +52325,7 @@ SQLITE_PRIVATE int sqlite3PagerWrite(PgHdr *pPg){ if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg); return SQLITE_OK; }else if( pPager->sectorSize > (u32)pPager->pageSize ){ + assert( pPager->tempFile==0 ); return pagerWriteLargeSector(pPg); }else{ return pager_write(pPg); @@ -49967,14 +52356,21 @@ SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){ ** ** Tests show that this optimization can quadruple the speed of large ** DELETE operations. +** +** This optimization cannot be used with a temp-file, as the page may +** have been dirty at the start of the transaction. In that case, if +** memory pressure forces page pPg out of the cache, the data does need +** to be written out to disk so that it may be read back in if the +** current transaction is rolled back. */ SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){ Pager *pPager = pPg->pPager; - if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){ + if( !pPager->tempFile && (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){ PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager))); IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) pPg->flags |= PGHDR_DONT_WRITE; pPg->flags &= ~PGHDR_WRITEABLE; + testcase( pPg->flags & PGHDR_NEED_SYNC ); pager_set_pagehash(pPg); } } @@ -50169,17 +52565,21 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( /* If a prior error occurred, report that error again. */ if( NEVER(pPager->errCode) ) return pPager->errCode; + /* Provide the ability to easily simulate an I/O error during testing */ + if( sqlite3FaultSim(400) ) return SQLITE_IOERR; + PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", pPager->zFilename, zMaster, pPager->dbSize)); /* If no database changes have been made, return early. */ if( pPager->eStatetempFile ); + assert( isOpen(pPager->fd) || pPager->tempFile ); + if( 0==pagerFlushOnCommit(pPager, 1) ){ /* If this is an in-memory db, or no pages have been written to, or this ** function has already been called, it is mostly a no-op. However, any - ** backup in progress needs to be restarted. - */ + ** backup in progress needs to be restarted. */ sqlite3BackupRestart(pPager->pBackup); }else{ if( pagerUseWal(pPager) ){ @@ -50518,10 +52918,10 @@ SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, i } /* -** Return true if this is an in-memory pager. +** Return true if this is an in-memory or temp-file backed pager. */ SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){ - return MEMDB; + return pPager->tempFile; } /* @@ -50622,7 +53022,11 @@ SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){ ** savepoint. If no errors occur, SQLITE_OK is returned. */ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ - int rc = pPager->errCode; /* Return code */ + int rc = pPager->errCode; + +#ifdef SQLITE_ENABLE_ZIPVFS + if( op==SAVEPOINT_RELEASE ) rc = SQLITE_OK; +#endif assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK ); assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK ); @@ -50663,6 +53067,20 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ rc = pagerPlaybackSavepoint(pPager, pSavepoint); assert(rc!=SQLITE_DONE); } + +#ifdef SQLITE_ENABLE_ZIPVFS + /* If the cache has been modified but the savepoint cannot be rolled + ** back journal_mode=off, put the pager in the error state. This way, + ** if the VFS used by this pager includes ZipVFS, the entire transaction + ** can be rolled back at the ZipVFS level. */ + else if( + pPager->journalMode==PAGER_JOURNALMODE_OFF + && pPager->eState>=PAGER_WRITER_CACHEMOD + ){ + pPager->errCode = SQLITE_ABORT; + pPager->eState = PAGER_ERROR; + } +#endif } return rc; @@ -50801,7 +53219,8 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i /* In order to be able to rollback, an in-memory database must journal ** the page we are moving from. */ - if( MEMDB ){ + assert( pPager->tempFile || !MEMDB ); + if( pPager->tempFile ){ rc = sqlite3PagerWrite(pPg); if( rc ) return rc; } @@ -50858,7 +53277,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i assert( !pPgOld || pPgOld->nRef==1 ); if( pPgOld ){ pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC); - if( MEMDB ){ + if( pPager->tempFile ){ /* Do not discard pages from an in-memory database since we might ** need to rollback later. Just move the page out of the way. */ sqlite3PcacheMove(pPgOld, pPager->dbSize+1); @@ -50875,8 +53294,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i ** to exist, in case the transaction needs to roll back. Use pPgOld ** as the original page since it has already been allocated. */ - if( MEMDB ){ - assert( pPgOld ); + if( pPager->tempFile && pPgOld ){ sqlite3PcacheMove(pPgOld, origPgno); sqlite3PagerUnrefNotNull(pPgOld); } @@ -51128,10 +53546,12 @@ SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){ ** Unless this is an in-memory or temporary database, clear the pager cache. */ SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *pPager){ - if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager); + assert( MEMDB==0 || pPager->tempFile ); + if( pPager->tempFile==0 ) pager_reset(pPager); } #endif + #ifndef SQLITE_OMIT_WAL /* ** This function is called when the user invokes "PRAGMA wal_checkpoint", @@ -51307,6 +53727,7 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){ pPager->pageSize, (u8*)pPager->pTmpSpace); pPager->pWal = 0; pagerFixMaplimit(pPager); + if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); } } return rc; @@ -51356,7 +53777,6 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ } #endif - #endif /* SQLITE_OMIT_DISKIO */ /************** End of pager.c ***********************************************/ @@ -54472,16 +56892,21 @@ SQLITE_PRIVATE int sqlite3WalFrames( ** past the sector boundary is written after the sync. */ if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){ + int bSync = 1; if( pWal->padToSectorBoundary ){ int sectorSize = sqlite3SectorSize(pWal->pWalFd); w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize; + bSync = (w.iSyncPoint==iOffset); + testcase( bSync ); while( iOffsetpSnapshot = (WalIndexHdr*)pSnapshot; } + +/* +** Return a +ve value if snapshot p1 is newer than p2. A -ve value if +** p1 is older than p2 and zero if p1 and p2 are the same snapshot. +*/ +SQLITE_API int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){ + WalIndexHdr *pHdr1 = (WalIndexHdr*)p1; + WalIndexHdr *pHdr2 = (WalIndexHdr*)p2; + + /* aSalt[0] is a copy of the value stored in the wal file header. It + ** is incremented each time the wal file is restarted. */ + if( pHdr1->aSalt[0]aSalt[0] ) return -1; + if( pHdr1->aSalt[0]>pHdr2->aSalt[0] ) return +1; + if( pHdr1->mxFramemxFrame ) return -1; + if( pHdr1->mxFrame>pHdr2->mxFrame ) return +1; + return 0; +} #endif /* SQLITE_ENABLE_SNAPSHOT */ #ifdef SQLITE_ENABLE_ZIPVFS @@ -55887,7 +58329,7 @@ static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0; ** The shared cache setting effects only future calls to ** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int enable){ +SQLITE_API int sqlite3_enable_shared_cache(int enable){ sqlite3GlobalConfig.sharedCacheEnabled = enable; return SQLITE_OK; } @@ -56251,6 +58693,15 @@ static void releasePage(MemPage *pPage); /* Forward reference */ static int cursorHoldsMutex(BtCursor *p){ return sqlite3_mutex_held(p->pBt->mutex); } + +/* Verify that the cursor and the BtShared agree about what is the current +** database connetion. This is important in shared-cache mode. If the database +** connection pointers get out-of-sync, it is possible for routines like +** btreeInitPage() to reference an stale connection pointer that references a +** a connection that has already closed. This routine is used inside assert() +** statements only and for the purpose of double-checking that the btree code +** does keep the database connection pointers up-to-date. +*/ static int cursorOwnsBtShared(BtCursor *p){ assert( cursorHoldsMutex(p) ); return (p->pBtree->db==p->pBt->db); @@ -56410,21 +58861,19 @@ static void btreeReleaseAllCursorPages(BtCursor *pCur){ ** the key. */ static int saveCursorKey(BtCursor *pCur){ - int rc; + int rc = SQLITE_OK; assert( CURSOR_VALID==pCur->eState ); assert( 0==pCur->pKey ); assert( cursorHoldsMutex(pCur) ); - rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); - assert( rc==SQLITE_OK ); /* KeySize() cannot fail */ - - /* If this is an intKey table, then the above call to BtreeKeySize() - ** stores the integer key in pCur->nKey. In this case this value is - ** all that is required. Otherwise, if pCur is not open on an intKey - ** table, then malloc space for and store the pCur->nKey bytes of key - ** data. */ - if( 0==pCur->curIntKey ){ - void *pKey = sqlite3Malloc( pCur->nKey ); + if( pCur->curIntKey ){ + /* Only the rowid is required for a table btree */ + pCur->nKey = sqlite3BtreeIntegerKey(pCur); + }else{ + /* For an index btree, save the complete key content */ + void *pKey; + pCur->nKey = sqlite3BtreePayloadSize(pCur); + pKey = sqlite3Malloc( pCur->nKey ); if( pKey ){ rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey); if( rc==SQLITE_OK ){ @@ -56557,7 +59006,7 @@ static int btreeMoveto( ){ int rc; /* Status code */ UnpackedRecord *pIdxKey; /* Unpacked index key */ - char aSpace[200]; /* Temp space for pIdxKey - to avoid a malloc */ + char aSpace[384]; /* Temp space for pIdxKey - to avoid a malloc */ char *pFree = 0; if( pKey ){ @@ -57399,8 +59848,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ if( data[iPtr+1]==0 && data[iPtr]==0 ){ iFreeBlk = 0; /* Shortcut for the case when the freelist is empty */ }else{ - while( (iFreeBlk = get2byte(&data[iPtr]))>0 && iFreeBlkiLast ) return SQLITE_CORRUPT_BKPT; @@ -57477,11 +59929,11 @@ static int decodeFlags(MemPage *pPage, int flagByte){ pPage->xCellSize = cellSizePtr; pBt = pPage->pBt; if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){ - /* EVIDENCE-OF: R-03640-13415 A value of 5 means the page is an interior - ** table b-tree page. */ + /* EVIDENCE-OF: R-07291-35328 A value of 5 (0x05) means the page is an + ** interior table b-tree page. */ assert( (PTF_LEAFDATA|PTF_INTKEY)==5 ); - /* EVIDENCE-OF: R-20501-61796 A value of 13 means the page is a leaf - ** table b-tree page. */ + /* EVIDENCE-OF: R-26900-09176 A value of 13 (0x0d) means the page is a + ** leaf table b-tree page. */ assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 ); pPage->intKey = 1; if( pPage->leaf ){ @@ -57495,11 +59947,11 @@ static int decodeFlags(MemPage *pPage, int flagByte){ pPage->maxLocal = pBt->maxLeaf; pPage->minLocal = pBt->minLeaf; }else if( flagByte==PTF_ZERODATA ){ - /* EVIDENCE-OF: R-27225-53936 A value of 2 means the page is an interior - ** index b-tree page. */ + /* EVIDENCE-OF: R-43316-37308 A value of 2 (0x02) means the page is an + ** interior index b-tree page. */ assert( (PTF_ZERODATA)==2 ); - /* EVIDENCE-OF: R-16571-11615 A value of 10 means the page is a leaf - ** index b-tree page. */ + /* EVIDENCE-OF: R-59615-42828 A value of 10 (0x0a) means the page is a + ** leaf index b-tree page. */ assert( (PTF_ZERODATA|PTF_LEAF)==10 ); pPage->intKey = 0; pPage->intKeyLeaf = 0; @@ -58131,9 +60583,9 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( #if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) /* Add the new BtShared object to the linked list sharable BtShareds. */ + pBt->nRef = 1; if( p->sharable ){ MUTEX_LOGIC( sqlite3_mutex *mutexShared; ) - pBt->nRef = 1; MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);) if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){ pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST); @@ -58204,6 +60656,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( assert( sqlite3_mutex_held(mutexOpen) ); sqlite3_mutex_leave(mutexOpen); } + assert( rc!=SQLITE_OK || sqlite3BtreeConnectionCount(*ppBtree)>0 ); return rc; } @@ -60063,46 +62516,33 @@ SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){ #endif /* NDEBUG */ /* -** Set *pSize to the size of the buffer needed to hold the value of -** the key for the current entry. If the cursor is not pointing -** to a valid entry, *pSize is set to 0. -** -** For a table with the INTKEY flag set, this routine returns the key -** itself, not the number of bytes in the key. -** -** The caller must position the cursor prior to invoking this routine. -** -** This routine cannot fail. It always returns SQLITE_OK. +** Return the value of the integer key or "rowid" for a table btree. +** This routine is only valid for a cursor that is pointing into a +** ordinary table btree. If the cursor points to an index btree or +** is invalid, the result of this routine is undefined. */ -SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ +SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); + assert( pCur->curIntKey ); getCellInfo(pCur); - *pSize = pCur->info.nKey; - return SQLITE_OK; + return pCur->info.nKey; } /* -** Set *pSize to the number of bytes of data in the entry the -** cursor currently points to. +** Return the number of bytes of payload for the entry that pCur is +** currently pointing to. For table btrees, this will be the amount +** of data. For index btrees, this will be the size of the key. ** ** The caller must guarantee that the cursor is pointing to a non-NULL ** valid entry. In other words, the calling procedure must guarantee ** that the cursor has Cursor.eState==CURSOR_VALID. -** -** Failure is not possible. This function always returns SQLITE_OK. -** It might just as well be a procedure (returning void) but we continue -** to return an integer result code for historical reasons. */ -SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ - assert( cursorOwnsBtShared(pCur) ); +SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPage>=0 ); - assert( pCur->iPageapPage[pCur->iPage]->intKeyLeaf==1 ); getCellInfo(pCur); - *pSize = pCur->info.nPayload; - return SQLITE_OK; + return pCur->info.nPayload; } /* @@ -60404,7 +62844,7 @@ static int accessPayload( && (bEnd || a==ovflSize) /* (6) */ && pBt->inTransaction==TRANS_READ /* (4) */ && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ - && pBt->pPage1->aData[19]==0x01 /* (5) */ + && 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */ && &pBuf[-4]>=pBufStart /* (7) */ ){ u8 aSave[4]; @@ -60544,10 +62984,7 @@ static const void *fetchPayload( ** These routines is used to get quick access to key and data ** in the common case where no overflow pages are used. */ -SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor *pCur, u32 *pAmt){ - return fetchPayload(pCur, pAmt); -} -SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){ +SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){ return fetchPayload(pCur, pAmt); } @@ -60880,11 +63317,12 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( pRes ); assert( (pIdxKey==0)==(pCur->pKeyInfo==0) ); + assert( pCur->eState!=CURSOR_VALID || (pIdxKey==0)==(pCur->curIntKey!=0) ); /* If the cursor is already positioned at the point we are trying ** to move to, then just return without doing any work */ - if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 - && pCur->curIntKey + if( pIdxKey==0 + && pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 ){ if( pCur->info.nKey==intKey ){ *pRes = 0; @@ -61873,9 +64311,7 @@ static int clearCell( static int fillInCell( MemPage *pPage, /* The page that contains the cell */ unsigned char *pCell, /* Complete text of the cell */ - const void *pKey, i64 nKey, /* The key */ - const void *pData,int nData, /* The data */ - int nZero, /* Extra zero bytes to append to pData */ + const BtreePayload *pX, /* Payload with which to construct the cell */ int *pnSize /* Write cell size here */ ){ int nPayload; @@ -61899,26 +64335,21 @@ static int fillInCell( /* Fill in the header. */ nHeader = pPage->childPtrSize; - nPayload = nData + nZero; - if( pPage->intKeyLeaf ){ + if( pPage->intKey ){ + nPayload = pX->nData + pX->nZero; + pSrc = pX->pData; + nSrc = pX->nData; + assert( pPage->intKeyLeaf ); /* fillInCell() only called for leaves */ nHeader += putVarint32(&pCell[nHeader], nPayload); + nHeader += putVarint(&pCell[nHeader], *(u64*)&pX->nKey); }else{ - assert( nData==0 ); - assert( nZero==0 ); + assert( pX->nKey<=0x7fffffff && pX->pKey!=0 ); + nSrc = nPayload = (int)pX->nKey; + pSrc = pX->pKey; + nHeader += putVarint32(&pCell[nHeader], nPayload); } - nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey); - /* Fill in the payload size */ - if( pPage->intKey ){ - pSrc = pData; - nSrc = nData; - nData = 0; - }else{ - assert( nKey<=0x7fffffff && pKey!=0 ); - nPayload = (int)nKey; - pSrc = pKey; - nSrc = (int)nKey; - } + /* Fill in the payload */ if( nPayload<=pPage->maxLocal ){ n = nHeader + nPayload; testcase( n==3 ); @@ -61956,7 +64387,7 @@ static int fillInCell( CellInfo info; pPage->xParseCell(pPage, pCell, &info); assert( nHeader==(int)(info.pPayload - pCell) ); - assert( info.nKey==nKey ); + assert( info.nKey==pX->nKey ); assert( *pnSize == info.nSize ); assert( spaceLeft == info.nLocal ); } @@ -62041,10 +64472,6 @@ static int fillInCell( pSrc += n; nSrc -= n; spaceLeft -= n; - if( nSrc==0 ){ - nSrc = nData; - pSrc = pData; - } } releasePage(pToRelease); return SQLITE_OK; @@ -62111,6 +64538,8 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ ** in pTemp or the original pCell) and also record its index. ** Allocating a new entry in pPage->aCell[] implies that ** pPage->nOverflow is incremented. +** +** *pRC must be SQLITE_OK when this routine is called. */ static void insertCell( MemPage *pPage, /* Page into which we are copying */ @@ -62126,8 +64555,7 @@ static void insertCell( u8 *data; /* The content of the whole page */ u8 *pIns; /* The point in pPage->aCellIdx[] where no cell inserted */ - if( *pRC ) return; - + assert( *pRC==SQLITE_OK ); assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); assert( MX_CELL(pPage->pBt)<=10921 ); assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB ); @@ -62201,7 +64629,7 @@ static void insertCell( /* ** A CellArray object contains a cache of pointers and sizes for a -** consecutive sequence of cells that might be held multiple pages. +** consecutive sequence of cells that might be held on multiple pages. */ typedef struct CellArray CellArray; struct CellArray { @@ -62346,8 +64774,8 @@ static int pageInsertArray( u8 *pSlot; sz = cachedCellSize(pCArray, i); if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){ + if( (pData - pBegin)apCell[i] will never overlap on a well-formed @@ -62509,7 +64937,7 @@ static int editPage( for(i=0; iapCell[i+iNew]; int iOff = get2byteAligned(&pPg->aCellIdx[i*2]); - if( pCell>=aData && pCell<&aData[pPg->pBt->usableSize] ){ + if( SQLITE_WITHIN(pCell, aData, &aData[pPg->pBt->usableSize]) ){ pCell = &pTmp[pCell - aData]; } assert( 0==memcmp(pCell, &aData[iOff], @@ -62633,8 +65061,10 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){ while( ((*(pOut++) = *(pCell++))&0x80) && pCellnCell, pSpace, (int)(pOut-pSpace), - 0, pPage->pgno, &rc); + if( rc==SQLITE_OK ){ + insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace), + 0, pPage->pgno, &rc); + } /* Set the right-child pointer of pParent to point to the new page. */ put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew); @@ -63154,7 +65584,7 @@ static int balance_nonroot( assert( r szLeft-(b.szCell[r]+2)) ){ + && (bBulk || szRight+b.szCell[d]+2 > szLeft-(b.szCell[r]+(i==k-1?0:2)))){ break; } szRight += b.szCell[d] + 2; @@ -63726,13 +66156,19 @@ static int balance(BtCursor *pCur){ /* -** Insert a new record into the BTree. The key is given by (pKey,nKey) -** and the data is given by (pData,nData). The cursor is used only to -** define what table the record should be inserted into. The cursor -** is left pointing at a random location. +** Insert a new record into the BTree. The content of the new record +** is described by the pX object. The pCur cursor is used only to +** define what table the record should be inserted into, and is left +** pointing at a random location. +** +** For a table btree (used for rowid tables), only the pX.nKey value of +** the key is used. The pX.pKey value must be NULL. The pX.nKey is the +** rowid or INTEGER PRIMARY KEY of the row. The pX.nData,pData,nZero fields +** hold the content of the row. ** -** For an INTKEY table, only the nKey value of the key is used. pKey is -** ignored. For a ZERODATA table, the pData and nData are both ignored. +** For an index btree (used for indexes and WITHOUT ROWID tables), the +** key is an arbitrary byte sequence stored in pX.pKey,nKey. The +** 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 @@ -63749,9 +66185,7 @@ static int balance(BtCursor *pCur){ */ SQLITE_PRIVATE int sqlite3BtreeInsert( BtCursor *pCur, /* Insert data into the table of this cursor */ - const void *pKey, i64 nKey, /* The key of the new record */ - const void *pData, int nData, /* The data of the new record */ - int nZero, /* Number of extra 0 bytes to append to data */ + const BtreePayload *pX, /* Content of the row to be inserted */ int appendBias, /* True if this is likely an append */ int seekResult /* Result of prior MovetoUnpacked() call */ ){ @@ -63781,7 +66215,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( ** keys with no associated data. If the cursor was opened expecting an ** intkey table, the caller should be inserting integer keys with a ** blob of associated data. */ - assert( (pKey==0)==(pCur->pKeyInfo==0) ); + assert( (pX->pKey==0)==(pCur->pKeyInfo==0) ); /* Save the positions of any other cursors open on this table. ** @@ -63800,38 +66234,38 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( } if( pCur->pKeyInfo==0 ){ - assert( pKey==0 ); + 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, nKey, 0); + invalidateIncrblobCursors(p, pX->nKey, 0); /* 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 && nKey>0 - && pCur->info.nKey==nKey-1 ){ + if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey>0 + && pCur->info.nKey==pX->nKey-1 ){ loc = -1; }else if( loc==0 ){ - rc = sqlite3BtreeMovetoUnpacked(pCur, 0, nKey, appendBias, &loc); + rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, appendBias, &loc); if( rc ) return rc; } }else if( loc==0 ){ - rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc); + rc = btreeMoveto(pCur, pX->pKey, pX->nKey, appendBias, &loc); if( rc ) return rc; } assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); pPage = pCur->apPage[pCur->iPage]; - assert( pPage->intKey || nKey>=0 ); + assert( pPage->intKey || pX->nKey>=0 ); assert( pPage->leaf || !pPage->intKey ); TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", - pCur->pgnoRoot, nKey, nData, pPage->pgno, + pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno, loc==0 ? "overwrite" : "new entry")); assert( pPage->isInit ); newCell = pBt->pTmpSpace; assert( newCell!=0 ); - rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew); + rc = fillInCell(pPage, newCell, pX, &szNew); if( rc ) goto end_insert; assert( szNew==pPage->xCellSize(pPage, newCell) ); assert( szNew <= MX_CELL_SIZE(pBt) ); @@ -63857,6 +66291,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( assert( pPage->leaf ); } insertCell(pPage, idx, newCell, szNew, 0, 0, &rc); + assert( pPage->nOverflow==0 || rc==SQLITE_OK ); assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); /* If no error has occurred and pPage has an overflow cell, call balance() @@ -63880,7 +66315,8 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( ** row without seeking the cursor. This can be a big performance boost. */ pCur->info.nSize = 0; - if( rc==SQLITE_OK && pPage->nOverflow ){ + if( pPage->nOverflow ){ + assert( rc==SQLITE_OK ); pCur->curFlags &= ~(BTCF_ValidNKey); rc = balance(pCur); @@ -63941,6 +66377,28 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ pPage = pCur->apPage[iCellDepth]; pCell = findCell(pPage, iCellIdx); + /* If the bPreserve flag is set to true, then the cursor position must + ** be preserved following this delete operation. If the current delete + ** will cause a b-tree rebalance, then this is done by saving the cursor + ** key and leaving the cursor in CURSOR_REQUIRESEEK state before + ** returning. + ** + ** Or, if the current delete will not cause a rebalance, then the cursor + ** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately + ** before or after the deleted entry. In this case set bSkipnext to true. */ + if( bPreserve ){ + if( !pPage->leaf + || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3) + ){ + /* A b-tree rebalance will be required after deleting this entry. + ** Save the cursor key. */ + rc = saveCursorKey(pCur); + if( rc ) return rc; + }else{ + bSkipnext = 1; + } + } + /* If the page containing the entry to delete is not a leaf page, move ** the cursor to the largest entry in the tree that is smaller than ** the entry being deleted. This cell will replace the cell being deleted @@ -63967,28 +66425,6 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ invalidateIncrblobCursors(p, pCur->info.nKey, 0); } - /* If the bPreserve flag is set to true, then the cursor position must - ** be preserved following this delete operation. If the current delete - ** will cause a b-tree rebalance, then this is done by saving the cursor - ** key and leaving the cursor in CURSOR_REQUIRESEEK state before - ** returning. - ** - ** Or, if the current delete will not cause a rebalance, then the cursor - ** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately - ** before or after the deleted entry. In this case set bSkipnext to true. */ - if( bPreserve ){ - if( !pPage->leaf - || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3) - ){ - /* A b-tree rebalance will be required after deleting this entry. - ** Save the cursor key. */ - rc = saveCursorKey(pCur); - if( rc ) return rc; - }else{ - bSkipnext = 1; - } - } - /* Make the page containing the entry to be deleted writable. Then free any ** overflow pages associated with the entry and finally remove the cell ** itself from within the page. */ @@ -64016,7 +66452,9 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ pTmp = pBt->pTmpSpace; assert( pTmp!=0 ); rc = sqlite3PagerWrite(pLeaf->pDbPage); - insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc); + if( rc==SQLITE_OK ){ + insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc); + } dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc); if( rc ) return rc; } @@ -65505,6 +67943,16 @@ SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); SQLITE_PRIVATE int sqlite3BtreeSharable(Btree *p){ return p->sharable; } + +/* +** Return the number of connections to the BtShared object accessed by +** the Btree handle passed as the only argument. For private caches +** this is always 1. For shared caches it may be 1 or greater. +*/ +SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree *p){ + testcase( p->sharable ); + return p->pBt->nRef; +} #endif /************** End of btree.c ***********************************************/ @@ -65594,22 +68042,16 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ int i = sqlite3FindDbName(pDb, zDb); if( i==1 ){ - Parse *pParse; + Parse sParse; int rc = 0; - pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse)); - if( pParse==0 ){ - sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory"); - rc = SQLITE_NOMEM_BKPT; - }else{ - pParse->db = pDb; - if( sqlite3OpenTempDatabase(pParse) ){ - sqlite3ErrorWithMsg(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); - rc = SQLITE_ERROR; - } - sqlite3DbFree(pErrorDb, pParse->zErrMsg); - sqlite3ParserReset(pParse); - sqlite3StackFree(pErrorDb, pParse); + memset(&sParse, 0, sizeof(sParse)); + sParse.db = pDb; + if( sqlite3OpenTempDatabase(&sParse) ){ + sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg); + rc = SQLITE_ERROR; } + sqlite3DbFree(pErrorDb, sParse.zErrMsg); + sqlite3ParserReset(&sParse); if( rc ){ return 0; } @@ -65655,7 +68097,7 @@ static int checkReadTransaction(sqlite3 *db, Btree *p){ ** If an error occurs, NULL is returned and an error code and error message ** stored in database handle pDestDb. */ -SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( +SQLITE_API sqlite3_backup *sqlite3_backup_init( sqlite3* pDestDb, /* Database to write to */ const char *zDestDb, /* Name of database within pDestDb */ sqlite3* pSrcDb, /* Database connection to read from */ @@ -65707,7 +68149,6 @@ SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( p->isAttached = 0; if( 0==p->pSrc || 0==p->pDest - || setDestPgsz(p)==SQLITE_NOMEM || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK ){ /* One (or both) of the named databases did not exist or an OOM @@ -65863,7 +68304,7 @@ static void attachBackupObject(sqlite3_backup *p){ /* ** Copy nPage pages from the source b-tree to the destination. */ -SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){ int rc; int destMode; /* Destination journal mode */ int pgszSrc = 0; /* Source page size */ @@ -65895,14 +68336,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ rc = SQLITE_OK; } - /* Lock the destination database, if it is not locked already. */ - if( SQLITE_OK==rc && p->bDestLocked==0 - && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2)) - ){ - p->bDestLocked = 1; - sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema); - } - /* If there is no open read-transaction on the source database, open ** one now. If a transaction is opened here, then it will be closed ** before this function exits. @@ -65912,6 +68345,24 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ bCloseTrans = 1; } + /* If the destination database has not yet been locked (i.e. if this + ** is the first call to backup_step() for the current backup operation), + ** try to set its page size to the same as the source database. This + ** is especially important on ZipVFS systems, as in that case it is + ** not possible to create a database file that uses one page size by + ** writing to it with another. */ + if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){ + rc = SQLITE_NOMEM; + } + + /* Lock the destination database, if it is not locked already. */ + if( SQLITE_OK==rc && p->bDestLocked==0 + && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2)) + ){ + p->bDestLocked = 1; + sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema); + } + /* Do not allow backup if the destination database is in WAL mode ** and the page sizes are different between source and destination */ pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); @@ -66107,7 +68558,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ /* ** Release all resources associated with an sqlite3_backup* handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p){ +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){ sqlite3_backup **pp; /* Ptr to head of pagers backup list */ sqlite3 *pSrcDb; /* Source database connection */ int rc; /* Value to return */ @@ -66159,7 +68610,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p){ ** Return the number of pages still to be backed up as of the most recent ** call to sqlite3_backup_step(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p){ +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p){ #ifdef SQLITE_ENABLE_API_ARMOR if( p==0 ){ (void)SQLITE_MISUSE_BKPT; @@ -66173,7 +68624,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p){ ** Return the total number of pages in the source database as of the most ** recent call to sqlite3_backup_step(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p){ +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p){ #ifdef SQLITE_ENABLE_API_ARMOR if( p==0 ){ (void)SQLITE_MISUSE_BKPT; @@ -66288,10 +68739,10 @@ SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ ** sqlite3_backup_step(), we can guarantee that the copy finishes ** within a single call (unless an error occurs). The assert() statement ** checks this assumption - (p->rc) should be set to either SQLITE_DONE - ** or an error code. - */ + ** or an error code. */ sqlite3_backup_step(&b, 0x7FFFFFFF); assert( b.rc!=SQLITE_OK ); + rc = sqlite3_backup_finish(&b); if( rc==SQLITE_OK ){ pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; @@ -66500,18 +68951,18 @@ SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. */ SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ - int f; assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( (pMem->flags&MEM_RowSet)==0 ); - ExpandBlob(pMem); - f = pMem->flags; - if( (f&(MEM_Str|MEM_Blob)) && (pMem->szMalloc==0 || pMem->z!=pMem->zMalloc) ){ - if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ - return SQLITE_NOMEM_BKPT; + if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){ + if( ExpandBlob(pMem) ) return SQLITE_NOMEM; + if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){ + if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ + return SQLITE_NOMEM_BKPT; + } + pMem->z[pMem->n] = 0; + pMem->z[pMem->n+1] = 0; + pMem->flags |= MEM_Term; } - pMem->z[pMem->n] = 0; - pMem->z[pMem->n+1] = 0; - pMem->flags |= MEM_Term; } pMem->flags &= ~MEM_Ephem; #ifdef SQLITE_DEBUG @@ -66527,25 +68978,24 @@ SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ */ #ifndef SQLITE_OMIT_INCRBLOB SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){ - if( pMem->flags & MEM_Zero ){ - int nByte; - assert( pMem->flags&MEM_Blob ); - assert( (pMem->flags&MEM_RowSet)==0 ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - - /* Set nByte to the number of bytes required to store the expanded blob. */ - nByte = pMem->n + pMem->u.nZero; - if( nByte<=0 ){ - nByte = 1; - } - if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){ - return SQLITE_NOMEM_BKPT; - } + int nByte; + assert( pMem->flags & MEM_Zero ); + assert( pMem->flags&MEM_Blob ); + assert( (pMem->flags&MEM_RowSet)==0 ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - memset(&pMem->z[pMem->n], 0, pMem->u.nZero); - pMem->n += pMem->u.nZero; - pMem->flags &= ~(MEM_Zero|MEM_Term); + /* Set nByte to the number of bytes required to store the expanded blob. */ + nByte = pMem->n + pMem->u.nZero; + if( nByte<=0 ){ + nByte = 1; + } + if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){ + return SQLITE_NOMEM_BKPT; } + + memset(&pMem->z[pMem->n], 0, pMem->u.nZero); + pMem->n += pMem->u.nZero; + pMem->flags &= ~(MEM_Zero|MEM_Term); return SQLITE_OK; } #endif @@ -66605,6 +69055,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){ + pMem->enc = 0; return SQLITE_NOMEM_BKPT; } @@ -66886,7 +69337,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ } } assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 ); - pMem->flags &= ~(MEM_Str|MEM_Blob); + pMem->flags &= ~(MEM_Str|MEM_Blob|MEM_Zero); return SQLITE_OK; } @@ -66904,7 +69355,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ if( (pMem->flags & MEM_Blob)==0 ){ sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); - MemSetTypeFlag(pMem, MEM_Blob); + if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob); }else{ pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); } @@ -67113,10 +69564,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int sr SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ int rc = SQLITE_OK; - /* The pFrom==0 case in the following assert() is when an sqlite3_value - ** from sqlite3_value_dup() is used as the argument - ** to sqlite3_result_value(). */ - assert( pTo->db==pFrom->db || pFrom->db==0 ); assert( (pFrom->flags & MEM_RowSet)==0 ); if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); @@ -67306,11 +69753,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree( /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() ** that both the BtShared and database handle mutexes are held. */ assert( (pMem->flags & MEM_RowSet)==0 ); - if( key ){ - zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); - }else{ - zData = (char *)sqlite3BtreeDataFetch(pCur, &available); - } + zData = (char *)sqlite3BtreePayloadFetch(pCur, &available); assert( zData!=0 ); if( offset+amt<=available ){ @@ -67337,9 +69780,6 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){ assert( (pVal->flags & (MEM_Null))==0 ); if( pVal->flags & (MEM_Blob|MEM_Str) ){ pVal->flags |= MEM_Str; - if( pVal->flags & MEM_Zero ){ - sqlite3VdbeMemExpandBlob(pVal); - } if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){ sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); } @@ -67592,10 +70032,7 @@ static int valueFromExpr( const char *zNeg = ""; int rc = SQLITE_OK; - if( !pExpr ){ - *ppVal = 0; - return SQLITE_OK; - } + assert( pExpr!=0 ); while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; @@ -67719,7 +70156,7 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr( u8 affinity, /* Affinity to use */ sqlite3_value **ppVal /* Write the new value here */ ){ - return valueFromExpr(db, pExpr, enc, affinity, ppVal, 0); + return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0; } #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 @@ -67839,9 +70276,9 @@ static int stat4ValueFromExpr( ** structures intended to be compared against sample index keys stored ** in the sqlite_stat4 table. ** -** A single call to this function attempts to populates field iVal (leftmost -** is 0 etc.) of the unpacked record with a value extracted from expression -** pExpr. Extraction of values is possible if: +** A single call to this function populates zero or more fields of the +** record starting with field iVal (fields are numbered from left to +** right starting with 0). A single field is populated if: ** ** * (pExpr==0). In this case the value is assumed to be an SQL NULL, ** @@ -67850,10 +70287,14 @@ static int stat4ValueFromExpr( ** * The sqlite3ValueFromExpr() function is able to extract a value ** from the expression (i.e. the expression is a literal value). ** -** If a value can be extracted, the affinity passed as the 5th argument -** is applied to it before it is copied into the UnpackedRecord. Output -** parameter *pbOk is set to true if a value is extracted, or false -** otherwise. +** Or, if pExpr is a TK_VECTOR, one field is populated for each of the +** vector components that match either of the two latter criteria listed +** above. +** +** Before any value is appended to the record, the affinity of the +** corresponding column within index pIdx is applied to it. Before +** this function returns, output parameter *pnExtract is set to the +** number of values appended to the record. ** ** When this function is called, *ppRec must either point to an object ** allocated by an earlier call to this function, or must be NULL. If it @@ -67869,22 +70310,33 @@ SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue( Index *pIdx, /* Index being probed */ UnpackedRecord **ppRec, /* IN/OUT: Probe record */ Expr *pExpr, /* The expression to extract a value from */ - u8 affinity, /* Affinity to use */ + int nElem, /* Maximum number of values to append */ int iVal, /* Array element to populate */ - int *pbOk /* OUT: True if value was extracted */ + int *pnExtract /* OUT: Values appended to the record */ ){ - int rc; - sqlite3_value *pVal = 0; - struct ValueNewStat4Ctx alloc; + int rc = SQLITE_OK; + int nExtract = 0; - alloc.pParse = pParse; - alloc.pIdx = pIdx; - alloc.ppRec = ppRec; - alloc.iVal = iVal; + if( pExpr==0 || pExpr->op!=TK_SELECT ){ + int i; + struct ValueNewStat4Ctx alloc; + + alloc.pParse = pParse; + alloc.pIdx = pIdx; + alloc.ppRec = ppRec; + + for(i=0; idb, pIdx, iVal+i); + alloc.iVal = iVal+i; + rc = stat4ValueFromExpr(pParse, pElem, aff, &alloc, &pVal); + if( !pVal ) break; + nExtract++; + } + } - rc = stat4ValueFromExpr(pParse, pExpr, affinity, &alloc, &pVal); - assert( pVal==0 || pVal->db==pParse->db ); - *pbOk = (pVal!=0); + *pnExtract = nExtract; return rc; } @@ -68047,8 +70499,9 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ sqlite3 *db = pParse->db; Vdbe *p; - p = sqlite3DbMallocZero(db, sizeof(Vdbe) ); + p = sqlite3DbMallocRawNN(db, sizeof(Vdbe) ); if( p==0 ) return 0; + memset(&p->aOp, 0, sizeof(Vdbe)-offsetof(Vdbe,aOp)); p->db = db; if( db->pVdbe ){ db->pVdbe->pPrev = p; @@ -68090,20 +70543,13 @@ SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepa p->isPrepareV2 = (u8)isPrepareV2; } -/* -** Return the SQL associated with a prepared statement -*/ -SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt){ - Vdbe *p = (Vdbe *)pStmt; - return p ? p->zSql : 0; -} - /* ** Swap all content between two VDBE structures. */ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){ Vdbe tmp, *pTmp; char *zTmp; + assert( pA->db==pB->db ); tmp = *pA; *pA = *pB; *pB = tmp; @@ -68217,9 +70663,8 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ if( p->db->flags & SQLITE_VdbeAddopTrace ){ int jj, kk; Parse *pParse = p->pParse; - for(jj=kk=0; jjnColCache; jj++){ struct yColCache *x = pParse->aColCache + jj; - if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue; printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn); kk++; } @@ -68407,7 +70852,6 @@ SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){ if( p->aLabel ){ p->aLabel[j] = v->nOp; } - p->iFixedOp = v->nOp - 1; } /* @@ -68570,73 +71014,84 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ ** (4) Initialize the p4.xAdvance pointer on opcodes that use it. ** ** (5) Reclaim the memory allocated for storing labels. +** +** This routine will only function correctly if the mkopcodeh.tcl generator +** script numbers the opcodes correctly. Changes to this routine must be +** coordinated with changes to mkopcodeh.tcl. */ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ - int i; int nMaxArgs = *pMaxFuncArgs; Op *pOp; Parse *pParse = p->pParse; int *aLabel = pParse->aLabel; p->readOnly = 1; p->bIsReader = 0; - for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ - u8 opcode = pOp->opcode; - - /* NOTE: Be sure to update mkopcodeh.tcl when adding or removing - ** cases from this switch! */ - switch( opcode ){ - case OP_Transaction: { - if( pOp->p2!=0 ) p->readOnly = 0; - /* fall thru */ - } - case OP_AutoCommit: - case OP_Savepoint: { - p->bIsReader = 1; - break; - } + pOp = &p->aOp[p->nOp-1]; + while(1){ + + /* Only JUMP opcodes and the short list of special opcodes in the switch + ** below need to be considered. The mkopcodeh.tcl generator script groups + ** all these opcodes together near the front of the opcode list. Skip + ** any opcode that does not need processing by virtual of the fact that + ** it is larger than SQLITE_MX_JUMP_OPCODE, as a performance optimization. + */ + if( pOp->opcode<=SQLITE_MX_JUMP_OPCODE ){ + /* NOTE: Be sure to update mkopcodeh.tcl when adding or removing + ** cases from this switch! */ + switch( pOp->opcode ){ + case OP_Transaction: { + if( pOp->p2!=0 ) p->readOnly = 0; + /* fall thru */ + } + case OP_AutoCommit: + case OP_Savepoint: { + p->bIsReader = 1; + break; + } #ifndef SQLITE_OMIT_WAL - case OP_Checkpoint: + case OP_Checkpoint: #endif - case OP_Vacuum: - case OP_JournalMode: { - p->readOnly = 0; - p->bIsReader = 1; - break; - } + case OP_Vacuum: + case OP_JournalMode: { + p->readOnly = 0; + p->bIsReader = 1; + break; + } #ifndef SQLITE_OMIT_VIRTUALTABLE - case OP_VUpdate: { - if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; - break; - } - case OP_VFilter: { - int n; - assert( p->nOp - i >= 3 ); - assert( pOp[-1].opcode==OP_Integer ); - n = pOp[-1].p1; - if( n>nMaxArgs ) nMaxArgs = n; - break; - } + case OP_VUpdate: { + if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; + break; + } + case OP_VFilter: { + int n; + assert( (pOp - p->aOp) >= 3 ); + assert( pOp[-1].opcode==OP_Integer ); + n = pOp[-1].p1; + if( n>nMaxArgs ) nMaxArgs = n; + break; + } #endif - case OP_Next: - case OP_NextIfOpen: - case OP_SorterNext: { - pOp->p4.xAdvance = sqlite3BtreeNext; - pOp->p4type = P4_ADVANCE; - break; + case OP_Next: + case OP_NextIfOpen: + case OP_SorterNext: { + pOp->p4.xAdvance = sqlite3BtreeNext; + pOp->p4type = P4_ADVANCE; + break; + } + case OP_Prev: + case OP_PrevIfOpen: { + pOp->p4.xAdvance = sqlite3BtreePrevious; + pOp->p4type = P4_ADVANCE; + break; + } } - case OP_Prev: - case OP_PrevIfOpen: { - pOp->p4.xAdvance = sqlite3BtreePrevious; - pOp->p4type = P4_ADVANCE; - break; + if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 && pOp->p2<0 ){ + assert( ADDR(pOp->p2)nLabel ); + pOp->p2 = aLabel[ADDR(pOp->p2)]; } } - - pOp->opflags = sqlite3OpcodeProperty[opcode]; - if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){ - assert( ADDR(pOp->p2)nLabel ); - pOp->p2 = aLabel[ADDR(pOp->p2)]; - } + if( pOp==p->aOp ) break; + pOp--; } sqlite3DbFree(p->db, pParse->aLabel); pParse->aLabel = 0; @@ -68787,7 +71242,8 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){ sqlite3VdbeGetOp(p,addr)->p3 = val; } SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){ - if( !p->db->mallocFailed ) p->aOp[p->nOp-1].p5 = p5; + assert( p->nOp>0 || p->db->mallocFailed ); + if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5; } /* @@ -68795,7 +71251,6 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){ ** the address of the next instruction to be coded. */ SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){ - p->pParse->iFixedOp = p->nOp - 1; sqlite3VdbeChangeP2(p, addr, p->nOp); } @@ -68805,7 +71260,7 @@ SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){ ** the FuncDef is not ephermal, then do nothing. */ static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){ - if( ALWAYS(pDef) && (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){ + if( (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){ sqlite3DbFree(db, pDef); } } @@ -68815,53 +71270,57 @@ static void vdbeFreeOpArray(sqlite3 *, Op *, int); /* ** Delete a P4 value if necessary. */ +static SQLITE_NOINLINE void freeP4Mem(sqlite3 *db, Mem *p){ + if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); + sqlite3DbFree(db, p); +} +static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){ + freeEphemeralFunction(db, p->pFunc); + sqlite3DbFree(db, p); +} static void freeP4(sqlite3 *db, int p4type, void *p4){ - if( p4 ){ - assert( db ); - switch( p4type ){ - case P4_FUNCCTX: { - freeEphemeralFunction(db, ((sqlite3_context*)p4)->pFunc); - /* Fall through into the next case */ - } - case P4_REAL: - case P4_INT64: - case P4_DYNAMIC: - case P4_INTARRAY: { - sqlite3DbFree(db, p4); - break; - } - case P4_KEYINFO: { - if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4); - break; - } + assert( db ); + switch( p4type ){ + case P4_FUNCCTX: { + freeP4FuncCtx(db, (sqlite3_context*)p4); + break; + } + case P4_REAL: + case P4_INT64: + case P4_DYNAMIC: + case P4_INTARRAY: { + sqlite3DbFree(db, p4); + break; + } + case P4_KEYINFO: { + if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4); + break; + } #ifdef SQLITE_ENABLE_CURSOR_HINTS - case P4_EXPR: { - sqlite3ExprDelete(db, (Expr*)p4); - break; - } + case P4_EXPR: { + sqlite3ExprDelete(db, (Expr*)p4); + break; + } #endif - case P4_MPRINTF: { - if( db->pnBytesFreed==0 ) sqlite3_free(p4); - break; - } - case P4_FUNCDEF: { - freeEphemeralFunction(db, (FuncDef*)p4); - break; - } - case P4_MEM: { - if( db->pnBytesFreed==0 ){ - sqlite3ValueFree((sqlite3_value*)p4); - }else{ - Mem *p = (Mem*)p4; - if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); - sqlite3DbFree(db, p); - } - break; - } - case P4_VTAB : { - if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4); - break; + case P4_MPRINTF: { + if( db->pnBytesFreed==0 ) sqlite3_free(p4); + break; + } + case P4_FUNCDEF: { + freeEphemeralFunction(db, (FuncDef*)p4); + break; + } + case P4_MEM: { + if( db->pnBytesFreed==0 ){ + sqlite3ValueFree((sqlite3_value*)p4); + }else{ + freeP4Mem(db, (Mem*)p4); } + break; + } + case P4_VTAB : { + if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4); + break; } } } @@ -68914,7 +71373,7 @@ SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe *p, int addr){ ** then remove it. Return true if and only if an opcode was removed. */ SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){ - if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){ + if( p->nOp>0 && p->aOp[p->nOp-1].opcode==op ){ return sqlite3VdbeChangeToNoop(p, p->nOp-1); }else{ return 0; @@ -69112,12 +71571,21 @@ static int displayComment( const char *zSynopsis; int nOpName; int ii, jj; + char zAlt[50]; zOpName = sqlite3OpcodeName(pOp->opcode); nOpName = sqlite3Strlen30(zOpName); if( zOpName[nOpName+1] ){ int seenCom = 0; char c; zSynopsis = zOpName += nOpName + 1; + if( strncmp(zSynopsis,"IF ",3)==0 ){ + if( pOp->p5 & SQLITE_STOREP2 ){ + sqlite3_snprintf(sizeof(zAlt), zAlt, "r[P2] = (%s)", zSynopsis+3); + }else{ + sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3); + } + zSynopsis = zAlt; + } for(ii=jj=0; jjp4.pTab->zName); + break; + } default: { zP4 = pOp->p4.z; if( zP4==0 ){ @@ -69464,6 +71936,21 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ } #endif +/* +** Initialize an array of N Mem element. +*/ +static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){ + while( (N--)>0 ){ + p->db = db; + p->flags = flags; + p->szMalloc = 0; +#ifdef SQLITE_DEBUG + p->pScopyFrom = 0; +#endif + p++; + } +} + /* ** Release an array of N Mem elements */ @@ -69675,6 +72162,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( pMem->flags = MEM_Str|MEM_Term; zP4 = displayP4(pOp, pMem->z, pMem->szMalloc); if( zP4!=pMem->z ){ + pMem->n = 0; sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); }else{ assert( pMem->z!=0 ); @@ -69817,7 +72305,7 @@ SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){ int i; #endif assert( p!=0 ); - assert( p->magic==VDBE_MAGIC_INIT ); + assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET ); /* There should be at least one opcode. */ @@ -69874,7 +72362,6 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( int nMem; /* Number of VM memory registers */ int nCursor; /* Number of cursors required */ int nArg; /* Number of arguments in subprograms */ - int nOnce; /* Number of OP_Once instructions */ int n; /* Loop counter */ struct ReusableSpace x; /* Reusable bulk memory */ @@ -69889,8 +72376,6 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( nMem = pParse->nMem; nCursor = pParse->nTab; nArg = pParse->nMaxArg; - nOnce = pParse->nOnce; - if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */ /* Each cursor uses a memory cell. The first cursor (cursor 0) can ** use aMem[0] which is not otherwise used by the VDBE program. Allocate @@ -69909,10 +72394,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ assert( x.nFree>=0 ); - if( x.nFree>0 ){ - memset(x.pSpace, 0, x.nFree); - assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); - } + assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); resolveP2Values(p, &nArg); p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); @@ -69937,36 +72419,34 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem)); p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*)); p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*)); - p->aOnceFlag = allocSpace(&x, p->aOnceFlag, nOnce); #ifdef SQLITE_ENABLE_STMT_SCANSTATUS p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64)); #endif if( x.nNeeded==0 ) break; - x.pSpace = p->pFree = sqlite3DbMallocZero(db, x.nNeeded); + x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded); x.nFree = x.nNeeded; }while( !db->mallocFailed ); - p->nCursor = nCursor; - p->nOnceFlag = nOnce; - if( p->aVar ){ - p->nVar = (ynVar)nVar; - for(n=0; naVar[n].flags = MEM_Null; - p->aVar[n].db = db; - } - } p->nzVar = pParse->nzVar; p->azVar = pParse->azVar; pParse->nzVar = 0; pParse->azVar = 0; - if( p->aMem ){ + p->explain = pParse->explain; + if( db->mallocFailed ){ + p->nVar = 0; + p->nCursor = 0; + p->nMem = 0; + }else{ + p->nCursor = nCursor; + p->nVar = (ynVar)nVar; + initMemArray(p->aVar, nVar, db, MEM_Null); p->nMem = nMem; - for(n=0; naMem[n].flags = MEM_Undefined; - p->aMem[n].db = db; - } + initMemArray(p->aMem, nMem, db, MEM_Undefined); + memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*)); +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + memset(p->anExec, 0, p->nOp*sizeof(i64)); +#endif } - p->explain = pParse->explain; sqlite3VdbeRewind(p); } @@ -70035,8 +72515,6 @@ SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS v->anExec = pFrame->anExec; #endif - v->aOnceFlag = pFrame->aOnceFlag; - v->nOnceFlag = pFrame->nOnceFlag; v->aOp = pFrame->aOp; v->nOp = pFrame->nOp; v->aMem = pFrame->aMem; @@ -70120,13 +72598,9 @@ SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ sqlite3DbFree(db, p->aColName); n = nResColumn*COLNAME_N; p->nResColumn = (u16)nResColumn; - p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n ); + p->aColName = pColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n ); if( p->aColName==0 ) return; - while( n-- > 0 ){ - pColName->flags = MEM_Null; - pColName->db = p->db; - pColName++; - } + initMemArray(p->aColName, n, p->db, MEM_Null); } /* @@ -70577,7 +73051,6 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ if( db->mallocFailed ){ p->rc = SQLITE_NOMEM_BKPT; } - if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag); closeAllCursors(p); if( p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_OK; @@ -70889,7 +73362,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ } #endif p->iCurrentTime = 0; - p->magic = VDBE_MAGIC_INIT; + p->magic = VDBE_MAGIC_RESET; return p->rc & db->errMask; } @@ -70953,19 +73426,21 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ SubProgram *pSub, *pNext; int i; assert( p->db==0 || p->db==db ); - releaseMemArray(p->aVar, p->nVar); releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); for(pSub=p->pProgram; pSub; pSub=pNext){ pNext = pSub->pNext; vdbeFreeOpArray(db, pSub->aOp, pSub->nOp); sqlite3DbFree(db, pSub); } - for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); - sqlite3DbFree(db, p->azVar); + 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->pFree); + } vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); - sqlite3DbFree(db, p->pFree); #ifdef SQLITE_ENABLE_STMT_SCANSTATUS for(i=0; inScan; i++){ sqlite3DbFree(db, p->aScan[i].zName); @@ -71533,6 +74008,7 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( pMem->db = pKeyInfo->db; /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */ pMem->szMalloc = 0; + pMem->z = 0; d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); pMem++; if( (++u)>=p->nField ) break; @@ -71720,15 +74196,49 @@ static int vdbeCompareMemString( } } +/* +** The input pBlob is guaranteed to be a Blob that is not marked +** with MEM_Zero. Return true if it could be a zero-blob. +*/ +static int isAllZero(const char *z, int n){ + int i; + for(i=0; iz, pB2->z, pB1->n>pB2->n ? pB2->n : pB1->n); + int c; + int n1 = pB1->n; + int n2 = pB2->n; + + /* It is possible to have a Blob value that has some non-zero content + ** followed by zero content. But that only comes up for Blobs formed + ** by the OP_MakeRecord opcode, and such Blobs never get passed into + ** sqlite3MemCompare(). */ + assert( (pB1->flags & MEM_Zero)==0 || n1==0 ); + assert( (pB2->flags & MEM_Zero)==0 || n2==0 ); + + if( (pB1->flags|pB2->flags) & MEM_Zero ){ + if( pB1->flags & pB2->flags & MEM_Zero ){ + return pB1->u.nZero - pB2->u.nZero; + }else if( pB1->flags & MEM_Zero ){ + if( !isAllZero(pB2->z, pB2->n) ) return -1; + return pB1->u.nZero - n2; + }else{ + if( !isAllZero(pB1->z, pB1->n) ) return +1; + return n1 - pB2->u.nZero; + } + } + c = memcmp(pB1->z, pB2->z, n1>n2 ? n2 : n1); if( c ) return c; - return pB1->n - pB2->n; + return n1 - n2; } /* @@ -72034,6 +74544,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( /* RHS is a blob */ else if( pRhs->flags & MEM_Blob ){ + assert( (pRhs->flags & MEM_Zero)==0 || pRhs->n==0 ); getVarint32(&aKey1[idx1], serial_type); testcase( serial_type==12 ); if( serial_type<12 || (serial_type & 0x01) ){ @@ -72045,6 +74556,12 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( if( (d1+nStr) > (unsigned)nKey1 ){ pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; return 0; /* Corruption */ + }else if( pRhs->flags & MEM_Zero ){ + if( !isAllZero((const char*)&aKey1[d1],nStr) ){ + rc = 1; + }else{ + rc = nStr - pRhs->u.nZero; + } }else{ int nCmp = MIN(nStr, pRhs->n); rc = memcmp(&aKey1[d1], pRhs->z, nCmp); @@ -72115,7 +74632,7 @@ static int vdbeRecordCompareInt( int res; u32 y; u64 x; - i64 v = pPKey2->aMem[0].u.i; + i64 v; i64 lhs; vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); @@ -72174,6 +74691,7 @@ static int vdbeRecordCompareInt( return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2); } + v = pPKey2->aMem[0].u.i; if( v>lhs ){ res = pPKey2->r1; }else if( veCurType==CURTYPE_BTREE ); pCur = pC->uc.pCursor; assert( sqlite3BtreeCursorIsValid(pCur) ); - VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey); - assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ + nCellKey = sqlite3BtreePayloadSize(pCur); /* nCellKey will always be between 0 and 0xffffffff because of the way ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ if( nCellKey<=0 || nCellKey>0x7fffffff ){ @@ -72513,6 +75029,90 @@ SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){ } #endif /* SQLITE_OMIT_VIRTUALTABLE */ +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + +/* +** If the second argument is not NULL, release any allocations associated +** with the memory cells in the p->aMem[] array. Also free the UnpackedRecord +** structure itself, using sqlite3DbFree(). +** +** This function is used to free UnpackedRecord structures allocated by +** the vdbeUnpackRecord() function found in vdbeapi.c. +*/ +static void vdbeFreeUnpacked(sqlite3 *db, UnpackedRecord *p){ + if( p ){ + int i; + for(i=0; inField; i++){ + Mem *pMem = &p->aMem[i]; + if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem); + } + sqlite3DbFree(db, p); + } +} +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK +/* +** Invoke the pre-update hook. If this is an UPDATE or DELETE pre-update call, +** then cursor passed as the second argument should point to the row about +** to be update or deleted. If the application calls sqlite3_preupdate_old(), +** the required value will be read from the row the cursor points to. +*/ +SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( + Vdbe *v, /* Vdbe pre-update hook is invoked by */ + VdbeCursor *pCsr, /* Cursor to grab old.* values from */ + int op, /* SQLITE_INSERT, UPDATE or DELETE */ + const char *zDb, /* Database name */ + Table *pTab, /* Modified table */ + i64 iKey1, /* Initial key value */ + int iReg /* Register for new.* record */ +){ + sqlite3 *db = v->db; + i64 iKey2; + PreUpdate preupdate; + const char *zTbl = pTab->zName; + static const u8 fakeSortOrder = 0; + + assert( db->pPreUpdate==0 ); + memset(&preupdate, 0, sizeof(PreUpdate)); + if( op==SQLITE_UPDATE ){ + iKey2 = v->aMem[iReg].u.i; + }else{ + iKey2 = iKey1; + } + + assert( pCsr->nField==pTab->nCol + || (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1) + ); + + preupdate.v = v; + preupdate.pCsr = pCsr; + preupdate.op = op; + preupdate.iNewReg = iReg; + preupdate.keyinfo.db = db; + preupdate.keyinfo.enc = ENC(db); + preupdate.keyinfo.nField = pTab->nCol; + preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; + preupdate.iKey1 = iKey1; + preupdate.iKey2 = iKey2; + preupdate.pTab = pTab; + + db->pPreUpdate = &preupdate; + 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); + if( preupdate.aNew ){ + int i; + for(i=0; inField; i++){ + sqlite3VdbeMemRelease(&preupdate.aNew[i]); + } + sqlite3DbFree(db, preupdate.aNew); + } +} +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + /************** End of vdbeaux.c *********************************************/ /************** Begin file vdbeapi.c *****************************************/ /* @@ -72542,7 +75142,7 @@ SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){ ** collating sequences are registered or if an authorizer function is ** added or changed. */ -SQLITE_API int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; return p==0 || p->expired; } @@ -72577,12 +75177,19 @@ static int vdbeSafetyNotNull(Vdbe *p){ */ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){ sqlite3_int64 iNow; + sqlite3_int64 iElapse; assert( p->startTime>0 ); - assert( db->xProfile!=0 ); + assert( db->xProfile!=0 || (db->mTrace & SQLITE_TRACE_PROFILE)!=0 ); assert( db->init.busy==0 ); assert( p->zSql!=0 ); sqlite3OsCurrentTimeInt64(db->pVfs, &iNow); - db->xProfile(db->pProfileArg, p->zSql, (iNow - p->startTime)*1000000); + iElapse = (iNow - p->startTime)*1000000; + if( db->xProfile ){ + db->xProfile(db->pProfileArg, p->zSql, iElapse); + } + if( db->mTrace & SQLITE_TRACE_PROFILE ){ + db->xTrace(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse); + } p->startTime = 0; } /* @@ -72604,7 +75211,7 @@ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){ ** This routine sets the error code and string returned by ** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL @@ -72631,7 +75238,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt){ ** This routine sets the error code and string returned by ** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; @@ -72652,7 +75259,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt){ /* ** Set all the parameters in the compiled SQL statement to NULL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ int i; int rc = SQLITE_OK; Vdbe *p = (Vdbe*)pStmt; @@ -72676,10 +75283,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt *pStmt){ ** The following routines extract information from a Mem or sqlite3_value ** structure. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value *pVal){ +SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){ Mem *p = (Mem*)pVal; if( p->flags & (MEM_Blob|MEM_Str) ){ - if( sqlite3VdbeMemExpandBlob(p)!=SQLITE_OK ){ + if( ExpandBlob(p)!=SQLITE_OK ){ assert( p->flags==MEM_Null && p->z==0 ); return 0; } @@ -72689,36 +75296,36 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value *pVal){ return sqlite3_value_text(pVal); } } -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value *pVal){ +SQLITE_API int sqlite3_value_bytes(sqlite3_value *pVal){ return sqlite3ValueBytes(pVal, SQLITE_UTF8); } -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value *pVal){ +SQLITE_API int sqlite3_value_bytes16(sqlite3_value *pVal){ return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE); } -SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value *pVal){ +SQLITE_API double sqlite3_value_double(sqlite3_value *pVal){ return sqlite3VdbeRealValue((Mem*)pVal); } -SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value *pVal){ +SQLITE_API int sqlite3_value_int(sqlite3_value *pVal){ return (int)sqlite3VdbeIntValue((Mem*)pVal); } -SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value *pVal){ +SQLITE_API sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal); } -SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value *pVal){ +SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value *pVal){ Mem *pMem = (Mem*)pVal; return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0); } -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value *pVal){ +SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value* pVal){ +SQLITE_API const void *sqlite3_value_text16(sqlite3_value* pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); } -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value *pVal){ +SQLITE_API const void *sqlite3_value_text16be(sqlite3_value *pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16BE); } -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value *pVal){ +SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16LE); } #endif /* SQLITE_OMIT_UTF16 */ @@ -72726,7 +75333,7 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value *pVal ** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating ** point number string BLOB NULL */ -SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value* pVal){ +SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){ static const u8 aType[] = { SQLITE_BLOB, /* 0x00 */ SQLITE_NULL, /* 0x01 */ @@ -72766,7 +75373,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value* pVal){ /* Make a copy of an sqlite3_value object */ -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value *pOrig){ +SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){ sqlite3_value *pNew; if( pOrig==0 ) return 0; pNew = sqlite3_malloc( sizeof(*pNew) ); @@ -72789,7 +75396,7 @@ SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value * /* Destroy an sqlite3_value object previously obtained from ** sqlite3_value_dup(). */ -SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value *pOld){ +SQLITE_API void sqlite3_value_free(sqlite3_value *pOld){ sqlite3ValueFree(pOld); } @@ -72832,7 +75439,7 @@ static int invokeValueDestructor( if( pCtx ) sqlite3_result_error_toobig(pCtx); return SQLITE_TOOBIG; } -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob( +SQLITE_API void sqlite3_result_blob( sqlite3_context *pCtx, const void *z, int n, @@ -72842,7 +75449,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_blob( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, 0, xDel); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64( +SQLITE_API void sqlite3_result_blob64( sqlite3_context *pCtx, const void *z, sqlite3_uint64 n, @@ -72856,43 +75463,43 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64( setResultStrOrError(pCtx, z, (int)n, 0, xDel); } } -SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context *pCtx, double rVal){ +SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetDouble(pCtx->pOut, rVal); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ +SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ +SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); } #endif -SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context *pCtx, int iVal){ +SQLITE_API void sqlite3_result_int(sqlite3_context *pCtx, int iVal){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetInt64(pCtx->pOut, (i64)iVal); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ +SQLITE_API void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetInt64(pCtx->pOut, iVal); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context *pCtx){ +SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ +SQLITE_API void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ Mem *pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); pOut->eSubtype = eSubtype & 0xff; pOut->flags |= MEM_Subtype; } -SQLITE_API void SQLITE_STDCALL sqlite3_result_text( +SQLITE_API void sqlite3_result_text( sqlite3_context *pCtx, const char *z, int n, @@ -72901,7 +75508,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_text( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_text64( +SQLITE_API void sqlite3_result_text64( sqlite3_context *pCtx, const char *z, sqlite3_uint64 n, @@ -72918,7 +75525,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_text64( } } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16( +SQLITE_API void sqlite3_result_text16( sqlite3_context *pCtx, const void *z, int n, @@ -72927,7 +75534,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_text16( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be( +SQLITE_API void sqlite3_result_text16be( sqlite3_context *pCtx, const void *z, int n, @@ -72936,7 +75543,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le( +SQLITE_API void sqlite3_result_text16le( sqlite3_context *pCtx, const void *z, int n, @@ -72946,15 +75553,15 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le( setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel); } #endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ +SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemCopy(pCtx->pOut, pValue); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ +SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n); } -SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ +SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ Mem *pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){ @@ -72963,7 +75570,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context *pCtx, u sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n); return SQLITE_OK; } -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ +SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ pCtx->isError = errCode; pCtx->fErrorOrAux = 1; #ifdef SQLITE_DEBUG @@ -72976,7 +75583,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context *pCtx, } /* Force an SQLITE_TOOBIG error. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context *pCtx){ +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_TOOBIG; pCtx->fErrorOrAux = 1; @@ -72985,7 +75592,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context *pCtx } /* An SQLITE_NOMEM error. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context *pCtx){ +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); pCtx->isError = SQLITE_NOMEM_BKPT; @@ -73009,7 +75616,7 @@ static int doWalCallbacks(sqlite3 *db){ nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); sqlite3BtreeLeave(pBt); if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ - rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); + rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zDbSName, nEntry); } } } @@ -73086,7 +75693,8 @@ static int sqlite3Step(Vdbe *p){ ); #ifndef SQLITE_OMIT_TRACE - if( db->xProfile && !db->init.busy && p->zSql ){ + if( (db->xProfile || (db->mTrace & SQLITE_TRACE_PROFILE)!=0) + && !db->init.busy && p->zSql ){ sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); }else{ assert( p->startTime==0 ); @@ -73156,7 +75764,7 @@ static int sqlite3Step(Vdbe *p){ ** sqlite3Step() to do most of the work. If a schema error occurs, ** call sqlite3Reprepare() and try again. */ -SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ int rc = SQLITE_OK; /* Result from sqlite3Step() */ int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */ Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */ @@ -73207,7 +75815,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt *pStmt){ ** Extract the user data from a sqlite3_context structure and return a ** pointer to it. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context *p){ +SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ assert( p && p->pFunc ); return p->pFunc->pUserData; } @@ -73222,7 +75830,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context *p){ ** sqlite3_create_function16() routines that originally registered the ** application defined function. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context *p){ +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ assert( p && p->pOut ); return p->pOut->db; } @@ -73298,7 +75906,7 @@ static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){ ** context is allocated on the first call. Subsequent calls return the ** same context that was returned on prior calls. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context *p, int nByte){ +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ assert( p && p->pFunc && p->pFunc->xFinalize ); assert( sqlite3_mutex_held(p->pOut->db->mutex) ); testcase( nByte<0 ); @@ -73313,7 +75921,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context *p, in ** Return the auxiliary data pointer, if any, for the iArg'th argument to ** the user-function defined by pCtx. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ AuxData *pAuxData; assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); @@ -73334,7 +75942,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context *pCtx, int i ** argument to the user-function defined by pCtx. Any previous value is ** deleted by calling the delete function specified when it was set. */ -SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata( +SQLITE_API void sqlite3_set_auxdata( sqlite3_context *pCtx, int iArg, void *pAux, @@ -73389,7 +75997,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata( ** implementations should keep their own counts within their aggregate ** context. */ -SQLITE_API int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context *p){ +SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){ assert( p && p->pMem && p->pFunc && p->pFunc->xFinalize ); return p->pMem->n; } @@ -73398,7 +76006,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context *p){ /* ** Return the number of columns in the result set for the statement pStmt. */ -SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; return pVm ? pVm->nResColumn : 0; } @@ -73407,7 +76015,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt){ ** Return the number of values available from the current row of the ** currently executing statement pStmt. */ -SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; if( pVm==0 || pVm->pResultSet==0 ) return 0; return pVm->nResColumn; @@ -73461,14 +76069,13 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ Mem *pOut; pVm = (Vdbe *)pStmt; - if( pVm && pVm->pResultSet!=0 && inResColumn && i>=0 ){ - sqlite3_mutex_enter(pVm->db->mutex); + if( pVm==0 ) return (Mem*)columnNullValue(); + assert( pVm->db ); + sqlite3_mutex_enter(pVm->db->mutex); + if( pVm->pResultSet!=0 && inResColumn && i>=0 ){ pOut = &pVm->pResultSet[i]; }else{ - if( pVm && ALWAYS(pVm->db) ){ - sqlite3_mutex_enter(pVm->db->mutex); - sqlite3Error(pVm->db, SQLITE_RANGE); - } + sqlite3Error(pVm->db, SQLITE_RANGE); pOut = (Mem*)columnNullValue(); } return pOut; @@ -73501,6 +76108,8 @@ static void columnMallocFailure(sqlite3_stmt *pStmt) */ Vdbe *p = (Vdbe *)pStmt; if( p ){ + assert( p->db!=0 ); + assert( sqlite3_mutex_held(p->db->mutex) ); p->rc = sqlite3ApiExit(p->db, p->rc); sqlite3_mutex_leave(p->db->mutex); } @@ -73510,7 +76119,7 @@ static void columnMallocFailure(sqlite3_stmt *pStmt) ** The following routines are used to access elements of the current row ** in the result set. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ +SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ const void *val; val = sqlite3_value_blob( columnMem(pStmt,i) ); /* Even though there is no encoding conversion, value_blob() might @@ -73520,37 +76129,37 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt *pStmt, i columnMallocFailure(pStmt); return val; } -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_bytes( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_bytes16( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt *pStmt, int i){ +SQLITE_API double sqlite3_column_double(sqlite3_stmt *pStmt, int i){ double val = sqlite3_value_double( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_column_int(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_int( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ +SQLITE_API sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt *pStmt, int i){ +SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){ const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt *pStmt, int i){ +SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){ Mem *pOut = columnMem(pStmt, i); if( pOut->flags&MEM_Static ){ pOut->flags &= ~MEM_Static; @@ -73560,13 +76169,13 @@ SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt *pStm return (sqlite3_value *)pOut; } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ +SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ const void *val = sqlite3_value_text16( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } #endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ int iType = sqlite3_value_type( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return iType; @@ -73630,12 +76239,12 @@ static const void *columnName( ** Return the name of the Nth column of the result set returned by SQL ** statement pStmt. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME); } @@ -73655,12 +76264,12 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt *pStmt, ** Return the column declaration type (if applicable) of the 'i'th column ** of the result set of SQL statement pStmt. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE); } @@ -73673,12 +76282,12 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt *pS ** NULL is returned if the result column is an expression or constant or ** anything else which is not an unambiguous reference to a database column. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE); } @@ -73689,12 +76298,12 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stm ** NULL is returned if the result column is an expression or constant or ** anything else which is not an unambiguous reference to a database column. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE); } @@ -73705,12 +76314,12 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt * ** NULL is returned if the result column is an expression or constant or ** anything else which is not an unambiguous reference to a database column. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN); } @@ -73811,7 +76420,7 @@ static int bindText( /* ** Bind a blob value to an SQL statement variable. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob( +SQLITE_API int sqlite3_bind_blob( sqlite3_stmt *pStmt, int i, const void *zData, @@ -73823,7 +76432,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob( #endif return bindText(pStmt, i, zData, nData, xDel, 0); } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64( +SQLITE_API int sqlite3_bind_blob64( sqlite3_stmt *pStmt, int i, const void *zData, @@ -73837,7 +76446,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64( return bindText(pStmt, i, zData, (int)nData, xDel, 0); } } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ +SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); @@ -73847,10 +76456,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt *pStmt, int i, do } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ +SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ return sqlite3_bind_int64(p, i, (i64)iValue); } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); @@ -73860,7 +76469,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sql } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ int rc; Vdbe *p = (Vdbe*)pStmt; rc = vdbeUnbind(p, i); @@ -73869,7 +76478,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text( +SQLITE_API int sqlite3_bind_text( sqlite3_stmt *pStmt, int i, const char *zData, @@ -73878,7 +76487,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_text( ){ return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8); } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64( +SQLITE_API int sqlite3_bind_text64( sqlite3_stmt *pStmt, int i, const char *zData, @@ -73895,7 +76504,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64( } } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16( +SQLITE_API int sqlite3_bind_text16( sqlite3_stmt *pStmt, int i, const void *zData, @@ -73905,7 +76514,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16( return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE); } #endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ +SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ int rc; switch( sqlite3_value_type((sqlite3_value*)pValue) ){ case SQLITE_INTEGER: { @@ -73936,7 +76545,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt *pStmt, int i, con } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); @@ -73946,7 +76555,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){ +SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){ int rc; Vdbe *p = (Vdbe *)pStmt; sqlite3_mutex_enter(p->db->mutex); @@ -73965,7 +76574,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i ** Return the number of wildcards that can be potentially bound to. ** This routine is added to support DBD::SQLite. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; return p ? p->nVar : 0; } @@ -73976,7 +76585,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ ** ** The result is always UTF-8. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ +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; @@ -74004,7 +76613,7 @@ SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nNa } return 0; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName)); } @@ -74038,7 +76647,7 @@ SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt ** an SQLITE_ERROR is returned. Nothing else can go wrong, so otherwise ** SQLITE_OK is returned. */ -SQLITE_API int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ +SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ Vdbe *pFrom = (Vdbe*)pFromStmt; Vdbe *pTo = (Vdbe*)pToStmt; if( pFrom->nVar!=pTo->nVar ){ @@ -74060,7 +76669,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, ** the first argument to the sqlite3_prepare() that was used to create ** the statement in the first place. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt *pStmt){ +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->db : 0; } @@ -74068,16 +76677,16 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt *pStmt){ ** Return true if the prepared statement is guaranteed to not modify the ** database. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->readOnly : 1; } /* ** Return true if the prepared statement is in need of being reset. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ Vdbe *v = (Vdbe*)pStmt; - return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN; + return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0; } /* @@ -74086,7 +76695,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt *pStmt){ ** prepared statement for the database connection. Return NULL if there ** are no more. */ -SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ sqlite3_stmt *pNext; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(pDb) ){ @@ -74107,7 +76716,7 @@ SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_ /* ** Return the value of a status counter for a prepared statement */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ +SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ Vdbe *pVdbe = (Vdbe*)pStmt; u32 v; #ifdef SQLITE_ENABLE_API_ARMOR @@ -74121,11 +76730,229 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, i return (int)v; } +/* +** Return the SQL associated with a prepared statement +*/ +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){ + Vdbe *p = (Vdbe *)pStmt; + return p ? p->zSql : 0; +} + +/* +** Return the SQL associated with a prepared statement with +** bound parameters expanded. Space to hold the returned string is +** obtained from sqlite3_malloc(). The caller is responsible for +** freeing the returned string by passing it to sqlite3_free(). +** +** The SQLITE_TRACE_SIZE_LIMIT puts an upper bound on the size of +** expanded bound parameters. +*/ +SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt){ +#ifdef SQLITE_OMIT_TRACE + return 0; +#else + char *z = 0; + const char *zSql = sqlite3_sql(pStmt); + if( zSql ){ + Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); + z = sqlite3VdbeExpandSql(p, zSql); + sqlite3_mutex_leave(p->db->mutex); + } + return z; +#endif +} + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK +/* +** Allocate and populate an UnpackedRecord structure based on the serialized +** record in nKey/pKey. Return a pointer to the new UnpackedRecord structure +** if successful, or a NULL pointer if an OOM error is encountered. +*/ +static UnpackedRecord *vdbeUnpackRecord( + KeyInfo *pKeyInfo, + int nKey, + const void *pKey +){ + char *dummy; /* Dummy argument for AllocUnpackedRecord() */ + UnpackedRecord *pRet; /* Return value */ + + pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo, 0, 0, &dummy); + if( pRet ){ + memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1)); + sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet); + } + return pRet; +} + +/* +** This function is called from within a pre-update callback to retrieve +** a field of the row currently being updated or deleted. +*/ +SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ + PreUpdate *p = db->pPreUpdate; + int rc = SQLITE_OK; + + /* Test that this call is being made from within an SQLITE_DELETE or + ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */ + if( !p || p->op==SQLITE_INSERT ){ + rc = SQLITE_MISUSE_BKPT; + goto preupdate_old_out; + } + if( iIdx>=p->pCsr->nField || iIdx<0 ){ + rc = SQLITE_RANGE; + goto preupdate_old_out; + } + + /* If the old.* record has not yet been loaded into memory, do so now. */ + if( p->pUnpacked==0 ){ + u32 nRec; + u8 *aRec; + + 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); + if( rc==SQLITE_OK ){ + p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec); + if( !p->pUnpacked ) rc = SQLITE_NOMEM; + } + if( rc!=SQLITE_OK ){ + sqlite3DbFree(db, aRec); + goto preupdate_old_out; + } + p->aRecord = aRec; + } + + 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); + } + } + } + + preupdate_old_out: + sqlite3Error(db, rc); + return sqlite3ApiExit(db, rc); +} +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK +/* +** This function is called from within a pre-update callback to retrieve +** the number of columns in the row being updated, deleted or inserted. +*/ +SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){ + PreUpdate *p = db->pPreUpdate; + return (p ? p->keyinfo.nField : 0); +} +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK +/* +** This function is designed to be called from within a pre-update callback +** only. It returns zero if the change that caused the callback was made +** immediately by a user SQL statement. Or, if the change was made by a +** trigger program, it returns the number of trigger programs currently +** on the stack (1 for a top-level trigger, 2 for a trigger fired by a +** top-level trigger etc.). +** +** For the purposes of the previous paragraph, a foreign key CASCADE, SET NULL +** or SET DEFAULT action is considered a trigger. +*/ +SQLITE_API int sqlite3_preupdate_depth(sqlite3 *db){ + PreUpdate *p = db->pPreUpdate; + return (p ? p->v->nFrame : 0); +} +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK +/* +** This function is called from within a pre-update callback to retrieve +** a field of the row currently being updated or inserted. +*/ +SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ + PreUpdate *p = db->pPreUpdate; + int rc = SQLITE_OK; + Mem *pMem; + + if( !p || p->op==SQLITE_DELETE ){ + rc = SQLITE_MISUSE_BKPT; + goto preupdate_new_out; + } + if( iIdx>=p->pCsr->nField || iIdx<0 ){ + rc = SQLITE_RANGE; + goto preupdate_new_out; + } + + if( p->op==SQLITE_INSERT ){ + /* For an INSERT, memory cell p->iNewReg contains the serialized record + ** that is being inserted. Deserialize it. */ + UnpackedRecord *pUnpack = p->pNewUnpacked; + if( !pUnpack ){ + Mem *pData = &p->v->aMem[p->iNewReg]; + rc = ExpandBlob(pData); + if( rc!=SQLITE_OK ) goto preupdate_new_out; + pUnpack = vdbeUnpackRecord(&p->keyinfo, pData->n, pData->z); + if( !pUnpack ){ + rc = SQLITE_NOMEM; + goto preupdate_new_out; + } + p->pNewUnpacked = pUnpack; + } + 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 + ** value. Make a copy of the cell contents and return a pointer to it. + ** It is not safe to return a pointer to the memory cell itself as the + ** caller may modify the value text encoding. + */ + assert( p->op==SQLITE_UPDATE ); + if( !p->aNew ){ + p->aNew = (Mem *)sqlite3DbMallocZero(db, sizeof(Mem) * p->pCsr->nField); + if( !p->aNew ){ + rc = SQLITE_NOMEM; + goto preupdate_new_out; + } + } + assert( iIdx>=0 && iIdxpCsr->nField ); + pMem = &p->aNew[iIdx]; + if( pMem->flags==0 ){ + if( iIdx==p->pTab->iPKey ){ + sqlite3VdbeMemSetInt64(pMem, p->iKey2); + }else{ + rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); + if( rc!=SQLITE_OK ) goto preupdate_new_out; + } + } + } + *ppValue = pMem; + + preupdate_new_out: + sqlite3Error(db, rc); + return sqlite3ApiExit(db, rc); +} +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + #ifdef SQLITE_ENABLE_STMT_SCANSTATUS /* ** Return status data for a single loop within query pStmt. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( +SQLITE_API int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement being queried */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Which metric to return */ @@ -74184,7 +77011,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( /* ** Zero all counters associated with the sqlite3_stmt_scanstatus() data. */ -SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ +SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; memset(p->anExec, 0, p->nOp * sizeof(i64)); } @@ -74275,10 +77102,13 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( int i; /* Loop counter */ Mem *pVar; /* Value of a host parameter */ StrAccum out; /* Accumulate the output here */ +#ifndef SQLITE_OMIT_UTF16 + Mem utf8; /* Used to convert UTF16 parameters into UTF8 for display */ +#endif char zBase[100]; /* Initial working space */ db = p->db; - sqlite3StrAccumInit(&out, db, zBase, sizeof(zBase), + sqlite3StrAccumInit(&out, 0, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); if( db->nVdbeExec>1 ){ while( *zRawSql ){ @@ -74329,12 +77159,14 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( int nOut; /* Number of bytes of the string text to include in output */ #ifndef SQLITE_OMIT_UTF16 u8 enc = ENC(db); - Mem utf8; if( enc!=SQLITE_UTF8 ){ memset(&utf8, 0, sizeof(utf8)); utf8.db = db; sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); - sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8); + if( SQLITE_NOMEM==sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8) ){ + out.accError = STRACCUM_NOMEM; + out.nAlloc = 0; + } pVar = &utf8; } #endif @@ -74376,6 +77208,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( } } } + if( out.accError ) sqlite3StrAccumReset(&out); return sqlite3StrAccumFinish(&out); } @@ -74471,6 +77304,16 @@ static void updateMaxBlobsize(Mem *p){ } #endif +/* +** This macro evaluates to true if either the update hook or the preupdate +** hook are enabled for database connect DB. +*/ +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK +# define HAS_UPDATE_HOOK(DB) ((DB)->xPreUpdateCallback||(DB)->xUpdateCallback) +#else +# define HAS_UPDATE_HOOK(DB) ((DB)->xUpdateCallback) +#endif + /* ** The next global variable is incremented each time the OP_Found opcode ** is executed. This is used to test whether or not the foreign key @@ -74590,7 +77433,7 @@ static VdbeCursor *allocateCursor( (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0); assert( iCur>=0 && iCurnCursor ); - if( p->apCsr[iCur] ){ + if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/ sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); p->apCsr[iCur] = 0; } @@ -74667,7 +77510,7 @@ static void applyAffinity( if( affinity>=SQLITE_AFF_NUMERIC ){ assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL || affinity==SQLITE_AFF_NUMERIC ); - if( (pRec->flags & MEM_Int)==0 ){ + if( (pRec->flags & MEM_Int)==0 ){ /*OPTIMIZATION-IF-FALSE*/ if( (pRec->flags & MEM_Real)==0 ){ if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1); }else{ @@ -74677,10 +77520,13 @@ static void applyAffinity( }else if( affinity==SQLITE_AFF_TEXT ){ /* Only attempt the conversion to TEXT if there is an integer or real ** representation (blob and NULL do not get converted) but no string - ** representation. - */ - if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){ - sqlite3VdbeMemStringify(pRec, enc, 1); + ** representation. It would be harmless to repeat the conversion if + ** there is already a string rep, but it is pointless to waste those + ** CPU cycles. */ + if( 0==(pRec->flags&MEM_Str) ){ /*OPTIMIZATION-IF-FALSE*/ + if( (pRec->flags&(MEM_Real|MEM_Int)) ){ + sqlite3VdbeMemStringify(pRec, enc, 1); + } } pRec->flags &= ~(MEM_Real|MEM_Int); } @@ -74692,7 +77538,7 @@ static void applyAffinity( ** is appropriate. But only do the conversion if it is possible without ** loss of information and return the revised type of the argument. */ -SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value *pVal){ +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){ int eType = sqlite3_value_type(pVal); if( eType==SQLITE_TEXT ){ Mem *pMem = (Mem*)pVal; @@ -74895,8 +77741,8 @@ static void registerTrace(int iReg, Mem *p){ ** This file contains inline asm code for retrieving "high-performance" ** counters for x86 class CPUs. */ -#ifndef _HWTIME_H_ -#define _HWTIME_H_ +#ifndef SQLITE_HWTIME_H +#define SQLITE_HWTIME_H /* ** The following routine only works on pentium-class (or newer) processors. @@ -74964,7 +77810,7 @@ SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } #endif -#endif /* !defined(_HWTIME_H_) */ +#endif /* !defined(SQLITE_HWTIME_H) */ /************** End of hwtime.h **********************************************/ /************** Continuing where we left off in vdbe.c ***********************/ @@ -75006,7 +77852,7 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){ assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); pOut = &p->aMem[pOp->p2]; memAboutToChange(p, pOut); - if( VdbeMemDynamic(pOut) ){ + if( VdbeMemDynamic(pOut) ){ /*OPTIMIZATION-IF-FALSE*/ return out2PrereleaseWithClear(pOut); }else{ pOut->flags = MEM_Int; @@ -75034,7 +77880,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ - int iCompare = 0; /* Result of last OP_Compare operation */ + 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 */ @@ -75138,37 +77984,39 @@ SQLITE_PRIVATE int sqlite3VdbeExec( /* Sanity checking on other operands */ #ifdef SQLITE_DEBUG - assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] ); - if( (pOp->opflags & OPFLG_IN1)!=0 ){ - assert( pOp->p1>0 ); - assert( pOp->p1<=(p->nMem+1 - p->nCursor) ); - assert( memIsValid(&aMem[pOp->p1]) ); - assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) ); - REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]); - } - if( (pOp->opflags & OPFLG_IN2)!=0 ){ - assert( pOp->p2>0 ); - assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); - assert( memIsValid(&aMem[pOp->p2]) ); - assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) ); - REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]); - } - if( (pOp->opflags & OPFLG_IN3)!=0 ){ - assert( pOp->p3>0 ); - assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); - assert( memIsValid(&aMem[pOp->p3]) ); - assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) ); - REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]); - } - if( (pOp->opflags & OPFLG_OUT2)!=0 ){ - assert( pOp->p2>0 ); - assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); - memAboutToChange(p, &aMem[pOp->p2]); - } - if( (pOp->opflags & OPFLG_OUT3)!=0 ){ - assert( pOp->p3>0 ); - assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); - memAboutToChange(p, &aMem[pOp->p3]); + { + u8 opProperty = sqlite3OpcodeProperty[pOp->opcode]; + if( (opProperty & OPFLG_IN1)!=0 ){ + assert( pOp->p1>0 ); + assert( pOp->p1<=(p->nMem+1 - p->nCursor) ); + assert( memIsValid(&aMem[pOp->p1]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) ); + REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]); + } + if( (opProperty & OPFLG_IN2)!=0 ){ + assert( pOp->p2>0 ); + assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); + assert( memIsValid(&aMem[pOp->p2]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) ); + REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]); + } + if( (opProperty & OPFLG_IN3)!=0 ){ + assert( pOp->p3>0 ); + assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); + assert( memIsValid(&aMem[pOp->p3]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) ); + REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]); + } + if( (opProperty & OPFLG_OUT2)!=0 ){ + assert( pOp->p2>0 ); + assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); + memAboutToChange(p, &aMem[pOp->p2]); + } + if( (opProperty & OPFLG_OUT3)!=0 ){ + assert( pOp->p3>0 ); + assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); + memAboutToChange(p, &aMem[pOp->p3]); + } } #endif #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) @@ -75364,7 +78212,7 @@ case OP_Yield: { /* in1, jump */ } /* Opcode: HaltIfNull P1 P2 P3 P4 P5 -** Synopsis: if r[P3]=null halt +** Synopsis: if r[P3]=null halt ** ** Check the value in register P3. If it is NULL then Halt using ** parameter P1, P2, and P4 as if this were a Halt instruction. If the @@ -75408,8 +78256,6 @@ case OP_HaltIfNull: { /* in3 */ ** is the same as executing Halt. */ case OP_Halt: { - const char *zType; - const char *zLogFmt; VdbeFrame *pFrame; int pcx; @@ -75438,34 +78284,28 @@ case OP_Halt: { p->rc = pOp->p1; p->errorAction = (u8)pOp->p2; p->pc = pcx; + assert( pOp->p5>=0 && pOp->p5<=4 ); if( p->rc ){ if( pOp->p5 ){ static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK", "FOREIGN KEY" }; - assert( pOp->p5>=1 && pOp->p5<=4 ); testcase( pOp->p5==1 ); testcase( pOp->p5==2 ); testcase( pOp->p5==3 ); testcase( pOp->p5==4 ); - zType = azType[pOp->p5-1]; + sqlite3VdbeError(p, "%s constraint failed", azType[pOp->p5-1]); + if( pOp->p4.z ){ + p->zErrMsg = sqlite3MPrintf(db, "%z: %s", p->zErrMsg, pOp->p4.z); + } }else{ - zType = 0; - } - assert( zType!=0 || pOp->p4.z!=0 ); - zLogFmt = "abort at %d in [%s]: %s"; - if( zType && pOp->p4.z ){ - sqlite3VdbeError(p, "%s constraint failed: %s", zType, pOp->p4.z); - }else if( pOp->p4.z ){ sqlite3VdbeError(p, "%s", pOp->p4.z); - }else{ - sqlite3VdbeError(p, "%s constraint failed", zType); } - sqlite3_log(pOp->p1, zLogFmt, pcx, p->zSql, p->zErrMsg); + sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); if( rc==SQLITE_BUSY ){ - p->rc = rc = SQLITE_BUSY; + p->rc = SQLITE_BUSY; }else{ assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ); assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 ); @@ -75531,10 +78371,7 @@ case OP_String8: { /* same as TK_STRING, out2 */ #ifndef SQLITE_OMIT_UTF16 if( encoding!=SQLITE_UTF8 ){ rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC); - if( rc ){ - assert( rc==SQLITE_TOOBIG ); /* This is the only possible error here */ - goto too_big; - } + assert( rc==SQLITE_OK || rc==SQLITE_TOOBIG ); if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z ); assert( VdbeMemDynamic(pOut)==0 ); @@ -75547,10 +78384,12 @@ case OP_String8: { /* same as TK_STRING, out2 */ pOp->p4.z = pOut->z; pOp->p1 = pOut->n; } + testcase( rc==SQLITE_TOOBIG ); #endif if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } + assert( rc==SQLITE_OK ); /* Fall through to the next case, OP_String */ } @@ -75559,10 +78398,12 @@ case OP_String8: { /* same as TK_STRING, out2 */ ** ** The string value P4 of length P1 (bytes) is stored in register P2. ** -** If P5!=0 and the content of register P3 is greater than zero, then +** If P3 is not zero and the content of register P3 is equal to P5, then ** the datatype of the register P2 is converted to BLOB. The content is ** the same sequence of bytes, it is merely interpreted as a BLOB instead -** of a string, as if it had been CAST. +** of a string, as if it had been CAST. In other words: +** +** if( P3!=0 and reg[P3]==P5 ) reg[P2] := CAST(reg[P2] as BLOB) */ case OP_String: { /* out2 */ assert( pOp->p4.z!=0 ); @@ -75573,19 +78414,18 @@ case OP_String: { /* out2 */ pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS - if( pOp->p5 ){ - assert( pOp->p3>0 ); + if( pOp->p3>0 ){ assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); pIn3 = &aMem[pOp->p3]; assert( pIn3->flags & MEM_Int ); - if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term; + if( pIn3->u.i==pOp->p5 ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term; } #endif break; } /* Opcode: Null P1 P2 P3 * * -** Synopsis: r[P2..P3]=NULL +** Synopsis: r[P2..P3]=NULL ** ** Write a NULL into registers P2. If P3 greater than P2, then also write ** NULL into register P3 and every register in between P2 and P3. If P3 @@ -75603,18 +78443,20 @@ case OP_Null: { /* out2 */ cnt = pOp->p3-pOp->p2; assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; + pOut->n = 0; while( cnt>0 ){ pOut++; memAboutToChange(p, pOut); sqlite3VdbeMemSetNull(pOut); pOut->flags = nullFlag; + pOut->n = 0; cnt--; } break; } /* Opcode: SoftNull P1 * * * * -** Synopsis: r[P1]=NULL +** Synopsis: r[P1]=NULL ** ** Set register P1 to have the value NULL as seen by the OP_MakeRecord ** instruction, but do not free any string or blob memory associated with @@ -75667,7 +78509,7 @@ case OP_Variable: { /* out2 */ } /* Opcode: Move P1 P2 P3 * * -** Synopsis: r[P2@P3]=r[P1@P3] +** Synopsis: r[P2@P3]=r[P1@P3] ** ** Move the P3 values in register P1..P1+P3-1 over into ** registers P2..P2+P3-1. Registers P1..P1+P3-1 are @@ -75777,7 +78619,7 @@ case OP_IntCopy: { /* out2 */ } /* Opcode: ResultRow P1 P2 * * * -** Synopsis: output=r[P1@P2] +** Synopsis: output=r[P1@P2] ** ** The registers P1 through P1+P2-1 contain a single row of ** results. This opcode causes the sqlite3_step() call to terminate @@ -75850,6 +78692,10 @@ case OP_ResultRow: { } if( db->mallocFailed ) goto no_mem; + if( db->mTrace & SQLITE_TRACE_ROW ){ + db->xTrace(SQLITE_TRACE_ROW, db->pTraceArg, p, 0); + } + /* Return SQLITE_ROW */ p->pc = (int)(pOp - aOp) + 1; @@ -75906,14 +78752,14 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ } /* Opcode: Add P1 P2 P3 * * -** Synopsis: r[P3]=r[P1]+r[P2] +** Synopsis: r[P3]=r[P1]+r[P2] ** ** Add the value in register P1 to the value in register P2 ** and store the result in register P3. ** If either input is NULL, the result is NULL. */ /* Opcode: Multiply P1 P2 P3 * * -** Synopsis: r[P3]=r[P1]*r[P2] +** Synopsis: r[P3]=r[P1]*r[P2] ** ** ** Multiply the value in register P1 by the value in register P2 @@ -75921,14 +78767,14 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ ** If either input is NULL, the result is NULL. */ /* Opcode: Subtract P1 P2 P3 * * -** Synopsis: r[P3]=r[P2]-r[P1] +** Synopsis: r[P3]=r[P2]-r[P1] ** ** Subtract the value in register P1 from the value in register P2 ** and store the result in register P3. ** If either input is NULL, the result is NULL. */ /* Opcode: Divide P1 P2 P3 * * -** Synopsis: r[P3]=r[P2]/r[P1] +** Synopsis: r[P3]=r[P2]/r[P1] ** ** Divide the value in register P1 by the value in register P2 ** and store the result in register P3 (P3=P2/P1). If the value in @@ -75936,7 +78782,7 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ ** NULL, the result is NULL. */ /* Opcode: Remainder P1 P2 P3 * * -** Synopsis: r[P3]=r[P2]%r[P1] +** Synopsis: r[P3]=r[P2]%r[P1] ** ** Compute the remainder after integer register P2 is divided by ** register P1 and store the result in register P3. @@ -76169,21 +79015,21 @@ case OP_Function: { } /* Opcode: BitAnd P1 P2 P3 * * -** Synopsis: r[P3]=r[P1]&r[P2] +** Synopsis: r[P3]=r[P1]&r[P2] ** ** Take the bit-wise AND of the values in register P1 and P2 and ** store the result in register P3. ** If either input is NULL, the result is NULL. */ /* Opcode: BitOr P1 P2 P3 * * -** Synopsis: r[P3]=r[P1]|r[P2] +** Synopsis: r[P3]=r[P1]|r[P2] ** ** Take the bit-wise OR of the values in register P1 and P2 and ** store the result in register P3. ** If either input is NULL, the result is NULL. */ /* Opcode: ShiftLeft P1 P2 P3 * * -** Synopsis: r[P3]=r[P2]<>r[P1] +** Synopsis: r[P3]=r[P2]>>r[P1] ** ** Shift the integer value in register P2 to the right by the ** number of bits specified by the integer in register P1. @@ -76251,7 +79097,7 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ } /* Opcode: AddImm P1 P2 * * * -** Synopsis: r[P1]=r[P1]+P2 +** Synopsis: r[P1]=r[P1]+P2 ** ** Add the constant P2 to the value in register P1. ** The result is always an integer. @@ -76343,15 +79189,12 @@ case OP_Cast: { /* in1 */ } #endif /* SQLITE_OMIT_CAST */ -/* Opcode: Lt P1 P2 P3 P4 P5 -** Synopsis: if r[P1]r[P3] goto P2 +** Synopsis: IF r[P3]>r[P1] ** ** This works just like the Lt opcode except that the jump is taken if ** the content of register P3 is greater than the content of ** register P1. See the Lt opcode for additional information. */ /* Opcode: Ge P1 P2 P3 P4 P5 -** Synopsis: if r[P1]>=r[P3] goto P2 +** Synopsis: IF r[P3]>=r[P1] ** ** This works just like the Lt opcode except that the jump is taken if ** the content of register P3 is greater than or equal to the content of @@ -76431,7 +79291,7 @@ case OP_Lt: /* same as TK_LT, jump, in1, in3 */ case OP_Le: /* same as TK_LE, jump, in1, in3 */ case OP_Gt: /* same as TK_GT, jump, in1, in3 */ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ - int res; /* Result of the comparison of pIn1 against pIn3 */ + int res, res2; /* Result of the comparison of pIn1 against pIn3 */ char affinity; /* Affinity to use for comparison */ u16 flags1; /* Copy of initial value of pIn1->flags */ u16 flags3; /* Copy of initial value of pIn3->flags */ @@ -76454,9 +79314,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ && (flags3&MEM_Null)!=0 && (flags3&MEM_Cleared)==0 ){ - res = 0; /* Results are equal */ + res = 0; /* Operands are equal */ }else{ - res = 1; /* Results are not equal */ + res = 1; /* Operands are not equal */ } }else{ /* SQLITE_NULLEQ is clear and at least one operand is NULL, @@ -76465,6 +79325,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ */ if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; + iCompare = 1; /* Operands are not equal */ memAboutToChange(p, pOut); MemSetTypeFlag(pOut, MEM_Null); REGISTER_TRACE(pOp->p2, pOut); @@ -76480,11 +79341,23 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ /* Neither operand is NULL. Do a comparison. */ affinity = pOp->p5 & SQLITE_AFF_MASK; if( affinity>=SQLITE_AFF_NUMERIC ){ - if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ - applyNumericAffinity(pIn1,0); + if( (flags1 | flags3)&MEM_Str ){ + if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ + applyNumericAffinity(pIn1,0); + testcase( flags3!=pIn3->flags ); /* Possible if pIn1==pIn3 */ + flags3 = pIn3->flags; + } + if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ + applyNumericAffinity(pIn3,0); + } } - if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ - applyNumericAffinity(pIn3,0); + /* Handle the common case of integer comparison here, as an + ** optimization, to avoid a call to sqlite3MemCompare() */ + if( (pIn1->flags & pIn3->flags & MEM_Int)!=0 ){ + if( pIn3->u.i > pIn1->u.i ){ res = +1; goto compare_op; } + if( pIn3->u.i < pIn1->u.i ){ res = -1; goto compare_op; } + res = 0; + goto compare_op; } }else if( affinity==SQLITE_AFF_TEXT ){ if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){ @@ -76493,6 +79366,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ sqlite3VdbeMemStringify(pIn1, encoding, 1); testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); + assert( pIn1!=pIn3 ); } if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){ testcase( pIn3->flags & MEM_Int ); @@ -76503,23 +79377,16 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ } } assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); - if( flags1 & MEM_Zero ){ - sqlite3VdbeMemExpandBlob(pIn1); - flags1 &= ~MEM_Zero; - } - if( flags3 & MEM_Zero ){ - sqlite3VdbeMemExpandBlob(pIn3); - flags3 &= ~MEM_Zero; - } res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); } +compare_op: switch( pOp->opcode ){ - case OP_Eq: res = res==0; break; - case OP_Ne: res = res!=0; break; - case OP_Lt: res = res<0; break; - case OP_Le: res = res<=0; break; - case OP_Gt: res = res>0; break; - default: res = res>=0; break; + case OP_Eq: res2 = res==0; break; + case OP_Ne: res2 = res; break; + case OP_Lt: res2 = res<0; break; + case OP_Le: res2 = res<=0; break; + case OP_Gt: res2 = res>0; break; + default: res2 = res>=0; break; } /* Undo any changes made by applyAffinity() to the input registers. */ @@ -76530,19 +79397,55 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; + iCompare = res; + res2 = res2!=0; /* For this path res2 must be exactly 0 or 1 */ + if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){ + /* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1 + ** and prevents OP_Ne from overwriting NULL with 0. This flag + ** is only used in contexts where either: + ** (1) op==OP_Eq && (r[P2]==NULL || r[P2]==0) + ** (2) op==OP_Ne && (r[P2]==NULL || r[P2]==1) + ** Therefore it is not necessary to check the content of r[P2] for + ** NULL. */ + assert( pOp->opcode==OP_Ne || pOp->opcode==OP_Eq ); + assert( res2==0 || res2==1 ); + testcase( res2==0 && pOp->opcode==OP_Eq ); + testcase( res2==1 && pOp->opcode==OP_Eq ); + testcase( res2==0 && pOp->opcode==OP_Ne ); + testcase( res2==1 && pOp->opcode==OP_Ne ); + if( (pOp->opcode==OP_Eq)==res2 ) break; + } memAboutToChange(p, pOut); MemSetTypeFlag(pOut, MEM_Int); - pOut->u.i = res; + pOut->u.i = res2; REGISTER_TRACE(pOp->p2, pOut); }else{ VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); - if( res ){ + if( res2 ){ goto jump_to_p2; } } break; } +/* Opcode: ElseNotEq * P2 * * * +** +** This opcode must immediately follow an OP_Lt or OP_Gt comparison operator. +** If result of an OP_Eq comparison on the same two operands +** would have be NULL or false (0), then then jump to P2. +** If the result of an OP_Eq comparison on the two previous operands +** would have been true (1), then fall through. +*/ +case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */ + assert( pOp>aOp ); + assert( pOp[-1].opcode==OP_Lt || pOp[-1].opcode==OP_Gt ); + assert( pOp[-1].p5 & SQLITE_STOREP2 ); + VdbeBranchTaken(iCompare!=0, 2); + if( iCompare!=0 ) goto jump_to_p2; + break; +} + + /* Opcode: Permutation * * * P4 * ** ** Set the permutation used by the OP_Compare operator to be the array @@ -76738,22 +79641,18 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */ /* Opcode: Once P1 P2 * * * ** -** Check the "once" flag number P1. If it is set, jump to instruction P2. -** Otherwise, set the flag and fall through to the next instruction. -** In other words, this opcode causes all following opcodes up through P2 -** (but not including P2) to run just once and to be skipped on subsequent -** times through the loop. -** -** All "once" flags are initially cleared whenever a prepared statement -** first begins to run. +** 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. */ case OP_Once: { /* jump */ - assert( pOp->p1nOnceFlag ); - VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2); - if( p->aOnceFlag[pOp->p1] ){ + 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; }else{ - p->aOnceFlag[pOp->p1] = 1; + pOp->p1 = p->aOp[0].p1; } break; } @@ -76792,7 +79691,7 @@ case OP_IfNot: { /* jump, in1 */ } /* Opcode: IsNull P1 P2 * * * -** Synopsis: if r[P1]==NULL goto P2 +** Synopsis: if r[P1]==NULL goto P2 ** ** Jump to P2 if the value in register P1 is NULL. */ @@ -76820,7 +79719,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ } /* Opcode: Column P1 P2 P3 P4 P5 -** Synopsis: r[P3]=PX +** Synopsis: r[P3]=PX ** ** Interpret the data that cursor P1 points to as a structure built using ** the MakeRecord instruction. (See the MakeRecord opcode for additional @@ -76845,7 +79744,6 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ ** skipped for length() and all content loading can be skipped for typeof(). */ case OP_Column: { - i64 payloadSize64; /* Number of bytes in the record */ int p2; /* column number to retrieve */ VdbeCursor *pC; /* The VDBE cursor */ BtCursor *pCrsr; /* The BTree cursor */ @@ -76868,6 +79766,7 @@ case OP_Column: { /* If the cursor cache is stale, bring it up-to-date */ rc = sqlite3VdbeCursorMoveto(&pC, &p2); + if( rc ) goto abort_due_to_error; assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); pDest = &aMem[pOp->p3]; @@ -76881,8 +79780,7 @@ case OP_Column: { assert( pC->eCurType!=CURTYPE_SORTER ); pCrsr = pC->uc.pCursor; - if( rc ) goto abort_due_to_error; - if( pC->cacheStatus!=p->cacheCtr ){ + if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/ if( pC->nullRow ){ if( pC->eCurType==CURTYPE_PSEUDO ){ assert( pC->uc.pseudoTableReg>0 ); @@ -76898,22 +79796,9 @@ case OP_Column: { }else{ assert( pC->eCurType==CURTYPE_BTREE ); assert( pCrsr ); - if( pC->isTable==0 ){ - assert( sqlite3BtreeCursorIsValid(pCrsr) ); - VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &payloadSize64); - assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ - /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the - ** payload size, so it is impossible for payloadSize64 to be - ** larger than 32 bits. */ - assert( (payloadSize64 & SQLITE_MAX_U32)==(u64)payloadSize64 ); - pC->aRow = sqlite3BtreeKeyFetch(pCrsr, &avail); - pC->payloadSize = (u32)payloadSize64; - }else{ - assert( sqlite3BtreeCursorIsValid(pCrsr) ); - VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &pC->payloadSize); - assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ - pC->aRow = sqlite3BtreeDataFetch(pCrsr, &avail); - } + assert( sqlite3BtreeCursorIsValid(pCrsr) ); + pC->payloadSize = sqlite3BtreePayloadSize(pCrsr); + pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &avail); assert( avail<=65536 ); /* Maximum page size is 64KiB */ if( pC->payloadSize <= (u32)avail ){ pC->szRow = pC->payloadSize; @@ -76929,7 +79814,7 @@ case OP_Column: { aOffset[0] = offset; - if( availaRow does not have to hold the entire row, but it does at least ** need to cover the header of the record. If pC->aRow does not contain ** the complete header, then set it to zero, forcing the header to be @@ -76950,14 +79835,15 @@ case OP_Column: { rc = SQLITE_CORRUPT_BKPT; goto abort_due_to_error; } + }else if( offset>0 ){ /*OPTIMIZATION-IF-TRUE*/ + /* The following goto is an optimization. It can be omitted and + ** everything will still work. But OP_Column is measurably faster + ** by skipping the subsequent conditional, which is always true. + */ + zData = pC->aRow; + assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */ + goto op_column_read_header; } - - /* The following goto is an optimization. It can be omitted and - ** everything will still work. But OP_Column is measurably faster - ** by skipping the subsequent conditional, which is always true. - */ - assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */ - goto op_column_read_header; } /* Make sure at least the first p2+1 entries of the header have been @@ -76967,7 +79853,6 @@ case OP_Column: { /* If there is more header available for parsing in the record, try ** to extract additional fields up through the p2+1-th field */ - op_column_read_header: if( pC->iHdrOffsetaRow==0 ){ @@ -76980,11 +79865,11 @@ case OP_Column: { } /* Fill in pC->aType[i] and aOffset[i] values through the p2-th field. */ + op_column_read_header: i = pC->nHdrParsed; offset64 = aOffset[i]; zHdr = zData + pC->iHdrOffset; zEndHdr = zData + aOffset[0]; - assert( i<=p2 && zHdraType[i++] = t; aOffset[i] = (u32)(offset64 & 0xffffffff); }while( i<=p2 && zHdrnHdrParsed = i; - pC->iHdrOffset = (u32)(zHdr - zData); - + /* The record is corrupt if any of the following are true: ** (1) the bytes of the header extend past the declared header size ** (2) the entire header was used but not all data was used @@ -77011,8 +79894,10 @@ case OP_Column: { rc = SQLITE_CORRUPT_BKPT; goto abort_due_to_error; } - if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); + pC->nHdrParsed = i; + pC->iHdrOffset = (u32)(zHdr - zData); + if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); }else{ t = 0; } @@ -77040,9 +79925,10 @@ case OP_Column: { assert( p2nHdrParsed ); assert( rc==SQLITE_OK ); assert( sqlite3VdbeCheckMemInvariants(pDest) ); - if( VdbeMemDynamic(pDest) ) sqlite3VdbeMemSetNull(pDest); + if( VdbeMemDynamic(pDest) ){ + sqlite3VdbeMemSetNull(pDest); + } assert( t==pC->aType[p2] ); - pDest->enc = encoding; if( pC->szRow>=aOffset[p2+1] ){ /* This is the common case where the desired content fits on the original ** page - where the content is not on an overflow page */ @@ -77056,6 +79942,7 @@ case OP_Column: { */ static const u16 aFlag[] = { MEM_Blob, MEM_Str|MEM_Term }; pDest->n = len = (t-12)/2; + pDest->enc = encoding; if( pDest->szMalloc < len+2 ){ pDest->flags = MEM_Null; if( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem; @@ -77068,6 +79955,7 @@ case OP_Column: { pDest->flags = aFlag[t&1]; } }else{ + pDest->enc = encoding; /* This branch happens only when content is on overflow pages */ if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)) @@ -77217,7 +80105,9 @@ case OP_MakeRecord: { testcase( serial_type==127 ); testcase( serial_type==128 ); nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type); - }while( (--pRec)>=pData0 ); + if( pRec==pData0 ) break; + pRec--; + }while(1); /* EVIDENCE-OF: R-22564-11647 The header begins with a single varint ** which determines the total number of bytes in the header. The varint @@ -77365,7 +80255,7 @@ case OP_Savepoint: { }else{ db->nSavepoint++; } - + /* Link the new savepoint into the database handle's list. */ pNew->pNext = db->pSavepoint; db->pSavepoint = pNew; @@ -77595,12 +80485,12 @@ case OP_Transaction: { rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); testcase( rc==SQLITE_BUSY_SNAPSHOT ); testcase( rc==SQLITE_BUSY_RECOVERY ); - if( (rc&0xff)==SQLITE_BUSY ){ - p->pc = (int)(pOp - aOp); - p->rc = rc; - goto vdbe_return; - } if( rc!=SQLITE_OK ){ + if( (rc&0xff)==SQLITE_BUSY ){ + p->pc = (int)(pOp - aOp); + p->rc = rc; + goto vdbe_return; + } goto abort_due_to_error; } @@ -77627,10 +80517,9 @@ case OP_Transaction: { } /* Gather the schema version number for checking: - ** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite - ** each time a query is executed to ensure that the internal cache of the - ** schema used when compiling the SQL query matches the schema of the - ** database against which the compiled query is actually executed. + ** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema + ** version is checked to ensure that the schema has not changed since the + ** SQL statement was prepared. */ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); iGen = db->aDb[pOp->p1].pSchema->iGeneration; @@ -78291,7 +81180,6 @@ case OP_SeekGT: { /* jump, in3 */ #ifdef SQLITE_DEBUG { int i; for(i=0; iuc.pCursor, &r, 0, 0, &res); if( rc!=SQLITE_OK ){ @@ -78339,7 +81227,6 @@ case OP_SeekGT: { /* jump, in3 */ } break; } - /* Opcode: Found P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] @@ -78433,13 +81320,13 @@ case OP_Found: { /* jump, in3 */ r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p4.i; r.aMem = pIn3; +#ifdef SQLITE_DEBUG for(ii=0; iip3+ii, &r.aMem[ii]); -#endif } +#endif pIdxKey = &r; }else{ pIdxKey = sqlite3VdbeAllocUnpackedRecord( @@ -78447,7 +81334,7 @@ case OP_Found: { /* jump, in3 */ ); if( pIdxKey==0 ) goto no_mem; assert( pIn3->flags & MEM_Blob ); - ExpandBlob(pIn3); + (void)ExpandBlob(pIn3); sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); } pIdxKey->default_rc = 0; @@ -78483,6 +81370,30 @@ case OP_Found: { /* jump, in3 */ break; } +/* Opcode: SeekRowid P1 P2 P3 * * +** Synopsis: intkey=r[P3] +** +** P1 is the index of a cursor open on an SQL table btree (with integer +** keys). If register P3 does not contain an integer or if P1 does not +** contain a record with rowid P3 then jump immediately to P2. +** Or, if P2 is 0, raise an SQLITE_CORRUPT error. If P1 does contain +** a record with rowid P3 then +** leave the cursor pointing at that record and fall through to the next +** instruction. +** +** The OP_NotExists opcode performs the same operation, but with OP_NotExists +** the P3 register must be guaranteed to contain an integer value. With this +** opcode, register P3 might not contain an integer. +** +** The OP_NotFound opcode performs the same operation on index btrees +** (with arbitrary multi-value keys). +** +** This opcode leaves the cursor in a state where it cannot be advanced +** in either direction. In other words, the Next and Prev opcodes will +** not work following this opcode. +** +** See also: Found, NotFound, NoConflict, SeekRowid +*/ /* Opcode: NotExists P1 P2 P3 * * ** Synopsis: intkey=r[P3] ** @@ -78493,6 +81404,10 @@ case OP_Found: { /* jump, in3 */ ** leave the cursor pointing at that record and fall through to the next ** instruction. ** +** The OP_SeekRowid opcode performs the same operation but also allows the +** P3 register to contain a non-integer value, in which case the jump is +** always taken. This opcode requires that P3 always contain an integer. +** ** The OP_NotFound opcode performs the same operation on index btrees ** (with arbitrary multi-value keys). ** @@ -78500,14 +81415,21 @@ case OP_Found: { /* jump, in3 */ ** in either direction. In other words, the Next and Prev opcodes will ** not work following this opcode. ** -** See also: Found, NotFound, NoConflict +** See also: Found, NotFound, NoConflict, SeekRowid */ -case OP_NotExists: { /* jump, in3 */ +case OP_SeekRowid: { /* jump, in3 */ VdbeCursor *pC; BtCursor *pCrsr; int res; u64 iKey; + pIn3 = &aMem[pOp->p3]; + if( (pIn3->flags & MEM_Int)==0 ){ + applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding); + if( (pIn3->flags & MEM_Int)==0 ) goto jump_to_p2; + } + /* Fall through into OP_NotExists */ +case OP_NotExists: /* jump, in3 */ pIn3 = &aMem[pOp->p3]; assert( pIn3->flags & MEM_Int ); assert( pOp->p1>=0 && pOp->p1nCursor ); @@ -78626,8 +81548,7 @@ case OP_NewRowid: { /* out2 */ v = 1; /* IMP: R-61914-48074 */ }else{ assert( sqlite3BtreeCursorIsValid(pC->uc.pCursor) ); - rc = sqlite3BtreeKeySize(pC->uc.pCursor, &v); - assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ + v = sqlite3BtreeIntegerKey(pC->uc.pCursor); if( v>=MAX_ROWID ){ pC->useRandomRowid = 1; }else{ @@ -78710,10 +81631,12 @@ case OP_NewRowid: { /* out2 */ ** 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) was a success, then this +** 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 opcode +** 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. ** @@ -78722,9 +81645,9 @@ case OP_NewRowid: { /* out2 */ ** is part of an INSERT operation. The difference is only important to ** the update hook. ** -** Parameter P4 may point to a string containing the table-name, or -** may be NULL. If it is not NULL, then the update-hook -** (sqlite3.xUpdateCallback) is invoked following a successful insert. +** Parameter P4 may point to a Table structure, or may be NULL. If it is +** not NULL, then the update-hook (sqlite3.xUpdateCallback) is invoked +** following a successful insert. ** ** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically ** allocated, then ownership of P2 is transferred to the pseudo-cursor @@ -78736,7 +81659,7 @@ case OP_NewRowid: { /* out2 */ ** for indices is OP_IdxInsert. */ /* Opcode: InsertInt P1 P2 P3 P4 P5 -** Synopsis: intkey=P3 data=r[P2] +** Synopsis: intkey=P3 data=r[P2] ** ** This works exactly like OP_Insert except that the key is the ** integer value P3, not the value of the integer stored in register P3. @@ -78745,14 +81668,14 @@ case OP_Insert: case OP_InsertInt: { Mem *pData; /* MEM cell holding data for the record to be inserted */ Mem *pKey; /* MEM cell holding key for the record */ - i64 iKey; /* The integer ROWID or key for the record to be inserted */ VdbeCursor *pC; /* Cursor to table into which insert is written */ - int nZero; /* Number of zero-bytes to append */ int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */ const char *zDb; /* database name - used by the update hook */ - const char *zTbl; /* Table name - used by the opdate hook */ + Table *pTab; /* Table structure - used by update and pre-update hooks */ int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ + BtreePayload x; /* Payload to be inserted */ + op = 0; pData = &aMem[pOp->p2]; assert( pOp->p1>=0 && pOp->p1nCursor ); assert( memIsValid(pData) ); @@ -78761,6 +81684,7 @@ case OP_InsertInt: { assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0 ); assert( pC->isTable ); + assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC ); REGISTER_TRACE(pOp->p2, pData); if( pOp->opcode==OP_Insert ){ @@ -78768,28 +81692,52 @@ case OP_InsertInt: { assert( pKey->flags & MEM_Int ); assert( memIsValid(pKey) ); REGISTER_TRACE(pOp->p3, pKey); - iKey = pKey->u.i; + x.nKey = pKey->u.i; }else{ assert( pOp->opcode==OP_InsertInt ); - iKey = pOp->p3; + x.nKey = pOp->p3; + } + + 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) ); + op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); + }else{ + pTab = 0; /* Not needed. Silence a comiler warning. */ + zDb = 0; /* Not needed. Silence a compiler warning. */ } +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + /* Invoke the pre-update hook, if any */ + if( db->xPreUpdateCallback + && pOp->p4type==P4_TABLE + && !(pOp->p5 & OPFLAG_ISUPDATE) + ){ + sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey, pOp->p2); + } +#endif + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; - if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = iKey; + if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = x.nKey; if( pData->flags & MEM_Null ){ - pData->z = 0; - pData->n = 0; + x.pData = 0; + x.nData = 0; }else{ assert( pData->flags & (MEM_Blob|MEM_Str) ); + x.pData = pData->z; + x.nData = pData->n; } seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0); if( pData->flags & MEM_Zero ){ - nZero = pData->u.nZero; + x.nZero = pData->u.nZero; }else{ - nZero = 0; + x.nZero = 0; } - rc = sqlite3BtreeInsert(pC->uc.pCursor, 0, iKey, - pData->z, pData->n, nZero, + x.pKey = 0; + rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, (pOp->p5 & OPFLAG_APPEND)!=0, seekResult ); pC->deferredMoveto = 0; @@ -78797,18 +81745,13 @@ case OP_InsertInt: { /* Invoke the update-hook if required. */ if( rc ) goto abort_due_to_error; - if( db->xUpdateCallback && pOp->p4.z ){ - zDb = db->aDb[pC->iDb].zName; - zTbl = pOp->p4.z; - op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); - assert( pC->isTable ); - db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey); - assert( pC->iDb>=0 ); + if( db->xUpdateCallback && op ){ + db->xUpdateCallback(db->pUpdateArg, op, zDb, pTab->zName, x.nKey); } break; } -/* Opcode: Delete P1 P2 * P4 P5 +/* Opcode: Delete P1 P2 P3 P4 P5 ** ** Delete the record at which the P1 cursor is currently pointing. ** @@ -78832,15 +81775,24 @@ case OP_InsertInt: { ** P1 must not be pseudo-table. It has to be a real table with ** multiple rows. ** -** If P4 is not NULL, then it is the name of the table that P1 is -** pointing to. The update hook will be invoked, if it exists. -** If P4 is not NULL then the P1 cursor must have been positioned -** using OP_NotFound prior to invoking this opcode. +** If P4 is not NULL then it points to a Table object. In this case either +** the update or pre-update hook, or both, may be invoked. The P1 cursor must +** have been positioned using OP_NotFound prior to invoking this opcode in +** this case. Specifically, if one is configured, the pre-update hook is +** invoked if P4 is not NULL. The update-hook is invoked if one is configured, +** P4 is not NULL, and the OPFLAG_NCHANGE flag is set in P2. +** +** If the OPFLAG_ISUPDATE flag is set in P2, then P3 contains the address +** of the memory cell that contains the value that the rowid of the row will +** be set to by the update. */ case OP_Delete: { VdbeCursor *pC; - u8 hasUpdateCallback; + const char *zDb; + Table *pTab; + int opflags; + opflags = pOp->p2; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); @@ -78848,22 +81800,47 @@ case OP_Delete: { assert( pC->uc.pCursor!=0 ); assert( pC->deferredMoveto==0 ); - hasUpdateCallback = db->xUpdateCallback && pOp->p4.z && pC->isTable; - if( pOp->p5 && hasUpdateCallback ){ - sqlite3BtreeKeySize(pC->uc.pCursor, &pC->movetoTarget); - } - #ifdef SQLITE_DEBUG - /* The seek operation that positioned the cursor prior to OP_Delete will - ** have also set the pC->movetoTarget field to the rowid of the row that - ** is being deleted */ - if( pOp->p4.z && pC->isTable && pOp->p5==0 ){ - i64 iKey = 0; - sqlite3BtreeKeySize(pC->uc.pCursor, &iKey); - assert( pC->movetoTarget==iKey ); + if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){ + /* If p5 is zero, the seek operation that positioned the cursor prior to + ** OP_Delete will have also set the pC->movetoTarget field to the rowid of + ** the row that is being deleted */ + i64 iKey = sqlite3BtreeIntegerKey(pC->uc.pCursor); + assert( pC->movetoTarget==iKey ); } #endif + /* If the update-hook or pre-update-hook will be invoked, set zDb to + ** the name of the db to pass as to it. Also set local pTab to a copy + ** of p4.pTab. Finally, if p5 is true, indicating that this cursor was + ** last moved with OP_Next or OP_Prev, not Seek or NotFound, set + ** VdbeCursor.movetoTarget to the current rowid. */ + if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ + assert( pC->iDb>=0 ); + assert( pOp->p4.pTab!=0 ); + zDb = db->aDb[pC->iDb].zDbSName; + pTab = pOp->p4.pTab; + if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){ + pC->movetoTarget = sqlite3BtreeIntegerKey(pC->uc.pCursor); + } + }else{ + zDb = 0; /* Not needed. Silence a compiler warning. */ + pTab = 0; /* Not needed. Silence a compiler warning. */ + } + +#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) ); + sqlite3VdbePreUpdateHook(p, pC, + (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, + zDb, pTab, pC->movetoTarget, + pOp->p3 + ); + } + if( opflags & OPFLAG_ISNOOP ) break; +#endif + /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 ); assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); @@ -78885,15 +81862,18 @@ case OP_Delete: { rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); pC->cacheStatus = CACHE_STALE; + if( rc ) goto abort_due_to_error; /* Invoke the update-hook if required. */ - if( rc ) goto abort_due_to_error; - if( hasUpdateCallback ){ - db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, - db->aDb[pC->iDb].zName, pOp->p4.z, pC->movetoTarget); - assert( pC->iDb>=0 ); + if( opflags & OPFLAG_NCHANGE ){ + p->nChange++; + if( db->xUpdateCallback && HasRowid(pTab) ){ + db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName, + pC->movetoTarget); + assert( pC->iDb>=0 ); + } } - if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; + break; } /* Opcode: ResetCount * * * * * @@ -78910,7 +81890,7 @@ case OP_ResetCount: { } /* Opcode: SorterCompare P1 P2 P3 P4 -** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2 +** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2 ** ** P1 is a sorter cursor. This instruction compares a prefix of the ** record blob in register P3 against a prefix of the entry that @@ -78995,7 +81975,6 @@ case OP_RowData: { VdbeCursor *pC; BtCursor *pCrsr; u32 n; - i64 n64; pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); @@ -79013,8 +81992,9 @@ case OP_RowData: { pCrsr = pC->uc.pCursor; /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists 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 + ** 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 ** would fail. Should this ever change (because of changes in the code ** generator) then the fix would be to insert a call to ** sqlite3VdbeCursorMoveto(). @@ -79026,20 +82006,9 @@ case OP_RowData: { if( rc!=SQLITE_OK ) goto abort_due_to_error; #endif - if( pC->isTable==0 ){ - assert( !pC->isTable ); - VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &n64); - assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ - if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - n = (u32)n64; - }else{ - VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &n); - assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ - if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } + n = sqlite3BtreePayloadSize(pCrsr); + if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; } testcase( n==0 ); if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){ @@ -79104,8 +82073,7 @@ case OP_Rowid: { /* out2 */ pOut->flags = MEM_Null; break; } - rc = sqlite3BtreeKeySize(pC->uc.pCursor, &v); - assert( rc==SQLITE_OK ); /* Always so because of CursorRestore() above */ + v = sqlite3BtreeIntegerKey(pC->uc.pCursor); } pOut->u.i = v; break; @@ -79380,8 +82348,7 @@ case OP_Next: /* jump */ case OP_SorterInsert: /* in2 */ case OP_IdxInsert: { /* in2 */ VdbeCursor *pC; - int nKey; - const char *zKey; + BtreePayload x; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; @@ -79397,9 +82364,9 @@ case OP_IdxInsert: { /* in2 */ if( pOp->opcode==OP_SorterInsert ){ rc = sqlite3VdbeSorterWrite(pC, pIn2); }else{ - nKey = pIn2->n; - zKey = pIn2->z; - rc = sqlite3BtreeInsert(pC->uc.pCursor, zKey, nKey, "", 0, 0, pOp->p3, + x.nKey = pIn2->n; + x.pKey = pIn2->z; + rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, pOp->p3, ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) ); assert( pC->deferredMoveto==0 ); @@ -79447,7 +82414,7 @@ case OP_IdxDelete: { } /* Opcode: Seek P1 * P3 P4 * -** Synopsis: Move P3 to P1.rowid +** Synopsis: Move P3 to P1.rowid ** ** 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 @@ -79818,7 +82785,7 @@ case OP_ParseSchema: { initData.pzErrMsg = &p->zErrMsg; zSql = sqlite3MPrintf(db, "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", - db->aDb[iDb].zName, zMaster, pOp->p4.z); + db->aDb[iDb].zDbSName, zMaster, pOp->p4.z); if( zSql==0 ){ rc = SQLITE_NOMEM_BKPT; }else{ @@ -79954,7 +82921,7 @@ case OP_IntegrityCk: { #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* Opcode: RowSetAdd P1 P2 * * * -** Synopsis: rowset(P1)=r[P2] +** Synopsis: rowset(P1)=r[P2] ** ** Insert the integer value held by register P2 into a boolean index ** held in register P1. @@ -79974,7 +82941,7 @@ case OP_RowSetAdd: { /* in1, in2 */ } /* Opcode: RowSetRead P1 P2 P3 * * -** Synopsis: r[P3]=rowset(P1) +** 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 @@ -80123,8 +83090,7 @@ case OP_Program: { /* jump */ if( pProgram->nCsr==0 ) nMem++; nByte = ROUND8(sizeof(VdbeFrame)) + nMem * sizeof(Mem) - + pProgram->nCsr * sizeof(VdbeCursor *) - + pProgram->nOnce * sizeof(u8); + + pProgram->nCsr * sizeof(VdbeCursor *); pFrame = sqlite3DbMallocZero(db, nByte); if( !pFrame ){ goto no_mem; @@ -80144,8 +83110,6 @@ case OP_Program: { /* jump */ pFrame->aOp = p->aOp; pFrame->nOp = p->nOp; pFrame->token = pProgram->token; - pFrame->aOnceFlag = p->aOnceFlag; - pFrame->nOnceFlag = p->nOnceFlag; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS pFrame->anExec = p->anExec; #endif @@ -80179,13 +83143,10 @@ case OP_Program: { /* jump */ p->apCsr = (VdbeCursor **)&aMem[p->nMem]; p->aOp = aOp = pProgram->aOp; p->nOp = pProgram->nOp; - p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor]; - p->nOnceFlag = pProgram->nOnce; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS p->anExec = 0; #endif pOp = &aOp[-1]; - memset(p->aOnceFlag, 0, p->nOnceFlag); break; } @@ -80373,21 +83334,6 @@ case OP_DecrJumpZero: { /* jump, in1 */ } -/* Opcode: JumpZeroIncr P1 P2 * * * -** Synopsis: if (r[P1]++)==0 ) goto P2 -** -** The register P1 must contain an integer. If register P1 is initially -** zero, then jump to P2. Increment register P1 regardless of whether or -** not the jump is taken. -*/ -case OP_JumpZeroIncr: { /* jump, in1 */ - pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags&MEM_Int ); - VdbeBranchTaken(pIn1->u.i==0, 2); - if( (pIn1->u.i++)==0 ) goto jump_to_p2; - break; -} - /* Opcode: AggStep0 * P2 P3 P4 P5 ** Synopsis: accum=r[P3] step(r[P2@P5]) ** @@ -80662,15 +83608,14 @@ case OP_JournalMode: { /* out2 */ #endif /* SQLITE_OMIT_PRAGMA */ #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) -/* Opcode: Vacuum * * * * * +/* Opcode: Vacuum P1 * * * * ** -** Vacuum the entire database. This opcode will cause other virtual -** machines to be created and run. It may not be called from within -** a transaction. +** Vacuum the entire database P1. P1 is 0 for "main", and 2 or more +** for an attached database. The "temp" database may not be vacuumed. */ case OP_Vacuum: { assert( p->readOnly==0 ); - rc = sqlite3RunVacuum(&p->zErrMsg, db); + rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1); if( rc ) goto abort_due_to_error; break; } @@ -81168,8 +84113,8 @@ case OP_MaxPgcnt: { /* out2 */ #endif -/* Opcode: Init * P2 * P4 * -** Synopsis: Start at P2 +/* Opcode: Init P1 P2 * P4 * +** Synopsis: Start at P2 ** ** Programs contain a single instance of this opcode as the very first ** opcode. @@ -81179,27 +84124,50 @@ case OP_MaxPgcnt: { /* out2 */ ** Or if P4 is blank, use the string returned by sqlite3_sql(). ** ** If P2 is not zero, jump to instruction P2. +** +** Increment the value of P1 so that OP_Once opcodes will jump the +** first time they are evaluated for this run. */ case OP_Init: { /* jump */ char *zTrace; - char *z; + int i; + + /* If the P4 argument is not NULL, then it must be an SQL comment string. + ** The "--" string is broken up to prevent false-positives with srcck1.c. + ** + ** This assert() provides evidence for: + ** EVIDENCE-OF: R-50676-09860 The callback can compute the same text that + ** would have been returned by the legacy sqlite3_trace() interface by + ** using the X argument when X begins with "--" and invoking + ** sqlite3_expanded_sql(P) otherwise. + */ + assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 ); + assert( pOp==p->aOp ); /* Always instruction 0 */ #ifndef SQLITE_OMIT_TRACE - if( db->xTrace + if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0 && !p->doingRerun && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){ - z = sqlite3VdbeExpandSql(p, zTrace); - db->xTrace(db->pTraceArg, z); - sqlite3DbFree(db, z); +#ifndef SQLITE_OMIT_DEPRECATED + if( db->mTrace & SQLITE_TRACE_LEGACY ){ + void (*x)(void*,const char*) = (void(*)(void*,const char*))db->xTrace; + char *z = sqlite3VdbeExpandSql(p, zTrace); + x(db->pTraceArg, z); + sqlite3_free(z); + }else +#endif + { + (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace); + } } #ifdef SQLITE_USE_FCNTL_TRACE zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); if( zTrace ){ - int i; - for(i=0; inDb; i++){ - if( DbMaskTest(p->btreeMask, i)==0 ) continue; - sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace); + int j; + for(j=0; jnDb; j++){ + if( DbMaskTest(p->btreeMask, j)==0 ) continue; + sqlite3_file_control(db, db->aDb[j].zDbSName, SQLITE_FCNTL_TRACE, zTrace); } } #endif /* SQLITE_USE_FCNTL_TRACE */ @@ -81211,8 +84179,15 @@ case OP_Init: { /* jump */ } #endif /* SQLITE_DEBUG */ #endif /* SQLITE_OMIT_TRACE */ - if( pOp->p2 ) goto jump_to_p2; - break; + assert( pOp->p2>0 ); + if( pOp->p1>=sqlite3GlobalConfig.iOnceResetThreshold ){ + for(i=1; inOp; i++){ + if( p->aOp[i].opcode==OP_Once ) p->aOp[i].p1 = 0; + } + pOp->p1 = 0; + } + pOp->p1++; + goto jump_to_p2; } #ifdef SQLITE_ENABLE_CURSOR_HINTS @@ -81280,11 +84255,12 @@ default: { /* This is really OP_Noop and OP_Explain */ #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeTrace ){ + u8 opProperty = sqlite3OpcodeProperty[pOrigOp->opcode]; if( rc!=0 ) printf("rc=%d\n",rc); - if( pOrigOp->opflags & (OPFLG_OUT2) ){ + if( opProperty & (OPFLG_OUT2) ){ registerTrace(pOrigOp->p2, &aMem[pOrigOp->p2]); } - if( pOrigOp->opflags & OPFLG_OUT3 ){ + if( opProperty & OPFLG_OUT3 ){ registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]); } } @@ -81388,6 +84364,8 @@ struct Incrblob { BtCursor *pCsr; /* Cursor pointing at blob row */ sqlite3_stmt *pStmt; /* Statement holding cursor open */ sqlite3 *db; /* The associated database */ + char *zDb; /* Database name */ + Table *pTab; /* Table object */ }; @@ -81462,7 +84440,7 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ /* ** Open a blob handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( +SQLITE_API int sqlite3_blob_open( sqlite3* db, /* The database connection */ const char *zDb, /* The attached database containing the blob */ const char *zTable, /* The table containing the blob */ @@ -81531,6 +84509,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( sqlite3BtreeLeaveAll(db); goto blob_open_out; } + pBlob->pTab = pTab; + pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName; /* Now search pTab for the exact column. */ for(iCol=0; iColnCol; iCol++) { @@ -81701,7 +84681,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( ** Close a blob handle that was previously created using ** sqlite3_blob_open(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *pBlob){ +SQLITE_API int sqlite3_blob_close(sqlite3_blob *pBlob){ Incrblob *p = (Incrblob *)pBlob; int rc; sqlite3 *db; @@ -81752,6 +84732,30 @@ static int blobReadWrite( */ assert( db == v->db ); sqlite3BtreeEnterCursor(p->pCsr); + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + if( xCall==sqlite3BtreePutData && db->xPreUpdateCallback ){ + /* If a pre-update hook is registered and this is a write cursor, + ** invoke it here. + ** + ** TODO: The preupdate-hook is passed SQLITE_DELETE, even though this + ** operation should really be an SQLITE_UPDATE. This is probably + ** incorrect, but is convenient because at this point the new.* values + ** are not easily obtainable. And for the sessions module, an + ** SQLITE_UPDATE where the PK columns do not change is handled in the + ** same way as an SQLITE_DELETE (the SQLITE_DELETE code is actually + ** slightly more efficient). Since you cannot write to a PK column + ** using the incremental-blob API, this works. For the sessions module + ** anyhow. + */ + sqlite3_int64 iKey; + iKey = sqlite3BtreeIntegerKey(p->pCsr); + sqlite3VdbePreUpdateHook( + v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1 + ); + } +#endif + rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); sqlite3BtreeLeaveCursor(p->pCsr); if( rc==SQLITE_ABORT ){ @@ -81770,14 +84774,14 @@ static int blobReadWrite( /* ** Read data from a blob handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ +SQLITE_API int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData); } /* ** Write data to a blob handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ +SQLITE_API int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData); } @@ -81787,7 +84791,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *pBlob, const void ** The Incrblob.nByte field is fixed for the lifetime of the Incrblob ** so no mutex is required for access. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *pBlob){ +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){ Incrblob *p = (Incrblob *)pBlob; return (p && p->pStmt) ? p->nByte : 0; } @@ -81802,7 +84806,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *pBlob){ ** subsequent calls to sqlite3_blob_xxx() functions (except blob_close()) ** immediately return SQLITE_ABORT. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ +SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ int rc; Incrblob *p = (Incrblob *)pBlob; sqlite3 *db; @@ -82769,7 +85773,6 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit( ){ int pgsz; /* Page size of main database */ int i; /* Used to iterate through aTask[] */ - int mxCache; /* Cache size */ VdbeSorter *pSorter; /* The new sorter */ KeyInfo *pKeyInfo; /* Copy of pCsr->pKeyInfo with db==0 */ int szKeyInfo; /* Size of pCsr->pKeyInfo in bytes */ @@ -82826,11 +85829,20 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit( } if( !sqlite3TempInMemory(db) ){ + i64 mxCache; /* Cache size in bytes*/ u32 szPma = sqlite3GlobalConfig.szPma; pSorter->mnPmaSize = szPma * pgsz; + mxCache = db->aDb[0].pSchema->cache_size; - if( mxCache<(int)szPma ) mxCache = (int)szPma; - pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ); + if( mxCache<0 ){ + /* A negative cache-size value C indicates that the cache is abs(C) + ** KiB in size. */ + mxCache = mxCache * -1024; + }else{ + mxCache = mxCache * pgsz; + } + mxCache = MIN(mxCache, SQLITE_MAX_PMASZ); + pSorter->mxPmaSize = MAX(pSorter->mnPmaSize, (int)mxCache); /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary @@ -83172,19 +86184,18 @@ static int vdbeSortAllocUnpacked(SortSubtask *pTask){ /* ** Merge the two sorted lists p1 and p2 into a single list. -** Set *ppOut to the head of the new list. */ -static void vdbeSorterMerge( +static SorterRecord *vdbeSorterMerge( SortSubtask *pTask, /* Calling thread context */ SorterRecord *p1, /* First list to merge */ - SorterRecord *p2, /* Second list to merge */ - SorterRecord **ppOut /* OUT: Head of merged list */ + SorterRecord *p2 /* Second list to merge */ ){ SorterRecord *pFinal = 0; SorterRecord **pp = &pFinal; int bCached = 0; - while( p1 && p2 ){ + assert( p1!=0 && p2!=0 ); + for(;;){ int res; res = pTask->xCompare( pTask, &bCached, SRVAL(p1), p1->nVal, SRVAL(p2), p2->nVal @@ -83194,15 +86205,22 @@ static void vdbeSorterMerge( *pp = p1; pp = &p1->u.pNext; p1 = p1->u.pNext; + if( p1==0 ){ + *pp = p2; + break; + } }else{ *pp = p2; pp = &p2->u.pNext; p2 = p2->u.pNext; bCached = 0; + if( p2==0 ){ + *pp = p1; + break; + } } } - *pp = p1 ? p1 : p2; - *ppOut = pFinal; + return pFinal; } /* @@ -83255,7 +86273,7 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){ p->u.pNext = 0; for(i=0; aSlot[i]; i++){ - vdbeSorterMerge(pTask, p, aSlot[i], &p); + p = vdbeSorterMerge(pTask, p, aSlot[i]); aSlot[i] = 0; } aSlot[i] = p; @@ -83264,7 +86282,8 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){ p = 0; for(i=0; i<64; i++){ - vdbeSorterMerge(pTask, p, aSlot[i], &p); + if( aSlot[i]==0 ) continue; + p = p ? vdbeSorterMerge(pTask, p, aSlot[i]) : aSlot[i]; } pList->pList = p; @@ -84594,6 +87613,15 @@ SQLITE_PRIVATE int sqlite3VdbeSorterCompare( ** This file contains code use to implement an in-memory rollback journal. ** The in-memory rollback journal is used to journal transactions for ** ":memory:" databases and when the journal_mode=MEMORY pragma is used. +** +** Update: The in-memory journal is also used to temporarily cache +** smaller journals that are not critical for power-loss recovery. +** For example, statement journals that are not too big will be held +** entirely in memory, thus reducing the number of file I/O calls, and +** more importantly, reducing temporary file creation events. If these +** journals become too large for memory, they are spilled to disk. But +** in the common case, they are usually small and no file I/O needs to +** occur. */ /* #include "sqliteInt.h" */ @@ -85034,17 +88062,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==WRC_Continue - && !ExprHasProperty(pExpr,EP_TokenOnly) ){ - if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; - if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; - }else{ - if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; - } + if( rc || ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ + return rc & WRC_Abort; } - 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; + } + return WRC_Continue; } SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){ return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue; @@ -85378,8 +88406,8 @@ static int lookupName( zDb = 0; }else{ for(i=0; inDb; i++){ - assert( db->aDb[i].zName ); - if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){ + assert( db->aDb[i].zDbSName ); + if( sqlite3StrICmp(db->aDb[i].zDbSName,zDb)==0 ){ pSchema = db->aDb[i].pSchema; break; } @@ -85557,6 +88585,10 @@ static int lookupName( sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); return WRC_Abort; } + if( sqlite3ExprVectorSize(pOrig)!=1 ){ + sqlite3ErrorMsg(pParse, "row value misused"); + return WRC_Abort; + } resolveAlias(pParse, pEList, j, pExpr, "", nSubquery); cnt = 1; pMatch = 0; @@ -85780,7 +88812,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ /* if( pSrcList==0 ) break; */ notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); - /*notValid(pParse, pNC, "the \".\" operator", NC_PartIdx|NC_IsCheck, 1);*/ pRight = pExpr->pRight; if( pRight->op==TK_ID ){ zDb = 0; @@ -85803,14 +88834,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ int no_such_func = 0; /* True if no such function exists */ int wrong_num_args = 0; /* True if wrong number of arguments */ int is_agg = 0; /* True if is an aggregate function */ - int auth; /* Authorization to use the function */ int nId; /* Number of characters in function name */ const char *zId; /* The function name. */ FuncDef *pDef; /* Information about the function */ u8 enc = ENC(pParse->db); /* The database encoding */ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - notValid(pParse, pNC, "functions", NC_PartIdx); zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); @@ -85847,15 +88876,17 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } } #ifndef SQLITE_OMIT_AUTHORIZATION - auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); - if( auth!=SQLITE_OK ){ - if( auth==SQLITE_DENY ){ - sqlite3ErrorMsg(pParse, "not authorized to use function: %s", - pDef->zName); - pNC->nErr++; + { + int auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0); + if( auth!=SQLITE_OK ){ + if( auth==SQLITE_DENY ){ + sqlite3ErrorMsg(pParse, "not authorized to use function: %s", + pDef->zName); + pNC->nErr++; + } + pExpr->op = TK_NULL; + return WRC_Prune; } - pExpr->op = TK_NULL; - return WRC_Prune; } #endif if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){ @@ -85868,14 +88899,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ /* Date/time functions that use 'now', and other functions like ** sqlite_version() that might change over time cannot be used ** in an index. */ - notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr); + notValid(pParse, pNC, "non-deterministic functions", + NC_IdxExpr|NC_PartIdx); } } if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); pNC->nErr++; is_agg = 0; - }else if( no_such_func && pParse->db->init.busy==0 ){ + }else if( no_such_func && pParse->db->init.busy==0 +#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION + && pParse->explain==0 +#endif + ){ sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); pNC->nErr++; }else if( wrong_num_args ){ @@ -85920,6 +88956,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ ExprSetProperty(pExpr, EP_VarSelect); + pNC->ncFlags |= NC_VarSelect; } } break; @@ -85928,6 +88965,42 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr); break; } + case TK_BETWEEN: + case TK_EQ: + case TK_NE: + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_IS: + case TK_ISNOT: { + int nLeft, nRight; + if( pParse->db->mallocFailed ) break; + assert( pExpr->pLeft!=0 ); + nLeft = sqlite3ExprVectorSize(pExpr->pLeft); + if( pExpr->op==TK_BETWEEN ){ + nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr); + if( nRight==nLeft ){ + nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr); + } + }else{ + assert( pExpr->pRight!=0 ); + nRight = sqlite3ExprVectorSize(pExpr->pRight); + } + if( nLeft!=nRight ){ + testcase( pExpr->op==TK_EQ ); + testcase( pExpr->op==TK_NE ); + testcase( pExpr->op==TK_LT ); + testcase( pExpr->op==TK_LE ); + testcase( pExpr->op==TK_GT ); + testcase( pExpr->op==TK_GE ); + testcase( pExpr->op==TK_IS ); + testcase( pExpr->op==TK_ISNOT ); + testcase( pExpr->op==TK_BETWEEN ); + sqlite3ErrorMsg(pParse, "row value misused"); + } + break; + } } return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue; } @@ -86670,6 +89743,18 @@ SQLITE_PRIVATE void sqlite3ResolveSelfReference( */ /* #include "sqliteInt.h" */ +/* Forward declarations */ +static void exprCodeBetween(Parse*,Expr*,int,void(*)(Parse*,Expr*,int,int),int); +static int exprCodeVector(Parse *pParse, Expr *p, int *piToFree); + +/* +** Return the affinity character for a single column of a table. +*/ +SQLITE_PRIVATE char sqlite3TableColumnAffinity(Table *pTab, int iCol){ + assert( iColnCol ); + return iCol>=0 ? pTab->aCol[iCol].affinity : SQLITE_AFF_INTEGER; +} + /* ** Return the 'affinity' of the expression pExpr if any. ** @@ -86695,21 +89780,21 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ assert( pExpr->flags&EP_xIsSelect ); return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); } + if( op==TK_REGISTER ) op = pExpr->op2; #ifndef SQLITE_OMIT_CAST if( op==TK_CAST ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); return sqlite3AffinityType(pExpr->u.zToken, 0); } #endif - if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) - && pExpr->pTab!=0 - ){ - /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally - ** a TK_COLUMN but was previously evaluated and cached in a register */ - int j = pExpr->iColumn; - if( j<0 ) return SQLITE_AFF_INTEGER; - assert( pExpr->pTab && jpTab->nCol ); - return pExpr->pTab->aCol[j].affinity; + if( op==TK_AGG_COLUMN || op==TK_COLUMN ){ + return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); + } + if( op==TK_SELECT_COLUMN ){ + assert( pExpr->pLeft->flags&EP_xIsSelect ); + return sqlite3ExprAffinity( + pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr + ); } return pExpr->affinity; } @@ -86875,7 +89960,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( !aff ){ + }else if( NEVER(aff==0) ){ aff = SQLITE_AFF_BLOB; } return aff; @@ -86965,6 +90050,270 @@ static int codeCompare( return addr; } +/* +** Return true if expression pExpr is a vector, or false otherwise. +** +** A vector is defined as any expression that results in two or more +** columns of result. Every TK_VECTOR node is an vector because the +** parser will not generate a TK_VECTOR with fewer than two entries. +** But a TK_SELECT might be either a vector or a scalar. It is only +** considered a vector if it has two or more result columns. +*/ +SQLITE_PRIVATE int sqlite3ExprIsVector(Expr *pExpr){ + return sqlite3ExprVectorSize(pExpr)>1; +} + +/* +** If the expression passed as the only argument is of type TK_VECTOR +** return the number of expressions in the vector. Or, if the expression +** is a sub-select, return the number of columns in the sub-select. For +** any other type of expression, return 1. +*/ +SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr){ + u8 op = pExpr->op; + if( op==TK_REGISTER ) op = pExpr->op2; + if( op==TK_VECTOR ){ + return pExpr->x.pList->nExpr; + }else if( op==TK_SELECT ){ + return pExpr->x.pSelect->pEList->nExpr; + }else{ + return 1; + } +} + +#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 +** ensure that i is within range. +** +** If pVector is really a scalar (and "scalar" here includes subqueries +** that return a single column!) then return pVector unmodified. +** +** pVector retains ownership of the returned subexpression. +** +** If the vector is a (SELECT ...) then the expression returned is +** just the expression for the i-th term of the result set, and may +** not be ready for evaluation because the table cursor has not yet +** been positioned. +*/ +SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){ + assert( iop2==0 || pVector->op==TK_REGISTER ); + if( pVector->op==TK_SELECT || pVector->op2==TK_SELECT ){ + return pVector->x.pSelect->pEList->a[i].pExpr; + }else{ + return pVector->x.pList->a[i].pExpr; + } + } + 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 +** the iField-th column of the vector expression pVector. +** +** It is ok for pVector to be a scalar (as long as iField==0). +** In that case, this routine works like sqlite3ExprDup(). +** +** The caller owns the returned Expr object and is responsible for +** ensuring that the returned value eventually gets freed. +** +** The caller retains ownership of pVector. If pVector is a TK_SELECT, +** then the returned object will reference pVector and so pVector must remain +** valid for the life of the returned object. If pVector is a TK_VECTOR +** or a scalar expression, then it can be deleted as soon as this routine +** returns. +** +** A trick to cause a TK_SELECT pVector to be deleted together with +** the returned Expr object is to attach the pVector to the pRight field +** of the returned TK_SELECT_COLUMN Expr object. +*/ +SQLITE_PRIVATE Expr *sqlite3ExprForVectorField( + Parse *pParse, /* Parsing context */ + Expr *pVector, /* The vector. List of expressions or a sub-SELECT */ + int iField /* Which column of the vector to return */ +){ + Expr *pRet; + if( pVector->op==TK_SELECT ){ + assert( pVector->flags & EP_xIsSelect ); + /* The TK_SELECT_COLUMN Expr node: + ** + ** pLeft: pVector containing TK_SELECT + ** pRight: not used. But recursively deleted. + ** iColumn: Index of a column in pVector + ** pLeft->iTable: First in an array of register holding result, or 0 + ** if the result is not yet computed. + ** + ** sqlite3ExprDelete() specifically skips the recursive delete of + ** pLeft on TK_SELECT_COLUMN nodes. But pRight is followed, so pVector + ** can be attached to pRight to cause this node to take ownership of + ** pVector. Typically there will be multiple TK_SELECT_COLUMN nodes + ** 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); + if( pRet ){ + pRet->iColumn = iField; + pRet->pLeft = pVector; + } + assert( pRet==0 || pRet->iTable==0 ); + }else{ + if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr; + pRet = sqlite3ExprDup(pParse->db, pVector, 0); + } + return pRet; +} +#endif /* !define(SQLITE_OMIT_SUBQUERY) */ + +/* +** If expression pExpr is of type TK_SELECT, generate code to evaluate +** it. Return the register in which the result is stored (or, if the +** sub-select returns more than one column, the first in an array +** of registers in which the result is stored). +** +** If pExpr is not a TK_SELECT expression, return 0. +*/ +static int exprCodeSubselect(Parse *pParse, Expr *pExpr){ + int reg = 0; +#ifndef SQLITE_OMIT_SUBQUERY + if( pExpr->op==TK_SELECT ){ + reg = sqlite3CodeSubselect(pParse, pExpr, 0, 0); + } +#endif + return reg; +} + +/* +** Argument pVector points to a vector expression - either a TK_VECTOR +** or TK_SELECT that returns more than one column. This function returns +** the register number of a register that contains the value of +** element iField of the vector. +** +** If pVector is a TK_SELECT expression, then code for it must have +** already been generated using the exprCodeSubselect() routine. In this +** case parameter regSelect should be the first in an array of registers +** containing the results of the sub-select. +** +** If pVector is of type TK_VECTOR, then code for the requested field +** is generated. In this case (*pRegFree) may be set to the number of +** a temporary register to be freed by the caller before returning. +** +** Before returning, output parameter (*ppExpr) is set to point to the +** Expr object corresponding to element iElem of the vector. +*/ +static int exprVectorRegister( + Parse *pParse, /* Parse context */ + Expr *pVector, /* Vector to extract element from */ + int iField, /* Field to extract from pVector */ + int regSelect, /* First in array of registers */ + Expr **ppExpr, /* OUT: Expression element */ + int *pRegFree /* OUT: Temp register to free */ +){ + u8 op = pVector->op; + assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT ); + if( op==TK_REGISTER ){ + *ppExpr = sqlite3VectorFieldSubexpr(pVector, iField); + return pVector->iTable+iField; + } + if( op==TK_SELECT ){ + *ppExpr = pVector->x.pSelect->pEList->a[iField].pExpr; + return regSelect+iField; + } + *ppExpr = pVector->x.pList->a[iField].pExpr; + return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree); +} + +/* +** Expression pExpr is a comparison between two vector values. Compute +** the result of the comparison (1, 0, or NULL) and write that +** result into register dest. +** +** The caller must satisfy the following preconditions: +** +** if pExpr->op==TK_IS: op==TK_EQ and p5==SQLITE_NULLEQ +** if pExpr->op==TK_ISNOT: op==TK_NE and p5==SQLITE_NULLEQ +** otherwise: op==pExpr->op and p5==0 +*/ +static void codeVectorCompare( + Parse *pParse, /* Code generator context */ + Expr *pExpr, /* The comparison operation */ + int dest, /* Write results into this register */ + u8 op, /* Comparison operator */ + u8 p5 /* SQLITE_NULLEQ or zero */ +){ + Vdbe *v = pParse->pVdbe; + Expr *pLeft = pExpr->pLeft; + Expr *pRight = pExpr->pRight; + int nLeft = sqlite3ExprVectorSize(pLeft); + int i; + int regLeft = 0; + int regRight = 0; + u8 opx = op; + int addrDone = sqlite3VdbeMakeLabel(v); + + assert( nLeft==sqlite3ExprVectorSize(pRight) ); + 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 + || pExpr->op==TK_LE || pExpr->op==TK_GE + ); + assert( pExpr->op==op || (pExpr->op==TK_IS && op==TK_EQ) + || (pExpr->op==TK_ISNOT && op==TK_NE) ); + assert( p5==0 || pExpr->op!=op ); + assert( p5==SQLITE_NULLEQ || pExpr->op==op ); + + p5 |= SQLITE_STOREP2; + if( opx==TK_LE ) opx = TK_LT; + if( opx==TK_GE ) opx = TK_GT; + + regLeft = exprCodeSubselect(pParse, pLeft); + regRight = exprCodeSubselect(pParse, pRight); + + for(i=0; 1 /*Loop exits by "break"*/; i++){ + int regFree1 = 0, regFree2 = 0; + Expr *pL, *pR; + int r1, r2; + assert( i>=0 && i0 ) sqlite3ExprCachePush(pParse); + r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, ®Free1); + r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2); + codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5); + testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); + if( i>0 ) sqlite3ExprCachePop(pParse); + if( i==nLeft-1 ){ + break; + } + if( opx==TK_EQ ){ + sqlite3VdbeAddOp2(v, OP_IfNot, dest, addrDone); VdbeCoverage(v); + p5 |= SQLITE_KEEPNULL; + }else if( opx==TK_NE ){ + sqlite3VdbeAddOp2(v, OP_If, dest, addrDone); VdbeCoverage(v); + p5 |= SQLITE_KEEPNULL; + }else{ + assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE ); + sqlite3VdbeAddOp2(v, OP_ElseNotEq, 0, addrDone); + VdbeCoverageIf(v, op==TK_LT); + VdbeCoverageIf(v, op==TK_GT); + VdbeCoverageIf(v, op==TK_LE); + VdbeCoverageIf(v, op==TK_GE); + if( i==nLeft-2 ) opx = op; + } + } + sqlite3VdbeResolveLabel(v, addrDone); +} + #if SQLITE_MAX_EXPR_DEPTH>0 /* ** Check that argument nHeight is less than or equal to the maximum @@ -87100,7 +90449,7 @@ SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ ** is allocated to hold the integer text and the dequote flag is ignored. */ SQLITE_PRIVATE Expr *sqlite3ExprAlloc( - sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ + sqlite3 *db, /* Handle for sqlite3DbMallocRawNN() */ int op, /* Expression opcode */ const Token *pToken, /* Token argument. Might be NULL */ int dequote /* True to dequote */ @@ -87127,15 +90476,13 @@ SQLITE_PRIVATE Expr *sqlite3ExprAlloc( pNew->flags |= EP_IntValue; pNew->u.iValue = iValue; }else{ - int c; pNew->u.zToken = (char*)&pNew[1]; assert( pToken->z!=0 || pToken->n==0 ); if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n); pNew->u.zToken[pToken->n] = 0; - if( dequote && nExtra>=3 - && ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){ + if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){ + if( pNew->u.zToken[0]=='"' ) pNew->flags |= EP_DblQuoted; sqlite3Dequote(pNew->u.zToken); - if( c=='"' ) pNew->flags |= EP_DblQuoted; } } } @@ -87218,6 +90565,22 @@ SQLITE_PRIVATE Expr *sqlite3PExpr( return p; } +/* +** Add pSelect to the Expr.x.pSelect field. Or, if pExpr is NULL (due +** do a memory allocation failure) then delete the pSelect object. +*/ +SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){ + if( pExpr ){ + pExpr->x.pSelect = pSelect; + ExprSetProperty(pExpr, EP_xIsSelect|EP_Subquery); + sqlite3ExprSetHeightAndFlags(pParse, pExpr); + }else{ + assert( pParse->db->mallocFailed ); + sqlite3SelectDelete(pParse->db, pSelect); + } +} + + /* ** If the expression is always either TRUE or FALSE (respectively), ** then return 1. If one cannot determine the truth value of the @@ -87304,7 +90667,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token * ** instance of the wildcard, the next sequential variable number is ** assigned. */ -SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ +SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){ sqlite3 *db = pParse->db; const char *z; @@ -87313,19 +90676,19 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ z = pExpr->u.zToken; assert( z!=0 ); assert( z[0]!=0 ); + assert( n==sqlite3Strlen30(z) ); if( z[1]==0 ){ /* Wildcard of the form "?". Assign the next variable number */ assert( z[0]=='?' ); pExpr->iColumn = (ynVar)(++pParse->nVar); }else{ - ynVar x = 0; - u32 n = sqlite3Strlen30(z); + ynVar x; 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); - pExpr->iColumn = x = (ynVar)i; + x = (ynVar)i; testcase( i==0 ); testcase( i==1 ); testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); @@ -87333,7 +90696,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); - x = 0; + return; } if( i>pParse->nVar ){ pParse->nVar = (int)i; @@ -87344,33 +90707,31 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ ** has never appeared before, reuse the same variable number */ ynVar i; - for(i=0; inzVar; i++){ + for(i=x=0; inzVar; i++){ if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){ - pExpr->iColumn = x = (ynVar)i+1; + x = (ynVar)i+1; break; } } - if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar); + if( x==0 ) x = (ynVar)(++pParse->nVar); } - if( x>0 ){ - 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( z[0]!='?' || pParse->azVar[x-1]==0 ){ - sqlite3DbFree(db, pParse->azVar[x-1]); - pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n); + 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( pParse->azVar[x-1]==0 ){ + pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n); } } - if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ + if( pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "too many SQL variables"); } } @@ -87378,26 +90739,36 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ /* ** Recursively delete an expression tree. */ -SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){ - if( p==0 ) return; +static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ + assert( p!=0 ); /* Sanity check: Assert that the IntValue is non-negative if it exists */ assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); - if( !ExprHasProperty(p, EP_TokenOnly) ){ +#ifdef SQLITE_DEBUG + if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ + assert( p->pLeft==0 ); + assert( p->pRight==0 ); + assert( p->x.pSelect==0 ); + } +#endif + if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){ /* The Expr.x union is never used at the same time as Expr.pRight */ assert( p->x.pList==0 || p->pRight==0 ); - sqlite3ExprDelete(db, p->pLeft); + if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft); sqlite3ExprDelete(db, p->pRight); - if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); if( ExprHasProperty(p, EP_xIsSelect) ){ sqlite3SelectDelete(db, p->x.pSelect); }else{ sqlite3ExprListDelete(db, p->x.pList); } } + if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); if( !ExprHasProperty(p, EP_Static) ){ sqlite3DbFree(db, p); } } +SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){ + if( p ) sqlite3ExprDeleteNN(db, p); +} /* ** Return the number of bytes allocated for the expression structure @@ -87449,7 +90820,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&EXPRDUP_REDUCE) ){ + if( 0==flags ){ nSize = EXPR_FULLSIZE; }else{ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); @@ -87511,88 +90882,92 @@ static int dupedExprSize(Expr *p, int flags){ ** if any. Before returning, *pzBuffer is set to the first byte past the ** portion of the buffer copied into by this function. */ -static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ - Expr *pNew = 0; /* Value to return */ - assert( flags==0 || flags==EXPRDUP_REDUCE ); +static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ + Expr *pNew; /* Value to return */ + u8 *zAlloc; /* Memory space from which to build Expr object */ + u32 staticFlag; /* EP_Static if space not obtained from malloc */ + assert( db!=0 ); - if( p ){ - const int isReduced = (flags&EXPRDUP_REDUCE); - u8 *zAlloc; - u32 staticFlag = 0; + assert( p ); + assert( dupFlags==0 || dupFlags==EXPRDUP_REDUCE ); + assert( pzBuffer==0 || dupFlags==EXPRDUP_REDUCE ); - assert( pzBuffer==0 || isReduced ); + /* Figure out where to write the new Expr structure. */ + if( pzBuffer ){ + zAlloc = *pzBuffer; + staticFlag = EP_Static; + }else{ + zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags)); + staticFlag = 0; + } + pNew = (Expr *)zAlloc; - /* Figure out where to write the new Expr structure. */ - if( pzBuffer ){ - zAlloc = *pzBuffer; - staticFlag = EP_Static; + if( pNew ){ + /* Set nNewSize to the size allocated for the structure pointed to + ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or + ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed + ** by the copy of the p->u.zToken string (if any). + */ + const unsigned nStructSize = dupedExprStructSize(p, dupFlags); + const int nNewSize = nStructSize & 0xfff; + int nToken; + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + nToken = sqlite3Strlen30(p->u.zToken) + 1; }else{ - zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, flags)); + nToken = 0; } - pNew = (Expr *)zAlloc; - - if( pNew ){ - /* Set nNewSize to the size allocated for the structure pointed to - ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or - ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed - ** by the copy of the p->u.zToken string (if any). - */ - const unsigned nStructSize = dupedExprStructSize(p, flags); - const int nNewSize = nStructSize & 0xfff; - int nToken; - if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ - nToken = sqlite3Strlen30(p->u.zToken) + 1; - }else{ - nToken = 0; - } - if( isReduced ){ - assert( ExprHasProperty(p, EP_Reduced)==0 ); - memcpy(zAlloc, p, nNewSize); - }else{ - u32 nSize = (u32)exprStructSize(p); - memcpy(zAlloc, p, nSize); - if( nSizeflags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken); - pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly); - pNew->flags |= staticFlag; + /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */ + pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken); + pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly); + pNew->flags |= staticFlag; - /* Copy the p->u.zToken string, if any. */ - if( nToken ){ - char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; - memcpy(zToken, p->u.zToken, nToken); - } + /* Copy the p->u.zToken string, if any. */ + if( nToken ){ + char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; + memcpy(zToken, p->u.zToken, nToken); + } - if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){ - /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ - if( ExprHasProperty(p, EP_xIsSelect) ){ - pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced); - }else{ - pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, isReduced); - } + if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){ + /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ + if( ExprHasProperty(p, EP_xIsSelect) ){ + pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); + }else{ + pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags); } + } - /* Fill in pNew->pLeft and pNew->pRight. */ - if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ - zAlloc += dupedExprNodeSize(p, flags); - if( ExprHasProperty(pNew, EP_Reduced) ){ - pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc); - pNew->pRight = exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc); - } - if( pzBuffer ){ - *pzBuffer = zAlloc; - } - }else{ - if( !ExprHasProperty(p, EP_TokenOnly) ){ + /* Fill in pNew->pLeft and pNew->pRight. */ + if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ + zAlloc += dupedExprNodeSize(p, dupFlags); + if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ + pNew->pLeft = p->pLeft ? + exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; + pNew->pRight = p->pRight ? + exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; + } + if( pzBuffer ){ + *pzBuffer = zAlloc; + } + }else{ + if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ + if( pNew->op==TK_SELECT_COLUMN ){ + pNew->pLeft = p->pLeft; + }else{ pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); - pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); } + pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); } - } } return pNew; @@ -87644,7 +91019,7 @@ static With *withDup(sqlite3 *db, With *p){ */ SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){ assert( flags==0 || flags==EXPRDUP_REDUCE ); - return exprDup(db, p, flags, 0); + return p ? exprDup(db, p, flags, 0) : 0; } SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ ExprList *pNew; @@ -87831,6 +91206,60 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend( return 0; } +/* +** pColumns and pExpr form a vector assignment which is part of the SET +** clause of an UPDATE statement. Like this: +** +** (a,b,c) = (expr1,expr2,expr3) +** 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 +** TK_SELECT_COLUMN expressions. +*/ +SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List to which to append. Might be NULL */ + IdList *pColumns, /* List of names of LHS of the assignment */ + Expr *pExpr /* Vector expression to be appended. Might be NULL */ +){ + sqlite3 *db = pParse->db; + int n; + int i; + int iFirst = pList ? pList->nExpr : 0; + /* pColumns can only be NULL due to an OOM but an OOM will cause an + ** 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 ){ + sqlite3ErrorMsg(pParse, "%d columns assigned %d values", + pColumns->nId, n); + goto vector_append_error; + } + for(i=0; inExpr==iFirst+i+1 ); + pList->a[pList->nExpr-1].zName = pColumns->a[i].zName; + 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; + } + } + +vector_append_error: + sqlite3ExprDelete(db, pExpr); + sqlite3IdListDelete(db, pColumns); + return pList; +} + /* ** Set the sort order for the last element on the given ExprList. */ @@ -87866,7 +91295,7 @@ SQLITE_PRIVATE void sqlite3ExprListSetName( pItem = &pList->a[pList->nExpr-1]; assert( pItem->zName==0 ); pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n); - if( dequote && pItem->zName ) sqlite3Dequote(pItem->zName); + if( dequote ) sqlite3Dequote(pItem->zName); } } @@ -87915,10 +91344,9 @@ SQLITE_PRIVATE void sqlite3ExprListCheckLength( /* ** Delete an entire expression list. */ -SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ +static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){ int i; struct ExprList_item *pItem; - if( pList==0 ) return; assert( pList->a!=0 || pList->nExpr==0 ); for(pItem=pList->a, i=0; inExpr; i++, pItem++){ sqlite3ExprDelete(db, pItem->pExpr); @@ -87928,6 +91356,9 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ sqlite3DbFree(db, pList->a); sqlite3DbFree(db, pList); } +SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ + if( pList ) exprListDeleteNN(db, pList); +} /* ** Return the bitwise-OR of all Expr.flags fields in the given @@ -88236,8 +91667,8 @@ static Select *isCandidateForInOpt(Expr *pX){ Select *p; SrcList *pSrc; ExprList *pEList; - Expr *pRes; Table *pTab; + int i; if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0; /* Not a subquery */ if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */ p = pX->x.pSelect; @@ -88260,23 +91691,18 @@ static Select *isCandidateForInOpt(Expr *pX){ assert( pTab->pSelect==0 ); /* FROM clause is not a view */ if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */ pEList = p->pEList; - if( pEList->nExpr!=1 ) return 0; /* One column in the result set */ - pRes = pEList->a[0].pExpr; - if( pRes->op!=TK_COLUMN ) return 0; /* Result is a column */ - assert( pRes->iTable==pSrc->a[0].iCursor ); /* Not a correlated subquery */ + assert( pEList!=0 ); + /* All SELECT results must be columns. */ + for(i=0; inExpr; i++){ + Expr *pRes = pEList->a[i].pExpr; + if( pRes->op!=TK_COLUMN ) return 0; + assert( pRes->iTable==pSrc->a[0].iCursor ); /* Not a correlated subquery */ + } return p; } #endif /* SQLITE_OMIT_SUBQUERY */ -/* -** Code an OP_Once instruction and allocate space for its flag. Return the -** address of the new instruction. -*/ -SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){ - Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ - return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++); -} - +#ifndef SQLITE_OMIT_SUBQUERY /* ** Generate code that checks the left-most column of index table iCur to see if ** it contains any NULL entries. Cause the register at regHasNull to be set @@ -88292,6 +91718,7 @@ static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){ VdbeComment((v, "first_entry_in(%d)", iCur)); sqlite3VdbeJumpHere(v, addr1); } +#endif #ifndef SQLITE_OMIT_SUBQUERY @@ -88336,7 +91763,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** An existing b-tree might be used if the RHS expression pX is a simple ** subquery such as: ** -** SELECT FROM +** SELECT , ... FROM
    ** ** If the RHS of the IN operator is a list or a more complex subquery, then ** an ephemeral table might need to be generated from the RHS and then @@ -88352,14 +91779,14 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** ** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate ** through the set members) then the b-tree must not contain duplicates. -** An epheremal table must be used unless the selected is guaranteed -** to be unique - either because it is an INTEGER PRIMARY KEY or it -** has a UNIQUE constraint or UNIQUE index. +** An epheremal table must be used unless the selected columns are guaranteed +** to be unique - either because it is an INTEGER PRIMARY KEY or due to +** a UNIQUE constraint or index. ** ** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used ** for fast set membership tests) then an epheremal table must -** be used unless is an INTEGER PRIMARY KEY or an index can -** be found with as its left-most column. +** be used unless is a single INTEGER PRIMARY KEY column or an +** index can be found with the specified as its left-most. ** ** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and ** if the RHS of the IN operator is a list (not a subquery) then this @@ -88380,9 +91807,26 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** the value in that register will be NULL if the b-tree contains one or more ** NULL values, and it will be some non-NULL value if the b-tree contains no ** NULL values. +** +** If the aiMap parameter is not NULL, it must point to an array containing +** one element for each column returned by the SELECT statement on the RHS +** of the IN(...) operator. The i'th entry of the array is populated with the +** offset of the index column that matches the i'th column returned by the +** SELECT. For example, if the expression and selected index are: +** +** (?,?,?) IN (SELECT a, b, c FROM t1) +** CREATE INDEX i1 ON t1(b, c, a); +** +** then aiMap[] is populated with {2, 0, 1}. */ #ifndef SQLITE_OMIT_SUBQUERY -SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){ +SQLITE_PRIVATE int sqlite3FindInIndex( + Parse *pParse, /* Parsing context */ + Expr *pX, /* The right-hand side (RHS) of the IN operator */ + u32 inFlags, /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */ + int *prRhsHasNull, /* Register holding NULL status. See notes */ + int *aiMap /* Mapping from Index fields to RHS fields */ +){ Select *p; /* SELECT to the right of IN operator */ int eType = 0; /* Type of RHS table. IN_INDEX_* */ int iTab = pParse->nTab++; /* Cursor of the RHS table */ @@ -88392,36 +91836,46 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int assert( pX->op==TK_IN ); mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0; + /* If the RHS of this IN(...) operator is a SELECT, and if it matters + ** whether or not the SELECT result contains NULL values, check whether + ** or not NULL is actually possible (it may not be, for example, due + ** to NOT NULL constraints in the schema). If no NULL values are possible, + ** set prRhsHasNull to 0 before continuing. */ + if( prRhsHasNull && (pX->flags & EP_xIsSelect) ){ + int i; + ExprList *pEList = pX->x.pSelect->pEList; + for(i=0; inExpr; i++){ + if( sqlite3ExprCanBeNull(pEList->a[i].pExpr) ) break; + } + if( i==pEList->nExpr ){ + prRhsHasNull = 0; + } + } + /* Check to see if an existing table or index can be used to ** satisfy the query. This is preferable to generating a new - ** ephemeral table. - */ + ** ephemeral table. */ if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){ sqlite3 *db = pParse->db; /* Database connection */ Table *pTab; /* Table
    . */ - Expr *pExpr; /* Expression */ - i16 iCol; /* Index of column */ i16 iDb; /* Database idx for pTab */ + ExprList *pEList = p->pEList; + int nExpr = pEList->nExpr; assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ pTab = p->pSrc->a[0].pTab; - pExpr = p->pEList->a[0].pExpr; - iCol = (i16)pExpr->iColumn; - + /* Code an OP_Transaction and OP_TableLock for
    . */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - /* This function is only called from two places. In both cases the vdbe - ** has already been allocated. So assume sqlite3GetVdbe() is always - ** successful here. - */ - assert(v); - if( iCol<0 ){ - int iAddr = sqlite3CodeOnce(pParse); + assert(v); /* sqlite3GetVdbe() has always been previously called */ + if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){ + /* The "x IN (SELECT rowid FROM table)" case */ + int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); @@ -88430,44 +91884,114 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int sqlite3VdbeJumpHere(v, iAddr); }else{ Index *pIdx; /* Iterator variable */ + int affinity_ok = 1; + int i; - /* The collation sequence used by the comparison. If an index is to - ** be used in place of a temp-table, it must be ordered according - ** to this collation sequence. */ - CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr); - - /* Check that the affinity that will be used to perform the - ** comparison is the same as the affinity of the column. If - ** it is not, it is not possible to use any index. - */ - int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity); - - for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){ - if( (pIdx->aiColumn[0]==iCol) - && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq - && (!mustBeUnique || (pIdx->nKeyCol==1 && IsUniqueIndex(pIdx))) - ){ - int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); - sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - VdbeComment((v, "%s", pIdx->zName)); - assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); - eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; - - if( prRhsHasNull && !pTab->aCol[iCol].notNull ){ - *prRhsHasNull = ++pParse->nMem; - sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull); + /* Check that the affinity that will be used to perform each + ** comparison is the same as the affinity of each column in table + ** on the RHS of the IN operator. If it not, it is not possible to + ** use any index of the RHS table. */ + for(i=0; ipLeft, i); + int iCol = pEList->a[i].pExpr->iColumn; + char idxaff = sqlite3TableColumnAffinity(pTab,iCol); /* RHS table */ + char cmpaff = sqlite3CompareAffinity(pLhs, idxaff); + testcase( cmpaff==SQLITE_AFF_BLOB ); + testcase( cmpaff==SQLITE_AFF_TEXT ); + switch( cmpaff ){ + case SQLITE_AFF_BLOB: + break; + case SQLITE_AFF_TEXT: + /* sqlite3CompareAffinity() only returns TEXT if one side or the + ** other has no affinity and the other side is TEXT. Hence, + ** the only way for cmpaff to be TEXT is for idxaff to be TEXT + ** and for the term on the LHS of the IN to have no affinity. */ + assert( idxaff==SQLITE_AFF_TEXT ); + break; + default: + affinity_ok = sqlite3IsNumericAffinity(idxaff); + } + } + + if( affinity_ok ){ + /* Search for an existing index that will work for this IN operator */ + for(pIdx=pTab->pIndex; pIdx && eType==0; pIdx=pIdx->pNext){ + Bitmask colUsed; /* Columns of the index used */ + Bitmask mCol; /* Mask for the current column */ + if( pIdx->nColumnnColumn==BMS-2 ); + testcase( pIdx->nColumn==BMS-1 ); + if( pIdx->nColumn>=BMS-1 ) continue; + if( mustBeUnique ){ + if( pIdx->nKeyCol>nExpr + ||(pIdx->nColumn>nExpr && !IsUniqueIndex(pIdx)) + ){ + continue; /* This index is not unique over the IN RHS columns */ + } } - sqlite3VdbeJumpHere(v, iAddr); - } - } - } - } + + colUsed = 0; /* Columns of index used so far */ + for(i=0; ipLeft, i); + Expr *pRhs = pEList->a[i].pExpr; + CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); + int j; + + assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr ); + for(j=0; jaiColumn[j]!=pRhs->iColumn ) continue; + assert( pIdx->azColl[j] ); + if( pReq!=0 && sqlite3StrICmp(pReq->zName, pIdx->azColl[j])!=0 ){ + continue; + } + break; + } + if( j==nExpr ) break; + mCol = MASKBIT(j); + if( mCol & colUsed ) break; /* Each column used only once */ + colUsed |= mCol; + if( aiMap ) aiMap[i] = j; + } + + assert( i==nExpr || colUsed!=(MASKBIT(nExpr)-1) ); + if( colUsed==(MASKBIT(nExpr)-1) ){ + /* If we reach this point, that means the index pIdx is usable */ + int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); +#ifndef SQLITE_OMIT_EXPLAIN + sqlite3VdbeAddOp4(v, OP_Explain, 0, 0, 0, + sqlite3MPrintf(db, "USING INDEX %s FOR IN-OPERATOR",pIdx->zName), + P4_DYNAMIC); +#endif + sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); + sqlite3VdbeSetP4KeyInfo(pParse, pIdx); + VdbeComment((v, "%s", pIdx->zName)); + assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); + eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; + + if( prRhsHasNull ){ +#ifdef SQLITE_ENABLE_COLUMN_USED_MASK + i64 mask = (1<nMem; + if( nExpr==1 ){ + sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull); + } + } + sqlite3VdbeJumpHere(v, iAddr); + } + } /* End loop over indexes */ + } /* End if( affinity_ok ) */ + } /* End if not an rowid index */ + } /* End attempt to optimize using an index */ /* If no preexisting index is available for the IN clause ** and IN_INDEX_NOOP is an allowed reply ** and the RHS of the IN operator is a list, not a subquery - ** and the RHS is not contant or has two or fewer terms, + ** and the RHS is not constant or has two or fewer terms, ** then it is not worth creating an ephemeral table to evaluate ** the IN operator so return IN_INDEX_NOOP. */ @@ -88478,7 +92002,6 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int ){ eType = IN_INDEX_NOOP; } - if( eType==0 ){ /* Could not find an existing table or index to use as the RHS b-tree. @@ -88500,10 +92023,63 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int }else{ pX->iTable = iTab; } + + if( aiMap && eType!=IN_INDEX_INDEX_ASC && eType!=IN_INDEX_INDEX_DESC ){ + int i, n; + n = sqlite3ExprVectorSize(pX->pLeft); + for(i=0; ipLeft; + int nVal = sqlite3ExprVectorSize(pLeft); + Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0; + char *zRet; + + assert( pExpr->op==TK_IN ); + zRet = sqlite3DbMallocZero(pParse->db, nVal+1); + if( zRet ){ + int i; + for(i=0; ipEList->a[i].pExpr, a); + }else{ + zRet[i] = a; + } + } + zRet[nVal] = '\0'; + } + return zRet; +} +#endif + +#ifndef SQLITE_OMIT_SUBQUERY +/* +** Load the Parse object passed as the first argument with an error +** message of the form: +** +** "sub-select returns N columns - expected M" +*/ +SQLITE_PRIVATE void sqlite3SubselectError(Parse *pParse, int nActual, int nExpect){ + const char *zFmt = "sub-select returns %d columns - expected %d"; + sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect); +} +#endif + /* ** Generate code for scalar subqueries used as a subquery expression, EXISTS, ** or IN operators. Examples: @@ -88529,7 +92105,9 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int ** value to non-NULL if the RHS is NULL-free. ** ** For a SELECT or EXISTS operator, return the register that holds the -** result. For IN operators or if an error occurs, the return value is 0. +** result. For a multi-column SELECT, the result is stored in a contiguous +** array of registers and the return value is the register of the left-most +** result column. Return 0 for IN operators or if an error occurs. */ #ifndef SQLITE_OMIT_SUBQUERY SQLITE_PRIVATE int sqlite3CodeSubselect( @@ -88544,8 +92122,8 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( if( NEVER(v==0) ) return 0; sqlite3ExprCachePush(pParse); - /* This code must be run in its entirety every time it is encountered - ** if any of the following is true: + /* The evaluation of the IN/EXISTS/SELECT must be repeated every time it + ** is encountered if any of the following is true: ** ** * The right-hand side is a correlated subquery ** * The right-hand side is an expression list containing variables @@ -88555,7 +92133,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** save the results, and reuse the same result on subsequent invocations. */ if( !ExprHasProperty(pExpr, EP_VarSelect) ){ - jmpIfDynamic = sqlite3CodeOnce(pParse); VdbeCoverage(v); + jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } #ifndef SQLITE_OMIT_EXPLAIN @@ -88571,17 +92149,18 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( switch( pExpr->op ){ case TK_IN: { - char affinity; /* Affinity of the LHS of the IN */ int addr; /* Address of OP_OpenEphemeral instruction */ Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */ KeyInfo *pKeyInfo = 0; /* Key information */ - - affinity = sqlite3ExprAffinity(pLeft); + int nVal; /* Size of vector pLeft */ + + nVal = sqlite3ExprVectorSize(pLeft); + assert( !isRowid || nVal==1 ); /* Whether this is an 'x IN(SELECT...)' or an 'x IN()' ** expression it is handled the same way. An ephemeral table is - ** filled with single-field index keys representing the results - ** from the SELECT or the . + ** filled with index keys representing the results from the + ** SELECT or the . ** ** If the 'x' expression is a column value, or the SELECT... ** statement returns a column value, then the affinity of that @@ -88592,8 +92171,9 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** is used. */ pExpr->iTable = pParse->nTab++; - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); - pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1, 1); + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, + pExpr->iTable, (isRowid?0:nVal)); + pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* Case 1: expr IN (SELECT ...) @@ -88602,27 +92182,37 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** table allocated and opened above. */ Select *pSelect = pExpr->x.pSelect; - SelectDest dest; - ExprList *pEList; + ExprList *pEList = pSelect->pEList; assert( !isRowid ); - sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); - dest.affSdst = (u8)affinity; - assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); - pSelect->iLimit = 0; - testcase( pSelect->selFlags & SF_Distinct ); - testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */ - if( sqlite3Select(pParse, pSelect, &dest) ){ - sqlite3KeyInfoUnref(pKeyInfo); - return 0; + /* If the LHS and RHS of the IN operator do not match, that + ** error will have been caught long before we reach this point. */ + if( ALWAYS(pEList->nExpr==nVal) ){ + SelectDest dest; + 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() */ + if( sqlite3Select(pParse, pSelect, &dest) ){ + sqlite3DbFree(pParse->db, dest.zAffSdst); + sqlite3KeyInfoUnref(pKeyInfo); + return 0; + } + sqlite3DbFree(pParse->db, dest.zAffSdst); + assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */ + assert( pEList!=0 ); + assert( pEList->nExpr>0 ); + assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); + for(i=0; iaColl[i] = sqlite3BinaryCompareCollSeq( + pParse, p, pEList->a[i].pExpr + ); + } } - pEList = pSelect->pEList; - assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */ - assert( pEList!=0 ); - assert( pEList->nExpr>0 ); - assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); - pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, - pEList->a[0].pExpr); }else if( ALWAYS(pExpr->x.pList!=0) ){ /* Case 2: expr IN (exprlist) ** @@ -88631,11 +92221,13 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** that columns affinity when building index keys. If is not ** a column, use numeric affinity. */ + char affinity; /* Affinity of the LHS of the IN */ int i; ExprList *pList = pExpr->x.pList; struct ExprList_item *pItem; int r1, r2, r3; + affinity = sqlite3ExprAffinity(pLeft); if( !affinity ){ affinity = SQLITE_AFF_BLOB; } @@ -88691,26 +92283,37 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( case TK_EXISTS: case TK_SELECT: default: { - /* If this has to be a scalar SELECT. Generate code to put the - ** value of this select in a memory cell and record the number - ** of the memory cell in iColumn. If this is an EXISTS, write - ** an integer 0 (not exists) or 1 (exists) into a memory cell - ** and record that memory cell in iColumn. + /* Case 3: (SELECT ... FROM ...) + ** or: EXISTS(SELECT ... FROM ...) + ** + ** For a SELECT, generate code to put the values for all columns of + ** the first row into an array of registers and return the index of + ** the first register. + ** + ** If this is an EXISTS, write an integer 0 (not exists) or 1 (exists) + ** into a register and return that register number. + ** + ** In both cases, the query is augmented with "LIMIT 1". Any + ** preexisting limit is discarded in place of the new LIMIT 1. */ Select *pSel; /* SELECT statement to encode */ - SelectDest dest; /* How to deal with SELECt result */ + SelectDest dest; /* How to deal with SELECT result */ + int nReg; /* Registers to allocate */ testcase( pExpr->op==TK_EXISTS ); testcase( pExpr->op==TK_SELECT ); assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); - assert( ExprHasProperty(pExpr, EP_xIsSelect) ); + pSel = pExpr->x.pSelect; - sqlite3SelectDestInit(&dest, 0, ++pParse->nMem); + nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1; + sqlite3SelectDestInit(&dest, 0, pParse->nMem+1); + pParse->nMem += nReg; if( pExpr->op==TK_SELECT ){ dest.eDest = SRT_Mem; dest.iSdst = dest.iSDParm; - sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iSDParm); + dest.nSdst = nReg; + sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1); VdbeComment((v, "Init subquery result")); }else{ dest.eDest = SRT_Exists; @@ -88718,8 +92321,8 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( VdbeComment((v, "Init EXISTS result")); } sqlite3ExprDelete(pParse->db, pSel->pLimit); - pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, - &sqlite3IntTokens[1]); + pSel->pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER, + &sqlite3IntTokens[1], 0); pSel->iLimit = 0; pSel->selFlags &= ~SF_MultiValue; if( sqlite3Select(pParse, pSel, &dest) ){ @@ -88744,6 +92347,32 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( } #endif /* SQLITE_OMIT_SUBQUERY */ +#ifndef SQLITE_OMIT_SUBQUERY +/* +** Expr pIn is an IN(...) expression. This function checks that the +** sub-select on the RHS of the IN() operator has the same number of +** columns as the vector on the LHS. Or, if the RHS of the IN() is not +** a sub-query, that the LHS is a vector of size 1. +*/ +SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){ + int nVector = sqlite3ExprVectorSize(pIn->pLeft); + if( (pIn->flags & EP_xIsSelect) ){ + if( nVector!=pIn->x.pSelect->pEList->nExpr ){ + sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector); + return 1; + } + }else if( nVector!=1 ){ + if( (pIn->pLeft->flags & EP_xIsSelect) ){ + sqlite3SubselectError(pParse, nVector, 1); + }else{ + sqlite3ErrorMsg(pParse, "row value misused"); + } + return 1; + } + return 0; +} +#endif + #ifndef SQLITE_OMIT_SUBQUERY /* ** Generate code for an IN expression. @@ -88751,16 +92380,24 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** x IN (SELECT ...) ** x IN (value, value, ...) ** -** The left-hand side (LHS) is a scalar expression. The right-hand side (RHS) -** is an array of zero or more values. The expression is true if the LHS is -** contained within the RHS. The value of the expression is unknown (NULL) -** if the LHS is NULL or if the LHS is not contained within the RHS and the -** RHS contains one or more NULL values. +** The left-hand side (LHS) is a scalar or vector expression. The +** right-hand side (RHS) is an array of zero or more scalar values, or a +** subquery. If the RHS is a subquery, the number of result columns must +** match the number of columns in the vector on the LHS. If the RHS is +** a list of values, the LHS must be a scalar. +** +** The IN operator is true if the LHS value is contained within the RHS. +** The result is false if the LHS is definitely not in the RHS. The +** result is NULL if the presence of the LHS in the RHS cannot be +** determined due to NULLs. ** ** This routine generates code that jumps to destIfFalse if the LHS is not ** contained within the RHS. If due to NULLs we cannot determine if the LHS ** is contained in the RHS then jump to destIfNull. If the LHS is contained ** within the RHS then fall through. +** +** See the separate in-operator.md documentation file in the canonical +** SQLite source tree for additional information. */ static void sqlite3ExprCodeIN( Parse *pParse, /* Parsing and code generating context */ @@ -88769,36 +92406,83 @@ static void sqlite3ExprCodeIN( int destIfNull /* Jump here if the results are unknown due to NULLs */ ){ int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */ - char affinity; /* Comparison affinity to use */ int eType; /* Type of the RHS */ - int r1; /* Temporary use register */ + int rLhs; /* Register(s) holding the LHS values */ + int rLhsOrig; /* LHS values prior to reordering by aiMap[] */ Vdbe *v; /* Statement under construction */ + int *aiMap = 0; /* Map from vector field to index column */ + char *zAff = 0; /* Affinity string for comparisons */ + int nVector; /* Size of vectors for this IN operator */ + int iDummy; /* Dummy parameter to exprCodeVector() */ + Expr *pLeft; /* The LHS of the IN operator */ + int i; /* loop counter */ + int destStep2; /* Where to jump when NULLs seen in step 2 */ + int destStep6 = 0; /* Start of code for Step 6 */ + int addrTruthOp; /* Address of opcode that determines the IN is true */ + int destNotNull; /* Jump here if a comparison is not true in step 6 */ + int addrTop; /* Top of the step-6 loop */ + + pLeft = pExpr->pLeft; + if( sqlite3ExprCheckIN(pParse, pExpr) ) return; + zAff = exprINAffinity(pParse, pExpr); + nVector = sqlite3ExprVectorSize(pExpr->pLeft); + aiMap = (int*)sqlite3DbMallocZero( + pParse->db, nVector*(sizeof(int) + sizeof(char)) + 1 + ); + if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error; - /* Compute the RHS. After this step, the table with cursor - ** pExpr->iTable will contains the values that make up the RHS. - */ + /* Attempt to compute the RHS. After this step, if anything other than + ** IN_INDEX_NOOP is returned, the table opened ith cursor pExpr->iTable + ** contains the values that make up the RHS. If IN_INDEX_NOOP is returned, + ** the RHS has not yet been coded. */ v = pParse->pVdbe; assert( v!=0 ); /* OOM detected prior to this routine */ VdbeNoopComment((v, "begin IN expr")); eType = sqlite3FindInIndex(pParse, pExpr, IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK, - destIfFalse==destIfNull ? 0 : &rRhsHasNull); + destIfFalse==destIfNull ? 0 : &rRhsHasNull, aiMap); - /* Figure out the affinity to use to create a key from the results - ** of the expression. affinityStr stores a static string suitable for - ** P4 of OP_MakeRecord. - */ - affinity = comparisonAffinity(pExpr); + assert( pParse->nErr || nVector==1 || eType==IN_INDEX_EPH + || eType==IN_INDEX_INDEX_ASC || eType==IN_INDEX_INDEX_DESC + ); +#ifdef SQLITE_DEBUG + /* Confirm that aiMap[] contains nVector integer values between 0 and + ** nVector-1. */ + for(i=0; i from " IN (...)". + /* Code the LHS, the from " IN (...)". If the LHS is a + ** vector, then it is stored in an array of nVector registers starting + ** at r1. + ** + ** sqlite3FindInIndex() might have reordered the fields of the LHS vector + ** so that the fields are in the same order as an existing index. The + ** aiMap[] array contains a mapping from the original LHS field order to + ** the field order that matches the RHS index. */ sqlite3ExprCachePush(pParse); - r1 = sqlite3GetTempReg(pParse); - sqlite3ExprCode(pParse, pExpr->pLeft, r1); + rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy); + for(i=0; ix.pList; @@ -88810,7 +92494,7 @@ static void sqlite3ExprCodeIN( assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); if( destIfNull!=destIfFalse ){ regCkNull = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_BitAnd, r1, r1, regCkNull); + sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull); } for(ii=0; iinExpr; ii++){ r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree); @@ -88818,16 +92502,16 @@ static void sqlite3ExprCodeIN( sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull); } if( iinExpr-1 || destIfNull!=destIfFalse ){ - sqlite3VdbeAddOp4(v, OP_Eq, r1, labelOk, r2, + sqlite3VdbeAddOp4(v, OP_Eq, rLhs, labelOk, r2, (void*)pColl, P4_COLLSEQ); VdbeCoverageIf(v, iinExpr-1); VdbeCoverageIf(v, ii==pList->nExpr-1); - sqlite3VdbeChangeP5(v, affinity); + sqlite3VdbeChangeP5(v, zAff[0]); }else{ assert( destIfNull==destIfFalse ); - sqlite3VdbeAddOp4(v, OP_Ne, r1, destIfFalse, r2, + sqlite3VdbeAddOp4(v, OP_Ne, rLhs, destIfFalse, r2, (void*)pColl, P4_COLLSEQ); VdbeCoverage(v); - sqlite3VdbeChangeP5(v, affinity | SQLITE_JUMPIFNULL); + sqlite3VdbeChangeP5(v, zAff[0] | SQLITE_JUMPIFNULL); } sqlite3ReleaseTempReg(pParse, regToFree); } @@ -88837,78 +92521,113 @@ static void sqlite3ExprCodeIN( } sqlite3VdbeResolveLabel(v, labelOk); sqlite3ReleaseTempReg(pParse, regCkNull); + goto sqlite3ExprCodeIN_finished; + } + + /* Step 2: Check to see if the LHS contains any NULL columns. If the + ** LHS does contain NULLs then the result must be either FALSE or NULL. + ** We will then skip the binary search of the RHS. + */ + if( destIfNull==destIfFalse ){ + destStep2 = destIfFalse; }else{ - - /* If the LHS is NULL, then the result is either false or NULL depending - ** on whether the RHS is empty or not, respectively. - */ - if( sqlite3ExprCanBeNull(pExpr->pLeft) ){ - if( destIfNull==destIfFalse ){ - /* Shortcut for the common case where the false and NULL outcomes are - ** the same. */ - sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v); - }else{ - int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); - VdbeCoverage(v); - sqlite3VdbeGoto(v, destIfNull); - sqlite3VdbeJumpHere(v, addr1); - } - } - - if( eType==IN_INDEX_ROWID ){ - /* In this case, the RHS is the ROWID of table b-tree - */ - sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1); + destStep2 = destStep6 = sqlite3VdbeMakeLabel(v); + } + for(i=0; ipLeft, i); + if( sqlite3ExprCanBeNull(p) ){ + sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2); VdbeCoverage(v); - }else{ - /* In this case, the RHS is an index b-tree. - */ - sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1); - - /* If the set membership test fails, then the result of the - ** "x IN (...)" expression must be either 0 or NULL. If the set - ** contains no NULL values, then the result is 0. If the set - ** contains one or more NULL values, then the result of the - ** expression is also NULL. - */ - assert( destIfFalse!=destIfNull || rRhsHasNull==0 ); - if( rRhsHasNull==0 ){ - /* This branch runs if it is known at compile time that the RHS - ** cannot contain NULL values. This happens as the result - ** of a "NOT NULL" constraint in the database schema. - ** - ** Also run this branch if NULL is equivalent to FALSE - ** for this particular IN operator. - */ - sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1); - VdbeCoverage(v); - }else{ - /* In this branch, the RHS of the IN might contain a NULL and - ** the presence of a NULL on the RHS makes a difference in the - ** outcome. - */ - int addr1; - - /* First check to see if the LHS is contained in the RHS. If so, - ** then the answer is TRUE the presence of NULLs in the RHS does - ** not matter. If the LHS is not contained in the RHS, then the - ** answer is NULL if the RHS contains NULLs and the answer is - ** FALSE if the RHS is NULL-free. - */ - addr1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_IsNull, rRhsHasNull, destIfNull); - VdbeCoverage(v); - sqlite3VdbeGoto(v, destIfFalse); - sqlite3VdbeJumpHere(v, addr1); - } } } - sqlite3ReleaseTempReg(pParse, r1); + + /* Step 3. The LHS is now known to be non-NULL. Do the binary search + ** of the RHS using the LHS as a probe. If found, the result is + ** true. + */ + if( eType==IN_INDEX_ROWID ){ + /* In this case, the RHS is the ROWID of table b-tree and so we also + ** know that the RHS is non-NULL. Hence, we combine steps 3 and 4 + ** into a single opcode. */ + sqlite3VdbeAddOp3(v, OP_SeekRowid, pExpr->iTable, destIfFalse, rLhs); + VdbeCoverage(v); + addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto); /* Return True */ + }else{ + sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector); + if( destIfFalse==destIfNull ){ + /* Combine Step 3 and Step 5 into a single opcode */ + sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, + rLhs, nVector); VdbeCoverage(v); + goto sqlite3ExprCodeIN_finished; + } + /* Ordinary Step 3, for the case where FALSE and NULL are distinct */ + addrTruthOp = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, + rLhs, nVector); VdbeCoverage(v); + } + + /* Step 4. If the RHS is known to be non-NULL and we did not find + ** an match on the search above, then the result must be FALSE. + */ + if( rRhsHasNull && nVector==1 ){ + sqlite3VdbeAddOp2(v, OP_NotNull, rRhsHasNull, destIfFalse); + VdbeCoverage(v); + } + + /* Step 5. If we do not care about the difference between NULL and + ** FALSE, then just return false. + */ + if( destIfFalse==destIfNull ) sqlite3VdbeGoto(v, destIfFalse); + + /* Step 6: Loop through rows of the RHS. Compare each row to the LHS. + ** If any comparison is NULL, then the result is NULL. If all + ** comparisons are FALSE then the final result is FALSE. + ** + ** For a scalar LHS, it is sufficient to check just the first row + ** of the RHS. + */ + if( destStep6 ) sqlite3VdbeResolveLabel(v, destStep6); + addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); + VdbeCoverage(v); + if( nVector>1 ){ + destNotNull = sqlite3VdbeMakeLabel(v); + }else{ + /* For nVector==1, combine steps 6 and 7 by immediately returning + ** FALSE if the first comparison is not NULL */ + destNotNull = destIfFalse; + } + for(i=0; iiTable, i, r3); + sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3, + (void*)pColl, P4_COLLSEQ); + VdbeCoverage(v); + sqlite3ReleaseTempReg(pParse, r3); + } + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); + if( nVector>1 ){ + sqlite3VdbeResolveLabel(v, destNotNull); + sqlite3VdbeAddOp2(v, OP_Next, pExpr->iTable, addrTop+1); + VdbeCoverage(v); + + /* Step 7: If we reach this point, we know that the result must + ** be false. */ + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); + } + + /* Jumps here in order to return true. */ + sqlite3VdbeJumpHere(v, addrTruthOp); + +sqlite3ExprCodeIN_finished: + if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs); sqlite3ExprCachePop(pParse); VdbeComment((v, "end IN expr")); +sqlite3ExprCodeIN_oom_error: + sqlite3DbFree(pParse->db, aiMap); + sqlite3DbFree(pParse->db, zAff); } #endif /* SQLITE_OMIT_SUBQUERY */ @@ -88973,14 +92692,17 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ } /* -** Clear a cache entry. +** Erase column-cache entry number i */ -static void cacheEntryClear(Parse *pParse, struct yColCache *p){ - if( p->tempReg ){ +static void cacheEntryClear(Parse *pParse, int i){ + if( pParse->aColCache[i].tempReg ){ if( pParse->nTempRegaTempReg) ){ - pParse->aTempReg[pParse->nTempReg++] = p->iReg; + pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; } - p->tempReg = 0; + } + pParse->nColCache--; + if( inColCache ){ + pParse->aColCache[i] = pParse->aColCache[pParse->nColCache]; } } @@ -89011,43 +92733,33 @@ SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int ** that the object will never already be in cache. Verify this guarantee. */ #ifndef NDEBUG - for(i=0, p=pParse->aColCache; iiReg==0 || p->iTable!=iTab || p->iColumn!=iCol ); + for(i=0, p=pParse->aColCache; inColCache; i++, p++){ + assert( p->iTable!=iTab || p->iColumn!=iCol ); } #endif - /* Find an empty slot and replace it */ - for(i=0, p=pParse->aColCache; iiReg==0 ){ - p->iLevel = pParse->iCacheLevel; - p->iTable = iTab; - p->iColumn = iCol; - p->iReg = iReg; - p->tempReg = 0; - p->lru = pParse->iCacheCnt++; - return; - } - } - - /* Replace the last recently used */ - minLru = 0x7fffffff; - idxLru = -1; - for(i=0, p=pParse->aColCache; ilrulru; + /* If the cache is already full, delete the least recently used entry */ + if( pParse->nColCache>=SQLITE_N_COLCACHE ){ + minLru = 0x7fffffff; + idxLru = -1; + for(i=0, p=pParse->aColCache; ilrulru; + } } - } - if( ALWAYS(idxLru>=0) ){ p = &pParse->aColCache[idxLru]; - p->iLevel = pParse->iCacheLevel; - p->iTable = iTab; - p->iColumn = iCol; - p->iReg = iReg; - p->tempReg = 0; - p->lru = pParse->iCacheCnt++; - return; + }else{ + p = &pParse->aColCache[pParse->nColCache++]; } + + /* Add the new entry to the end of the cache */ + p->iLevel = pParse->iCacheLevel; + p->iTable = iTab; + p->iColumn = iCol; + p->iReg = iReg; + p->tempReg = 0; + p->lru = pParse->iCacheCnt++; } /* @@ -89055,14 +92767,13 @@ SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int ** Purge the range of registers from the column cache. */ SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){ - int i; - int iLast = iReg + nReg - 1; - struct yColCache *p; - for(i=0, p=pParse->aColCache; iiReg; - if( r>=iReg && r<=iLast ){ - cacheEntryClear(pParse, p); - p->iReg = 0; + int i = 0; + while( inColCache ){ + struct yColCache *p = &pParse->aColCache[i]; + if( p->iReg >= iReg && p->iReg < iReg+nReg ){ + cacheEntryClear(pParse, i); + }else{ + i++; } } } @@ -89087,8 +92798,7 @@ SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){ ** the cache to the state it was in prior the most recent Push. */ SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){ - int i; - struct yColCache *p; + int i = 0; assert( pParse->iCacheLevel>=1 ); pParse->iCacheLevel--; #ifdef SQLITE_DEBUG @@ -89096,10 +92806,11 @@ SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){ printf("POP to %d\n", pParse->iCacheLevel); } #endif - for(i=0, p=pParse->aColCache; iiReg && p->iLevel>pParse->iCacheLevel ){ - cacheEntryClear(pParse, p); - p->iReg = 0; + while( inColCache ){ + if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){ + cacheEntryClear(pParse, i); + }else{ + i++; } } } @@ -89113,7 +92824,7 @@ SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){ static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ int i; struct yColCache *p; - for(i=0, p=pParse->aColCache; iaColCache; inColCache; i++, p++){ if( p->iReg==iReg ){ p->tempReg = 0; } @@ -89157,7 +92868,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable( }else{ int op = IsVirtual(pTab) ? OP_VColumn : OP_Column; int x = iCol; - if( !HasRowid(pTab) ){ + if( !HasRowid(pTab) && !IsVirtual(pTab) ){ x = sqlite3ColumnOfIndex(sqlite3PrimaryKeyIndex(pTab), iCol); } sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut); @@ -89191,8 +92902,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( int i; struct yColCache *p; - for(i=0, p=pParse->aColCache; iiReg>0 && p->iTable==iTable && p->iColumn==iColumn ){ + for(i=0, p=pParse->aColCache; inColCache; i++, p++){ + if( p->iTable==iTable && p->iColumn==iColumn ){ p->lru = pParse->iCacheCnt++; sqlite3ExprCachePinRegister(pParse, p->iReg); return p->iReg; @@ -89224,19 +92935,20 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg( */ SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ int i; - struct yColCache *p; #if SQLITE_DEBUG if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ printf("CLEAR\n"); } #endif - for(i=0, p=pParse->aColCache; iiReg ){ - cacheEntryClear(pParse, p); - p->iReg = 0; + for(i=0; inColCache; i++){ + if( pParse->aColCache[i].tempReg + && pParse->nTempRegaTempReg) + ){ + pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; } } + pParse->nColCache = 0; } /* @@ -89268,7 +92980,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int n static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ int i; struct yColCache *p; - for(i=0, p=pParse->aColCache; iaColCache; inColCache; i++, p++){ int r = p->iReg; if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/ } @@ -89276,8 +92988,11 @@ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ } #endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */ + /* -** Convert an expression node to a TK_REGISTER +** Convert a scalar expression node to a TK_REGISTER referencing +** register iReg. The caller must ensure that iReg already contains +** the correct value for the expression. */ static void exprToRegister(Expr *p, int iReg){ p->op2 = p->op; @@ -89286,6 +93001,38 @@ static void exprToRegister(Expr *p, int iReg){ ExprClearProperty(p, EP_Skip); } +/* +** Evaluate an expression (either a vector or a scalar expression) and store +** the result in continguous temporary registers. Return the index of +** the first register used to store the result. +** +** If the returned result register is a temporary scalar, then also write +** that register number into *piFreeable. If the returned result register +** is not a temporary or if the expression is a vector set *piFreeable +** to 0. +*/ +static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){ + int iResult; + int nResult = sqlite3ExprVectorSize(p); + if( nResult==1 ){ + iResult = sqlite3ExprCodeTemp(pParse, p, piFreeable); + }else{ + *piFreeable = 0; + if( p->op==TK_SELECT ){ + iResult = sqlite3CodeSubselect(pParse, p, 0, 0); + }else{ + int i; + iResult = pParse->nMem+1; + pParse->nMem += nResult; + for(i=0; ix.pList->a[i].pExpr, i+iResult); + } + } + } + return iResult; +} + + /* ** Generate code into the current Vdbe to evaluate the given ** expression. Attempt to store the results in register "target". @@ -89303,9 +93050,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) int inReg = target; /* Results stored in register inReg */ int regFree1 = 0; /* If non-zero free this temporary register */ int regFree2 = 0; /* If non-zero free this temporary register */ - int r1, r2, r3, r4; /* Various register numbers */ - sqlite3 *db = pParse->db; /* The database connection */ + int r1, r2; /* Various register numbers */ Expr tempX; /* Temporary expression node */ + int p5 = 0; assert( target>0 && target<=pParse->nMem ); if( v==0 ){ @@ -89324,12 +93071,11 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg]; if( !pAggInfo->directMode ){ assert( pCol->iMem>0 ); - inReg = pCol->iMem; - break; + return pCol->iMem; }else if( pAggInfo->useSortingIdx ){ sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, pCol->iSorterColumn, target); - break; + return target; } /* Otherwise, fall thru into the TK_COLUMN case */ } @@ -89338,38 +93084,36 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) if( iTab<0 ){ if( pParse->ckBase>0 ){ /* Generating CHECK constraints or inserting into partial index */ - inReg = pExpr->iColumn + pParse->ckBase; - break; + return pExpr->iColumn + pParse->ckBase; }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; } } - inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, + return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, pExpr->iColumn, iTab, target, pExpr->op2); - break; } case TK_INTEGER: { codeInteger(pParse, pExpr, 0, target); - break; + return target; } #ifndef SQLITE_OMIT_FLOATING_POINT case TK_FLOAT: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); codeReal(v, pExpr->u.zToken, 0, target); - break; + return target; } #endif case TK_STRING: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3VdbeLoadString(v, target, pExpr->u.zToken); - break; + return target; } case TK_NULL: { sqlite3VdbeAddOp2(v, OP_Null, 0, target); - break; + return target; } #ifndef SQLITE_OMIT_BLOB_LITERAL case TK_BLOB: { @@ -89384,7 +93128,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) assert( z[n]=='\'' ); zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n); sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC); - break; + return target; } #endif case TK_VARIABLE: { @@ -89397,11 +93141,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) || strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 ); sqlite3VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC); } - break; + return target; } case TK_REGISTER: { - inReg = pExpr->iTable; - break; + return pExpr->iTable; } #ifndef SQLITE_OMIT_CAST case TK_CAST: { @@ -89415,42 +93158,37 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) sqlite3AffinityType(pExpr->u.zToken, 0)); testcase( usedAsColumnCache(pParse, inReg, inReg) ); sqlite3ExprCacheAffinityChange(pParse, inReg, 1); - break; + return inReg; } #endif /* SQLITE_OMIT_CAST */ + case TK_IS: + case TK_ISNOT: + op = (op==TK_IS) ? TK_EQ : TK_NE; + p5 = SQLITE_NULLEQ; + /* fall-through */ case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, inReg, SQLITE_STOREP2); - assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); - assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); - assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); - assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); - assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); - assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_IS: - case TK_ISNOT: { - testcase( op==TK_IS ); - testcase( op==TK_ISNOT ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - op = (op==TK_IS) ? TK_EQ : TK_NE; - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ); - VdbeCoverageIf(v, op==TK_EQ); - VdbeCoverageIf(v, op==TK_NE); - testcase( regFree1==0 ); - testcase( regFree2==0 ); + Expr *pLeft = pExpr->pLeft; + if( sqlite3ExprIsVector(pLeft) ){ + codeVectorCompare(pParse, pExpr, target, op, p5); + }else{ + r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + codeCompare(pParse, pLeft, pExpr->pRight, op, + r1, r2, inReg, SQLITE_STOREP2 | p5); + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + } break; } case TK_AND: @@ -89488,10 +93226,12 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) assert( pLeft ); if( pLeft->op==TK_INTEGER ){ codeInteger(pParse, pLeft, 1, target); + return target; #ifndef SQLITE_OMIT_FLOATING_POINT }else if( pLeft->op==TK_FLOAT ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); codeReal(v, pLeft->u.zToken, 1, target); + return target; #endif }else{ tempX.op = TK_INTEGER; @@ -89502,7 +93242,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); testcase( regFree2==0 ); } - inReg = target; break; } case TK_BITNOT: @@ -89511,7 +93250,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) assert( TK_NOT==OP_Not ); testcase( op==TK_NOT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); testcase( regFree1==0 ); - inReg = target; sqlite3VdbeAddOp2(v, op, r1, inReg); break; } @@ -89536,7 +93274,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken); }else{ - inReg = pInfo->aFunc[pExpr->iAgg].iMem; + return pInfo->aFunc[pExpr->iAgg].iMem; } break; } @@ -89547,6 +93285,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) const char *zId; /* The function name */ u32 constMask = 0; /* Mask of function arguments that are constant */ int i; /* Loop counter */ + sqlite3 *db = pParse->db; /* The database connection */ u8 enc = ENC(db); /* The text encoding used by this database */ CollSeq *pColl = 0; /* A collating sequence */ @@ -89560,6 +93299,11 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) assert( !ExprHasProperty(pExpr, EP_IntValue) ); zId = pExpr->u.zToken; pDef = sqlite3FindFunction(db, zId, nFarg, enc, 0); +#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION + if( pDef==0 && pParse->explain ){ + pDef = sqlite3FindFunction(db, "unknown", nFarg, enc, 0); + } +#endif if( pDef==0 || pDef->xFinalize!=0 ){ sqlite3ErrorMsg(pParse, "unknown function: %s()", zId); break; @@ -89590,8 +93334,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) */ if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ assert( nFarg>=1 ); - inReg = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target); - break; + return sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target); } for(i=0; ix.pSelect->pEList->nExpr)!=1 ){ + sqlite3SubselectError(pParse, nCol, 1); + }else{ + return sqlite3CodeSubselect(pParse, pExpr, 0, 0); + } break; } + case TK_SELECT_COLUMN: { + if( pExpr->pLeft->iTable==0 ){ + pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0); + } + return pExpr->pLeft->iTable + pExpr->iColumn; + } case TK_IN: { int destIfFalse = sqlite3VdbeMakeLabel(v); int destIfNull = sqlite3VdbeMakeLabel(v); @@ -89685,7 +93439,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) sqlite3VdbeResolveLabel(v, destIfFalse); sqlite3VdbeAddOp2(v, OP_AddImm, target, 0); sqlite3VdbeResolveLabel(v, destIfNull); - break; + return target; } #endif /* SQLITE_OMIT_SUBQUERY */ @@ -89702,35 +93456,13 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) ** Z is stored in pExpr->pList->a[1].pExpr. */ case TK_BETWEEN: { - Expr *pLeft = pExpr->pLeft; - struct ExprList_item *pLItem = pExpr->x.pList->a; - Expr *pRight = pLItem->pExpr; - - r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - r3 = sqlite3GetTempReg(pParse); - r4 = sqlite3GetTempReg(pParse); - codeCompare(pParse, pLeft, pRight, OP_Ge, - r1, r2, r3, SQLITE_STOREP2); VdbeCoverage(v); - pLItem++; - pRight = pLItem->pExpr; - sqlite3ReleaseTempReg(pParse, regFree2); - r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); - testcase( regFree2==0 ); - codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); - sqlite3ReleaseTempReg(pParse, r3); - sqlite3ReleaseTempReg(pParse, r4); - break; + exprCodeBetween(pParse, pExpr, target, 0, 0); + return target; } case TK_SPAN: case TK_COLLATE: case TK_UPLUS: { - inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); - break; + return sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); } case TK_TRIGGER: { @@ -89789,6 +93521,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) break; } + case TK_VECTOR: { + sqlite3ErrorMsg(pParse, "row value misused"); + break; + } /* ** Form A: @@ -89832,8 +93568,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) if( (pX = pExpr->pLeft)!=0 ){ tempX = *pX; testcase( pX->op==TK_COLUMN ); - exprToRegister(&tempX, sqlite3ExprCodeTemp(pParse, pX, ®Free1)); + exprToRegister(&tempX, exprCodeVector(pParse, &tempX, ®Free1)); testcase( regFree1==0 ); + memset(&opCompare, 0, sizeof(opCompare)); opCompare.op = TK_EQ; opCompare.pLeft = &tempX; pTest = &opCompare; @@ -89867,7 +93604,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } - assert( db->mallocFailed || pParse->nErr>0 + assert( pParse->db->mallocFailed || pParse->nErr>0 || pParse->iCacheLevel==iCacheLevel ); sqlite3VdbeResolveLabel(v, endLabel); break; @@ -90112,20 +93849,33 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList( ** ** Code it as such, taking care to do the common subexpression ** elimination of x. +** +** The xJumpIf parameter determines details: +** +** NULL: Store the boolean result in reg[dest] +** sqlite3ExprIfTrue: Jump to dest if true +** sqlite3ExprIfFalse: Jump to dest if false +** +** The jumpIfNull parameter is ignored if xJumpIf is NULL. */ static void exprCodeBetween( Parse *pParse, /* Parsing and code generating context */ Expr *pExpr, /* The BETWEEN expression */ - int dest, /* Jump here if the jump is taken */ - int jumpIfTrue, /* Take the jump if the BETWEEN is true */ + int dest, /* Jump destination or storage location */ + void (*xJump)(Parse*,Expr*,int,int), /* Action to take */ int jumpIfNull /* Take the jump if the BETWEEN is NULL */ ){ - Expr exprAnd; /* The AND operator in x>=y AND x<=z */ + Expr exprAnd; /* The AND operator in x>=y AND x<=z */ Expr compLeft; /* The x>=y term */ Expr compRight; /* The x<=z term */ Expr exprX; /* The x subexpression */ int regFree1 = 0; /* Temporary use register */ + + memset(&compLeft, 0, sizeof(Expr)); + memset(&compRight, 0, sizeof(Expr)); + memset(&exprAnd, 0, sizeof(Expr)); + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); exprX = *pExpr->pLeft; exprAnd.op = TK_AND; @@ -90137,23 +93887,25 @@ static void exprCodeBetween( compRight.op = TK_LE; compRight.pLeft = &exprX; compRight.pRight = pExpr->x.pList->a[1].pExpr; - exprToRegister(&exprX, sqlite3ExprCodeTemp(pParse, &exprX, ®Free1)); - if( jumpIfTrue ){ - sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull); + exprToRegister(&exprX, exprCodeVector(pParse, &exprX, ®Free1)); + if( xJump ){ + xJump(pParse, &exprAnd, dest, jumpIfNull); }else{ - sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull); + exprX.flags |= EP_FromJoin; + sqlite3ExprCodeTarget(pParse, &exprAnd, dest); } sqlite3ReleaseTempReg(pParse, regFree1); /* Ensure adequate test coverage */ - testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1==0 ); - testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1!=0 ); - testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1==0 ); - testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1!=0 ); - testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1==0 ); - testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1!=0 ); - testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1==0 ); - testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1!=0 ); + testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1==0 ); + testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1!=0 ); + testcase( xJump==sqlite3ExprIfTrue && jumpIfNull!=0 && regFree1==0 ); + testcase( xJump==sqlite3ExprIfTrue && jumpIfNull!=0 && regFree1!=0 ); + testcase( xJump==sqlite3ExprIfFalse && jumpIfNull==0 && regFree1==0 ); + testcase( xJump==sqlite3ExprIfFalse && jumpIfNull==0 && regFree1!=0 ); + testcase( xJump==sqlite3ExprIfFalse && jumpIfNull!=0 && regFree1==0 ); + testcase( xJump==sqlite3ExprIfFalse && jumpIfNull!=0 && regFree1!=0 ); + testcase( xJump==0 ); } /* @@ -90218,6 +93970,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int case TK_GE: case TK_NE: case TK_EQ: { + if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr; testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); @@ -90250,7 +94003,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int } case TK_BETWEEN: { testcase( jumpIfNull==0 ); - exprCodeBetween(pParse, pExpr, dest, 1, jumpIfNull); + exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfTrue, jumpIfNull); break; } #ifndef SQLITE_OMIT_SUBQUERY @@ -90264,6 +94017,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int } #endif default: { + default_expr: if( exprAlwaysTrue(pExpr) ){ sqlite3VdbeGoto(v, dest); }else if( exprAlwaysFalse(pExpr) ){ @@ -90370,6 +94124,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int case TK_GE: case TK_NE: case TK_EQ: { + if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr; testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); @@ -90400,7 +94155,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int } case TK_BETWEEN: { testcase( jumpIfNull==0 ); - exprCodeBetween(pParse, pExpr, dest, 0, jumpIfNull); + exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfFalse, jumpIfNull); break; } #ifndef SQLITE_OMIT_SUBQUERY @@ -90416,6 +94171,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int } #endif default: { + default_expr: if( exprAlwaysFalse(pExpr) ){ sqlite3VdbeGoto(v, dest); }else if( exprAlwaysTrue(pExpr) ){ @@ -90582,6 +94338,61 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){ return 0; } +/* +** An instance of the following structure is used by the tree walker +** to determine if an expression can be evaluated by reference to the +** index only, without having to do a search for the corresponding +** table entry. The IdxCover.pIdx field is the index. IdxCover.iCur +** is the cursor for the table. +*/ +struct IdxCover { + Index *pIdx; /* The index to be tested for coverage */ + int iCur; /* Cursor number for the table corresponding to the index */ +}; + +/* +** Check to see if there are references to columns in table +** pWalker->u.pIdxCover->iCur can be satisfied using the index +** pWalker->u.pIdxCover->pIdx. +*/ +static int exprIdxCover(Walker *pWalker, Expr *pExpr){ + if( pExpr->op==TK_COLUMN + && pExpr->iTable==pWalker->u.pIdxCover->iCur + && sqlite3ColumnOfIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0 + ){ + pWalker->eCode = 1; + return WRC_Abort; + } + return WRC_Continue; +} + +/* +** Determine if an index pIdx on table with cursor iCur contains will +** the expression pExpr. Return true if the index does cover the +** expression and false if the pExpr expression references table columns +** that are not found in the index pIdx. +** +** An index covering an expression means that the expression can be +** evaluated using only the index and without having to lookup the +** corresponding table entry. +*/ +SQLITE_PRIVATE int sqlite3ExprCoveredByIndex( + Expr *pExpr, /* The index to be tested */ + int iCur, /* The cursor number for the corresponding table */ + Index *pIdx /* The index that might be used for coverage */ +){ + Walker w; + struct IdxCover xcov; + memset(&w, 0, sizeof(w)); + xcov.iCur = iCur; + xcov.pIdx = pIdx; + w.xExprCallback = exprIdxCover; + w.u.pIdxCover = &xcov; + sqlite3WalkExpr(&w, pExpr); + return !w.eCode; +} + + /* ** An instance of the following structure is used by the tree walker ** to count references to table columns in the arguments of an @@ -90865,7 +94676,7 @@ SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ if( iReg && pParse->nTempRegaTempReg) ){ int i; struct yColCache *p; - for(i=0, p=pParse->aColCache; iaColCache; inColCache; i++, p++){ if( p->iReg==iReg ){ p->tempReg = 1; return; @@ -90876,10 +94687,11 @@ SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ } /* -** Allocate or deallocate a block of nReg consecutive registers +** Allocate or deallocate a block of nReg consecutive registers. */ SQLITE_PRIVATE int sqlite3GetTempRange(Parse *pParse, int nReg){ int i, n; + if( nReg==1 ) return sqlite3GetTempReg(pParse); i = pParse->iRangeReg; n = pParse->nRangeReg; if( nReg<=n ){ @@ -90893,6 +94705,10 @@ SQLITE_PRIVATE int sqlite3GetTempRange(Parse *pParse, int nReg){ return i; } SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){ + if( nReg==1 ){ + sqlite3ReleaseTempReg(pParse, iReg); + return; + } sqlite3ExprCacheRemove(pParse, iReg, nReg); if( nReg>pParse->nRangeReg ){ pParse->nRangeReg = nReg; @@ -91348,7 +95164,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_rename_table; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; db->flags |= SQLITE_PreferBuiltin; /* Get a NULL terminated version of the new table name. */ @@ -91536,6 +95352,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ Expr *pDflt; /* Default value for the new column */ sqlite3 *db; /* The database connection; */ Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */ + int r1; /* Temporary registers */ db = pParse->db; if( pParse->nErr || db->mallocFailed ) return; @@ -91545,7 +95362,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pNew->pSchema); - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ pCol = &pNew->aCol[pNew->nCol-1]; pDflt = pCol->pDflt; @@ -91630,16 +95447,18 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ db->flags = savedDbFlags; } - /* If the default value of the new column is NULL, then the file - ** format to 2. If the default value of the new column is not NULL, - ** the file format be 3. Back when this feature was first added - ** in 2006, we went to the trouble to upgrade the file format to the - ** minimum support values. But 10-years on, we can assume that all - ** extent versions of SQLite support file-format 4, so we always and - ** unconditionally upgrade to 4. + /* Make sure the schema version is at least 3. But do not upgrade + ** from less than 3 to 4, as that will corrupt any preexisting DESC + ** index. */ - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, - SQLITE_MAX_FILE_FORMAT); + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); + sqlite3VdbeUsesBtree(v, iDb); + sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2); + sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3); + sqlite3ReleaseTempReg(pParse, r1); /* Reload the schema of the modified table. */ reloadTableSchema(pParse, pTab, pTab->zName); @@ -91953,14 +95772,14 @@ static void openStatTable( for(i=0; izName))==0 ){ + if( (pStat = sqlite3FindTable(db, zTab, pDb->zDbSName))==0 ){ if( aTable[i].zCols ){ /* The sqlite_statN table does not exist. Create it. Note that a ** side-effect of the CREATE TABLE statement is to leave the rootpage ** of the new table in register pParse->regRoot. This is important ** because the OpenWrite opcode below will be needing it. */ sqlite3NestedParse(pParse, - "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols + "CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols ); aRoot[i] = pParse->regRoot; aCreateTbl[i] = OPFLAG_P2ISREG; @@ -91975,7 +95794,7 @@ static void openStatTable( if( zWhere ){ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE %s=%Q", - pDb->zName, zTab, zWhereType, zWhere + pDb->zDbSName, zTab, zWhereType, zWhere ); }else{ /* The sqlite_stat[134] table already exists. Delete all rows. */ @@ -92737,7 +96556,7 @@ static void analyzeOneTable( assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, - db->aDb[iDb].zName ) ){ + db->aDb[iDb].zDbSName ) ){ return; } #endif @@ -93127,7 +96946,7 @@ SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ /* Form 3: Analyze the fully qualified table name */ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); if( iDb>=0 ){ - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; z = sqlite3NameFromToken(db, pTableName); if( z ){ if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){ @@ -93569,7 +97388,7 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ analysisInfo sInfo; HashElem *i; char *zSql; - int rc; + int rc = SQLITE_OK; assert( iDb>=0 && iDbnDb ); assert( db->aDb[iDb].pBt!=0 ); @@ -93578,31 +97397,34 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); - sqlite3DefaultRowEst(pIdx); + pIdx->aiRowLogEst[0] = 0; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 sqlite3DeleteIndexSamples(db, pIdx); pIdx->aSample = 0; #endif } - /* Check to make sure the sqlite_stat1 table exists */ + /* Load new statistics out of the sqlite_stat1 table */ sInfo.db = db; - sInfo.zDatabase = db->aDb[iDb].zName; - if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){ - return SQLITE_ERROR; + sInfo.zDatabase = db->aDb[iDb].zDbSName; + if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)!=0 ){ + zSql = sqlite3MPrintf(db, + "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase); + if( zSql==0 ){ + rc = SQLITE_NOMEM_BKPT; + }else{ + rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); + sqlite3DbFree(db, zSql); + } } - /* Load new statistics out of the sqlite_stat1 table */ - zSql = sqlite3MPrintf(db, - "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase); - if( zSql==0 ){ - rc = SQLITE_NOMEM_BKPT; - }else{ - rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); - sqlite3DbFree(db, zSql); + /* 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)){ + Index *pIdx = sqliteHashData(i); + if( pIdx->aiRowLogEst[0]==0 ) sqlite3DefaultRowEst(pIdx); } - /* Load the statistics from the sqlite_stat4 table. */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ @@ -93727,7 +97549,7 @@ static void attachFunc( goto attach_error; } for(i=0; inDb; i++){ - char *z = db->aDb[i].zName; + char *z = db->aDb[i].zDbSName; assert( z && zName ); if( sqlite3StrICmp(z, zName)==0 ){ zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); @@ -93792,8 +97614,8 @@ static void attachFunc( sqlite3BtreeLeave(aNew->pBt); } aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - aNew->zName = sqlite3DbStrDup(db, zName); - if( rc==SQLITE_OK && aNew->zName==0 ){ + aNew->zDbSName = sqlite3DbStrDup(db, zName); + if( rc==SQLITE_OK && aNew->zDbSName==0 ){ rc = SQLITE_NOMEM_BKPT; } @@ -93822,7 +97644,7 @@ static void attachFunc( case SQLITE_NULL: /* No key specified. Use the key from the main database */ sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); - if( nKey>0 || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){ + if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){ rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); } break; @@ -93905,7 +97727,7 @@ static void detachFunc( for(i=0; inDb; i++){ pDb = &db->aDb[i]; if( pDb->pBt==0 ) continue; - if( sqlite3StrICmp(pDb->zName, zName)==0 ) break; + if( sqlite3StrICmp(pDb->zDbSName, zName)==0 ) break; } if( i>=db->nDb ){ @@ -93955,6 +97777,7 @@ static void codeAttach( sqlite3* db = pParse->db; int regArgs; + if( pParse->nErr ) goto attach_end; memset(&sName, 0, sizeof(NameContext)); sName.pParse = pParse; @@ -94063,7 +97886,7 @@ SQLITE_PRIVATE void sqlite3FixInit( db = pParse->db; assert( db->nDb>iDb ); pFix->pParse = pParse; - pFix->zDb = db->aDb[iDb].zName; + pFix->zDb = db->aDb[iDb].zDbSName; pFix->pSchema = db->aDb[iDb].pSchema; pFix->zType = zType; pFix->pName = pName; @@ -94160,7 +97983,7 @@ SQLITE_PRIVATE int sqlite3FixExpr( return 1; } } - if( ExprHasProperty(pExpr, EP_TokenOnly) ) break; + if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; }else{ @@ -94281,7 +98104,7 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep( ** Setting the auth function to NULL disables this hook. The default ** setting of the auth function is NULL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( +SQLITE_API int sqlite3_set_authorizer( sqlite3 *db, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pArg @@ -94321,10 +98144,11 @@ SQLITE_PRIVATE int sqlite3AuthReadCol( const char *zCol, /* Column name */ int iDb /* Index of containing database. */ ){ - sqlite3 *db = pParse->db; /* Database handle */ - char *zDb = db->aDb[iDb].zName; /* Name of attached database */ - int rc; /* Auth callback return code */ + sqlite3 *db = pParse->db; /* Database handle */ + char *zDb = db->aDb[iDb].zDbSName; /* Schema name of attached database */ + int rc; /* Auth callback return code */ + if( db->init.busy ) return SQLITE_OK; rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext #ifdef SQLITE_USER_AUTHENTICATION ,db->auth.zAuthUser @@ -94623,15 +98447,14 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ assert( !pParse->isMultiWrite || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); if( v ){ - while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){} sqlite3VdbeAddOp0(v, OP_Halt); #if SQLITE_USER_AUTHENTICATION if( pParse->nTableLock>0 && db->init.busy==0 ){ sqlite3UserAuthInit(db); if( db->auth.authLevelrc = SQLITE_AUTH_USER; sqlite3ErrorMsg(pParse, "user not authenticated"); + pParse->rc = SQLITE_AUTH_USER; return; } } @@ -94650,14 +98473,16 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init ); sqlite3VdbeJumpHere(v, 0); for(iDb=0; iDbnDb; iDb++){ + Schema *pSchema; if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue; sqlite3VdbeUsesBtree(v, iDb); + pSchema = db->aDb[iDb].pSchema; sqlite3VdbeAddOp4Int(v, OP_Transaction, /* Opcode */ iDb, /* P1 */ DbMaskTest(pParse->writeMask,iDb), /* P2 */ - pParse->cookieValue[iDb], /* P3 */ - db->aDb[iDb].pSchema->iGeneration /* P4 */ + pSchema->schema_cookie, /* P3 */ + pSchema->iGeneration /* P4 */ ); if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); VdbeComment((v, @@ -94708,16 +98533,6 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ }else{ pParse->rc = SQLITE_ERROR; } - - /* We are done with this Parse object. There is no need to de-initialize it */ -#if 0 - pParse->colNamesSet = 0; - pParse->nTab = 0; - pParse->nMem = 0; - pParse->nSet = 0; - pParse->nVar = 0; - DbMaskZero(pParse->cookieMask); -#endif } /* @@ -94737,8 +98552,7 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ char *zSql; char *zErrMsg = 0; sqlite3 *db = pParse->db; -# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar)) - char saveBuf[SAVE_SZ]; + char saveBuf[PARSE_TAIL_SZ]; if( pParse->nErr ) return; assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ @@ -94749,12 +98563,12 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ return; /* A malloc must have failed */ } pParse->nested++; - memcpy(saveBuf, &pParse->nVar, SAVE_SZ); - memset(&pParse->nVar, 0, SAVE_SZ); + memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ); + memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); sqlite3RunParser(pParse, zSql, &zErrMsg); sqlite3DbFree(db, zErrMsg); sqlite3DbFree(db, zSql); - memcpy(&pParse->nVar, saveBuf, SAVE_SZ); + memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ); pParse->nested--; } @@ -94795,10 +98609,11 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const cha #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].zName) ) continue; - assert( sqlite3SchemaMutexHeld(db, j, 0) ); - p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName); - if( p ) break; + 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; + } } return p; } @@ -94815,7 +98630,7 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const cha */ SQLITE_PRIVATE Table *sqlite3LocateTable( Parse *pParse, /* context in which to report errors */ - int isView, /* True if looking for a VIEW rather than a TABLE */ + u32 flags, /* LOCATE_VIEW or LOCATE_NOERR */ const char *zName, /* Name of the table we are looking for */ const char *zDbase /* Name of the database. Might be NULL */ ){ @@ -94829,7 +98644,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTable( p = sqlite3FindTable(pParse->db, zName, zDbase); if( p==0 ){ - const char *zMsg = isView ? "no such view" : "no such table"; + const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table"; #ifndef SQLITE_OMIT_VIRTUALTABLE if( sqlite3FindDbName(pParse->db, zDbase)<1 ){ /* If zName is the not the name of a table in the schema created using @@ -94841,12 +98656,14 @@ SQLITE_PRIVATE Table *sqlite3LocateTable( } } #endif - if( zDbase ){ - sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName); - }else{ - sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName); + if( (flags & LOCATE_NOERR)==0 ){ + if( zDbase ){ + sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName); + }else{ + sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName); + } + pParse->checkSchema = 1; } - pParse->checkSchema = 1; } return p; @@ -94863,18 +98680,18 @@ SQLITE_PRIVATE Table *sqlite3LocateTable( */ SQLITE_PRIVATE Table *sqlite3LocateTableItem( Parse *pParse, - int isView, + u32 flags, struct SrcList_item *p ){ const char *zDb; assert( p->pSchema==0 || p->zDatabase==0 ); if( p->pSchema ){ int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema); - zDb = pParse->db->aDb[iDb].zName; + zDb = pParse->db->aDb[iDb].zDbSName; }else{ zDb = p->zDatabase; } - return sqlite3LocateTable(pParse, isView, p->zName, zDb); + return sqlite3LocateTable(pParse, flags, p->zName, zDb); } /* @@ -94898,7 +98715,7 @@ SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const cha int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ Schema *pSchema = db->aDb[j].pSchema; assert( pSchema ); - if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; + if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zDbSName) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); p = sqlite3HashFind(&pSchema->idxHash, zName); if( p ) break; @@ -94967,8 +98784,8 @@ SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3 *db){ for(i=j=2; inDb; i++){ struct Db *pDb = &db->aDb[i]; if( pDb->pBt==0 ){ - sqlite3DbFree(db, pDb->zName); - pDb->zName = 0; + sqlite3DbFree(db, pDb->zDbSName); + pDb->zDbSName = 0; continue; } if( jpnBytesFreed to measure the memory ** used by the Table object. */ -SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ +static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){ Index *pIndex, *pNext; TESTONLY( int nLookaside; ) /* Used to verify lookaside not used for schema */ - assert( !pTable || pTable->nRef>0 ); - - /* Do not delete the table until the reference count reaches zero. */ - if( !pTable ) return; - if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return; - /* Record the number of outstanding lookaside allocations in schema Tables ** prior to doing any free() operations. Since schema Tables do not use ** lookaside, this number should not change. */ @@ -95088,8 +98899,9 @@ SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ /* Delete all indices associated with this table. */ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; - assert( pIndex->pSchema==pTable->pSchema ); - if( !db || db->pnBytesFreed==0 ){ + assert( pIndex->pSchema==pTable->pSchema + || (IsVirtual(pTable) && pIndex->idxType!=SQLITE_IDXTYPE_APPDEF) ); + if( (db==0 || db->pnBytesFreed==0) && !IsVirtual(pTable) ){ char *zName = pIndex->zName; TESTONLY ( Index *pOld = ) sqlite3HashInsert( &pIndex->pSchema->idxHash, zName, 0 @@ -95118,6 +98930,13 @@ SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ /* Verify that no lookaside memory was used by schema tables */ assert( nLookaside==0 || nLookaside==db->lookaside.nOut ); } +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; + deleteTable(db, pTable); +} + /* ** Unlink the given table from the hash tables and the delete the @@ -95186,7 +99005,7 @@ 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->zName, zName) ) break; + if( 0==sqlite3StrICmp(pDb->zDbSName, zName) ) break; } } return i; @@ -95245,7 +99064,7 @@ SQLITE_PRIVATE int sqlite3TwoPartName( return -1; } }else{ - assert( db->init.iDb==0 || db->init.busy ); + assert( db->init.iDb==0 || db->init.busy || (db->flags & SQLITE_Vacuum)!=0); iDb = db->init.iDb; *pUnqual = pName1; } @@ -95356,7 +99175,7 @@ SQLITE_PRIVATE void sqlite3StartTable( SQLITE_CREATE_VIEW, SQLITE_CREATE_TEMP_VIEW }; - char *zDb = db->aDb[iDb].zName; + char *zDb = db->aDb[iDb].zDbSName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ goto begin_table_error; } @@ -95375,7 +99194,7 @@ SQLITE_PRIVATE void sqlite3StartTable( ** collisions. */ if( !IN_DECLARE_VTAB ){ - char *zDb = db->aDb[iDb].zName; + char *zDb = db->aDb[iDb].zDbSName; if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto begin_table_error; } @@ -95563,6 +99382,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ zType = z + sqlite3Strlen30(z) + 1; memcpy(zType, pType->z, pType->n); zType[pType->n] = 0; + sqlite3Dequote(zType); pCol->affinity = sqlite3AffinityType(zType, &pCol->szEst); pCol->colFlags |= COLFLAG_HASTYPE; } @@ -95763,7 +99583,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey( Column *pCol = 0; int iCol = -1, i; int nTerm; - if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit; + if( pTab==0 ) goto primary_key_exit; if( pTab->tabFlags & TF_HasPrimaryKey ){ sqlite3ErrorMsg(pParse, "table \"%s\" has more than one primary key", pTab->zName); @@ -95809,12 +99629,8 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey( "INTEGER PRIMARY KEY"); #endif }else{ - Index *p; - p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, - 0, sortOrder, 0); - if( p ){ - p->idxType = SQLITE_IDXTYPE_PRIMARYKEY; - } + sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, + 0, sortOrder, 0, SQLITE_IDXTYPE_PRIMARYKEY); pList = 0; } @@ -95933,6 +99749,9 @@ SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){ ** set back to prior value. But schema changes are infrequent ** and the probability of hitting the same cookie value is only ** 1 chance in 2^32. So we're safe enough. +** +** IMPLEMENTATION-OF: R-34230-56049 SQLite automatically increments +** the schema-version whenever the schema changes. */ SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ sqlite3 *db = pParse->db; @@ -96131,21 +99950,23 @@ static int hasColumn(const i16 *aiCol, int nCol, int x){ ** are appropriate for a WITHOUT ROWID table instead of a rowid table. ** Changes include: ** -** (1) Convert the OP_CreateTable into an OP_CreateIndex. There is +** (1) Set all columns of the PRIMARY KEY schema object to be NOT NULL. +** (2) Convert the OP_CreateTable into an OP_CreateIndex. There is ** no rowid btree for a WITHOUT ROWID. Instead, the canonical ** data storage is a covering index btree. -** (2) Bypass the creation of the sqlite_master table entry +** (3) Bypass the creation of the sqlite_master table entry ** for the PRIMARY KEY as the primary key index is now ** identified by the sqlite_master table entry of the table itself. -** (3) Set the Index.tnum of the PRIMARY KEY Index object in the +** (4) Set the Index.tnum of the PRIMARY KEY Index object in the ** schema to the rootpage from the main table. -** (4) Set all columns of the PRIMARY KEY schema object to be NOT NULL. ** (5) Add all table columns to the PRIMARY KEY Index object ** so that the PRIMARY KEY is a covering index. The surplus ** columns are part of KeyInfo.nXField and are not used for ** sorting or lookup or uniqueness checks. ** (6) Replace the rowid tail on all automatically generated UNIQUE ** indices with the PRIMARY KEY columns. +** +** For virtual tables, only (1) is performed. */ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ Index *pIdx; @@ -96155,6 +99976,20 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ sqlite3 *db = pParse->db; Vdbe *v = pParse->pVdbe; + /* Mark every PRIMARY KEY column as NOT NULL (except for imposter tables) + */ + if( !db->init.imposterTable ){ + for(i=0; inCol; i++){ + if( (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0 ){ + pTab->aCol[i].notNull = OE_Abort; + } + } + } + + /* The remaining transformations only apply to b-tree tables, not to + ** virtual tables */ + if( IN_DECLARE_VTAB ) return; + /* Convert the OP_CreateTable opcode that would normally create the ** root-page for the table into an OP_CreateIndex opcode. The index ** created will become the PRIMARY KEY index. @@ -96176,9 +100011,10 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ if( pList==0 ) return; pList->a[0].sortOrder = pParse->iPkSortOrder; assert( pParse->pNewTable==pTab ); - pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0); - if( pPk==0 ) return; - pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY; + sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0, + SQLITE_IDXTYPE_PRIMARYKEY); + if( db->mallocFailed ) return; + pPk = sqlite3PrimaryKeyIndex(pTab); pTab->iPKey = -1; }else{ pPk = sqlite3PrimaryKeyIndex(pTab); @@ -96206,19 +100042,11 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ } pPk->nKeyCol = j; } - pPk->isCovering = 1; assert( pPk!=0 ); + pPk->isCovering = 1; + if( !db->init.imposterTable ) pPk->uniqNotNull = 1; nPk = pPk->nKeyCol; - /* Make sure every column of the PRIMARY KEY is NOT NULL. (Except, - ** do not enforce this for imposter tables.) */ - if( !db->init.imposterTable ){ - for(i=0; iaCol[pPk->aiColumn[i]].notNull = OE_Abort; - } - pPk->uniqNotNull = 1; - } - /* The root page of the PRIMARY KEY is the table root page */ pPk->tnum = pTab->tnum; @@ -96462,7 +100290,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].zName, SCHEMA_TABLE(iDb), + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), zType, p->zName, p->zName, @@ -96477,13 +100305,13 @@ SQLITE_PRIVATE void sqlite3EndTable( /* Check to see if we need to create an sqlite_sequence table for ** keeping track of autoincrement keys. */ - if( p->tabFlags & TF_Autoincrement ){ + if( (p->tabFlags & TF_Autoincrement)!=0 ){ Db *pDb = &db->aDb[iDb]; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( pDb->pSchema->pSeqTab==0 ){ sqlite3NestedParse(pParse, "CREATE TABLE %Q.sqlite_sequence(name,seq)", - pDb->zName + pDb->zDbSName ); } } @@ -96607,7 +100435,9 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ int nErr = 0; /* Number of errors encountered */ int n; /* Temporarily holds the number of cursors assigned */ sqlite3 *db = pParse->db; /* Database connection for malloc errors */ +#ifndef SQLITE_OMIT_AUTHORIZATION sqlite3_xauth xAuth; /* Saved xAuth pointer */ +#endif assert( pTable ); @@ -96697,7 +100527,7 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ pTable->nCol = 0; nErr++; } - if( pSelTab ) sqlite3DeleteTable(db, pSelTab); + sqlite3DeleteTable(db, pSelTab); sqlite3SelectDelete(db, pSel); db->lookaside.bDisable--; } else { @@ -96797,7 +100627,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].zName, SCHEMA_TABLE(iDb), iTable, r1, r1); + pParse->db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), iTable, r1, r1); #endif sqlite3ReleaseTempReg(pParse, r1); } @@ -96873,7 +100703,7 @@ static void sqlite3ClearStatTables( const char *zName /* Name of index or table */ ){ int i; - const char *zDbName = pParse->db->aDb[iDb].zName; + const char *zDbName = pParse->db->aDb[iDb].zDbSName; for(i=1; i<=4; i++){ char zTab[24]; sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i); @@ -96926,7 +100756,7 @@ SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, in if( pTab->tabFlags & TF_Autoincrement ){ sqlite3NestedParse(pParse, "DELETE FROM %Q.sqlite_sequence WHERE name=%Q", - pDb->zName, pTab->zName + pDb->zDbSName, pTab->zName ); } #endif @@ -96940,7 +100770,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->zName, SCHEMA_TABLE(iDb), pTab->zName); + pDb->zDbSName, SCHEMA_TABLE(iDb), pTab->zName); if( !isView && !IsVirtual(pTab) ){ destroyTable(pParse, pTab); } @@ -96973,6 +100803,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, assert( pName->nSrc==1 ); if( sqlite3ReadSchema(pParse) ) goto exit_drop_table; if( noErr ) db->suppressErr++; + assert( isView==0 || isView==LOCATE_VIEW ); pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]); if( noErr ) db->suppressErr--; @@ -96993,7 +100824,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, { int code; const char *zTab = SCHEMA_TABLE(iDb); - const char *zDb = db->aDb[iDb].zName; + const char *zDb = db->aDb[iDb].zDbSName; const char *zArg2 = 0; if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ goto exit_drop_table; @@ -97234,7 +101065,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, - db->aDb[iDb].zName ) ){ + db->aDb[iDb].zDbSName ) ){ return; } #endif @@ -97250,6 +101081,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ tnum = pIndex->tnum; } pKey = sqlite3KeyInfoOfIndex(pParse, pIndex); + assert( pKey!=0 || db->mallocFailed || pParse->nErr ); /* Open the sorter cursor if we are to use one. */ iSorter = pParse->nTab++; @@ -97273,8 +101105,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); - assert( pKey!=0 || db->mallocFailed || pParse->nErr ); - if( IsUniqueIndex(pIndex) && pKey!=0 ){ + if( IsUniqueIndex(pIndex) ){ int j2 = sqlite3VdbeCurrentAddr(v) + 3; sqlite3VdbeGoto(v, j2); addr2 = sqlite3VdbeCurrentAddr(v); @@ -97343,12 +101174,8 @@ SQLITE_PRIVATE Index *sqlite3AllocateIndexObject( ** pList is a list of columns to be indexed. pList will be NULL if this ** is a primary key or unique-constraint on the most recent column added ** to the table currently under construction. -** -** If the index is created successfully, return a pointer to the new Index -** structure. This is used by sqlite3AddPrimaryKey() to mark the index -** as the tables primary key (Index.idxType==SQLITE_IDXTYPE_PRIMARYKEY) */ -SQLITE_PRIVATE Index *sqlite3CreateIndex( +SQLITE_PRIVATE void sqlite3CreateIndex( Parse *pParse, /* All information about this parse */ Token *pName1, /* First part of index name. May be NULL */ Token *pName2, /* Second part of index name. May be NULL */ @@ -97358,9 +101185,9 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( Token *pStart, /* The CREATE token that begins this statement */ Expr *pPIWhere, /* WHERE clause for partial indices */ int sortOrder, /* Sort order of primary key when pList==NULL */ - int ifNotExist /* Omit error if index already exists */ + int ifNotExist, /* Omit error if index already exists */ + u8 idxType /* The index type */ ){ - Index *pRet = 0; /* Pointer to return */ Table *pTab = 0; /* Table to be indexed */ Index *pIndex = 0; /* The index to be created */ char *zName = 0; /* Name of the index */ @@ -97378,7 +101205,10 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( char *zExtra = 0; /* Extra space after the Index object */ Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */ - if( db->mallocFailed || IN_DECLARE_VTAB || pParse->nErr>0 ){ + if( db->mallocFailed || pParse->nErr>0 ){ + goto exit_create_index; + } + if( IN_DECLARE_VTAB && idxType!=SQLITE_IDXTYPE_PRIMARYKEY ){ goto exit_create_index; } if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ @@ -97487,7 +101317,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( goto exit_create_index; } } - if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){ + if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){ if( !ifNotExist ){ sqlite3ErrorMsg(pParse, "index %s already exists", zName); }else{ @@ -97504,13 +101334,20 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( if( zName==0 ){ goto exit_create_index; } + + /* Automatic index names generated from within sqlite3_declare_vtab() + ** must have names that are distinct from normal automatic index names. + ** The following statement converts "sqlite3_autoindex..." into + ** "sqlite3_butoindex..." in order to make the names distinct. + ** The "vtab_err.test" test demonstrates the need of this statement. */ + if( IN_DECLARE_VTAB ) zName[7]++; } /* Check for authorization to create an index. */ #ifndef SQLITE_OMIT_AUTHORIZATION { - const char *zDb = pDb->zName; + const char *zDb = pDb->zDbSName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ goto exit_create_index; } @@ -97567,7 +101404,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( pIndex->pTable = pTab; pIndex->onError = (u8)onError; pIndex->uniqNotNull = onError!=OE_None; - pIndex->idxType = pName ? SQLITE_IDXTYPE_APPDEF : SQLITE_IDXTYPE_UNIQUE; + pIndex->idxType = idxType; pIndex->pSchema = db->aDb[iDb].pSchema; pIndex->nKeyCol = pList->nExpr; if( pPIWhere ){ @@ -97747,7 +101584,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( pIdx->onError = pIndex->onError; } } - pRet = pIdx; + if( idxType==SQLITE_IDXTYPE_PRIMARYKEY ) pIdx->idxType = idxType; goto exit_create_index; } } @@ -97759,6 +101596,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( assert( pParse->nErr==0 ); if( db->init.busy ){ Index *p; + assert( !IN_DECLARE_VTAB ); assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); p = sqlite3HashInsert(&pIndex->pSchema->idxHash, pIndex->zName, pIndex); @@ -97824,7 +101662,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( */ sqlite3NestedParse(pParse, "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pIndex->zName, pTab->zName, iMem, @@ -97840,7 +101678,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(v, iDb, sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName)); - sqlite3VdbeAddOp1(v, OP_Expire, 0); + sqlite3VdbeAddOp0(v, OP_Expire); } sqlite3VdbeJumpHere(v, pIndex->tnum); @@ -97865,7 +101703,6 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( pIndex->pNext = pOther->pNext; pOther->pNext = pIndex; } - pRet = pIndex; pIndex = 0; } @@ -97876,7 +101713,6 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( sqlite3ExprListDelete(db, pList); sqlite3SrcListDelete(db, pTblName); sqlite3DbFree(db, zName); - return pRet; } /* @@ -97905,10 +101741,11 @@ SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){ int i; /* Set the first entry (number of rows in the index) to the estimated - ** number of rows in the table. Or 10, if the estimated number of rows - ** in the table is less than that. */ + ** 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. */ a[0] = pIdx->pTable->nRowLogEst; - if( a[0]<33 ) a[0] = 33; assert( 33==sqlite3LogEst(10) ); + if( pIdx->pPartIdxWhere!=0 ) a[0] -= 10; assert( 10==sqlite3LogEst(2) ); + if( a[0]<33 ) a[0] = 33; assert( 33==sqlite3LogEst(10) ); /* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is ** 6 and each subsequent value (if any) is 5. */ @@ -97959,7 +101796,7 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists { int code = SQLITE_DROP_INDEX; Table *pTab = pIndex->pTable; - const char *zDb = db->aDb[iDb].zName; + const char *zDb = db->aDb[iDb].zDbSName; const char *zTab = SCHEMA_TABLE(iDb); if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ goto exit_drop_index; @@ -97977,7 +101814,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].zName, SCHEMA_TABLE(iDb), pIndex->zName + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pIndex->zName ); sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName); sqlite3ChangeCookie(pParse, iDb); @@ -98498,15 +102335,13 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ */ SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ Parse *pToplevel = sqlite3ParseToplevel(pParse); - sqlite3 *db = pToplevel->db; - assert( iDb>=0 && iDbnDb ); - assert( db->aDb[iDb].pBt!=0 || iDb==1 ); + assert( iDb>=0 && iDbdb->nDb ); + assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 ); assert( iDbdb, iDb, 0) ); if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){ DbMaskSet(pToplevel->cookieMask, iDb); - pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; if( !OMIT_TEMPDB && iDb==1 ){ sqlite3OpenTempDatabase(pToplevel); } @@ -98522,7 +102357,7 @@ SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb) int i; for(i=0; inDb; i++){ Db *pDb = &db->aDb[i]; - if( pDb->pBt && (!zDb || 0==sqlite3StrICmp(zDb, pDb->zName)) ){ + if( pDb->pBt && (!zDb || 0==sqlite3StrICmp(zDb, pDb->zDbSName)) ){ sqlite3CodeVerifySchema(pParse, i); } } @@ -98769,7 +102604,7 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ if( iDb<0 ) return; z = sqlite3NameFromToken(db, pObjName); if( z==0 ) return; - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; pTab = sqlite3FindTable(db, z, zDb); if( pTab ){ reindexTable(pParse, pTab, 0); @@ -98790,10 +102625,6 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ /* ** Return a KeyInfo structure that is appropriate for the given Index. ** -** The KeyInfo structure for an index is cached in the Index object. -** So there might be multiple references to the returned pointer. The -** caller should not try to modify the KeyInfo object. -** ** The caller should invoke sqlite3KeyInfoUnref() on the returned object ** when it has finished using it. */ @@ -99487,7 +103318,7 @@ SQLITE_PRIVATE void sqlite3MaterializeView( if( pFrom ){ assert( pFrom->nSrc==1 ); pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName); - pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); + pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); assert( pFrom->a[0].pOn==0 ); assert( pFrom->a[0].pUsing==0 ); } @@ -99528,7 +103359,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( */ if( pOrderBy && (pLimit == 0) ) { sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType); - goto limit_where_cleanup_2; + goto limit_where_cleanup; } /* We only need to generate a select expression if there @@ -99550,16 +103381,16 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( */ pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); - if( pSelectRowid == 0 ) goto limit_where_cleanup_2; + if( pSelectRowid == 0 ) goto limit_where_cleanup; pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid); - if( pEList == 0 ) goto limit_where_cleanup_2; + if( pEList == 0 ) goto limit_where_cleanup; /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree ** and the SELECT subtree. */ pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0); if( pSelectSrc == 0 ) { sqlite3ExprListDelete(pParse->db, pEList); - goto limit_where_cleanup_2; + goto limit_where_cleanup; } /* generate the SELECT expression tree. */ @@ -99569,21 +103400,11 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); - if( pWhereRowid == 0 ) goto limit_where_cleanup_1; - pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0); - if( pInClause == 0 ) goto limit_where_cleanup_1; - - pInClause->x.pSelect = pSelect; - pInClause->flags |= EP_xIsSelect; - sqlite3ExprSetHeightAndFlags(pParse, pInClause); + pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0) : 0; + sqlite3PExprAddSelect(pParse, pInClause, pSelect); return pInClause; - /* something went wrong. clean up anything allocated. */ -limit_where_cleanup_1: - sqlite3SelectDelete(pParse->db, pSelect); - return 0; - -limit_where_cleanup_2: +limit_where_cleanup: sqlite3ExprDelete(pParse->db, pWhere); sqlite3ExprListDelete(pParse->db, pOrderBy); sqlite3ExprDelete(pParse->db, pLimit); @@ -99607,7 +103428,6 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( ){ Vdbe *v; /* The virtual database engine */ Table *pTab; /* The table from which records will be deleted */ - const char *zDb; /* Name of database holding pTab */ int i; /* Loop counter */ WhereInfo *pWInfo; /* Information about the WHERE clause */ Index *pIdx; /* For looping over indices of the table */ @@ -99634,11 +103454,12 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( int addrBypass = 0; /* Address of jump over the delete logic */ int addrLoop = 0; /* Top of the delete loop */ int addrEphOpen = 0; /* Instruction to open the Ephemeral table */ + int bComplex; /* True if there are triggers or FKs or + ** subqueries in the WHERE clause */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ Trigger *pTrigger; /* List of table triggers, if required */ - int bComplex; /* True if there are either triggers or FKs */ #endif memset(&sContext, 0, sizeof(sContext)); @@ -99666,7 +103487,6 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( #else # define pTrigger 0 # define isView 0 -# define bComplex 0 #endif #ifdef SQLITE_OMIT_VIEW # undef isView @@ -99684,8 +103504,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDbnDb ); - zDb = db->aDb[iDb].zName; - rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb); + rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, + db->aDb[iDb].zDbSName); assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); if( rcauth==SQLITE_DENY ){ goto delete_from_cleanup; @@ -99751,6 +103571,9 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( && pWhere==0 && !bComplex && !IsVirtual(pTab) +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + && db->xPreUpdateCallback==0 +#endif ){ assert( !isView ); sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); @@ -99765,7 +103588,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( }else #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ { - u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK; + u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK|WHERE_SEEK_TABLE; + if( sNC.ncFlags & NC_VarSelect ) bComplex = 1; wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW); if( HasRowid(pTab) ){ /* For a rowid table, initialize the RowSet to an empty set */ @@ -99865,7 +103689,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( if( !isView ){ int iAddrOnce = 0; if( eOnePass==ONEPASS_MULTI ){ - iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); + iAddrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } testcase( IsVirtual(pTab) ); sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE, @@ -100100,14 +103924,19 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete( /* Delete the index and table entries. Skip this step if pTab is really ** a view (in which case the only effect of the DELETE statement is to - ** fire the INSTEAD OF triggers). */ + ** fire the INSTEAD OF triggers). + ** + ** If variable 'count' is non-zero, then this OP_Delete instruction should + ** invoke the update-hook. The pre-update-hook, on the other hand should + ** be invoked unless table pTab is a system table. The difference is that + ** the update-hook is not invoked for rows removed by REPLACE, but the + ** pre-update-hook is. + */ if( pTab->pSelect==0 ){ u8 p5 = 0; sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); - if( count ){ - sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); - } + sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE); if( eMode!=ONEPASS_OFF ){ sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); } @@ -100494,6 +104323,8 @@ static void instrFunc( zHaystack = sqlite3_value_text(argv[0]); zNeedle = sqlite3_value_text(argv[1]); isText = 1; + if( zNeedle==0 ) return; + assert( zHaystack ); } while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){ N++; @@ -101026,7 +104857,7 @@ static int patternCompare( } c2 = Utf8Read(zString); if( c==c2 ) continue; - if( noCase && c<0x80 && c2<0x80 && sqlite3Tolower(c)==sqlite3Tolower(c2) ){ + if( noCase && sqlite3Tolower(c)==sqlite3Tolower(c2) && c<0x80 && c2<0x80 ){ continue; } if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue; @@ -101038,14 +104869,14 @@ static int patternCompare( /* ** The sqlite3_strglob() interface. */ -SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlobPattern, const char *zString){ +SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){ return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[')==0; } /* ** The sqlite3_strlike() interface. */ -SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){ +SQLITE_API int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){ return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc)==0; } @@ -101602,6 +105433,26 @@ static void trimFunc( } +#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION +/* +** The "unknown" function is automatically substituted in place of +** any unrecognized function name when doing an EXPLAIN or EXPLAIN QUERY PLAN +** when the SQLITE_ENABLE_UNKNOWN_FUNCTION compile-time option is used. +** When the "sqlite3" command-line shell is built using this functionality, +** that allows an EXPLAIN or EXPLAIN QUERY PLAN for complex queries +** involving application-defined functions to be examined in a generic +** sqlite3 shell. +*/ +static void unknownFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + /* no-op */ +} +#endif /*SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION*/ + + /* IMP: R-25361-16150 This function is omitted from SQLite by default. It ** is only available if the SQLITE_SOUNDEX compile-time option is used ** when SQLite is built. @@ -101672,6 +105523,14 @@ static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ sqlite3 *db = sqlite3_context_db_handle(context); char *zErrMsg = 0; + /* Disallow the load_extension() SQL function unless the SQLITE_LoadExtFunc + ** flag is set. See the sqlite3_enable_load_extension() API. + */ + if( (db->flags & SQLITE_LoadExtFunc)==0 ){ + sqlite3_result_error(context, "not authorized", -1); + return; + } + if( argc==2 ){ zProc = (const char *)sqlite3_value_text(argv[1]); }else{ @@ -102064,13 +105923,16 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize), LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), - #ifdef SQLITE_CASE_SENSITIVE_LIKE +#ifdef SQLITE_CASE_SENSITIVE_LIKE LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), - #else +#else LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE), LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE), - #endif +#endif +#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION + FUNCTION(unknown, -1, 0, 0, unknownFunc ), +#endif FUNCTION(coalesce, 1, 0, 0, 0 ), FUNCTION(coalesce, 0, 0, 0, 0 ), FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), @@ -102976,7 +106838,7 @@ SQLITE_PRIVATE void sqlite3FkCheck( if( (db->flags&SQLITE_ForeignKeys)==0 ) return; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; /* Loop through all the foreign key constraints for which pTab is the ** child table (the table that the foreign key definition is part of). */ @@ -103270,7 +107132,6 @@ static Trigger *fkActionTrigger( if( action==OE_Restrict && (db->flags & SQLITE_DeferFKs) ){ return 0; } - pTrigger = pFKey->apTrigger[iAction]; if( action!=OE_None && !pTrigger ){ @@ -103348,10 +107209,10 @@ static Trigger *fkActionTrigger( if( pDflt ){ pNew = sqlite3ExprDup(db, pDflt, 0); }else{ - pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); + pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); } }else{ - pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); + pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); } pList = sqlite3ExprListAppend(pParse, pList, pNew); sqlite3ExprListSetName(pParse, pList, &tFromCol, 0); @@ -103478,7 +107339,8 @@ SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){ FKey *pFKey; /* Iterator variable */ FKey *pNext; /* Copy of pFKey->pNextFrom */ - assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) ); + assert( db==0 || IsVirtual(pTab) + || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) ); for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){ /* Remove the FK from the fkeyHash hash table. */ @@ -103716,7 +107578,9 @@ static int readsTable(Parse *p, int iDb, Table *pTab){ /* ** Locate or create an AutoincInfo structure associated with table pTab ** which is in database iDb. Return the register number for the register -** that holds the maximum rowid. +** that holds the maximum rowid. Return zero if pTab is not an AUTOINCREMENT +** table. (Also return zero when doing a VACUUM since we do not want to +** update the AUTOINCREMENT counters during a VACUUM.) ** ** There is at most one AutoincInfo structure per table even if the ** same table is autoincremented multiple times due to inserts within @@ -103739,7 +107603,9 @@ static int autoIncBegin( Table *pTab /* The table we are writing to */ ){ int memId = 0; /* Register holding maximum rowid */ - if( pTab->tabFlags & TF_Autoincrement ){ + if( (pTab->tabFlags & TF_Autoincrement)!=0 + && (pParse->db->flags & SQLITE_Vacuum)==0 + ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); AutoincInfo *pInfo; @@ -103997,7 +107863,6 @@ 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 */ - const char *zDb; /* Name of the database holding this table */ int i, j, idx; /* Loop counters */ Vdbe *v; /* Generate code into this virtual machine */ Index *pIdx; /* For looping over indices of the table */ @@ -104012,7 +107877,6 @@ SQLITE_PRIVATE void sqlite3Insert( int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */ SelectDest dest; /* Destination for SELECT on rhs of INSERT */ int iDb; /* Index of database holding TABLE */ - Db *pDb; /* The database containing table being inserted into */ u8 useTempTable = 0; /* Store SELECT results in intermediate table */ u8 appendFlag = 0; /* True if the insert is likely to be an append */ u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ @@ -104062,9 +107926,8 @@ SQLITE_PRIVATE void sqlite3Insert( } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDbnDb ); - pDb = &db->aDb[iDb]; - zDb = pDb->zName; - if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, + db->aDb[iDb].zDbSName) ){ goto insert_cleanup; } withoutRowid = !HasRowid(pTab); @@ -104947,9 +108810,18 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ sqlite3MultiWrite(pParse); sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, - regNewData, 1, 0, OE_Replace, - ONEPASS_SINGLE, -1); + regNewData, 1, 0, OE_Replace, 1, -1); }else{ +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + if( HasRowid(pTab) ){ + /* This OP_Delete opcode fires the pre-update-hook only. It does + ** not modify the b-tree. It is more efficient to let the coming + ** 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); + } +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ if( pTab->pIndex ){ sqlite3MultiWrite(pParse); sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,-1); @@ -105219,7 +109091,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion( } sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData); if( !pParse->nested ){ - sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); + sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE); } sqlite3VdbeChangeP5(v, pik_flags); } @@ -105284,15 +109156,15 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices( for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ int iIdxCur = iBase++; assert( pIdx->pSchema==pTab->pSchema ); + if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ + if( piDataCur ) *piDataCur = iIdxCur; + p5 = 0; + } if( aToOpen==0 || aToOpen[i+1] ){ sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - VdbeComment((v, "%s", pIdx->zName)); - } - if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ - if( piDataCur ) *piDataCur = iIdxCur; - }else{ sqlite3VdbeChangeP5(v, p5); + VdbeComment((v, "%s", pIdx->zName)); } } if( iBase>pParse->nTab ) pParse->nTab = iBase; @@ -105619,7 +109491,7 @@ static int xferOptimization( } sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData); sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid, - pDest->zName, 0); + (char*)pDest, P4_TABLE); sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); @@ -105683,6 +109555,7 @@ static int xferOptimization( sqlite3ReleaseTempReg(pParse, regRowid); sqlite3ReleaseTempReg(pParse, regData); if( emptyDestTest ){ + sqlite3AutoincrementEnd(pParse); sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0); sqlite3VdbeJumpHere(v, emptyDestTest); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); @@ -105724,7 +109597,7 @@ static int xferOptimization( ** argument to xCallback(). If xCallback=NULL then no callback ** is invoked, even for queries. */ -SQLITE_API int SQLITE_STDCALL sqlite3_exec( +SQLITE_API int sqlite3_exec( sqlite3 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ sqlite3_callback xCallback, /* Invoke this callback routine */ @@ -105879,12 +109752,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec( ** as extensions by SQLite should #include this file instead of ** sqlite3.h. */ -#ifndef _SQLITE3EXT_H_ -#define _SQLITE3EXT_H_ +#ifndef SQLITE3EXT_H +#define SQLITE3EXT_H /* #include "sqlite3.h" */ -typedef struct sqlite3_api_routines sqlite3_api_routines; - /* ** The following structure holds pointers to all of the SQLite API ** routines. @@ -106145,8 +110016,21 @@ struct sqlite3_api_routines { int (*db_cacheflush)(sqlite3*); /* Version 3.12.0 and later */ int (*system_errno)(sqlite3*); + /* Version 3.14.0 and later */ + int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*); + char *(*expanded_sql)(sqlite3_stmt*); }; +/* +** This is the function signature used for all extension entry points. It +** is also defined in the file "loadext.c". +*/ +typedef int (*sqlite3_loadext_entry)( + sqlite3 *db, /* Handle to the database. */ + char **pzErrMsg, /* Used to set error string on failure. */ + const sqlite3_api_routines *pThunk /* Extension API function pointers. */ +); + /* ** The following macros redefine the API routines so that they are ** redirected through the global sqlite3_api structure. @@ -106390,6 +110274,9 @@ struct sqlite3_api_routines { #define sqlite3_db_cacheflush sqlite3_api->db_cacheflush /* Version 3.12.0 and later */ #define sqlite3_system_errno sqlite3_api->system_errno +/* Version 3.14.0 and later */ +#define sqlite3_trace_v2 sqlite3_api->trace_v2 +#define sqlite3_expanded_sql sqlite3_api->expanded_sql #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) @@ -106407,7 +110294,7 @@ struct sqlite3_api_routines { # define SQLITE_EXTENSION_INIT3 /*no-op*/ #endif -#endif /* _SQLITE3EXT_H_ */ +#endif /* SQLITE3EXT_H */ /************** End of sqlite3ext.h ******************************************/ /************** Continuing where we left off in loadext.c ********************/ @@ -106415,7 +110302,6 @@ struct sqlite3_api_routines { /* #include */ #ifndef SQLITE_OMIT_LOAD_EXTENSION - /* ** Some API routines are omitted when various features are ** excluded from a build of SQLite. Substitute a NULL pointer @@ -106485,7 +110371,7 @@ struct sqlite3_api_routines { # define sqlite3_enable_shared_cache 0 #endif -#ifdef SQLITE_OMIT_TRACE +#if defined(SQLITE_OMIT_TRACE) || defined(SQLITE_OMIT_DEPRECATED) # define sqlite3_profile 0 # define sqlite3_trace 0 #endif @@ -106505,6 +110391,10 @@ struct sqlite3_api_routines { #define sqlite3_blob_reopen 0 #endif +#if defined(SQLITE_OMIT_TRACE) +# define sqlite3_trace_v2 0 +#endif + /* ** The following structure contains pointers to all SQLite API routines. ** A pointer to this structure is passed into extensions when they are @@ -106810,7 +110700,10 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_strlike, sqlite3_db_cacheflush, /* Version 3.12.0 and later */ - sqlite3_system_errno + sqlite3_system_errno, + /* Version 3.14.0 and later */ + sqlite3_trace_v2, + sqlite3_expanded_sql }; /* @@ -106833,13 +110726,14 @@ static int sqlite3LoadExtension( ){ sqlite3_vfs *pVfs = db->pVfs; void *handle; - int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); + sqlite3_loadext_entry xInit; char *zErrmsg = 0; const char *zEntry; char *zAltEntry = 0; void **aHandle; u64 nMsg = 300 + sqlite3Strlen30(zFile); int ii; + int rc; /* Shared library endings to try if zFile cannot be loaded as written */ static const char *azEndings[] = { @@ -106858,8 +110752,9 @@ static int sqlite3LoadExtension( /* Ticket #1863. To avoid a creating security problems for older ** applications that relink against newer versions of SQLite, the ** ability to run load_extension is turned off by default. One - ** must call sqlite3_enable_load_extension() to turn on extension - ** loading. Otherwise you get the following error. + ** must call either sqlite3_enable_load_extension(db) or + ** sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, 0) + ** to turn on extension loading. */ if( (db->flags & SQLITE_LoadExtension)==0 ){ if( pzErrMsg ){ @@ -106890,8 +110785,7 @@ static int sqlite3LoadExtension( } return SQLITE_ERROR; } - xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) - sqlite3OsDlSym(pVfs, handle, zEntry); + xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); /* If no entry point was specified and the default legacy ** entry point name "sqlite3_extension_init" was not found, then @@ -106923,8 +110817,7 @@ static int sqlite3LoadExtension( } memcpy(zAltEntry+iEntry, "_init", 6); zEntry = zAltEntry; - xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) - sqlite3OsDlSym(pVfs, handle, zEntry); + xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); } if( xInit==0 ){ if( pzErrMsg ){ @@ -106941,7 +110834,9 @@ static int sqlite3LoadExtension( return SQLITE_ERROR; } sqlite3_free(zAltEntry); - if( xInit(db, &zErrmsg, &sqlite3Apis) ){ + rc = xInit(db, &zErrmsg, &sqlite3Apis); + if( rc ){ + if( rc==SQLITE_OK_LOAD_PERMANENTLY ) return SQLITE_OK; if( pzErrMsg ){ *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg); } @@ -106964,7 +110859,7 @@ static int sqlite3LoadExtension( db->aExtension[db->nExtension++] = handle; return SQLITE_OK; } -SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( +SQLITE_API int sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ @@ -106995,29 +110890,18 @@ SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3 *db){ ** Enable or disable extension loading. Extension loading is disabled by ** default so as not to open security holes in older applications. */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff){ +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ sqlite3_mutex_enter(db->mutex); if( onoff ){ - db->flags |= SQLITE_LoadExtension; + db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc; }else{ - db->flags &= ~SQLITE_LoadExtension; + db->flags &= ~(SQLITE_LoadExtension|SQLITE_LoadExtFunc); } sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ - -/* -** The auto-extension code added regardless of whether or not extension -** loading is supported. We need a dummy sqlite3Apis pointer for that -** code if regular extension loading is not available. This is that -** dummy pointer. -*/ -#ifdef SQLITE_OMIT_LOAD_EXTENSION -static const sqlite3_api_routines sqlite3Apis = { 0 }; -#endif - +#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */ /* ** The following object holds the list of automatically loaded @@ -107052,7 +110936,9 @@ static SQLITE_WSD struct sqlite3AutoExtList { ** Register a statically linked extension that is automatically ** loaded by every new database connection. */ -SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xInit)(void)){ +SQLITE_API int sqlite3_auto_extension( + void (*xInit)(void) +){ int rc = SQLITE_OK; #ifndef SQLITE_OMIT_AUTOINIT rc = sqlite3_initialize(); @@ -107097,7 +110983,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xInit)(void)){ ** Return 1 if xInit was found on the list and removed. Return 0 if xInit ** was not on the list. */ -SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xInit)(void)){ +SQLITE_API int sqlite3_cancel_auto_extension( + void (*xInit)(void) +){ #if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif @@ -107120,7 +111008,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xInit)(void)) /* ** Reset the automatic extension loading mechanism. */ -SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void){ +SQLITE_API void sqlite3_reset_auto_extension(void){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize()==SQLITE_OK ) #endif @@ -107146,7 +111034,7 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ u32 i; int go = 1; int rc; - int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); + sqlite3_loadext_entry xInit; wsdAutoextInit; if( wsdAutoext.nExt==0 ){ @@ -107157,18 +111045,22 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ char *zErrmsg; #if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); +#endif +#ifdef SQLITE_OMIT_LOAD_EXTENSION + const sqlite3_api_routines *pThunk = 0; +#else + const sqlite3_api_routines *pThunk = &sqlite3Apis; #endif sqlite3_mutex_enter(mutex); if( i>=wsdAutoext.nExt ){ xInit = 0; go = 0; }else{ - xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) - wsdAutoext.aExt[i]; + xInit = (sqlite3_loadext_entry)wsdAutoext.aExt[i]; } sqlite3_mutex_leave(mutex); zErrmsg = 0; - if( xInit && (rc = xInit(db, &zErrmsg, &sqlite3Apis))!=0 ){ + if( xInit && (rc = xInit(db, &zErrmsg, pThunk))!=0 ){ sqlite3ErrorWithMsg(db, rc, "automatic extension loading failed: %s", zErrmsg); go = 0; @@ -107987,7 +111879,7 @@ SQLITE_PRIVATE void sqlite3Pragma( } assert( pId2 ); - zDb = pId2->n>0 ? pDb->zName : 0; + zDb = pId2->n>0 ? pDb->zDbSName : 0; if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ goto pragma_out; } @@ -108679,7 +112571,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** compiler (eg. count_changes). So add an opcode to expire all ** compiled SQL statements after modifying a pragma value. */ - sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); + sqlite3VdbeAddOp0(v, OP_Expire); setAllPagerFlags(db); } break; @@ -108701,7 +112593,7 @@ SQLITE_PRIVATE void sqlite3Pragma( */ case PragTyp_TABLE_INFO: if( zRight ){ Table *pTab; - pTab = sqlite3FindTable(db, zRight, zDb); + pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); if( pTab ){ static const char *azCol[] = { "cid", "name", "type", "notnull", "dflt_value", "pk" @@ -108840,10 +112732,10 @@ SQLITE_PRIVATE void sqlite3Pragma( setAllColumnNames(v, 3, azCol); assert( 3==ArraySize(azCol) ); for(i=0; inDb; i++){ if( db->aDb[i].pBt==0 ) continue; - assert( db->aDb[i].zName!=0 ); + assert( db->aDb[i].zDbSName!=0 ); sqlite3VdbeMultiLoad(v, 1, "iss", i, - db->aDb[i].zName, + db->aDb[i].zDbSName, sqlite3BtreeGetFilename(db->aDb[i].pBt)); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); } @@ -108983,12 +112875,10 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); sqlite3ColumnDefault(v, pTab, iKey, regRow); sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, - sqlite3VdbeCurrentAddr(v)+3); VdbeCoverage(v); }else{ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); } - sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_SeekRowid, i, 0, regRow); VdbeCoverage(v); sqlite3VdbeGoto(v, addrOk); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); }else{ @@ -109134,7 +113024,7 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeChangeP5(v, (u8)i); addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, - sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), + sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName), P4_DYNAMIC); sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2); @@ -109573,15 +113463,15 @@ SQLITE_PRIVATE void sqlite3Pragma( Btree *pBt; const char *zState = "unknown"; int j; - if( db->aDb[i].zName==0 ) continue; + if( db->aDb[i].zDbSName==0 ) continue; pBt = db->aDb[i].pBt; if( pBt==0 || sqlite3BtreePager(pBt)==0 ){ zState = "closed"; - }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0, + }else if( sqlite3_file_control(db, i ? db->aDb[i].zDbSName : 0, SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){ zState = azLockName[j]; } - sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zName, zState); + sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zDbSName, zState); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); } break; @@ -109717,6 +113607,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char ** structures that describe the table, index, or view. */ int rc; + u8 saved_iDb = db->init.iDb; sqlite3_stmt *pStmt; TESTONLY(int rcp); /* Return code from sqlite3_prepare() */ @@ -109727,7 +113618,8 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0); rc = db->errCode; assert( (rc&0xFF)==(rcp&0xFF) ); - db->init.iDb = 0; + db->init.iDb = saved_iDb; + assert( saved_iDb==0 || (db->flags & SQLITE_Vacuum)!=0 ); if( SQLITE_OK!=rc ){ if( db->init.orphanTrigger ){ assert( iDb==1 ); @@ -109751,7 +113643,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char ** to do here is record the root page number for that index. */ Index *pIndex; - pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName); + pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName); if( pIndex==0 ){ /* This can occur if there exists an index on a TEMP table which ** has the same name as another index on a permanent index. Since @@ -109930,7 +113822,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ char *zSql; zSql = sqlite3MPrintf(db, "SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid", - db->aDb[iDb].zName, zMasterName); + db->aDb[iDb].zDbSName, zMasterName); #ifndef SQLITE_OMIT_AUTHORIZATION { sqlite3_xauth xAuth; @@ -110160,18 +114052,14 @@ static int sqlite3Prepare( sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ - Parse *pParse; /* Parsing context */ char *zErrMsg = 0; /* Error message */ int rc = SQLITE_OK; /* Result code */ int i; /* Loop counter */ + Parse sParse; /* Parsing context */ - /* Allocate the parsing context */ - pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); - if( pParse==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto end_prepare; - } - pParse->pReprepare = pReprepare; + memset(&sParse, 0, PARSE_HDR_SZ); + memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ); + sParse.pReprepare = pReprepare; assert( ppStmt && *ppStmt==0 ); /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */ assert( sqlite3_mutex_held(db->mutex) ); @@ -110205,7 +114093,7 @@ static int sqlite3Prepare( assert( sqlite3BtreeHoldsMutex(pBt) ); rc = sqlite3BtreeSchemaLocked(pBt); if( rc ){ - const char *zDb = db->aDb[i].zName; + const char *zDb = db->aDb[i].zDbSName; sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb); testcase( db->flags & SQLITE_ReadUncommitted ); goto end_prepare; @@ -110215,8 +114103,7 @@ static int sqlite3Prepare( sqlite3VtabUnlockList(db); - pParse->db = db; - pParse->nQueryLoop = 0; /* Logarithmic, so 0 really means 1 */ + sParse.db = db; if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ char *zSqlCopy; int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; @@ -110229,61 +114116,61 @@ static int sqlite3Prepare( } zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); if( zSqlCopy ){ - sqlite3RunParser(pParse, zSqlCopy, &zErrMsg); - pParse->zTail = &zSql[pParse->zTail-zSqlCopy]; + sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); + sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; sqlite3DbFree(db, zSqlCopy); }else{ - pParse->zTail = &zSql[nBytes]; + sParse.zTail = &zSql[nBytes]; } }else{ - sqlite3RunParser(pParse, zSql, &zErrMsg); + sqlite3RunParser(&sParse, zSql, &zErrMsg); } - assert( 0==pParse->nQueryLoop ); + assert( 0==sParse.nQueryLoop ); - if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK; - if( pParse->checkSchema ){ - schemaIsValid(pParse); + if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; + if( sParse.checkSchema ){ + schemaIsValid(&sParse); } if( db->mallocFailed ){ - pParse->rc = SQLITE_NOMEM_BKPT; + sParse.rc = SQLITE_NOMEM_BKPT; } if( pzTail ){ - *pzTail = pParse->zTail; + *pzTail = sParse.zTail; } - rc = pParse->rc; + rc = sParse.rc; #ifndef SQLITE_OMIT_EXPLAIN - if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){ + if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ static const char * const azColName[] = { "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", "selectid", "order", "from", "detail" }; int iFirst, mx; - if( pParse->explain==2 ){ - sqlite3VdbeSetNumCols(pParse->pVdbe, 4); + if( sParse.explain==2 ){ + sqlite3VdbeSetNumCols(sParse.pVdbe, 4); iFirst = 8; mx = 12; }else{ - sqlite3VdbeSetNumCols(pParse->pVdbe, 8); + sqlite3VdbeSetNumCols(sParse.pVdbe, 8); iFirst = 0; mx = 8; } for(i=iFirst; ipVdbe, i-iFirst, COLNAME_NAME, + sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME, azColName[i], SQLITE_STATIC); } } #endif if( db->init.busy==0 ){ - Vdbe *pVdbe = pParse->pVdbe; - sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag); + Vdbe *pVdbe = sParse.pVdbe; + sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag); } - if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ - sqlite3VdbeFinalize(pParse->pVdbe); + if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ + sqlite3VdbeFinalize(sParse.pVdbe); assert(!(*ppStmt)); }else{ - *ppStmt = (sqlite3_stmt*)pParse->pVdbe; + *ppStmt = (sqlite3_stmt*)sParse.pVdbe; } if( zErrMsg ){ @@ -110294,16 +114181,15 @@ static int sqlite3Prepare( } /* Delete any TriggerPrg structures allocated while parsing this statement. */ - while( pParse->pTriggerPrg ){ - TriggerPrg *pT = pParse->pTriggerPrg; - pParse->pTriggerPrg = pT->pNext; + while( sParse.pTriggerPrg ){ + TriggerPrg *pT = sParse.pTriggerPrg; + sParse.pTriggerPrg = pT->pNext; sqlite3DbFree(db, pT); } end_prepare: - sqlite3ParserReset(pParse); - sqlite3StackFree(db, pParse); + sqlite3ParserReset(&sParse); rc = sqlite3ApiExit(db, rc); assert( (rc&db->errMask)==rc ); return rc; @@ -110384,7 +114270,7 @@ SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){ ** and the statement is automatically recompiled if an schema change ** occurs. */ -SQLITE_API int SQLITE_STDCALL sqlite3_prepare( +SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -110396,7 +114282,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_prepare( assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2( +SQLITE_API int sqlite3_prepare_v2( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -110472,7 +114358,7 @@ static int sqlite3Prepare16( ** and the statement is automatically recompiled if an schema change ** occurs. */ -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( +SQLITE_API int sqlite3_prepare16( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-16 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -110484,7 +114370,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( +SQLITE_API int sqlite3_prepare16_v2( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-16 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -110559,6 +114445,7 @@ struct SortCtx { int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */ int labelDone; /* Jump here when done, ex: LIMIT reached */ u8 sortFlags; /* Zero or more SORTFLAG_* bits */ + u8 bOrderedInnerLoop; /* ORDER BY correctly sorts the inner loop */ }; #define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */ @@ -110577,7 +114464,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){ sqlite3ExprListDelete(db, p->pOrderBy); sqlite3ExprDelete(db, p->pLimit); sqlite3ExprDelete(db, p->pOffset); - sqlite3WithDelete(db, p->pWith); + if( p->pWith ) sqlite3WithDelete(db, p->pWith); if( bFree ) sqlite3DbFree(db, p); p = pPrior; bFree = 1; @@ -110590,7 +114477,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){ SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ pDest->eDest = (u8)eDest; pDest->iSDParm = iParm; - pDest->affSdst = 0; + pDest->zAffSdst = 0; pDest->iSdst = 0; pDest->nSdst = 0; } @@ -110672,7 +114559,7 @@ SQLITE_PRIVATE void sqlite3SelectSetName(Select *p, const char *zName){ ** Delete the given Select structure and all of its substructures. */ SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){ - clearSelect(db, p, 1); + if( p ) clearSelect(db, p, 1); } /* @@ -111092,9 +114979,30 @@ static void pushOntoSorter( sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord); if( iLimit ){ int addr; + int r1 = 0; + /* Fill the sorter until it contains LIMIT+OFFSET entries. (The iLimit + ** 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); sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor); + if( pSort->bOrderedInnerLoop ){ + r1 = ++pParse->nMem; + sqlite3VdbeAddOp3(v, OP_Column, pSort->iECursor, nExpr, r1); + VdbeComment((v, "seq")); + } sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor); + if( pSort->bOrderedInnerLoop ){ + /* If the inner loop is driven by an index such that values from + ** the same iteration of the inner loop are in sorted order, then + ** immediately jump to the next iteration of an inner loop if the + ** entry from the current iteration does not fit into the top + ** LIMIT+OFFSET entries of the sorter. */ + int iBrk = sqlite3VdbeCurrentAddr(v) + 2; + sqlite3VdbeAddOp3(v, OP_Eq, regBase+nExpr, iBrk, r1); + sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); + VdbeCoverage(v); + } sqlite3VdbeJumpHere(v, addr); } } @@ -111140,30 +115048,6 @@ static void codeDistinct( sqlite3ReleaseTempReg(pParse, r1); } -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Generate an error message when a SELECT is used within a subexpression -** (example: "a IN (SELECT * FROM table)") but it has more than 1 result -** column. We do this in a subroutine because the error used to occur -** in multiple places. (The error only occurs in one place now, but we -** retain the subroutine to minimize code disruption.) -*/ -static int checkForMultiColumnSelectError( - Parse *pParse, /* Parse context. */ - SelectDest *pDest, /* Destination of SELECT results */ - int nExpr /* Number of result columns returned by SELECT */ -){ - int eDest = pDest->eDest; - if( nExpr>1 && (eDest==SRT_Mem || eDest==SRT_Set) ){ - sqlite3ErrorMsg(pParse, "only a single result allowed for " - "a SELECT that is part of an expression"); - return 1; - }else{ - return 0; - } -} -#endif - /* ** This routine generates the code for the inside of the inner loop ** of a SELECT. @@ -111373,19 +115257,19 @@ static void selectInnerLoop( ** item into the set table with bogus data. */ case SRT_Set: { - assert( nResultCol==1 ); - pDest->affSdst = - sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst); if( pSort ){ /* At first glance you would think we could optimize out the ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ - pushOntoSorter(pParse, pSort, p, regResult, regResult, 1, nPrefixReg); + pushOntoSorter( + pParse, pSort, p, regResult, regResult, nResultCol, nPrefixReg); }else{ int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1); - sqlite3ExprCacheAffinityChange(pParse, regResult, 1); + 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); sqlite3ReleaseTempReg(pParse, r1); } @@ -111401,13 +115285,14 @@ static void selectInnerLoop( } /* If this is a scalar select that is part of an expression, then - ** store the results in the appropriate memory cell and break out - ** of the scan loop. + ** store the results in the appropriate memory cell or array of + ** memory cells and break out of the scan loop. */ case SRT_Mem: { - assert( nResultCol==1 ); + assert( nResultCol==pDest->nSdst ); if( pSort ){ - pushOntoSorter(pParse, pSort, p, regResult, regResult, 1, nPrefixReg); + pushOntoSorter( + pParse, pSort, p, regResult, regResult, nResultCol, nPrefixReg); }else{ assert( regResult==iParm ); /* The LIMIT clause will jump out of the loop for us */ @@ -111509,7 +115394,7 @@ static void selectInnerLoop( */ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ int nExtra = (N+X)*(sizeof(CollSeq*)+1); - KeyInfo *p = sqlite3Malloc(sizeof(KeyInfo) + nExtra); + KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra); if( p ){ p->aSortOrder = (u8*)&p->aColl[N+X]; p->nField = (u16)N; @@ -111531,7 +115416,7 @@ SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo *p){ if( p ){ assert( p->nRef>0 ); p->nRef--; - if( p->nRef==0 ) sqlite3DbFree(0, p); + if( p->nRef==0 ) sqlite3DbFree(p->db, p); } } @@ -111722,21 +115607,21 @@ static void generateSortTail( sqlite3VdbeResolveLabel(v, pSort->labelBkOut); } iTab = pSort->iECursor; - if( eDest==SRT_Output || eDest==SRT_Coroutine ){ + if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){ regRowid = 0; regRow = pDest->iSdst; nSortData = nColumn; }else{ regRowid = sqlite3GetTempReg(pParse); - regRow = sqlite3GetTempReg(pParse); - nSortData = 1; + regRow = sqlite3GetTempRange(pParse, nColumn); + nSortData = nColumn; } nKey = pOrderBy->nExpr - pSort->nOBSat; if( pSort->sortFlags & SORTFLAG_UseSorter ){ int regSortOut = ++pParse->nMem; iSortTab = pParse->nTab++; if( pSort->labelBkOut ){ - addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); + addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData); if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); @@ -111764,16 +115649,14 @@ static void generateSortTail( } #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { - assert( nColumn==1 ); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, - &pDest->affSdst, 1); - sqlite3ExprCacheAffinityChange(pParse, regRow, 1); + assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) ); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid, + pDest->zAffSdst, nColumn); + sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid); break; } case SRT_Mem: { - assert( nColumn==1 ); - sqlite3ExprCodeMove(pParse, regRow, iParm, 1); /* The LIMIT clause will terminate the loop for us */ break; } @@ -111792,7 +115675,11 @@ static void generateSortTail( } } if( regRowid ){ - sqlite3ReleaseTempReg(pParse, regRow); + if( eDest==SRT_Set ){ + sqlite3ReleaseTempRange(pParse, regRow, nColumn); + }else{ + sqlite3ReleaseTempReg(pParse, regRow); + } sqlite3ReleaseTempReg(pParse, regRowid); } /* The bottom of the loop @@ -111939,7 +115826,7 @@ static const char *columnTypeImpl( zOrigTab = pTab->zName; if( pNC->pParse ){ int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); - zOrigDb = pNC->pParse->db->aDb[iDb].zName; + zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName; } #else if( iCol<0 ){ @@ -112292,20 +116179,20 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ ** Get a VDBE for the given parser context. Create a new one if necessary. ** If an error occurs, return NULL and leave a message in pParse. */ -SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ - Vdbe *v = pParse->pVdbe; - if( v==0 ){ - v = pParse->pVdbe = sqlite3VdbeCreate(pParse); - if( v ) sqlite3VdbeAddOp0(v, OP_Init); - if( pParse->pToplevel==0 - && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst) - ){ - pParse->okConstFactor = 1; - } - +static SQLITE_NOINLINE Vdbe *allocVdbe(Parse *pParse){ + Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(pParse); + if( v ) sqlite3VdbeAddOp2(v, OP_Init, 0, 1); + if( pParse->pToplevel==0 + && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst) + ){ + pParse->okConstFactor = 1; } return v; } +SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ + Vdbe *v = pParse->pVdbe; + return v ? v : allocVdbe(pParse); +} /* @@ -113133,18 +117020,15 @@ static int generateOutputSubroutine( } #ifndef SQLITE_OMIT_SUBQUERY - /* If we are creating a set for an "expr IN (SELECT ...)" construct, - ** then there should be a single item on the stack. Write this - ** item into the set table with bogus data. + /* If we are creating a set for an "expr IN (SELECT ...)". */ case SRT_Set: { int r1; - assert( pIn->nSdst==1 || pParse->nErr>0 ); - pDest->affSdst = - sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst); + testcase( pIn->nSdst>1 ); r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &pDest->affSdst,1); - sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1); + 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); sqlite3ReleaseTempReg(pParse, r1); break; @@ -114200,12 +118084,13 @@ static int flattenSubquery( assert( pParent->pHaving==0 ); pParent->pHaving = pParent->pWhere; pParent->pWhere = pWhere; - pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving, - sqlite3ExprDup(db, pSub->pHaving, 0)); + pParent->pHaving = sqlite3ExprAnd(db, + sqlite3ExprDup(db, pSub->pHaving, 0), pParent->pHaving + ); assert( pParent->pGroupBy==0 ); pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); }else{ - pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere); + pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere); } substSelect(db, pParent, iParent, pSub->pEList, 0); @@ -114288,12 +118173,18 @@ static int pushDownWhereTerms( ){ Expr *pNew; int nChng = 0; + Select *pX; /* For looping over compound SELECTs in pSubq */ if( pWhere==0 ) return 0; - if( (pSubq->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){ - return 0; /* restrictions (1) and (2) */ + for(pX=pSubq; pX; pX=pX->pPrior){ + if( (pX->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){ + testcase( pX->selFlags & SF_Aggregate ); + testcase( pX->selFlags & SF_Recursive ); + testcase( pX!=pSubq ); + return 0; /* restrictions (1) and (2) */ + } } if( pSubq->pLimit!=0 ){ - return 0; /* restriction (3) */ + return 0; /* restriction (3) */ } while( pWhere->op==TK_AND ){ nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor); @@ -114889,7 +118780,7 @@ static int selectExpander(Walker *pWalker, Select *p){ continue; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*"; + zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*"; } for(j=0; jnCol; j++){ char *zName = pTab->aCol[j].zName; @@ -115372,16 +119263,6 @@ SQLITE_PRIVATE int sqlite3Select( } #endif - - /* If writing to memory or generating a set - ** only a single column may be output. - */ -#ifndef SQLITE_OMIT_SUBQUERY - if( checkForMultiColumnSelectError(pParse, pDest, p->pEList->nExpr) ){ - goto select_end; - } -#endif - /* Try to flatten subqueries in the FROM clause up into the main query */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) @@ -115536,7 +119417,7 @@ SQLITE_PRIVATE int sqlite3Select( /* If the subquery is not correlated and if we are not inside of ** a trigger, then we only need to compute the value of the subquery ** once. */ - onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); + onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName)); }else{ VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName)); @@ -115595,6 +119476,13 @@ SQLITE_PRIVATE int sqlite3Select( ** the sDistinct.isTnct is still set. Hence, isTnct represents the ** original setting of the SF_Distinct flag, not the current setting */ assert( sDistinct.isTnct ); + +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x400 ){ + SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n")); + sqlite3TreeViewSelect(0, p, 0); + } +#endif } /* If there is an ORDER BY clause, then create an ephemeral index to @@ -115666,6 +119554,7 @@ SQLITE_PRIVATE int sqlite3Select( } if( sSort.pOrderBy ){ sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo); + sSort.bOrderedInnerLoop = sqlite3WhereOrderedInnerLoop(pWInfo); if( sSort.nOBSat==sSort.pOrderBy->nExpr ){ sSort.pOrderBy = 0; } @@ -116291,7 +120180,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ ** Instead, the entire table should be passed to sqlite3_free_table() when ** the calling procedure is finished using it. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_table( +SQLITE_API int sqlite3_get_table( sqlite3 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ char ***pazResult, /* Write the result table here */ @@ -116360,7 +120249,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_table( /* ** This routine frees the space the sqlite3_get_table() malloced. */ -SQLITE_API void SQLITE_STDCALL sqlite3_free_table( +SQLITE_API void sqlite3_free_table( char **azResult /* Result returned from sqlite3_get_table() */ ){ if( azResult ){ @@ -116475,7 +120364,6 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( int iDb; /* The database to store the trigger in */ Token *pName; /* The unqualified db name */ DbFixer sFix; /* State vector for the DB fixer */ - int iTabDb; /* Index of the database holding pTab */ assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ assert( pName2!=0 ); @@ -116588,13 +120476,13 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( " trigger on table: %S", pTableName, 0); goto trigger_cleanup; } - iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); #ifndef SQLITE_OMIT_AUTHORIZATION { + int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); int code = SQLITE_CREATE_TRIGGER; - const char *zDb = db->aDb[iTabDb].zName; - const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; + const char *zDb = db->aDb[iTabDb].zDbSName; + const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb; if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ goto trigger_cleanup; @@ -116688,7 +120576,7 @@ SQLITE_PRIVATE void sqlite3FinishTrigger( z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); sqlite3NestedParse(pParse, "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName, + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), zName, pTrig->table, z); sqlite3DbFree(db, z); sqlite3ChangeCookie(pParse, iDb); @@ -116877,7 +120765,7 @@ SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr) assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; + if( zDb && sqlite3StrICmp(db->aDb[j].zDbSName, zDb) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName); if( pTrigger ) break; @@ -116923,7 +120811,7 @@ SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_TRIGGER; - const char *zDb = db->aDb[iDb].zName; + const char *zDb = db->aDb[iDb].zDbSName; const char *zTab = SCHEMA_TABLE(iDb); if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) || @@ -116939,7 +120827,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].zName, SCHEMA_TABLE(iDb), pTrigger->zName + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pTrigger->zName ); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0); @@ -117042,8 +120930,10 @@ static SrcList *targetSrcList( pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget); iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema); if( iDb==0 || iDb>=2 ){ + const char *zDb; assert( iDbnDb ); - pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); + zDb = db->aDb[iDb].zDbSName; + pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, zDb); } } return pSrc; @@ -117257,7 +121147,6 @@ static TriggerPrg *codeRowTrigger( } pProgram->nMem = pSubParse->nMem; pProgram->nCsr = pSubParse->nTab; - pProgram->nOnce = pSubParse->nOnce; pProgram->token = (void *)pTrigger; pPrg->aColmask[0] = pSubParse->oldmask; pPrg->aColmask[1] = pSubParse->newmask; @@ -117730,7 +121619,7 @@ SQLITE_PRIVATE void sqlite3Update( int rc; rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, j<0 ? "ROWID" : pTab->aCol[j].zName, - db->aDb[iDb].zName); + db->aDb[iDb].zDbSName); if( rc==SQLITE_DENY ){ goto update_cleanup; }else if( rc==SQLITE_IGNORE ){ @@ -117833,7 +121722,8 @@ SQLITE_PRIVATE void sqlite3Update( if( HasRowid(pTab) ){ sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); pWInfo = sqlite3WhereBegin( - pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, iIdxCur + pParse, pTabList, pWhere, 0, 0, + WHERE_ONEPASS_DESIRED | WHERE_SEEK_TABLE, iIdxCur ); if( pWInfo==0 ) goto update_cleanup; okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); @@ -118071,11 +121961,30 @@ SQLITE_PRIVATE void sqlite3Update( VdbeCoverageNeverTaken(v); } sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1); - - /* If changing the record number, delete the old record. */ + + /* If changing the rowid value, or if there are foreign key constraints + ** to process, delete the old record. Otherwise, add a noop OP_Delete + ** to invoke the pre-update hook. + ** + ** That (regNew==regnewRowid+1) is true is also important for the + ** pre-update hook. If the caller invokes preupdate_new(), the returned + ** value is copied from memory cell (regNewRowid+1+iCol), where iCol + ** is the column index supplied by the user. + */ + assert( regNew==regNewRowid+1 ); +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + sqlite3VdbeAddOp3(v, OP_Delete, iDataCur, + OPFLAG_ISUPDATE | ((hasFK || chngKey || pPk!=0) ? 0 : OPFLAG_ISNOOP), + regNewRowid + ); + if( !pParse->nested ){ + sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE); + } +#else if( hasFK || chngKey || pPk!=0 ){ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); } +#endif if( bReplace || chngKey ){ sqlite3VdbeJumpHere(v, addr1); } @@ -118312,57 +122221,52 @@ static void updateVirtualTable( /* #include "vdbeInt.h" */ #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) -/* -** Finalize a prepared statement. If there was an error, store the -** text of the error message in *pzErrMsg. Return the result code. -*/ -static int vacuumFinalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){ - int rc; - rc = sqlite3VdbeFinalize((Vdbe*)pStmt); - if( rc ){ - sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); - } - return rc; -} /* -** Execute zSql on database db. Return an error code. +** Execute zSql on database db. +** +** If zSql returns rows, then each row will have exactly one +** column. (This will only happen if zSql begins with "SELECT".) +** Take each row of result and call execSql() again recursively. +** +** The execSqlF() routine does the same thing, except it accepts +** a format string as its third argument */ static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ - sqlite3_stmt *pStmt; - VVA_ONLY( int rc; ) - if( !zSql ){ - return SQLITE_NOMEM_BKPT; - } - if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){ - sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); - return sqlite3_errcode(db); - } - VVA_ONLY( rc = ) sqlite3_step(pStmt); - assert( rc!=SQLITE_ROW || (db->flags&SQLITE_CountRows) ); - return vacuumFinalize(db, pStmt, pzErrMsg); -} - -/* -** Execute zSql on database db. The statement returns exactly -** one column. Execute this as SQL on the same database. -*/ -static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ sqlite3_stmt *pStmt; int rc; - rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); + /* printf("SQL: [%s]\n", zSql); fflush(stdout); */ + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; - - while( SQLITE_ROW==sqlite3_step(pStmt) ){ - rc = execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0)); - if( rc!=SQLITE_OK ){ - vacuumFinalize(db, pStmt, pzErrMsg); - return rc; + while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ + const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0); + assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 ); + if( zSubSql ){ + assert( zSubSql[0]!='S' ); + rc = execSql(db, pzErrMsg, zSubSql); + if( rc!=SQLITE_OK ) break; } } - - return vacuumFinalize(db, pStmt, pzErrMsg); + assert( rc!=SQLITE_ROW ); + if( rc==SQLITE_DONE ) rc = SQLITE_OK; + if( rc ){ + sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); + } + (void)sqlite3_finalize(pStmt); + return rc; +} +static int execSqlF(sqlite3 *db, char **pzErrMsg, const char *zSql, ...){ + char *z; + va_list ap; + int rc; + va_start(ap, zSql); + z = sqlite3VMPrintf(db, zSql, ap); + va_end(ap); + if( z==0 ) return SQLITE_NOMEM; + rc = execSql(db, pzErrMsg, z); + sqlite3DbFree(db, z); + return rc; } /* @@ -118395,11 +122299,12 @@ static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ ** transient would cause the database file to appear to be deleted ** following reboot. */ -SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){ +SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm){ Vdbe *v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0); - sqlite3VdbeUsesBtree(v, 0); + int iDb = pNm ? sqlite3TwoPartName(pParse, pNm, pNm, &pNm) : 0; + if( v && (iDb>=2 || iDb==0) ){ + sqlite3VdbeAddOp1(v, OP_Vacuum, iDb); + sqlite3VdbeUsesBtree(v, iDb); } return; } @@ -118407,19 +122312,19 @@ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){ /* ** This routine implements the OP_Vacuum opcode of the VDBE. */ -SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ +SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){ int rc = SQLITE_OK; /* Return code from service routines */ Btree *pMain; /* The database being vacuumed */ Btree *pTemp; /* The temporary database we vacuum into */ - char *zSql = 0; /* SQL statements */ 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 */ - void (*saved_xTrace)(void*,const char*); /* Saved db->xTrace */ + u8 saved_mTrace; /* Saved trace settings */ Db *pDb = 0; /* Database to detach at end of vacuum */ int isMemDb; /* True if vacuuming a :memory: database */ int nRes; /* Bytes of reserved space at the end of each page */ int nDb; /* Number of attached databases */ + const char *zDbMain; /* Schema name of database to vacuum */ if( !db->autoCommit ){ sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); @@ -118436,12 +122341,14 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ saved_flags = db->flags; saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; - saved_xTrace = db->xTrace; - db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin; - db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder); - db->xTrace = 0; - - pMain = db->aDb[0].pBt; + saved_mTrace = db->mTrace; + db->flags |= (SQLITE_WriteSchema | SQLITE_IgnoreChecks + | SQLITE_PreferBuiltin | SQLITE_Vacuum); + db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows); + db->mTrace = 0; + + zDbMain = db->aDb[iDb].zDbSName; + pMain = db->aDb[iDb].pBt; isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); /* Attach the temporary database as 'vacuum_db'. The synchronous pragma @@ -118459,18 +122366,12 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ ** to write the journal header file. */ nDb = db->nDb; - if( sqlite3TempInMemory(db) ){ - zSql = "ATTACH ':memory:' AS vacuum_db;"; - }else{ - zSql = "ATTACH '' AS vacuum_db;"; - } - rc = execSql(db, pzErrMsg, zSql); - if( db->nDb>nDb ){ - pDb = &db->aDb[db->nDb-1]; - assert( strcmp(pDb->zName,"vacuum_db")==0 ); - } + rc = execSql(db, pzErrMsg, "ATTACH''AS vacuum_db"); if( rc!=SQLITE_OK ) goto end_of_vacuum; - pTemp = db->aDb[db->nDb-1].pBt; + assert( (db->nDb-1)==nDb ); + pDb = &db->aDb[nDb]; + assert( strcmp(pDb->zDbSName,"vacuum_db")==0 ); + pTemp = pDb->pBt; /* The call to execSql() to attach the temp database has left the file ** locked (as there was more than one active statement when the transaction @@ -118491,14 +122392,15 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ } #endif - rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF"); - if( rc!=SQLITE_OK ) goto end_of_vacuum; + sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); + sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); + sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL); /* Begin a transaction and take an exclusive lock on the main database ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, ** to ensure that we do not try to change the page-size on a WAL database. */ - rc = execSql(db, pzErrMsg, "BEGIN;"); + rc = execSql(db, pzErrMsg, "BEGIN"); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = sqlite3BtreeBeginTrans(pMain, 2); if( rc!=SQLITE_OK ) goto end_of_vacuum; @@ -118525,64 +122427,48 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ /* Query the schema of the main database. Create a mirror schema ** in the temporary database. */ - rc = execExecSql(db, pzErrMsg, - "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) " - " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'" - " AND coalesce(rootpage,1)>0" + db->init.iDb = nDb; /* force new CREATE statements into vacuum_db */ + rc = execSqlF(db, pzErrMsg, + "SELECT sql FROM \"%w\".sqlite_master" + " WHERE type='table'AND name<>'sqlite_sequence'" + " AND coalesce(rootpage,1)>0", + zDbMain ); if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = execExecSql(db, pzErrMsg, - "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)" - " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' "); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = execExecSql(db, pzErrMsg, - "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) " - " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"); + rc = execSqlF(db, pzErrMsg, + "SELECT sql FROM \"%w\".sqlite_master" + " WHERE type='index' AND length(sql)>10", + zDbMain + ); if( rc!=SQLITE_OK ) goto end_of_vacuum; + db->init.iDb = 0; /* Loop through the tables in the main database. For each, do ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy ** the contents to the temporary database. */ - assert( (db->flags & SQLITE_Vacuum)==0 ); - db->flags |= SQLITE_Vacuum; - rc = execExecSql(db, pzErrMsg, - "SELECT 'INSERT INTO vacuum_db.' || quote(name) " - "|| ' SELECT * FROM main.' || quote(name) || ';'" - "FROM main.sqlite_master " - "WHERE type = 'table' AND name!='sqlite_sequence' " - " AND coalesce(rootpage,1)>0" + rc = execSqlF(db, pzErrMsg, + "SELECT'INSERT INTO vacuum_db.'||quote(name)" + "||' SELECT*FROM\"%w\".'||quote(name)" + "FROM vacuum_db.sqlite_master " + "WHERE type='table'AND coalesce(rootpage,1)>0", + zDbMain ); assert( (db->flags & SQLITE_Vacuum)!=0 ); db->flags &= ~SQLITE_Vacuum; if( rc!=SQLITE_OK ) goto end_of_vacuum; - /* Copy over the sequence table - */ - rc = execExecSql(db, pzErrMsg, - "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' " - "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' " - ); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = execExecSql(db, pzErrMsg, - "SELECT 'INSERT INTO vacuum_db.' || quote(name) " - "|| ' SELECT * FROM main.' || quote(name) || ';' " - "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';" - ); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - - /* Copy the triggers, views, and virtual tables from the main database ** over to the temporary database. None of these objects has any ** associated storage, so all we have to do is copy their entries ** from the SQLITE_MASTER table. */ - rc = execSql(db, pzErrMsg, - "INSERT INTO vacuum_db.sqlite_master " - " SELECT type, name, tbl_name, rootpage, sql" - " FROM main.sqlite_master" - " WHERE type='view' OR type='trigger'" - " OR (type='table' AND rootpage=0)" + rc = execSqlF(db, pzErrMsg, + "INSERT INTO vacuum_db.sqlite_master" + " SELECT*FROM \"%w\".sqlite_master" + " WHERE type IN('view','trigger')" + " OR(type='table'AND rootpage=0)", + zDbMain ); if( rc ) goto end_of_vacuum; @@ -118636,10 +122522,11 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ end_of_vacuum: /* Restore the original value of db->flags */ + db->init.iDb = 0; db->flags = saved_flags; db->nChange = saved_nChange; db->nTotalChange = saved_nTotalChange; - db->xTrace = saved_xTrace; + db->mTrace = saved_mTrace; sqlite3BtreeSetPageSize(pMain, -1, -1, 1); /* Currently there is an SQL level transaction open on the vacuum @@ -118748,7 +122635,7 @@ static int createModule( /* ** External API function used to create a new virtual-table module. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_module( +SQLITE_API int sqlite3_create_module( 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 */ @@ -118763,7 +122650,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_module( /* ** External API function used to create a new virtual-table module. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2( +SQLITE_API int sqlite3_create_module_v2( 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 */ @@ -119014,7 +122901,7 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse( */ if( pTable->azModuleArg ){ sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, - pTable->azModuleArg[0], pParse->db->aDb[iDb].zName); + pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName); } #endif } @@ -119078,7 +122965,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].zName, SCHEMA_TABLE(iDb), + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pTab->zName, pTab->zName, zStmt, @@ -119088,7 +122975,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ v = sqlite3GetVdbe(pParse); sqlite3ChangeCookie(pParse, iDb); - sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); + sqlite3VdbeAddOp0(v, OP_Expire); zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName); sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); @@ -119188,7 +123075,7 @@ static int vtabCallConstructor( pVTable->pMod = pMod; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - pTab->azModuleArg[1] = db->aDb[iDb].zName; + pTab->azModuleArg[1] = db->aDb[iDb].zDbSName; /* Invoke the virtual table constructor */ assert( &db->pVtabCtx ); @@ -119342,7 +123229,7 @@ static void addToVTrans(sqlite3 *db, VTable *pVTab){ ** This function is invoked by the vdbe to call the xCreate method ** of the virtual table named zTab in database iDb. ** -** If an error occurs, *pzErr is set to point an an English language +** If an error occurs, *pzErr is set to point to an English language ** description of the error and an SQLITE_XXX error code is returned. ** In this case the caller must call sqlite3DbFree(db, ) on *pzErr. */ @@ -119352,7 +123239,7 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, Module *pMod; const char *zMod; - pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); + pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable ); /* Locate the required virtual table module */ @@ -119387,7 +123274,7 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, ** valid to call this function from within the xCreate() or xConnect() of a ** virtual table module. */ -SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ +SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ VtabCtx *pCtx; Parse *pParse; int rc = SQLITE_OK; @@ -119424,10 +123311,24 @@ SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3 *db, const char *zCre && (pParse->pNewTable->tabFlags & TF_Virtual)==0 ){ if( !pTab->aCol ){ - pTab->aCol = pParse->pNewTable->aCol; - pTab->nCol = pParse->pNewTable->nCol; - pParse->pNewTable->nCol = 0; - pParse->pNewTable->aCol = 0; + Table *pNew = pParse->pNewTable; + Index *pIdx; + pTab->aCol = pNew->aCol; + pTab->nCol = pNew->nCol; + pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid); + pNew->nCol = 0; + pNew->aCol = 0; + assert( pTab->pIndex==0 ); + if( !HasRowid(pNew) && pCtx->pVTable->pMod->pModule->xUpdate!=0 ){ + rc = SQLITE_ERROR; + } + pIdx = pNew->pIndex; + if( pIdx ){ + assert( pIdx->pNext==0 ); + pTab->pIndex = pIdx; + pNew->pIndex = 0; + pIdx->pTable = pTab; + } } pCtx->bDeclared = 1; }else{ @@ -119462,8 +123363,8 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab int rc = SQLITE_OK; Table *pTab; - pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); - if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){ + pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); + if( pTab!=0 && ALWAYS(pTab->pVTable!=0) ){ VTable *p; int (*xDestroy)(sqlite3_vtab *); for(p=pTab->pVTable; p; p=p->pNext){ @@ -119603,7 +123504,10 @@ SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){ if( rc==SQLITE_OK ){ int iSvpt = db->nStatement + db->nSavepoint; addToVTrans(db, pVTab); - if( iSvpt ) rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, iSvpt-1); + if( iSvpt && pModule->xSavepoint ){ + pVTab->iSavepoint = iSvpt; + rc = pModule->xSavepoint(pVTab->pVtab, iSvpt-1); + } } } } @@ -119757,7 +123661,7 @@ SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ } /* -** Check to see if virtual tale module pMod can be have an eponymous +** Check to see if virtual table module pMod can be have an eponymous ** virtual table instance. If it can, create one if one does not already ** exist. Return non-zero if the eponymous virtual table instance exists ** when this routine returns, and return zero if it does not exist. @@ -119774,17 +123678,18 @@ SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){ const sqlite3_module *pModule = pMod->pModule; Table *pTab; char *zErr = 0; - int nName; int rc; sqlite3 *db = pParse->db; if( pMod->pEpoTab ) return 1; if( pModule->xCreate!=0 && pModule->xCreate!=pModule->xConnect ) return 0; - nName = sqlite3Strlen30(pMod->zName) + 1; - pTab = sqlite3DbMallocZero(db, sizeof(Table) + nName); + pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ) return 0; + pTab->zName = sqlite3DbStrDup(db, pMod->zName); + if( pTab->zName==0 ){ + sqlite3DbFree(db, pTab); + return 0; + } pMod->pEpoTab = pTab; - pTab->zName = (char*)&pTab[1]; - memcpy(pTab->zName, pMod->zName, nName); pTab->nRef = 1; pTab->pSchema = db->aDb[0].pSchema; pTab->tabFlags |= TF_Virtual; @@ -119810,9 +123715,11 @@ SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){ SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){ Table *pTab = pMod->pEpoTab; if( pTab!=0 ){ - sqlite3DeleteColumnNames(db, pTab); - sqlite3VtabClear(db, pTab); - sqlite3DbFree(db, pTab); + /* Mark the table as Ephemeral prior to deleting it, so that the + ** sqlite3DeleteTable() routine will know that it is not stored in + ** the schema. */ + pTab->tabFlags |= TF_Ephemeral; + sqlite3DeleteTable(db, pTab); pMod->pEpoTab = 0; } } @@ -119824,7 +123731,7 @@ SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){ ** The results of this routine are undefined unless it is called from ** within an xUpdate method. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *db){ +SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){ static const unsigned char aMap[] = { SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE }; @@ -119842,7 +123749,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *db){ ** the SQLite core with additional information about the behavior ** of the virtual table being implemented. */ -SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3 *db, int op, ...){ +SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){ va_list ap; int rc = SQLITE_OK; @@ -119971,7 +123878,7 @@ struct WhereLevel { int addrFirst; /* First instruction of interior of the loop */ int addrBody; /* Beginning of the body of this loop */ #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS - int iLikeRepCntr; /* LIKE range processing counter register */ + u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */ int addrLikeRep; /* LIKE range processing address */ #endif u8 iFrom; /* Which entry in the FROM clause */ @@ -120023,6 +123930,8 @@ struct WhereLoop { union { struct { /* Information for internal btree tables */ u16 nEq; /* Number of equality constraints */ + u16 nBtm; /* Size of BTM vector */ + u16 nTop; /* Size of TOP vector */ Index *pIndex; /* Index used, or NULL */ } btree; struct { /* Information for virtual tables */ @@ -120145,19 +124054,20 @@ struct WherePath { */ struct WhereTerm { Expr *pExpr; /* Pointer to the subexpression that is this term */ + WhereClause *pWC; /* The clause this term is part of */ + LogEst truthProb; /* Probability of truth for this expression */ + u16 wtFlags; /* TERM_xxx bit flags. See below */ + u16 eOperator; /* A WO_xx value describing */ + u8 nChild; /* Number of children that must disable us */ + u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ int iParent; /* Disable pWC->a[iParent] when this term disabled */ int leftCursor; /* Cursor number of X in "X " */ + int iField; /* Field in (?,?,?) IN (SELECT...) vector */ union { int leftColumn; /* Column number of X in "X " */ WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ } u; - LogEst truthProb; /* Probability of truth for this expression */ - u16 eOperator; /* A WO_xx value describing */ - u16 wtFlags; /* TERM_xxx bit flags. See below */ - u8 nChild; /* Number of children that must disable us */ - u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ - WhereClause *pWC; /* The clause this term is part of */ Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ }; @@ -120309,25 +124219,26 @@ 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 *pResultSet; /* Result set. DISTINCT operates on these */ - WhereLoop *pLoops; /* List of all WhereLoop objects */ - Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ - LogEst nRowOut; /* Estimated number of output rows */ + ExprList *pDistinctSet; /* DISTINCT over all these values */ 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 */ + int iBreak; /* Jump here to break out of the loop */ + int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ + u8 nLevel; /* Number of nested loop */ i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */ u8 sorted; /* True if really sorted (not just grouped) */ u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ - u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */ - u8 nLevel; /* Number of nested loop */ + u8 eDistinct; /* One of the WHERE_DISTINCT_* values */ + u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */ int iTop; /* The very beginning of the WHERE loop */ - int iContinue; /* Jump here to continue with next record */ - int iBreak; /* Jump here to break out of the loop */ - int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ - int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ - WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ + WhereLoop *pLoops; /* List of all WhereLoop objects */ + Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ + LogEst nRowOut; /* Estimated number of output rows */ WhereClause sWC; /* Decomposition of the WHERE clause */ + WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ WhereLevel a[1]; /* Information about each nest loop in WHERE */ }; @@ -120337,6 +124248,9 @@ struct WhereInfo { ** where.c: */ SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet*,int); +#ifdef WHERETRACE_ENABLED +SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC); +#endif SQLITE_PRIVATE WhereTerm *sqlite3WhereFindTerm( WhereClause *pWC, /* The WHERE clause to be searched */ int iCur, /* Cursor number of LHS */ @@ -120393,6 +124307,14 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereC ** operators that are of interest to the query planner. An ** OR-ed combination of these values can be used when searching for ** particular WhereTerms within a WhereClause. +** +** Value constraints: +** WO_EQ == SQLITE_INDEX_CONSTRAINT_EQ +** WO_LT == SQLITE_INDEX_CONSTRAINT_LT +** WO_LE == SQLITE_INDEX_CONSTRAINT_LE +** WO_GT == SQLITE_INDEX_CONSTRAINT_GT +** WO_GE == SQLITE_INDEX_CONSTRAINT_GE +** WO_MATCH == SQLITE_INDEX_CONSTRAINT_MATCH */ #define WO_IN 0x0001 #define WO_EQ 0x0002 @@ -120440,6 +124362,17 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereC /************** Continuing where we left off in wherecode.c ******************/ #ifndef SQLITE_OMIT_EXPLAIN + +/* +** Return the name of the i-th column of the pIdx index. +*/ +static const char *explainIndexColumnName(Index *pIdx, int i){ + i = pIdx->aiColumn[i]; + if( i==XN_EXPR ) return ""; + if( i==XN_ROWID ) return "rowid"; + return pIdx->pTable->aCol[i].zName; +} + /* ** This routine is a helper for explainIndexRange() below ** @@ -120450,24 +124383,32 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereC */ static void explainAppendTerm( StrAccum *pStr, /* The text expression being built */ - int iTerm, /* Index of this term. First is zero */ - const char *zColumn, /* Name of the column */ + Index *pIdx, /* Index to read column names from */ + int nTerm, /* Number of terms */ + int iTerm, /* Zero-based index of first term. */ + int bAnd, /* Non-zero to append " AND " */ const char *zOp /* Name of the operator */ ){ - if( iTerm ) sqlite3StrAccumAppend(pStr, " AND ", 5); - sqlite3StrAccumAppendAll(pStr, zColumn); + int i; + + assert( nTerm>=1 ); + if( bAnd ) sqlite3StrAccumAppend(pStr, " AND ", 5); + + if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1); + for(i=0; i1 ) sqlite3StrAccumAppend(pStr, ")", 1); + sqlite3StrAccumAppend(pStr, zOp, 1); - sqlite3StrAccumAppend(pStr, "?", 1); -} -/* -** Return the name of the i-th column of the pIdx index. -*/ -static const char *explainIndexColumnName(Index *pIdx, int i){ - i = pIdx->aiColumn[i]; - if( i==XN_EXPR ) return ""; - if( i==XN_ROWID ) return "rowid"; - return pIdx->pTable->aCol[i].zName; + if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1); + for(i=0; i1 ) sqlite3StrAccumAppend(pStr, ")", 1); } /* @@ -120500,12 +124441,11 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){ j = i; if( pLoop->wsFlags&WHERE_BTM_LIMIT ){ - const char *z = explainIndexColumnName(pIndex, i); - explainAppendTerm(pStr, i++, z, ">"); + explainAppendTerm(pStr, pIndex, pLoop->u.btree.nBtm, j, i, ">"); + i = 1; } if( pLoop->wsFlags&WHERE_TOP_LIMIT ){ - const char *z = explainIndexColumnName(pIndex, j); - explainAppendTerm(pStr, i, z, "<"); + explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<"); } sqlite3StrAccumAppend(pStr, ")", 1); } @@ -120545,7 +124485,7 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan( pLoop = pLevel->pWLoop; flags = pLoop->wsFlags; - if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return 0; + if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_OR_SUBCLAUSE) ) return 0; isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0)) @@ -120695,7 +124635,7 @@ SQLITE_PRIVATE void sqlite3WhereAddScanStatus( */ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ int nLoop = 0; - while( pTerm + while( ALWAYS(pTerm!=0) && (pTerm->wtFlags & TERM_CODED)==0 && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin)) && (pLevel->notReady & pTerm->prereqAll)==0 @@ -120751,16 +124691,45 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){ } } +/* +** Expression pRight, which is the RHS of a comparison operation, is +** either a vector of n elements or, if n==1, a scalar expression. +** Before the comparison operation, affinity zAff is to be applied +** to the pRight values. This function modifies characters within the +** affinity string to SQLITE_AFF_BLOB if either: +** +** * the comparison will be performed with no affinity, or +** * the affinity change in zAff is guaranteed not to change the value. +*/ +static void updateRangeAffinityStr( + Expr *pRight, /* RHS of comparison */ + int n, /* Number of vector elements in comparison */ + char *zAff /* Affinity string to modify */ +){ + int i; + for(i=0; ipVdbe; int iReg; /* Register holding results */ + assert( pLevel->pWLoop->aLTerm[iEq]==pTerm ); assert( iTarget>0 ); if( pX->op==TK_EQ || pX->op==TK_IS ){ iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); @@ -120783,10 +124753,13 @@ static int codeEqualityTerm( sqlite3VdbeAddOp2(v, OP_Null, 0, iReg); #ifndef SQLITE_OMIT_SUBQUERY }else{ - int eType; + int eType = IN_INDEX_NOOP; int iTab; struct InLoop *pIn; WhereLoop *pLoop = pLevel->pWLoop; + int i; + int nEq = 0; + int *aiMap = 0; if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 @@ -120798,7 +124771,78 @@ static int codeEqualityTerm( } assert( pX->op==TK_IN ); iReg = iTarget; - eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0); + + for(i=0; iaLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){ + disableTerm(pLevel, pTerm); + return iTarget; + } + } + for(i=iEq;inLTerm; i++){ + if( ALWAYS(pLoop->aLTerm[i]) && pLoop->aLTerm[i]->pExpr==pX ) nEq++; + } + + if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){ + eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0); + }else{ + Select *pSelect = pX->x.pSelect; + sqlite3 *db = pParse->db; + u16 savedDbOptFlags = db->dbOptFlags; + ExprList *pOrigRhs = pSelect->pEList; + ExprList *pOrigLhs = pX->pLeft->x.pList; + ExprList *pRhs = 0; /* New Select.pEList for RHS */ + ExprList *pLhs = 0; /* New pX->pLeft vector */ + + for(i=iEq;inLTerm; i++){ + if( pLoop->aLTerm[i]->pExpr==pX ){ + int iField = pLoop->aLTerm[i]->iField - 1; + Expr *pNewRhs = sqlite3ExprDup(db, pOrigRhs->a[iField].pExpr, 0); + Expr *pNewLhs = sqlite3ExprDup(db, pOrigLhs->a[iField].pExpr, 0); + + pRhs = sqlite3ExprListAppend(pParse, pRhs, pNewRhs); + pLhs = sqlite3ExprListAppend(pParse, pLhs, pNewLhs); + } + } + if( !db->mallocFailed ){ + Expr *pLeft = pX->pLeft; + + if( pSelect->pOrderBy ){ + /* If the SELECT statement has an ORDER BY clause, zero the + ** iOrderByCol variables. These are set to non-zero when an + ** ORDER BY term exactly matches one of the terms of the + ** result-set. Since the result-set of the SELECT statement may + ** have been modified or reordered, these variables are no longer + ** set correctly. Since setting them is just an optimization, + ** it's easiest just to zero them here. */ + ExprList *pOrderBy = pSelect->pOrderBy; + for(i=0; inExpr; i++){ + pOrderBy->a[i].u.x.iOrderByCol = 0; + } + } + + /* Take care here not to generate a TK_VECTOR containing only a + ** single value. Since the parser never creates such a vector, some + ** of the subroutines do not handle this case. */ + if( pLhs->nExpr==1 ){ + pX->pLeft = pLhs->a[0].pExpr; + }else{ + pLeft->x.pList = pLhs; + aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int) * nEq); + testcase( aiMap==0 ); + } + pSelect->pEList = pRhs; + db->dbOptFlags |= SQLITE_QueryFlattener; + eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap); + db->dbOptFlags = savedDbOptFlags; + testcase( aiMap!=0 && aiMap[0]!=0 ); + pSelect->pEList = pOrigRhs; + pLeft->x.pList = pOrigLhs; + pX->pLeft = pLeft; + } + sqlite3ExprListDelete(pParse->db, pLhs); + sqlite3ExprListDelete(pParse->db, pRhs); + } + if( eType==IN_INDEX_INDEX_DESC ){ testcase( bRev ); bRev = !bRev; @@ -120808,28 +124852,45 @@ static int codeEqualityTerm( VdbeCoverageIf(v, bRev); VdbeCoverageIf(v, !bRev); assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); + pLoop->wsFlags |= WHERE_IN_ABLE; if( pLevel->u.in.nIn==0 ){ pLevel->addrNxt = sqlite3VdbeMakeLabel(v); } - pLevel->u.in.nIn++; + + i = pLevel->u.in.nIn; + pLevel->u.in.nIn += nEq; pLevel->u.in.aInLoop = sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop, sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); pIn = pLevel->u.in.aInLoop; if( pIn ){ - pIn += pLevel->u.in.nIn - 1; - pIn->iCur = iTab; - if( eType==IN_INDEX_ROWID ){ - pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg); - }else{ - pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg); + int iMap = 0; /* Index in aiMap[] */ + pIn += i; + for(i=iEq;inLTerm; i++){ + if( pLoop->aLTerm[i]->pExpr==pX ){ + int iOut = iReg + i - iEq; + if( eType==IN_INDEX_ROWID ){ + testcase( nEq>1 ); /* Happens with a UNIQUE index on ROWID */ + pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut); + }else{ + int iCol = aiMap ? aiMap[iMap++] : 0; + pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut); + } + sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v); + if( i==iEq ){ + pIn->iCur = iTab; + pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen; + }else{ + pIn->eEndLoopOp = OP_Noop; + } + pIn++; + } } - pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen; - sqlite3VdbeAddOp1(v, OP_IsNull, iReg); VdbeCoverage(v); }else{ pLevel->u.in.nIn = 0; } + sqlite3DbFree(pParse->db, aiMap); #endif } disableTerm(pLevel, pTerm); @@ -120955,9 +125016,15 @@ static int codeAllEqualityTerms( sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j); } } - testcase( pTerm->eOperator & WO_ISNULL ); - testcase( pTerm->eOperator & WO_IN ); - if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ + if( pTerm->eOperator & WO_IN ){ + if( pTerm->pExpr->flags & EP_xIsSelect ){ + /* No affinity ever needs to be (or should be) applied to a value + ** from the RHS of an "? IN (SELECT ...)" expression. The + ** sqlite3FindInIndex() routine has already ensured that the + ** affinity of the comparison has been applied to the value. */ + if( zAff ) zAff[j] = SQLITE_AFF_BLOB; + } + }else if( (pTerm->eOperator & WO_ISNULL)==0 ){ Expr *pRight = pTerm->pExpr->pRight; if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); @@ -120979,15 +125046,16 @@ static int codeAllEqualityTerms( #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS /* -** If the most recently coded instruction is a constant range contraint -** that originated from the LIKE optimization, then change the P3 to be -** pLoop->iLikeRepCntr and set P5. +** If the most recently coded instruction is a constant range constraint +** (a string literal) that originated from the LIKE optimization, then +** set P3 and P5 on the OP_String opcode so that the string will be cast +** to a BLOB at appropriate times. ** ** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range ** expression: "x>='ABC' AND x<'abd'". But this requires that the range ** scan loop run twice, once for strings and a second time for BLOBs. ** The OP_String opcodes on the second pass convert the upper and lower -** bound string contants to blobs. This routine makes the necessary changes +** bound string constants to blobs. This routine makes the necessary changes ** to the OP_String opcodes for that to happen. ** ** Except, of course, if SQLITE_LIKE_DOESNT_MATCH_BLOBS is defined, then @@ -121006,8 +125074,8 @@ static void whereLikeOptimizationStringFixup( assert( pOp!=0 ); assert( pOp->opcode==OP_String8 || pTerm->pWC->pWInfo->pParse->db->mallocFailed ); - pOp->p3 = pLevel->iLikeRepCntr; - pOp->p5 = 1; + pOp->p3 = (int)(pLevel->iLikeRepCntr>>1); /* Register holding counter */ + pOp->p5 = (u8)(pLevel->iLikeRepCntr&1); /* ASC or DESC */ } } #else @@ -121044,6 +125112,38 @@ static int codeCursorHintCheckExpr(Walker *pWalker, Expr *pExpr){ return WRC_Continue; } +/* +** Test whether or not expression pExpr, which was part of a WHERE clause, +** should be included in the cursor-hint for a table that is on the rhs +** of a LEFT JOIN. Set Walker.eCode to non-zero before returning if the +** expression is not suitable. +** +** An expression is unsuitable if it might evaluate to non NULL even if +** a TK_COLUMN node that does affect the value of the expression is set +** to NULL. For example: +** +** col IS NULL +** col IS NOT NULL +** coalesce(col, 1) +** CASE WHEN col THEN 0 ELSE 1 END +*/ +static int codeCursorHintIsOrFunction(Walker *pWalker, Expr *pExpr){ + if( pExpr->op==TK_IS + || pExpr->op==TK_ISNULL || pExpr->op==TK_ISNOT + || pExpr->op==TK_NOTNULL || pExpr->op==TK_CASE + ){ + pWalker->eCode = 1; + }else if( pExpr->op==TK_FUNCTION ){ + int d1; + char d2[3]; + if( 0==sqlite3IsLikeFunction(pWalker->pParse->db, pExpr, &d1, d2) ){ + pWalker->eCode = 1; + } + } + + return WRC_Continue; +} + /* ** This function is called on every node of an expression tree used as an @@ -121096,6 +125196,7 @@ static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){ ** Insert an OP_CursorHint instruction if it is appropriate to do so. */ static void codeCursorHint( + struct SrcList_item *pTabItem, /* FROM clause item */ WhereInfo *pWInfo, /* The where clause */ WhereLevel *pLevel, /* Which loop to provide hints for */ WhereTerm *pEndRange /* Hint this end-of-scan boundary term if not NULL */ @@ -121126,7 +125227,42 @@ static void codeCursorHint( pTerm = &pWC->a[i]; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( pTerm->prereqAll & pLevel->notReady ) continue; - if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue; + + /* Any terms specified as part of the ON(...) clause for any LEFT + ** JOIN for which the current table is not the rhs are omitted + ** from the cursor-hint. + ** + ** If this table is the rhs of a LEFT JOIN, "IS" or "IS NULL" terms + ** that were specified as part of the WHERE clause must be excluded. + ** This is to address the following: + ** + ** SELECT ... t1 LEFT JOIN t2 ON (t1.a=t2.b) WHERE t2.c IS NULL; + ** + ** Say there is a single row in t2 that matches (t1.a=t2.b), but its + ** t2.c values is not NULL. If the (t2.c IS NULL) constraint is + ** pushed down to the cursor, this row is filtered out, causing + ** SQLite to synthesize a row of NULL values. Which does match the + ** WHERE clause, and so the query returns a row. Which is incorrect. + ** + ** For the same reason, WHERE terms such as: + ** + ** WHERE 1 = (t2.c IS NULL) + ** + ** are also excluded. See codeCursorHintIsOrFunction() for details. + */ + if( pTabItem->fg.jointype & JT_LEFT ){ + Expr *pExpr = pTerm->pExpr; + if( !ExprHasProperty(pExpr, EP_FromJoin) + || pExpr->iRightJoinTable!=pTabItem->iCursor + ){ + sWalker.eCode = 0; + sWalker.xExprCallback = codeCursorHintIsOrFunction; + sqlite3WalkExpr(&sWalker, pTerm->pExpr); + if( sWalker.eCode ) continue; + } + }else{ + if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue; + } /* All terms in pWLoop->aLTerm[] except pEndRange are used to initialize ** the cursor. These terms are not needed as hints for a pure range @@ -121160,7 +125296,7 @@ static void codeCursorHint( } } #else -# define codeCursorHint(A,B,C) /* No-op */ +# define codeCursorHint(A,B,C,D) /* No-op */ #endif /* SQLITE_ENABLE_CURSOR_HINTS */ /* @@ -121194,7 +125330,7 @@ static void codeDeferredSeek( assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 ); sqlite3VdbeAddOp3(v, OP_Seek, iIdxCur, 0, iCur); - if( (pWInfo->wctrlFlags & WHERE_FORCE_TABLE) + if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE) && DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask) ){ int i; @@ -121211,6 +125347,39 @@ static void codeDeferredSeek( } } +/* +** If the expression passed as the second argument is a vector, generate +** code to write the first nReg elements of the vector into an array +** of registers starting with iReg. +** +** If the expression is not a vector, then nReg must be passed 1. In +** this case, generate code to evaluate the expression and leave the +** result in register iReg. +*/ +static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){ + assert( nReg>0 ); + if( sqlite3ExprIsVector(p) ){ +#ifndef SQLITE_OMIT_SUBQUERY + if( (p->flags & EP_xIsSelect) ){ + Vdbe *v = pParse->pVdbe; + int iSelect = sqlite3CodeSubselect(pParse, p, 0, 0); + sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1); + }else +#endif + { + int i; + ExprList *pList = p->x.pList; + assert( nReg<=pList->nExpr ); + for(i=0; ia[i].pExpr, iReg+i); + } + } + }else{ + assert( nReg==1 ); + sqlite3ExprCode(pParse, p, iReg); + } +} + /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. @@ -121249,7 +125418,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); bRev = (pWInfo->revMask>>iLevel)&1; omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 - && (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0; + && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0; VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName)); /* Create labels for the "break" and "continue" instructions @@ -121306,7 +125475,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); addrNotFound = pLevel->addrNxt; }else{ - sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget); + Expr *pRight = pTerm->pExpr->pRight; + codeExprOrVector(pParse, pRight, iTarget, 1); } } sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); @@ -121360,7 +125530,13 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( } } } - sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); + /* These registers need to be preserved in case there is an IN operator + ** loop. So we could deallocate the registers here (and potentially + ** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems + ** simpler and safer to simply not reuse the registers. + ** + ** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); + */ sqlite3ExprCachePop(pParse); }else #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -121383,8 +125559,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg); addrNxt = pLevel->addrNxt; - sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg); + sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg); VdbeCoverage(v); sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); @@ -121411,10 +125586,11 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pStart = pEnd; pEnd = pTerm; } - codeCursorHint(pWInfo, pLevel, pEnd); + codeCursorHint(pTabItem, pWInfo, pLevel, pEnd); if( pStart ){ Expr *pX; /* The expression that defines the start bound */ int r1, rTemp; /* Registers for holding the start boundary */ + int op; /* Cursor seek operation */ /* The following constant maps TK_xx codes into corresponding ** seek opcodes. It depends on a particular ordering of TK_xx @@ -121434,8 +125610,16 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pX = pStart->pExpr; assert( pX!=0 ); testcase( pStart->leftCursor!=iCur ); /* transitive constraints */ - r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); - sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1); + if( sqlite3ExprIsVector(pX->pRight) ){ + r1 = rTemp = sqlite3GetTempReg(pParse); + codeExprOrVector(pParse, pX->pRight, r1, 1); + op = aMoveOp[(pX->op - TK_GT) | 0x0001]; + }else{ + r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); + disableTerm(pLevel, pStart); + op = aMoveOp[(pX->op - TK_GT)]; + } + sqlite3VdbeAddOp3(v, op, iCur, addrBrk, r1); VdbeComment((v, "pk")); VdbeCoverageIf(v, pX->op==TK_GT); VdbeCoverageIf(v, pX->op==TK_LE); @@ -121443,7 +125627,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( VdbeCoverageIf(v, pX->op==TK_GE); sqlite3ExprCacheAffinityChange(pParse, r1, 1); sqlite3ReleaseTempReg(pParse, rTemp); - disableTerm(pLevel, pStart); }else{ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk); VdbeCoverageIf(v, bRev==0); @@ -121457,13 +125640,17 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */ testcase( pEnd->wtFlags & TERM_VIRTUAL ); memEndValue = ++pParse->nMem; - sqlite3ExprCode(pParse, pX->pRight, memEndValue); - if( pX->op==TK_LT || pX->op==TK_GT ){ + codeExprOrVector(pParse, pX->pRight, memEndValue, 1); + if( 0==sqlite3ExprIsVector(pX->pRight) + && (pX->op==TK_LT || pX->op==TK_GT) + ){ testOp = bRev ? OP_Le : OP_Ge; }else{ testOp = bRev ? OP_Lt : OP_Gt; } - disableTerm(pLevel, pEnd); + if( 0==sqlite3ExprIsVector(pX->pRight) ){ + disableTerm(pLevel, pEnd); + } } start = sqlite3VdbeCurrentAddr(v); pLevel->op = bRev ? OP_Prev : OP_Next; @@ -121530,6 +125717,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( OP_IdxLT, /* 3: (end_constraints && bRev && endEq) */ }; u16 nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */ + u16 nBtm = pLoop->u.btree.nBtm; /* Length of BTM vector */ + u16 nTop = pLoop->u.btree.nTop; /* Length of TOP vector */ int regBase; /* Base register holding constraint values */ WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */ WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */ @@ -121542,7 +125731,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( int nExtraReg = 0; /* Number of extra registers needed */ int op; /* Instruction opcode */ char *zStartAff; /* Affinity for start of range constraint */ - char cEndAff = 0; /* Affinity for end of range constraint */ + char *zEndAff = 0; /* Affinity for end of range constraint */ u8 bSeekPastNull = 0; /* True to seek past initial nulls */ u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */ @@ -121576,33 +125765,36 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( j = nEq; if( pLoop->wsFlags & WHERE_BTM_LIMIT ){ pRangeStart = pLoop->aLTerm[j++]; - nExtraReg = 1; + nExtraReg = MAX(nExtraReg, pLoop->u.btree.nBtm); /* Like optimization range constraints always occur in pairs */ assert( (pRangeStart->wtFlags & TERM_LIKEOPT)==0 || (pLoop->wsFlags & WHERE_TOP_LIMIT)!=0 ); } if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ pRangeEnd = pLoop->aLTerm[j++]; - nExtraReg = 1; + nExtraReg = MAX(nExtraReg, pLoop->u.btree.nTop); #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){ assert( pRangeStart!=0 ); /* LIKE opt constraints */ assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */ - pLevel->iLikeRepCntr = ++pParse->nMem; - testcase( bRev ); - testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC ); - sqlite3VdbeAddOp2(v, OP_Integer, - bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC), - pLevel->iLikeRepCntr); + pLevel->iLikeRepCntr = (u32)++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 1, (int)pLevel->iLikeRepCntr); VdbeComment((v, "LIKE loop counter")); pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v); + /* iLikeRepCntr actually stores 2x the counter register number. The + ** bottom bit indicates whether the search order is ASC or DESC. */ + testcase( bRev ); + testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC ); + assert( (bRev & ~1)==0 ); + pLevel->iLikeRepCntr <<=1; + pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC); } #endif - if( pRangeStart==0 - && (j = pIdx->aiColumn[nEq])>=0 - && pIdx->pTable->aCol[j].notNull==0 - ){ - bSeekPastNull = 1; + if( pRangeStart==0 ){ + j = pIdx->aiColumn[nEq]; + if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){ + bSeekPastNull = 1; + } } } assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); @@ -121616,16 +125808,19 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ){ SWAP(WhereTerm *, pRangeEnd, pRangeStart); SWAP(u8, bSeekPastNull, bStopAtNull); + SWAP(u8, nBtm, nTop); } /* Generate code to evaluate all constraint terms using == or IN ** and store the values of those terms in an array of registers ** starting at regBase. */ - codeCursorHint(pWInfo, pLevel, pRangeEnd); + codeCursorHint(pTabItem, pWInfo, pLevel, pRangeEnd); regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff); assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq ); - if( zStartAff ) cEndAff = zStartAff[nEq]; + if( zStartAff && nTop ){ + zEndAff = sqlite3DbStrDup(db, &zStartAff[nEq]); + } addrNxt = pLevel->addrNxt; testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); @@ -121640,7 +125835,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( nConstraint = nEq; if( pRangeStart ){ Expr *pRight = pRangeStart->pExpr->pRight; - sqlite3ExprCode(pParse, pRight, regBase+nEq); + codeExprOrVector(pParse, pRight, regBase+nEq, nBtm); whereLikeOptimizationStringFixup(v, pLevel, pRangeStart); if( (pRangeStart->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) @@ -121649,18 +125844,16 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( VdbeCoverage(v); } if( zStartAff ){ - if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_BLOB){ - /* Since the comparison is to be performed with no conversions - ** applied to the operands, set the affinity to apply to pRight to - ** SQLITE_AFF_BLOB. */ - zStartAff[nEq] = SQLITE_AFF_BLOB; - } - if( sqlite3ExprNeedsNoAffinityChange(pRight, zStartAff[nEq]) ){ - zStartAff[nEq] = SQLITE_AFF_BLOB; - } + updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]); } - nConstraint++; + nConstraint += nBtm; testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); + if( sqlite3ExprIsVector(pRight)==0 ){ + disableTerm(pLevel, pRangeStart); + }else{ + startEq = 1; + } + bSeekPastNull = 0; }else if( bSeekPastNull ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); nConstraint++; @@ -121692,7 +125885,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( pRangeEnd ){ Expr *pRight = pRangeEnd->pExpr->pRight; sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); - sqlite3ExprCode(pParse, pRight, regBase+nEq); + codeExprOrVector(pParse, pRight, regBase+nEq, nTop); whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); if( (pRangeEnd->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) @@ -121700,19 +125893,27 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); VdbeCoverage(v); } - if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_BLOB - && !sqlite3ExprNeedsNoAffinityChange(pRight, cEndAff) - ){ - codeApplyAffinity(pParse, regBase+nEq, 1, &cEndAff); + if( zEndAff ){ + updateRangeAffinityStr(pRight, nTop, zEndAff); + codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff); + }else{ + assert( pParse->db->mallocFailed ); } - nConstraint++; + nConstraint += nTop; testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); + + if( sqlite3ExprIsVector(pRight)==0 ){ + disableTerm(pLevel, pRangeEnd); + }else{ + endEq = 1; + } }else if( bStopAtNull ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); endEq = 0; nConstraint++; } sqlite3DbFree(db, zStartAff); + sqlite3DbFree(db, zEndAff); /* Top of the loop body */ pLevel->p2 = sqlite3VdbeCurrentAddr(v); @@ -121728,12 +125929,10 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( } /* Seek the table cursor, if required */ - disableTerm(pLevel, pRangeStart); - disableTerm(pLevel, pRangeEnd); if( omitTable ){ /* pIdx is a covering index. No need to access the main table. */ }else if( HasRowid(pIdx->pTable) ){ - if( pWInfo->eOnePass!=ONEPASS_OFF ){ + if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE)!=0 ){ iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); @@ -121753,9 +125952,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( iRowidReg, pPk->nKeyCol); VdbeCoverage(v); } - /* Record the instruction used to terminate the loop. Disable - ** WHERE clause terms made redundant by the index range scan. - */ + /* Record the instruction used to terminate the loop. */ if( pLoop->wsFlags & WHERE_ONEROW ){ pLevel->op = OP_Noop; }else if( bRev ){ @@ -121832,7 +126029,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( u16 wctrlFlags; /* Flags for sub-WHERE clause */ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ Table *pTab = pTabItem->pTab; - + pTerm = pLoop->aLTerm[0]; assert( pTerm!=0 ); assert( pTerm->eOperator & WO_OR ); @@ -121926,10 +126123,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** eliminating duplicates from other WHERE clauses, the action for each ** sub-WHERE clause is to to invoke the main loop body as a subroutine. */ - wctrlFlags = WHERE_OMIT_OPEN_CLOSE - | WHERE_FORCE_TABLE - | WHERE_ONETABLE_ONLY - | WHERE_NO_AUTOINDEX; + wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE); for(ii=0; iinTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ @@ -122037,7 +126231,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ){ assert( pSubWInfo->a[0].iIdxCur==iCovCur ); pCov = pSubLoop->u.btree.pIndex; - wctrlFlags |= WHERE_REOPEN_IDX; }else{ pCov = 0; } @@ -122074,7 +126267,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** a pseudo-cursor. No need to Rewind or Next such cursors. */ pLevel->op = OP_Noop; }else{ - codeCursorHint(pWInfo, pLevel, 0); + codeCursorHint(pTabItem, pWInfo, pLevel, 0); pLevel->op = aStep[bRev]; pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); @@ -122099,7 +126292,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & pLevel->notReady)!=0 ){ testcase( pWInfo->untestedTerms==0 - && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ); + && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ); pWInfo->untestedTerms = 1; continue; } @@ -122109,11 +126302,17 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( 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; #else - assert( pLevel->iLikeRepCntr>0 ); - skipLikeAddr = sqlite3VdbeAddOp1(v, OP_IfNot, pLevel->iLikeRepCntr); + u32 x = pLevel->iLikeRepCntr; + assert( x>0 ); + skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)? OP_IfNot : OP_If, (int)(x>>1)); VdbeCoverage(v); #endif } @@ -122131,7 +126330,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** the implied "t1.a=123" constraint. */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ - Expr *pE, *pEAlt; + Expr *pE, sEAlt; WhereTerm *pAlt; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue; @@ -122149,13 +126348,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( testcase( pAlt->eOperator & WO_IS ); testcase( pAlt->eOperator & WO_IN ); VdbeModuleComment((v, "begin transitive constraint")); - pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt)); - if( pEAlt ){ - *pEAlt = *pAlt->pExpr; - pEAlt->pLeft = pE->pLeft; - sqlite3ExprIfFalse(pParse, pEAlt, addrCont, SQLITE_JUMPIFNULL); - sqlite3StackFree(db, pEAlt); - } + sEAlt = *pAlt->pExpr; + sEAlt.pLeft = pE->pLeft; + sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL); } /* For a LEFT OUTER JOIN, generate code that will record the fact that @@ -122264,7 +126459,6 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ sqlite3DbFree(db, pOld); } pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); - memset(&pWC->a[pWC->nTerm], 0, sizeof(pWC->a[0])*(pWC->nSlot-pWC->nTerm)); } pTerm = &pWC->a[idx = pWC->nTerm++]; if( p && ExprHasProperty(p, EP_Unlikely) ){ @@ -122276,13 +126470,15 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ pTerm->wtFlags = wtFlags; pTerm->pWC = pWC; pTerm->iParent = -1; + memset(&pTerm->eOperator, 0, + sizeof(WhereTerm) - offsetof(WhereTerm,eOperator)); return idx; } /* ** Return TRUE if the given operator is one of the operators that is ** allowed for an indexable WHERE clause term. The allowed operators are -** "=", "<", ">", "<=", ">=", "IN", and "IS NULL" +** "=", "<", ">", "<=", ">=", "IN", "IS", and "IS NULL" */ static int allowedOp(int op){ assert( TK_GT>TK_EQ && TK_GTmallocFailed ){ for(j=0, pAndTerm=pAndWC->a; jnTerm; j++, pAndTerm++){ assert( pAndTerm->pExpr ); - if( allowedOp(pAndTerm->pExpr->op) ){ + if( allowedOp(pAndTerm->pExpr->op) + || pAndTerm->eOperator==WO_MATCH + ){ b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); } } @@ -122970,12 +127168,10 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr){ pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight); if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1; pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); - /* Since pLeft and pRight are both a column references, their collating - ** sequence should always be defined. */ - zColl1 = ALWAYS(pColl) ? pColl->zName : 0; + zColl1 = pColl ? pColl->zName : 0; pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight); - zColl2 = ALWAYS(pColl) ? pColl->zName : 0; - return sqlite3StrICmp(zColl1, zColl2)==0; + zColl2 = pColl ? pColl->zName : 0; + return sqlite3_stricmp(zColl1, zColl2)==0; } /* @@ -123010,7 +127206,8 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){ ** 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 -** of the column that is indexed, or -2 if an expression is being indexed. +** of the column that is indexed, or XN_EXPR (-2) if an expression is being +** indexed. ** ** If pExpr is a TK_COLUMN column reference, then this routine always returns ** true even if that particular column is not indexed, because the column @@ -123018,6 +127215,7 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){ */ static int exprMightBeIndexed( 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 */ @@ -123026,6 +127224,17 @@ static int exprMightBeIndexed( Index *pIdx; int i; int iCur; + + /* 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. */ + assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE ); + assert( TK_ISop==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){ + pExpr = pExpr->x.pList->a[0].pExpr; + } + if( pExpr->op==TK_COLUMN ){ *piCur = pExpr->iTable; *piColumn = pExpr->iColumn; @@ -123038,10 +127247,10 @@ static int exprMightBeIndexed( 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]!=(-2) ) continue; + if( pIdx->aiColumn[i]!=XN_EXPR ) continue; if( sqlite3ExprCompare(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ *piCur = iCur; - *piColumn = -2; + *piColumn = XN_EXPR; return 1; } } @@ -123098,6 +127307,7 @@ static void exprAnalyze( op = pExpr->op; if( op==TK_IN ){ assert( pExpr->pRight==0 ); + if( sqlite3ExprCheckIN(pParse, pExpr) ) return; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect); }else{ @@ -123124,18 +127334,26 @@ static void exprAnalyze( Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; - if( exprMightBeIndexed(pSrc, prereqLeft, pLeft, &iCur, &iColumn) ){ + + if( pTerm->iField>0 ){ + assert( op==TK_IN ); + assert( pLeft->op==TK_VECTOR ); + pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr; + } + + if( exprMightBeIndexed(pSrc, op, prereqLeft, pLeft, &iCur, &iColumn) ){ pTerm->leftCursor = iCur; pTerm->u.leftColumn = iColumn; pTerm->eOperator = operatorMask(op) & opMask; } if( op==TK_IS ) pTerm->wtFlags |= TERM_IS; if( pRight - && exprMightBeIndexed(pSrc, pTerm->prereqRight, pRight, &iCur, &iColumn) + && exprMightBeIndexed(pSrc, op, pTerm->prereqRight, pRight, &iCur,&iColumn) ){ WhereTerm *pNew; Expr *pDup; u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ + assert( pTerm->iField==0 ); if( pTerm->leftCursor>=0 ){ int idxNew; pDup = sqlite3ExprDup(db, pExpr, 0); @@ -123309,7 +127527,7 @@ static void exprAnalyze( ** virtual tables. The native query optimizer does not attempt ** to do anything with MATCH functions. */ - if( isMatchOfColumn(pExpr, &eOp2) ){ + if( pWC->op==TK_AND && isMatchOfColumn(pExpr, &eOp2) ){ int idxNew; Expr *pRight, *pLeft; WhereTerm *pNewTerm; @@ -123339,6 +127557,60 @@ static void exprAnalyze( } #endif /* SQLITE_OMIT_VIRTUALTABLE */ + /* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create + ** new terms for each component comparison - "a = ?" and "b = ?". The + ** new terms completely replace the original vector comparison, which is + ** no longer used. + ** + ** This is only required if at least one side of the comparison operation + ** is not a sub-select. */ + if( pWC->op==TK_AND + && (pExpr->op==TK_EQ || pExpr->op==TK_IS) + && sqlite3ExprIsVector(pExpr->pLeft) + && ( (pExpr->pLeft->flags & EP_xIsSelect)==0 + || (pExpr->pRight->flags & EP_xIsSelect)==0 + )){ + int nLeft = sqlite3ExprVectorSize(pExpr->pLeft); + 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); + transferJoinMarkings(pNew, pExpr); + idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); + exprAnalyze(pSrc, pWC, idxNew); + } + pTerm = &pWC->a[idxTerm]; + pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ + pTerm->eOperator = 0; + } + + /* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create + ** a virtual term for each vector component. The expression object + ** used by each such virtual term is pExpr (the full vector IN(...) + ** expression). The WhereTerm.iField variable identifies the index within + ** the vector on the LHS that the virtual term represents. + ** + ** This only works if the RHS is a simple SELECT, not a compound + */ + if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->iField==0 + && pExpr->pLeft->op==TK_VECTOR + && pExpr->x.pSelect->pPrior==0 + ){ + int i; + for(i=0; ipLeft); i++){ + int idxNew; + idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL); + pWC->a[idxNew].iField = i+1; + exprAnalyze(pSrc, pWC, idxNew); + markTermAsChild(pWC, idxNew, idxTerm); + } + } + #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 /* When sqlite_stat3 histogram data is available an operator of the ** form "x IS NOT NULL" can sometimes be evaluated more efficiently @@ -123359,7 +127631,7 @@ static void exprAnalyze( pNewExpr = sqlite3PExpr(pParse, TK_GT, sqlite3ExprDup(db, pLeft, 0), - sqlite3PExpr(pParse, TK_NULL, 0, 0, 0), 0); + sqlite3ExprAlloc(db, TK_NULL, 0, 0), 0); idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); @@ -123380,6 +127652,8 @@ static void exprAnalyze( /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ + testcase( pTerm!=&pWC->a[idxTerm] ); + pTerm = &pWC->a[idxTerm]; pTerm->prereqRight |= extraRight; } @@ -123462,17 +127736,18 @@ SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause *pWC){ ** tree. */ SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ - Bitmask mask = 0; + Bitmask mask; if( p==0 ) return 0; if( p->op==TK_COLUMN ){ mask = sqlite3WhereGetMask(pMaskSet, p->iTable); return mask; } - mask = sqlite3WhereExprUsage(pMaskSet, p->pRight); - mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft); + 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) ){ mask |= exprSelectUsage(pMaskSet, p->x.pSelect); - }else{ + }else if( p->x.pList ){ mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList); } return mask; @@ -123536,7 +127811,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs( pTab->zName, j); return; } - pColRef = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); + pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0); if( pColRef==0 ) return; pColRef->iTable = pItem->iCursor; pColRef->iColumn = k++; @@ -123602,6 +127877,18 @@ SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo *pWInfo){ return pWInfo->nOBSat; } +/* +** Return TRUE if the innermost loop of the WHERE clause implementation +** returns rows in ORDER BY order for complete run of the inner loop. +** +** Across multiple iterations of outer loops, the output rows need not be +** sorted. As long as rows are sorted for just the innermost loop, this +** routine can return TRUE. +*/ +SQLITE_PRIVATE int sqlite3WhereOrderedInnerLoop(WhereInfo *pWInfo){ + return pWInfo->bOrderedInnerLoop; +} + /* ** Return the VDBE address or label to jump to in order to continue ** immediately with the next row of a WHERE clause. @@ -123812,7 +128099,10 @@ static WhereTerm *whereScanNext(WhereScan *pScan){ ** ** The scanner will be searching the WHERE clause pWC. It will look ** for terms of the form "X " where X is column iColumn of table -** iCur. The must be one of the operators described by opMask. +** iCur. Or if pIdx!=0 then X is column iColumn of index pIdx. pIdx +** must be one of the indexes of table iCur. +** +** The must be one of the operators described by opMask. ** ** If the search is for X and the WHERE clause contains terms of the ** form X=Y then this routine might also return terms of the form @@ -123860,11 +128150,12 @@ static WhereTerm *whereScanInit( /* ** Search for a term in the WHERE clause that is of the form "X " -** where X is a reference to the iColumn of table iCur and is one of -** the WO_xx operator codes specified by the op parameter. -** Return a pointer to the term. Return 0 if not found. +** where X is a reference to the iColumn of table iCur or of index pIdx +** if pIdx!=0 and is one of the WO_xx operator codes specified by +** the op parameter. Return a pointer to the term. Return 0 if not found. ** -** If pIdx!=0 then search for terms matching the iColumn-th column of pIdx +** If pIdx!=0 then it must be one of the indexes of table iCur. +** Search for terms matching the iColumn-th column of pIdx ** rather than the iColumn-th column of table iCur. ** ** The term returned might by Y= if there is another constraint in @@ -124186,7 +128477,7 @@ static void constructAutomaticIndex( ** transient index on 2nd and subsequent iterations of the loop. */ v = pParse->pVdbe; assert( v!=0 ); - addrInit = sqlite3CodeOnce(pParse); VdbeCoverage(v); + addrInit = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); /* Count the number of columns that will be added to the index ** and used to match WHERE clause constraints */ @@ -124361,7 +128652,8 @@ static sqlite3_index_info *allocateIndexInfo( WhereClause *pWC, Bitmask mUnusable, /* Ignore terms with these prereqs */ struct SrcList_item *pSrc, - ExprList *pOrderBy + ExprList *pOrderBy, + u16 *pmNoOmit /* Mask of terms not to omit */ ){ int i, j; int nTerm; @@ -124371,6 +128663,7 @@ static sqlite3_index_info *allocateIndexInfo( WhereTerm *pTerm; int nOrderBy; sqlite3_index_info *pIdxInfo; + u16 mNoOmit = 0; /* Count the number of possible WHERE clause constraints referring ** to this virtual table */ @@ -124459,6 +128752,15 @@ static sqlite3_index_info *allocateIndexInfo( assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); + + if( op & (WO_LT|WO_LE|WO_GT|WO_GE) + && sqlite3ExprIsVector(pTerm->pExpr->pRight) + ){ + if( i<16 ) mNoOmit |= (1 << i); + if( op==WO_LT ) pIdxCons[j].op = WO_LE; + if( op==WO_GT ) pIdxCons[j].op = WO_GE; + } + j++; } for(i=0; ia[i].sortOrder; } + *pmNoOmit = mNoOmit; return pIdxInfo; } @@ -124742,7 +129045,7 @@ static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){ /* ** Return the affinity for a single column of an index. */ -static char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){ +SQLITE_PRIVATE char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){ assert( iCol>=0 && iColnColumn ); if( !pIdx->zColAff ){ if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB; @@ -124919,7 +129222,8 @@ static int whereRangeScanEst( if( nEq==pBuilder->nRecValid ){ UnpackedRecord *pRec = pBuilder->pRec; tRowcnt a[2]; - u8 aff; + int nBtm = pLoop->u.btree.nBtm; + int nTop = pLoop->u.btree.nTop; /* Variable iLower will be set to the estimate of the number of rows in ** the index that are less than the lower bound of the range query. The @@ -124949,8 +129253,6 @@ static int whereRangeScanEst( testcase( pRec->nField!=pBuilder->nRecValid ); pRec->nField = pBuilder->nRecValid; } - aff = sqlite3IndexColumnAffinity(pParse->db, p, nEq); - assert( nEq!=p->nKeyCol || aff==SQLITE_AFF_INTEGER ); /* Determine iLower and iUpper using ($P) only. */ if( nEq==0 ){ iLower = 0; @@ -124969,17 +129271,20 @@ static int whereRangeScanEst( if( p->aSortOrder[nEq] ){ /* The roles of pLower and pUpper are swapped for a DESC index */ SWAP(WhereTerm*, pLower, pUpper); + SWAP(int, nBtm, nTop); } /* If possible, improve on the iLower estimate using ($P:$L). */ if( pLower ){ - int bOk; /* True if value is extracted from pExpr */ + int n; /* Values extracted from pExpr */ Expr *pExpr = pLower->pExpr->pRight; - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); - if( rc==SQLITE_OK && bOk ){ + rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nBtm, nEq, &n); + if( rc==SQLITE_OK && n ){ tRowcnt iNew; + u16 mask = WO_GT|WO_LE; + if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT); iLwrIdx = whereKeyStats(pParse, p, pRec, 0, a); - iNew = a[0] + ((pLower->eOperator & (WO_GT|WO_LE)) ? a[1] : 0); + iNew = a[0] + ((pLower->eOperator & mask) ? a[1] : 0); if( iNew>iLower ) iLower = iNew; nOut--; pLower = 0; @@ -124988,13 +129293,15 @@ static int whereRangeScanEst( /* If possible, improve on the iUpper estimate using ($P:$U). */ if( pUpper ){ - int bOk; /* True if value is extracted from pExpr */ + int n; /* Values extracted from pExpr */ Expr *pExpr = pUpper->pExpr->pRight; - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); - if( rc==SQLITE_OK && bOk ){ + rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nTop, nEq, &n); + if( rc==SQLITE_OK && n ){ tRowcnt iNew; + u16 mask = WO_GT|WO_LE; + if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT); iUprIdx = whereKeyStats(pParse, p, pRec, 1, a); - iNew = a[0] + ((pUpper->eOperator & (WO_GT|WO_LE)) ? a[1] : 0); + iNew = a[0] + ((pUpper->eOperator & mask) ? a[1] : 0); if( iNewpNew->u.btree.pIndex; int nEq = pBuilder->pNew->u.btree.nEq; UnpackedRecord *pRec = pBuilder->pRec; - u8 aff; /* Column affinity */ int rc; /* Subfunction return code */ tRowcnt a[2]; /* Statistics */ int bOk; @@ -125108,8 +129414,7 @@ static int whereEqualScanEst( return SQLITE_OK; } - aff = sqlite3IndexColumnAffinity(pParse->db, p, nEq-1); - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk); + rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, 1, nEq-1, &bOk); pBuilder->pRec = pRec; if( rc!=SQLITE_OK ) return rc; if( bOk==0 ) return SQLITE_NOTFOUND; @@ -125183,30 +129488,58 @@ static void whereTermPrint(WhereTerm *pTerm, int iTerm){ sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm); }else{ char zType[4]; + char zLeft[50]; memcpy(zType, "...", 4); if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V'; if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E'; if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L'; + if( pTerm->eOperator & WO_SINGLE ){ + sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}", + pTerm->leftCursor, pTerm->u.leftColumn); + }else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){ + sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%lld", + pTerm->u.pOrInfo->indexable); + }else{ + sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor); + } sqlite3DebugPrintf( - "TERM-%-3d %p %s cursor=%-3d prob=%-3d op=0x%03x wtFlags=0x%04x\n", - iTerm, pTerm, zType, pTerm->leftCursor, pTerm->truthProb, + "TERM-%-3d %p %s %-12s prob=%-3d op=0x%03x wtFlags=0x%04x", + iTerm, pTerm, zType, zLeft, pTerm->truthProb, pTerm->eOperator, pTerm->wtFlags); + if( pTerm->iField ){ + sqlite3DebugPrintf(" iField=%d\n", pTerm->iField); + }else{ + sqlite3DebugPrintf("\n"); + } sqlite3TreeViewExpr(0, pTerm->pExpr, 0); } } #endif +#ifdef WHERETRACE_ENABLED +/* +** Show the complete content of a WhereClause +*/ +SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC){ + int i; + for(i=0; inTerm; i++){ + whereTermPrint(&pWC->a[i], i); + } +} +#endif + #ifdef WHERETRACE_ENABLED /* ** Print a WhereLoop object for debugging purposes */ static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){ WhereInfo *pWInfo = pWC->pWInfo; - int nb = 1+(pWInfo->pTabList->nSrc+7)/8; + int nb = 1+(pWInfo->pTabList->nSrc+3)/4; struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab; Table *pTab = pItem->pTab; + Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1; sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId, - p->iTab, nb, p->maskSelf, nb, p->prereq); + p->iTab, nb, p->maskSelf, nb, p->prereq & mAll); sqlite3DebugPrintf(" %12s", pItem->zAlias ? pItem->zAlias : pTab->zName); if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ @@ -125699,6 +130032,72 @@ static void whereLoopOutputAdjust( if( pLoop->nOut > nRow-iReduce ) pLoop->nOut = nRow - iReduce; } +/* +** Term pTerm is a vector range comparison operation. The first comparison +** in the vector can be optimized using column nEq of the index. This +** function returns the total number of vector elements that can be used +** as part of the range comparison. +** +** For example, if the query is: +** +** WHERE a = ? AND (b, c, d) > (?, ?, ?) +** +** and the index: +** +** CREATE INDEX ... ON (a, b, c, d, e) +** +** then this function would be invoked with nEq=1. The value returned in +** this case is 3. +*/ +static int whereRangeVectorLen( + Parse *pParse, /* Parsing context */ + int iCur, /* Cursor open on pIdx */ + Index *pIdx, /* The index to be used for a inequality constraint */ + int nEq, /* Number of prior equality constraints on same index */ + WhereTerm *pTerm /* The vector inequality constraint */ +){ + int nCmp = sqlite3ExprVectorSize(pTerm->pExpr->pLeft); + int i; + + nCmp = MIN(nCmp, (pIdx->nColumn - nEq)); + for(i=1; ipExpr->pLeft->x.pList->a[i].pExpr; + Expr *pRhs = pTerm->pExpr->pRight; + if( pRhs->flags & EP_xIsSelect ){ + pRhs = pRhs->x.pSelect->pEList->a[i].pExpr; + }else{ + pRhs = pRhs->x.pList->a[i].pExpr; + } + + /* Check that the LHS of the comparison is a column reference to + ** the right column of the right source table. And that the sort + ** order of the index column is the same as the sort order of the + ** leftmost index column. */ + if( pLhs->op!=TK_COLUMN + || pLhs->iTable!=iCur + || pLhs->iColumn!=pIdx->aiColumn[i+nEq] + || pIdx->aSortOrder[i+nEq]!=pIdx->aSortOrder[nEq] + ){ + break; + } + + testcase( pLhs->iColumn==XN_ROWID ); + aff = sqlite3CompareAffinity(pRhs, sqlite3ExprAffinity(pLhs)); + idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn); + if( aff!=idxaff ) break; + + pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); + if( pColl==0 ) break; + if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break; + } + return i; +} + /* ** Adjust the cost C by the costMult facter T. This only occurs if ** compiled with -DSQLITE_ENABLE_COSTMULT @@ -125737,6 +130136,8 @@ static int whereLoopAddBtreeIndex( Bitmask saved_prereq; /* Original value of pNew->prereq */ u16 saved_nLTerm; /* Original value of pNew->nLTerm */ u16 saved_nEq; /* Original value of pNew->u.btree.nEq */ + u16 saved_nBtm; /* Original value of pNew->u.btree.nBtm */ + u16 saved_nTop; /* Original value of pNew->u.btree.nTop */ u16 saved_nSkip; /* Original value of pNew->nSkip */ u32 saved_wsFlags; /* Original value of pNew->wsFlags */ LogEst saved_nOut; /* Original value of pNew->nOut */ @@ -125747,12 +130148,15 @@ static int whereLoopAddBtreeIndex( pNew = pBuilder->pNew; if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; + WHERETRACE(0x800, ("BEGIN addBtreeIdx(%s), nEq=%d\n", + pProbe->zName, pNew->u.btree.nEq)); assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); if( pNew->wsFlags & WHERE_BTM_LIMIT ){ opMask = WO_LT|WO_LE; }else{ + assert( pNew->u.btree.nBtm==0 ); opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; } if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); @@ -125760,6 +130164,8 @@ static int whereLoopAddBtreeIndex( assert( pNew->u.btree.nEqnColumn ); saved_nEq = pNew->u.btree.nEq; + saved_nBtm = pNew->u.btree.nBtm; + saved_nTop = pNew->u.btree.nTop; saved_nSkip = pNew->nSkip; saved_nLTerm = pNew->nLTerm; saved_wsFlags = pNew->wsFlags; @@ -125803,6 +130209,8 @@ static int whereLoopAddBtreeIndex( pNew->wsFlags = saved_wsFlags; pNew->u.btree.nEq = saved_nEq; + pNew->u.btree.nBtm = saved_nBtm; + pNew->u.btree.nTop = saved_nTop; pNew->nLTerm = saved_nLTerm; if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ pNew->aLTerm[pNew->nLTerm++] = pTerm; @@ -125819,14 +130227,23 @@ static int whereLoopAddBtreeIndex( pNew->wsFlags |= WHERE_COLUMN_IN; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ + int i; nIn = 46; assert( 46==sqlite3LogEst(25) ); + + /* The expression may actually be of the form (x, y) IN (SELECT...). + ** In this case there is a separate term for each of (x) and (y). + ** However, the nIn multiplier should only be applied once, not once + ** for each such term. The following loop checks that pTerm is the + ** first such term in use, and sets nIn back to 0 if it is not. */ + for(i=0; inLTerm-1; i++){ + if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0; + } }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ /* "x IN (value, value, ...)" */ nIn = sqlite3LogEst(pExpr->x.pList->nExpr); + assert( nIn>0 ); /* RHS always has 2 or more terms... The parser + ** changes "x IN (?)" into "x=?". */ } - assert( nIn>0 ); /* RHS always has 2 or more terms... The parser - ** changes "x IN (?)" into "x=?". */ - }else if( eOp & (WO_EQ|WO_IS) ){ int iCol = pProbe->aiColumn[saved_nEq]; pNew->wsFlags |= WHERE_COLUMN_EQ; @@ -125846,6 +130263,9 @@ static int whereLoopAddBtreeIndex( testcase( eOp & WO_GT ); testcase( eOp & WO_GE ); pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; + pNew->u.btree.nBtm = whereRangeVectorLen( + pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm + ); pBtm = pTerm; pTop = 0; if( pTerm->wtFlags & TERM_LIKEOPT ){ @@ -125858,12 +130278,16 @@ static int whereLoopAddBtreeIndex( if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ pNew->aLTerm[pNew->nLTerm++] = pTop; pNew->wsFlags |= WHERE_TOP_LIMIT; + pNew->u.btree.nTop = 1; } }else{ assert( eOp & (WO_LT|WO_LE) ); testcase( eOp & WO_LT ); testcase( eOp & WO_LE ); pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT; + pNew->u.btree.nTop = whereRangeVectorLen( + pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm + ); pTop = pTerm; pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ? pNew->aLTerm[pNew->nLTerm-2] : 0; @@ -125963,6 +130387,8 @@ static int whereLoopAddBtreeIndex( } pNew->prereq = saved_prereq; pNew->u.btree.nEq = saved_nEq; + pNew->u.btree.nBtm = saved_nBtm; + pNew->u.btree.nTop = saved_nTop; pNew->nSkip = saved_nSkip; pNew->wsFlags = saved_wsFlags; pNew->nOut = saved_nOut; @@ -126002,6 +130428,8 @@ static int whereLoopAddBtreeIndex( pNew->wsFlags = saved_wsFlags; } + WHERETRACE(0x800, ("END addBtreeIdx(%s), nEq=%d, rc=%d\n", + pProbe->zName, saved_nEq, rc)); return rc; } @@ -126084,7 +130512,7 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ /* ** Add all WhereLoop objects for a single table of the join where the table -** is idenfied by pBuilder->pNew->iTab. That table is guaranteed to be +** is identified by pBuilder->pNew->iTab. That table is guaranteed to be ** a b-tree table, not a virtual table. ** ** The costs (WhereLoop.rRun) of the b-tree loops added by this function @@ -126181,7 +130609,7 @@ static int whereLoopAddBtree( #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ if( !pBuilder->pOrSet /* Not part of an OR optimization */ - && (pWInfo->wctrlFlags & WHERE_NO_AUTOINDEX)==0 + && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 && pSrc->pIBIndex==0 /* Has no INDEXED BY clause */ && !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */ @@ -126213,6 +130641,7 @@ static int whereLoopAddBtree( pNew->rSetup += 24; } ApplyCostMultiplier(pNew->rSetup, pTab->costMult); + if( pNew->rSetup<0 ) pNew->rSetup = 0; /* TUNING: Each index lookup yields 20 rows in the table. This ** is more than the usual guess of 10 rows, since we have no way ** of knowing how selective the index will ultimately be. It would @@ -126237,6 +130666,8 @@ static int whereLoopAddBtree( } rSize = pProbe->aiRowLogEst[0]; pNew->u.btree.nEq = 0; + pNew->u.btree.nBtm = 0; + pNew->u.btree.nTop = 0; pNew->nSkip = 0; pNew->nLTerm = 0; pNew->iSortIdx = 0; @@ -126273,6 +130704,7 @@ static int whereLoopAddBtree( /* Full scan via index */ if( b || !HasRowid(pTab) + || pProbe->pPartIdxWhere!=0 || ( m==0 && pProbe->bUnordered==0 && (pProbe->szIdxRowszTabRow) @@ -126285,11 +130717,34 @@ static int whereLoopAddBtree( /* The cost of visiting the index rows is N*K, where K is ** between 1.1 and 3.0, depending on the relative sizes of the - ** index and table rows. If this is a non-covering index scan, - ** also add the cost of visiting table rows (N*3.0). */ + ** index and table rows. */ pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow; if( m!=0 ){ - pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16); + /* If this is a non-covering index scan, add in the cost of + ** doing table lookups. The cost will be 3x the number of + ** lookups. Take into account WHERE clause terms that can be + ** satisfied using just the index, and that do not require a + ** table lookup. */ + LogEst nLookup = rSize + 16; /* Base cost: N*3 */ + int ii; + int iCur = pSrc->iCursor; + WhereClause *pWC2 = &pWInfo->sWC; + for(ii=0; iinTerm; ii++){ + WhereTerm *pTerm = &pWC2->a[ii]; + if( !sqlite3ExprCoveredByIndex(pTerm->pExpr, iCur, pProbe) ){ + break; + } + /* pTerm can be evaluated using just the index. So reduce + ** the expected number of table lookups accordingly */ + if( pTerm->truthProb<=0 ){ + nLookup += pTerm->truthProb; + }else{ + nLookup--; + if( pTerm->eOperator & (WO_EQ|WO_IS) ) nLookup -= 19; + } + } + + pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup); } ApplyCostMultiplier(pNew->rRun, pTab->costMult); whereLoopOutputAdjust(pWC, pNew, rSize); @@ -126341,6 +130796,7 @@ static int whereLoopAddVirtualOne( Bitmask mUsable, /* Mask of usable tables */ u16 mExclude, /* Exclude terms using these operators */ sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */ + u16 mNoOmit, /* Do not omit these constraints */ int *pbIn /* OUT: True if plan uses an IN(...) op */ ){ WhereClause *pWC = pBuilder->pWC; @@ -126429,6 +130885,7 @@ static int whereLoopAddVirtualOne( } } } + pNew->u.vtab.omitMask &= ~mNoOmit; pNew->nLTerm = mxTerm+1; assert( pNew->nLTerm<=pNew->nLSlot ); @@ -126502,6 +130959,7 @@ static int whereLoopAddVirtual( int bIn; /* True if plan uses IN(...) operator */ WhereLoop *pNew; Bitmask mBest; /* Tables used by best possible plan */ + u16 mNoOmit; assert( (mPrereq & mUnusable)==0 ); pWInfo = pBuilder->pWInfo; @@ -126510,7 +130968,8 @@ static int whereLoopAddVirtual( pNew = pBuilder->pNew; pSrc = &pWInfo->pTabList->a[pNew->iTab]; assert( IsVirtual(pSrc->pTab) ); - p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy); + p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy, + &mNoOmit); if( p==0 ) return SQLITE_NOMEM_BKPT; pNew->rSetup = 0; pNew->wsFlags = WHERE_VIRTUALTABLE; @@ -126524,7 +130983,7 @@ static int whereLoopAddVirtual( /* First call xBestIndex() with all constraints usable. */ WHERETRACE(0x40, (" VirtualOne: all usable\n")); - rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, &bIn); + rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn); /* If the call to xBestIndex() with all terms enabled produced a plan ** that does not require any source tables (IOW: a plan with mBest==0), @@ -126541,7 +131000,8 @@ static int whereLoopAddVirtual( ** xBestIndex again, this time with IN(...) terms disabled. */ if( bIn ){ WHERETRACE(0x40, (" VirtualOne: all usable w/o IN\n")); - rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, WO_IN, p, &bIn); + rc = whereLoopAddVirtualOne( + pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn); assert( bIn==0 ); mBestNoIn = pNew->prereq & ~mPrereq; if( mBestNoIn==0 ){ @@ -126567,7 +131027,8 @@ static int whereLoopAddVirtual( if( mNext==mBest || mNext==mBestNoIn ) continue; WHERETRACE(0x40, (" VirtualOne: mPrev=%04llx mNext=%04llx\n", (sqlite3_uint64)mPrev, (sqlite3_uint64)mNext)); - rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mNext|mPrereq, 0, p, &bIn); + rc = whereLoopAddVirtualOne( + pBuilder, mPrereq, mNext|mPrereq, 0, p, mNoOmit, &bIn); if( pNew->prereq==mPrereq ){ seenZero = 1; if( bIn==0 ) seenZeroNoIN = 1; @@ -126579,7 +131040,8 @@ static int whereLoopAddVirtual( ** usable), make a call here with all source tables disabled */ if( rc==SQLITE_OK && seenZero==0 ){ WHERETRACE(0x40, (" VirtualOne: all disabled\n")); - rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mPrereq, 0, p, &bIn); + rc = whereLoopAddVirtualOne( + pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn); if( bIn==0 ) seenZeroNoIN = 1; } @@ -126588,7 +131050,8 @@ static int whereLoopAddVirtual( ** operator, make a final call to obtain one here. */ if( rc==SQLITE_OK && seenZeroNoIN==0 ){ WHERETRACE(0x40, (" VirtualOne: all disabled and w/o IN\n")); - rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mPrereq, WO_IN, p, &bIn); + rc = whereLoopAddVirtualOne( + pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn); } } @@ -126658,9 +131121,7 @@ static int whereLoopAddOr( WHERETRACE(0x200, ("OR-term %d of %p has %d subterms:\n", (int)(pOrTerm-pOrWC->a), pTerm, sSubBuild.pWC->nTerm)); if( sqlite3WhereTrace & 0x400 ){ - for(i=0; inTerm; i++){ - whereTermPrint(&sSubBuild.pWC->a[i], i); - } + sqlite3WhereClausePrint(sSubBuild.pWC); } #endif #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -126753,6 +131214,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ mPrereq = mPrior; } priorJointype = pItem->fg.jointype; +#ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pItem->pTab) ){ struct SrcList_item *p; for(p=&pItem[1]; paLoop[] */ WhereLoop *pLast, /* Add this WhereLoop to the end of pPath->aLoop[] */ Bitmask *pRevMask /* OUT: Mask of WhereLoops to run in reverse order */ @@ -126807,6 +131271,7 @@ static i8 wherePathSatisfiesOrderBy( u8 isOrderDistinct; /* All prior WhereLoops are order-distinct */ u8 distinctColumns; /* True if the loop has UNIQUE NOT NULL columns */ u8 isMatch; /* iColumn matches a term of the ORDER BY clause */ + u16 eqOpMask; /* Allowed equality operators */ u16 nKeyCol; /* Number of key columns in pIndex */ u16 nColumn; /* Total number of ordered columns in the index */ u16 nOrderBy; /* Number terms in the ORDER BY clause */ @@ -126857,9 +131322,16 @@ static i8 wherePathSatisfiesOrderBy( obDone = MASKBIT(nOrderBy)-1; orderDistinctMask = 0; ready = 0; + eqOpMask = WO_EQ | WO_IS | WO_ISNULL; + if( wctrlFlags & WHERE_ORDERBY_LIMIT ) eqOpMask |= WO_IN; for(iLoop=0; isOrderDistinct && obSat0 ) ready |= pLoop->maskSelf; - pLoop = iLoopaLoop[iLoop] : pLast; + if( iLoopaLoop[iLoop]; + if( wctrlFlags & WHERE_ORDERBY_LIMIT ) continue; + }else{ + pLoop = pLast; + } if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){ if( pLoop->u.vtab.isOrdered ) obSat = obDone; break; @@ -126877,8 +131349,16 @@ static i8 wherePathSatisfiesOrderBy( if( pOBExpr->op!=TK_COLUMN ) continue; if( pOBExpr->iTable!=iCur ) continue; pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn, - ~ready, WO_EQ|WO_ISNULL|WO_IS, 0); + ~ready, eqOpMask, 0); if( pTerm==0 ) continue; + if( pTerm->eOperator==WO_IN ){ + /* IN terms are only valid for sorting in the ORDER BY LIMIT + ** optimization, and then only if they are actually used + ** by the query plan */ + assert( wctrlFlags & WHERE_ORDERBY_LIMIT ); + for(j=0; jnLTerm && pTerm!=pLoop->aLTerm[j]; j++){} + if( j>=pLoop->nLTerm ) continue; + } if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){ const char *z1, *z2; pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); @@ -126915,18 +131395,42 @@ static i8 wherePathSatisfiesOrderBy( rev = revSet = 0; distinctColumns = 0; for(j=0; ju.btree.nEq - && pLoop->nSkip==0 - && ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL|WO_IS))!=0 - ){ - if( i & WO_ISNULL ){ - testcase( isOrderDistinct ); - isOrderDistinct = 0; + assert( j>=pLoop->u.btree.nEq + || (pLoop->aLTerm[j]==0)==(jnSkip) + ); + if( ju.btree.nEq && j>=pLoop->nSkip ){ + u16 eOp = pLoop->aLTerm[j]->eOperator; + + /* Skip over == and IS and ISNULL terms. (Also skip IN terms when + ** doing WHERE_ORDERBY_LIMIT processing). + ** + ** If the current term is a column of an ((?,?) IN (SELECT...)) + ** expression for which the SELECT returns more than one column, + ** check that it is the only column used by this loop. Otherwise, + ** if it is one of two or more, none of the columns can be + ** considered to match an ORDER BY term. */ + if( (eOp & eqOpMask)!=0 ){ + if( eOp & WO_ISNULL ){ + testcase( isOrderDistinct ); + isOrderDistinct = 0; + } + continue; + }else if( ALWAYS(eOp & WO_IN) ){ + /* ALWAYS() justification: eOp is an equality operator due to the + ** ju.btree.nEq constraint above. Any equality other + ** than WO_IN is captured by the previous "if". So this one + ** always has to be WO_IN. */ + Expr *pX = pLoop->aLTerm[j]->pExpr; + for(i=j+1; iu.btree.nEq; i++){ + if( pLoop->aLTerm[i]->pExpr==pX ){ + assert( (pLoop->aLTerm[i]->eOperator & WO_IN) ); + bOnce = 0; + break; + } + } } - continue; } /* Get the column number in the table (iColumn) and sort order @@ -126955,7 +131459,6 @@ static i8 wherePathSatisfiesOrderBy( /* Find the ORDER BY term that corresponds to the j-th column ** of the index and mark that ORDER BY term off */ - bOnce = 1; isMatch = 0; for(i=0; bOnce && ipResultSet, pFrom, + int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pDistinctSet, pFrom, WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used); - if( rc==pWInfo->pResultSet->nExpr ){ + if( rc==pWInfo->pDistinctSet->nExpr ){ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; } } @@ -127444,8 +131947,26 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ } }else{ pWInfo->nOBSat = pFrom->isOrdered; - if( pWInfo->nOBSat<0 ) pWInfo->nOBSat = 0; pWInfo->revMask = pFrom->revLoop; + if( pWInfo->nOBSat<=0 ){ + pWInfo->nOBSat = 0; + if( nLoop>0 ){ + u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags; + if( (wsFlags & WHERE_ONEROW)==0 + && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN) + ){ + Bitmask m = 0; + int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, + WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m); + testcase( wsFlags & WHERE_IPK ); + testcase( wsFlags & WHERE_COLUMN_IN ); + if( rc==pWInfo->pOrderBy->nExpr ){ + pWInfo->bOrderedInnerLoop = 1; + pWInfo->revMask = m; + } + } + } + } } if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0 @@ -127493,7 +132014,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){ Index *pIdx; pWInfo = pBuilder->pWInfo; - if( pWInfo->wctrlFlags & WHERE_FORCE_TABLE ) return 0; + if( pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE ) return 0; assert( pWInfo->pTabList->nSrc>=1 ); pItem = pWInfo->pTabList->a; pTab = pItem->pTab; @@ -127640,7 +132161,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){ ** is called from an UPDATE or DELETE statement, then pOrderBy is NULL. ** ** The iIdxCur parameter is the cursor number of an index. If -** WHERE_ONETABLE_ONLY is set, iIdxCur is the cursor number of an index +** WHERE_OR_SUBCLAUSE is set, iIdxCur is the cursor number of an index ** to use for OR clause processing. The WHERE clause should use this ** specific cursor. If WHERE_ONEPASS_DESIRED is set, then iIdxCur is ** the first cursor in an array of cursors for all indices. iIdxCur should @@ -127648,14 +132169,14 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){ ** used. */ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( - Parse *pParse, /* The parser context */ - 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 *pResultSet, /* Result set of the query */ - u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ - int iAuxArg /* If WHERE_ONETABLE_ONLY is set, index cursor number, - ** If WHERE_USE_LIMIT, then the limit amount */ + Parse *pParse, /* The parser context */ + 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 */ + 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 */ ){ int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ int nTabList; /* Number of elements in pTabList */ @@ -127673,11 +132194,11 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || ( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 - && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 + && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 )); - /* Only one of WHERE_ONETABLE_ONLY or WHERE_USE_LIMIT */ - assert( (wctrlFlags & WHERE_ONETABLE_ONLY)==0 + /* Only one of WHERE_OR_SUBCLAUSE or WHERE_USE_LIMIT */ + assert( (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 || (wctrlFlags & WHERE_USE_LIMIT)==0 ); /* Variable initialization */ @@ -127705,11 +132226,11 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( } /* This function normally generates a nested loop for all tables in - ** pTabList. But if the WHERE_ONETABLE_ONLY flag is set, then we should + ** pTabList. But if the WHERE_OR_SUBCLAUSE flag is set, then we should ** only generate code for the first table in pTabList and assume that ** any cursors associated with subsequent tables are uninitialized. */ - nTabList = (wctrlFlags & WHERE_ONETABLE_ONLY) ? 1 : pTabList->nSrc; + nTabList = (wctrlFlags & WHERE_OR_SUBCLAUSE) ? 1 : pTabList->nSrc; /* Allocate and initialize the WhereInfo structure that will become the ** return value. A single allocation is used to store the WhereInfo @@ -127719,22 +132240,25 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( ** some architectures. Hence the ROUND8() below. */ nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); - pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop)); + pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop)); if( db->mallocFailed ){ sqlite3DbFree(db, pWInfo); pWInfo = 0; goto whereBeginError; } - pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; - pWInfo->nLevel = nTabList; pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; pWInfo->pOrderBy = pOrderBy; - pWInfo->pResultSet = pResultSet; + pWInfo->pDistinctSet = pDistinctSet; + pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; + pWInfo->nLevel = nTabList; pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v); pWInfo->wctrlFlags = wctrlFlags; pWInfo->iLimit = iAuxArg; pWInfo->savedNQueryLoop = pParse->nQueryLoop; + memset(&pWInfo->nOBSat, 0, + offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat)); + memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel)); assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ pMaskSet = &pWInfo->sMaskSet; sWLB.pWInfo = pWInfo; @@ -127785,7 +132309,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( ** Note that bitmasks are created for all pTabList->nSrc tables in ** pTabList, not just the first nTabList tables. nTabList is normally ** equal to pTabList->nSrc but might be shortened to 1 if the - ** WHERE_ONETABLE_ONLY flag is set. + ** WHERE_OR_SUBCLAUSE flag is set. */ for(ii=0; iinSrc; ii++){ createMask(pMaskSet, pTabList->a[ii].iCursor); @@ -127803,13 +132327,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( if( db->mallocFailed ) goto whereBeginError; if( wctrlFlags & WHERE_WANT_DISTINCT ){ - if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ + if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pDistinctSet) ){ /* 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 = pResultSet; + pWInfo->pOrderBy = pDistinctSet; } } @@ -127823,10 +132347,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( sqlite3DebugPrintf(")\n"); } if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */ - int i; - for(i=0; inTerm; i++){ - whereTermPrint(&sWLB.pWC->a[i], i); - } + sqlite3WhereClausePrint(sWLB.pWC); } #endif @@ -127888,10 +132409,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( #endif /* Attempt to omit tables from the join that do not effect the result */ if( pWInfo->nLevel>=2 - && pResultSet!=0 + && pDistinctSet!=0 && OptimizationEnabled(db, SQLITE_OmitNoopJoin) ){ - Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet); + Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pDistinctSet); if( sWLB.pOrderBy ){ tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); } @@ -127968,7 +132489,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( }else #endif if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 - && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ + && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){ int op = OP_OpenRead; if( pWInfo->eOnePass!=ONEPASS_OFF ){ op = OP_OpenWrite; @@ -128007,7 +132528,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( /* iAuxArg is always set if to a positive value if ONEPASS is possible */ assert( iAuxArg!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 ); if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx) - && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 + && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ){ /* This is one term of an OR-optimization using the PRIMARY KEY of a ** WITHOUT ROWID table. No need for a separate index */ @@ -128023,9 +132544,9 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( } op = OP_OpenWrite; pWInfo->aiCurOnePass[1] = iIndexCur; - }else if( iAuxArg && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){ + }else if( iAuxArg && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ){ iIndexCur = iAuxArg; - if( wctrlFlags & WHERE_REOPEN_IDX ) op = OP_ReopenIdx; + op = OP_ReopenIdx; }else{ iIndexCur = pParse->nTab++; } @@ -128087,7 +132608,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( pLevel->addrBody = sqlite3VdbeCurrentAddr(v); notReady = sqlite3WhereCodeOneLoopStart(pWInfo, ii, notReady); pWInfo->iContinue = pLevel->addrCont; - if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_ONETABLE_ONLY)==0 ){ + if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_OR_SUBCLAUSE)==0 ){ sqlite3WhereAddScanStatus(v, pTabList, pLevel, addrExplain); } } @@ -128141,10 +132662,12 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ sqlite3VdbeResolveLabel(v, pLevel->addrNxt); for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ sqlite3VdbeJumpHere(v, pIn->addrInTop+1); - sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); - VdbeCoverage(v); - VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen); - VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen); + if( pIn->eEndLoopOp!=OP_Noop ){ + sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); + VdbeCoverage(v); + VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen); + VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen); + } sqlite3VdbeJumpHere(v, pIn->addrInTop-1); } } @@ -128157,24 +132680,21 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ } #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS if( pLevel->addrLikeRep ){ - int op; - if( sqlite3VdbeGetOp(v, pLevel->addrLikeRep-1)->p1 ){ - op = OP_DecrJumpZero; - }else{ - op = OP_JumpZeroIncr; - } - sqlite3VdbeAddOp2(v, op, pLevel->iLikeRepCntr, pLevel->addrLikeRep); + sqlite3VdbeAddOp2(v, OP_DecrJumpZero, (int)(pLevel->iLikeRepCntr>>1), + pLevel->addrLikeRep); VdbeCoverage(v); } #endif if( pLevel->iLeftJoin ){ + int ws = pLoop->wsFlags; addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 - || (pLoop->wsFlags & WHERE_INDEXED)!=0 ); - if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){ + assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); + if( (ws & WHERE_IDX_ONLY)==0 ){ sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); } - if( pLoop->wsFlags & WHERE_INDEXED ){ + if( (ws & WHERE_INDEXED) + || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) + ){ sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); } if( pLevel->op==OP_Return ){ @@ -128215,12 +132735,12 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ /* Close all of the cursors that were opened by sqlite3WhereBegin. ** Except, do not close cursors that will be reused by the OR optimization - ** (WHERE_OMIT_OPEN_CLOSE). And do not close the OP_OpenWrite cursors + ** (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_OMIT_OPEN_CLOSE)==0 + && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){ int ws = pLoop->wsFlags; if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){ @@ -128351,15 +132871,6 @@ struct LimitVal { Expr *pOffset; /* The OFFSET expression. NULL if there is none */ }; -/* -** An instance of this structure is used to store the LIKE, -** GLOB, NOT LIKE, and NOT GLOB operators. -*/ -struct LikeOp { - Token eOperator; /* "like" or "glob" or "regexp" */ - int bNot; /* True if the NOT keyword is present */ -}; - /* ** An instance of the following structure describes the event of a ** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, @@ -128371,11 +132882,6 @@ struct LikeOp { */ struct TrigEvent { int a; IdList * b; }; -/* -** An instance of this structure holds the ATTACH key and the key type. -*/ -struct AttachKey { int type; Token key; }; - /* ** Disable lookaside memory allocation for objects that might be ** shared across database connections. @@ -128422,7 +132928,24 @@ static void disableLookaside(Parse *pParse){ ** that created the expression. */ static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token t){ - pOut->pExpr = sqlite3PExpr(pParse, op, 0, 0, &t); + Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); + if( p ){ + memset(p, 0, sizeof(Expr)); + p->op = (u8)op; + p->flags = EP_Leaf; + p->iAgg = -1; + p->u.zToken = (char*)&p[1]; + memcpy(p->u.zToken, t.z, t.n); + p->u.zToken[t.n] = 0; + if( sqlite3Isquote(p->u.zToken[0]) ){ + if( p->u.zToken[0]=='"' ) p->flags |= EP_DblQuoted; + sqlite3Dequote(p->u.zToken); + } +#if SQLITE_MAX_EXPR_DEPTH>0 + p->nHeight = 1; +#endif + } + pOut->pExpr = p; pOut->zStart = t.z; pOut->zEnd = &t.z[t.n]; } @@ -128567,26 +133090,25 @@ static void disableLookaside(Parse *pParse){ #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned char -#define YYNOCODE 251 +#define YYNOCODE 252 #define YYACTIONTYPE unsigned short int -#define YYWILDCARD 70 +#define YYWILDCARD 96 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; sqlite3ParserTOKENTYPE yy0; - struct LimitVal yy64; - Expr* yy122; - Select* yy159; - IdList* yy180; - struct {int value; int mask;} yy207; - struct LikeOp yy318; - TriggerStep* yy327; - With* yy331; - ExprSpan yy342; - SrcList* yy347; - int yy392; - struct TrigEvent yy410; - ExprList* yy442; + Expr* yy72; + TriggerStep* yy145; + ExprList* yy148; + SrcList* yy185; + ExprSpan yy190; + int yy194; + Select* yy243; + IdList* yy254; + With* yy285; + struct TrigEvent yy332; + struct LimitVal yy354; + struct {int value; int mask;} yy497; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 @@ -128596,16 +133118,16 @@ typedef union { #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse #define sqlite3ParserARG_STORE yypParser->pParse = pParse #define YYFALLBACK 1 -#define YYNSTATE 440 -#define YYNRULE 326 -#define YY_MAX_SHIFT 439 -#define YY_MIN_SHIFTREDUCE 649 -#define YY_MAX_SHIFTREDUCE 974 -#define YY_MIN_REDUCE 975 -#define YY_MAX_REDUCE 1300 -#define YY_ERROR_ACTION 1301 -#define YY_ACCEPT_ACTION 1302 -#define YY_NO_ACTION 1303 +#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 /************* End control #defines *******************************************/ /* Define the yytestcase() macro to be a no-op if is not already defined @@ -128637,7 +133159,7 @@ typedef union { ** ** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE ** and YY_MAX_REDUCE - +** ** N == YY_ERROR_ACTION A syntax error has occurred. ** ** N == YY_ACCEPT_ACTION The parser accepts its input. @@ -128646,16 +133168,20 @@ typedef union { ** slots in the yy_action[] table. ** ** The action table is constructed as a single large table named yy_action[]. -** Given state S and lookahead X, the action is computed as +** Given state S and lookahead X, the action is computed as either: ** -** yy_action[ yy_shift_ofst[S] + X ] +** (A) N = yy_action[ yy_shift_ofst[S] + X ] +** (B) N = yy_default[S] ** -** If the index value yy_shift_ofst[S]+X is out of range or if the value -** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] -** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table -** and that yy_default[S] should be used instead. +** The (A) formula is preferred. The B formula is used instead if: +** (1) The yy_shift_ofst[S]+X value is out of range, or +** (2) yy_lookahead[yy_shift_ofst[S]+X] is not equal to X, or +** (3) yy_shift_ofst[S] equal YY_SHIFT_USE_DFLT. +** (Implementation note: YY_SHIFT_USE_DFLT is chosen so that +** YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. +** Hence only tests (1) and (2) need to be evaluated.) ** -** The formula above is for computing the action when the lookahead is +** The formulas above are for computing the action when the lookahead is ** a terminal symbol. If the lookahead is a non-terminal (as occurs after ** a reduce action) then the yy_reduce_ofst[] array is used in place of ** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of @@ -128673,444 +133199,463 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (1499) +#define YY_ACTTAB_COUNT (1567) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 315, 1302, 146, 921, 2, 194, 922, 342, 952, 91, - /* 10 */ 91, 91, 91, 84, 89, 89, 89, 89, 88, 88, - /* 20 */ 87, 87, 87, 86, 339, 87, 87, 87, 86, 339, - /* 30 */ 331, 819, 819, 91, 91, 91, 91, 339, 89, 89, - /* 40 */ 89, 89, 88, 88, 87, 87, 87, 86, 339, 319, - /* 50 */ 933, 933, 92, 93, 83, 831, 834, 823, 823, 90, - /* 60 */ 90, 91, 91, 91, 91, 123, 89, 89, 89, 89, - /* 70 */ 88, 88, 87, 87, 87, 86, 339, 315, 952, 89, - /* 80 */ 89, 89, 89, 88, 88, 87, 87, 87, 86, 339, - /* 90 */ 365, 772, 360, 24, 933, 933, 947, 694, 933, 933, - /* 100 */ 773, 937, 933, 933, 434, 715, 328, 434, 819, 819, - /* 110 */ 203, 160, 278, 391, 273, 390, 190, 933, 933, 370, - /* 120 */ 934, 935, 367, 271, 953, 48, 679, 953, 48, 92, - /* 130 */ 93, 83, 831, 834, 823, 823, 90, 90, 91, 91, - /* 140 */ 91, 91, 123, 89, 89, 89, 89, 88, 88, 87, - /* 150 */ 87, 87, 86, 339, 315, 682, 337, 336, 218, 412, - /* 160 */ 398, 68, 412, 403, 934, 935, 743, 959, 934, 935, - /* 170 */ 810, 937, 934, 935, 957, 221, 958, 88, 88, 87, - /* 180 */ 87, 87, 86, 339, 291, 819, 819, 934, 935, 185, - /* 190 */ 94, 792, 388, 385, 384, 1240, 1240, 792, 804, 960, - /* 200 */ 960, 290, 798, 383, 123, 315, 92, 93, 83, 831, - /* 210 */ 834, 823, 823, 90, 90, 91, 91, 91, 91, 326, - /* 220 */ 89, 89, 89, 89, 88, 88, 87, 87, 87, 86, - /* 230 */ 339, 681, 741, 803, 803, 803, 819, 819, 944, 56, - /* 240 */ 253, 353, 242, 85, 82, 168, 253, 358, 252, 110, - /* 250 */ 96, 233, 397, 698, 677, 683, 683, 92, 93, 83, - /* 260 */ 831, 834, 823, 823, 90, 90, 91, 91, 91, 91, - /* 270 */ 433, 89, 89, 89, 89, 88, 88, 87, 87, 87, - /* 280 */ 86, 339, 315, 434, 439, 651, 396, 57, 733, 733, - /* 290 */ 234, 291, 107, 287, 395, 86, 339, 810, 427, 728, - /* 300 */ 933, 933, 185, 953, 30, 388, 385, 384, 215, 949, - /* 310 */ 434, 933, 933, 819, 819, 697, 383, 162, 161, 407, - /* 320 */ 400, 85, 82, 168, 677, 804, 335, 113, 771, 798, - /* 330 */ 953, 48, 22, 351, 92, 93, 83, 831, 834, 823, - /* 340 */ 823, 90, 90, 91, 91, 91, 91, 870, 89, 89, - /* 350 */ 89, 89, 88, 88, 87, 87, 87, 86, 339, 315, - /* 360 */ 803, 803, 803, 268, 123, 412, 394, 1, 933, 933, - /* 370 */ 934, 935, 933, 933, 85, 82, 168, 232, 5, 343, - /* 380 */ 194, 934, 935, 952, 85, 82, 168, 54, 956, 434, - /* 390 */ 819, 819, 431, 938, 939, 792, 67, 759, 350, 144, - /* 400 */ 166, 770, 123, 896, 889, 955, 348, 288, 758, 953, - /* 410 */ 47, 92, 93, 83, 831, 834, 823, 823, 90, 90, - /* 420 */ 91, 91, 91, 91, 892, 89, 89, 89, 89, 88, - /* 430 */ 88, 87, 87, 87, 86, 339, 315, 113, 934, 935, - /* 440 */ 687, 893, 934, 935, 253, 358, 252, 85, 82, 168, - /* 450 */ 820, 820, 956, 952, 338, 938, 939, 894, 701, 721, - /* 460 */ 359, 289, 233, 397, 434, 349, 434, 819, 819, 955, - /* 470 */ 866, 722, 23, 389, 832, 835, 692, 357, 904, 667, - /* 480 */ 194, 702, 402, 952, 953, 48, 953, 48, 92, 93, - /* 490 */ 83, 831, 834, 823, 823, 90, 90, 91, 91, 91, - /* 500 */ 91, 824, 89, 89, 89, 89, 88, 88, 87, 87, - /* 510 */ 87, 86, 339, 315, 434, 113, 434, 680, 434, 332, - /* 520 */ 434, 408, 889, 356, 380, 940, 401, 720, 948, 864, - /* 530 */ 191, 165, 329, 689, 953, 9, 953, 9, 953, 9, - /* 540 */ 953, 9, 718, 948, 819, 819, 953, 8, 325, 111, - /* 550 */ 327, 153, 224, 952, 410, 113, 189, 337, 336, 913, - /* 560 */ 1295, 852, 75, 1295, 73, 92, 93, 83, 831, 834, - /* 570 */ 823, 823, 90, 90, 91, 91, 91, 91, 359, 89, - /* 580 */ 89, 89, 89, 88, 88, 87, 87, 87, 86, 339, - /* 590 */ 315, 730, 148, 236, 797, 366, 789, 892, 1179, 434, - /* 600 */ 960, 960, 400, 148, 314, 212, 873, 911, 757, 404, - /* 610 */ 872, 300, 320, 434, 893, 311, 237, 271, 405, 953, - /* 620 */ 34, 819, 819, 225, 371, 945, 360, 913, 1296, 113, - /* 630 */ 894, 1296, 417, 953, 35, 1245, 922, 342, 259, 247, - /* 640 */ 290, 315, 92, 93, 83, 831, 834, 823, 823, 90, - /* 650 */ 90, 91, 91, 91, 91, 148, 89, 89, 89, 89, - /* 660 */ 88, 88, 87, 87, 87, 86, 339, 310, 434, 796, - /* 670 */ 434, 240, 819, 819, 266, 911, 876, 876, 373, 346, - /* 680 */ 167, 654, 655, 656, 259, 244, 19, 246, 953, 11, - /* 690 */ 953, 26, 222, 92, 93, 83, 831, 834, 823, 823, - /* 700 */ 90, 90, 91, 91, 91, 91, 757, 89, 89, 89, - /* 710 */ 89, 88, 88, 87, 87, 87, 86, 339, 315, 434, - /* 720 */ 261, 434, 264, 696, 434, 241, 434, 344, 971, 308, - /* 730 */ 757, 434, 796, 434, 324, 434, 393, 423, 434, 953, - /* 740 */ 36, 953, 37, 20, 953, 38, 953, 27, 434, 819, - /* 750 */ 819, 953, 28, 953, 39, 953, 40, 738, 953, 41, - /* 760 */ 71, 738, 737, 245, 307, 973, 737, 259, 953, 10, - /* 770 */ 92, 93, 83, 831, 834, 823, 823, 90, 90, 91, - /* 780 */ 91, 91, 91, 434, 89, 89, 89, 89, 88, 88, - /* 790 */ 87, 87, 87, 86, 339, 315, 434, 372, 434, 259, - /* 800 */ 149, 434, 167, 953, 42, 188, 187, 186, 219, 434, - /* 810 */ 748, 434, 974, 434, 796, 434, 953, 98, 953, 43, - /* 820 */ 862, 953, 44, 434, 920, 2, 819, 819, 757, 953, - /* 830 */ 31, 953, 45, 953, 46, 953, 32, 74, 307, 912, - /* 840 */ 220, 259, 259, 953, 115, 909, 315, 92, 93, 83, - /* 850 */ 831, 834, 823, 823, 90, 90, 91, 91, 91, 91, - /* 860 */ 434, 89, 89, 89, 89, 88, 88, 87, 87, 87, - /* 870 */ 86, 339, 434, 248, 434, 215, 949, 819, 819, 333, - /* 880 */ 953, 116, 895, 860, 176, 259, 974, 400, 361, 259, - /* 890 */ 951, 887, 953, 117, 953, 52, 884, 315, 92, 93, - /* 900 */ 83, 831, 834, 823, 823, 90, 90, 91, 91, 91, - /* 910 */ 91, 434, 89, 89, 89, 89, 88, 88, 87, 87, - /* 920 */ 87, 86, 339, 434, 113, 434, 258, 883, 819, 819, - /* 930 */ 727, 953, 33, 363, 259, 673, 321, 189, 430, 321, - /* 940 */ 368, 365, 364, 953, 99, 953, 49, 365, 315, 92, - /* 950 */ 81, 83, 831, 834, 823, 823, 90, 90, 91, 91, - /* 960 */ 91, 91, 434, 89, 89, 89, 89, 88, 88, 87, - /* 970 */ 87, 87, 86, 339, 434, 723, 434, 214, 165, 819, - /* 980 */ 819, 772, 953, 100, 322, 124, 1269, 158, 65, 710, - /* 990 */ 773, 700, 699, 320, 953, 101, 953, 97, 255, 315, - /* 1000 */ 216, 93, 83, 831, 834, 823, 823, 90, 90, 91, - /* 1010 */ 91, 91, 91, 434, 89, 89, 89, 89, 88, 88, - /* 1020 */ 87, 87, 87, 86, 339, 434, 251, 434, 707, 708, - /* 1030 */ 819, 819, 223, 953, 114, 908, 794, 254, 309, 193, - /* 1040 */ 67, 381, 869, 869, 199, 953, 112, 953, 105, 269, - /* 1050 */ 726, 260, 67, 83, 831, 834, 823, 823, 90, 90, - /* 1060 */ 91, 91, 91, 91, 263, 89, 89, 89, 89, 88, - /* 1070 */ 88, 87, 87, 87, 86, 339, 79, 429, 690, 3, - /* 1080 */ 1174, 228, 434, 113, 340, 340, 868, 868, 265, 79, - /* 1090 */ 429, 735, 3, 859, 70, 432, 434, 340, 340, 434, - /* 1100 */ 1259, 434, 953, 104, 434, 670, 416, 766, 432, 434, - /* 1110 */ 193, 434, 413, 434, 418, 806, 953, 102, 420, 953, - /* 1120 */ 103, 953, 48, 123, 953, 51, 810, 418, 424, 953, - /* 1130 */ 53, 953, 50, 953, 25, 267, 123, 711, 113, 810, - /* 1140 */ 428, 277, 695, 272, 764, 113, 76, 77, 690, 434, - /* 1150 */ 795, 113, 276, 78, 436, 435, 412, 414, 798, 76, - /* 1160 */ 77, 113, 855, 859, 376, 199, 78, 436, 435, 953, - /* 1170 */ 29, 798, 744, 113, 755, 79, 429, 675, 3, 415, - /* 1180 */ 109, 292, 293, 340, 340, 806, 802, 678, 672, 803, - /* 1190 */ 803, 803, 805, 18, 432, 661, 660, 662, 927, 209, - /* 1200 */ 150, 352, 803, 803, 803, 805, 18, 6, 306, 280, - /* 1210 */ 282, 284, 786, 418, 250, 386, 243, 886, 694, 362, - /* 1220 */ 286, 163, 275, 79, 429, 810, 3, 857, 856, 159, - /* 1230 */ 419, 340, 340, 298, 930, 968, 126, 196, 965, 903, - /* 1240 */ 901, 323, 432, 136, 55, 76, 77, 742, 147, 58, - /* 1250 */ 121, 129, 78, 436, 435, 65, 783, 798, 354, 131, - /* 1260 */ 355, 418, 379, 132, 133, 134, 175, 139, 151, 369, - /* 1270 */ 888, 180, 791, 810, 61, 851, 871, 69, 429, 375, - /* 1280 */ 3, 756, 210, 257, 181, 340, 340, 145, 803, 803, - /* 1290 */ 803, 805, 18, 76, 77, 377, 432, 262, 182, 183, - /* 1300 */ 78, 436, 435, 663, 312, 798, 392, 714, 713, 712, - /* 1310 */ 330, 705, 692, 313, 704, 418, 686, 406, 752, 685, - /* 1320 */ 274, 684, 942, 64, 279, 195, 281, 810, 753, 839, - /* 1330 */ 751, 283, 72, 750, 285, 422, 803, 803, 803, 805, - /* 1340 */ 18, 334, 426, 95, 411, 229, 409, 76, 77, 230, - /* 1350 */ 734, 66, 231, 294, 78, 436, 435, 204, 295, 798, - /* 1360 */ 217, 296, 297, 669, 21, 305, 304, 303, 206, 301, - /* 1370 */ 437, 928, 664, 205, 208, 207, 438, 658, 657, 652, - /* 1380 */ 118, 108, 119, 226, 650, 341, 157, 170, 169, 239, - /* 1390 */ 803, 803, 803, 805, 18, 125, 120, 235, 238, 317, - /* 1400 */ 318, 345, 106, 790, 867, 127, 865, 128, 130, 724, - /* 1410 */ 249, 172, 174, 882, 135, 137, 59, 138, 173, 60, - /* 1420 */ 885, 123, 171, 177, 178, 881, 7, 12, 179, 256, - /* 1430 */ 874, 140, 193, 962, 374, 141, 666, 152, 378, 276, - /* 1440 */ 184, 382, 142, 122, 62, 13, 387, 703, 270, 14, - /* 1450 */ 63, 227, 809, 808, 837, 732, 15, 841, 736, 4, - /* 1460 */ 765, 211, 399, 164, 213, 143, 760, 201, 70, 316, - /* 1470 */ 67, 838, 836, 891, 198, 192, 16, 197, 890, 917, - /* 1480 */ 154, 17, 202, 421, 918, 155, 200, 156, 425, 840, - /* 1490 */ 807, 1261, 676, 80, 302, 299, 347, 1260, 923, + /* 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, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 19, 144, 145, 146, 147, 24, 1, 2, 27, 80, - /* 10 */ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 20 */ 91, 92, 93, 94, 95, 91, 92, 93, 94, 95, - /* 30 */ 19, 50, 51, 80, 81, 82, 83, 95, 85, 86, - /* 40 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 157, - /* 50 */ 27, 28, 71, 72, 73, 74, 75, 76, 77, 78, - /* 60 */ 79, 80, 81, 82, 83, 66, 85, 86, 87, 88, - /* 70 */ 89, 90, 91, 92, 93, 94, 95, 19, 97, 85, - /* 80 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - /* 90 */ 152, 33, 152, 22, 27, 28, 179, 180, 27, 28, - /* 100 */ 42, 27, 27, 28, 152, 188, 95, 152, 50, 51, - /* 110 */ 99, 100, 101, 102, 103, 104, 105, 27, 28, 227, - /* 120 */ 97, 98, 230, 112, 172, 173, 172, 172, 173, 71, - /* 130 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - /* 140 */ 82, 83, 66, 85, 86, 87, 88, 89, 90, 91, - /* 150 */ 92, 93, 94, 95, 19, 172, 89, 90, 218, 207, - /* 160 */ 208, 26, 207, 208, 97, 98, 91, 100, 97, 98, - /* 170 */ 69, 97, 97, 98, 107, 237, 109, 89, 90, 91, - /* 180 */ 92, 93, 94, 95, 152, 50, 51, 97, 98, 99, - /* 190 */ 55, 59, 102, 103, 104, 119, 120, 59, 97, 132, - /* 200 */ 133, 152, 101, 113, 66, 19, 71, 72, 73, 74, - /* 210 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 187, - /* 220 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - /* 230 */ 95, 172, 210, 132, 133, 134, 50, 51, 185, 53, - /* 240 */ 108, 109, 110, 221, 222, 223, 108, 109, 110, 22, - /* 250 */ 22, 119, 120, 181, 27, 27, 28, 71, 72, 73, - /* 260 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - /* 270 */ 152, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 280 */ 94, 95, 19, 152, 148, 149, 115, 24, 117, 118, - /* 290 */ 154, 152, 156, 152, 163, 94, 95, 69, 249, 163, - /* 300 */ 27, 28, 99, 172, 173, 102, 103, 104, 194, 195, - /* 310 */ 152, 27, 28, 50, 51, 181, 113, 89, 90, 152, - /* 320 */ 206, 221, 222, 223, 97, 97, 187, 196, 175, 101, - /* 330 */ 172, 173, 196, 219, 71, 72, 73, 74, 75, 76, - /* 340 */ 77, 78, 79, 80, 81, 82, 83, 11, 85, 86, - /* 350 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 19, - /* 360 */ 132, 133, 134, 23, 66, 207, 208, 22, 27, 28, - /* 370 */ 97, 98, 27, 28, 221, 222, 223, 199, 22, 243, - /* 380 */ 24, 97, 98, 27, 221, 222, 223, 209, 152, 152, - /* 390 */ 50, 51, 168, 169, 170, 59, 26, 124, 100, 58, - /* 400 */ 152, 175, 66, 240, 163, 169, 170, 152, 124, 172, - /* 410 */ 173, 71, 72, 73, 74, 75, 76, 77, 78, 79, - /* 420 */ 80, 81, 82, 83, 12, 85, 86, 87, 88, 89, - /* 430 */ 90, 91, 92, 93, 94, 95, 19, 196, 97, 98, - /* 440 */ 23, 29, 97, 98, 108, 109, 110, 221, 222, 223, - /* 450 */ 50, 51, 152, 97, 168, 169, 170, 45, 37, 47, - /* 460 */ 219, 224, 119, 120, 152, 229, 152, 50, 51, 169, - /* 470 */ 170, 59, 231, 52, 74, 75, 106, 236, 152, 21, - /* 480 */ 24, 60, 163, 27, 172, 173, 172, 173, 71, 72, - /* 490 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - /* 500 */ 83, 101, 85, 86, 87, 88, 89, 90, 91, 92, - /* 510 */ 93, 94, 95, 19, 152, 196, 152, 23, 152, 207, - /* 520 */ 152, 207, 163, 65, 19, 171, 152, 190, 191, 229, - /* 530 */ 211, 212, 111, 179, 172, 173, 172, 173, 172, 173, - /* 540 */ 172, 173, 190, 191, 50, 51, 172, 173, 186, 22, - /* 550 */ 186, 24, 186, 97, 186, 196, 51, 89, 90, 22, - /* 560 */ 23, 103, 137, 26, 139, 71, 72, 73, 74, 75, - /* 570 */ 76, 77, 78, 79, 80, 81, 82, 83, 219, 85, - /* 580 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - /* 590 */ 19, 195, 152, 152, 23, 236, 163, 12, 140, 152, - /* 600 */ 132, 133, 206, 152, 164, 23, 31, 70, 26, 19, - /* 610 */ 35, 160, 107, 152, 29, 164, 152, 112, 28, 172, - /* 620 */ 173, 50, 51, 183, 49, 185, 152, 22, 23, 196, - /* 630 */ 45, 26, 47, 172, 173, 0, 1, 2, 152, 16, - /* 640 */ 152, 19, 71, 72, 73, 74, 75, 76, 77, 78, - /* 650 */ 79, 80, 81, 82, 83, 152, 85, 86, 87, 88, - /* 660 */ 89, 90, 91, 92, 93, 94, 95, 164, 152, 152, - /* 670 */ 152, 152, 50, 51, 16, 70, 108, 109, 110, 193, - /* 680 */ 98, 7, 8, 9, 152, 62, 22, 64, 172, 173, - /* 690 */ 172, 173, 218, 71, 72, 73, 74, 75, 76, 77, - /* 700 */ 78, 79, 80, 81, 82, 83, 124, 85, 86, 87, - /* 710 */ 88, 89, 90, 91, 92, 93, 94, 95, 19, 152, - /* 720 */ 62, 152, 64, 181, 152, 193, 152, 241, 246, 247, - /* 730 */ 26, 152, 152, 152, 217, 152, 91, 249, 152, 172, - /* 740 */ 173, 172, 173, 79, 172, 173, 172, 173, 152, 50, - /* 750 */ 51, 172, 173, 172, 173, 172, 173, 116, 172, 173, - /* 760 */ 138, 116, 121, 140, 22, 23, 121, 152, 172, 173, - /* 770 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 780 */ 81, 82, 83, 152, 85, 86, 87, 88, 89, 90, - /* 790 */ 91, 92, 93, 94, 95, 19, 152, 217, 152, 152, - /* 800 */ 24, 152, 98, 172, 173, 108, 109, 110, 193, 152, - /* 810 */ 213, 152, 70, 152, 152, 152, 172, 173, 172, 173, - /* 820 */ 152, 172, 173, 152, 146, 147, 50, 51, 124, 172, - /* 830 */ 173, 172, 173, 172, 173, 172, 173, 138, 22, 23, - /* 840 */ 193, 152, 152, 172, 173, 152, 19, 71, 72, 73, - /* 850 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - /* 860 */ 152, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 870 */ 94, 95, 152, 152, 152, 194, 195, 50, 51, 217, - /* 880 */ 172, 173, 193, 193, 26, 152, 70, 206, 152, 152, - /* 890 */ 26, 163, 172, 173, 172, 173, 152, 19, 71, 72, - /* 900 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - /* 910 */ 83, 152, 85, 86, 87, 88, 89, 90, 91, 92, - /* 920 */ 93, 94, 95, 152, 196, 152, 193, 152, 50, 51, - /* 930 */ 193, 172, 173, 19, 152, 166, 167, 51, 166, 167, - /* 940 */ 152, 152, 28, 172, 173, 172, 173, 152, 19, 71, - /* 950 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - /* 960 */ 82, 83, 152, 85, 86, 87, 88, 89, 90, 91, - /* 970 */ 92, 93, 94, 95, 152, 193, 152, 211, 212, 50, - /* 980 */ 51, 33, 172, 173, 244, 245, 23, 123, 130, 26, - /* 990 */ 42, 100, 101, 107, 172, 173, 172, 173, 152, 19, - /* 1000 */ 22, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 1010 */ 81, 82, 83, 152, 85, 86, 87, 88, 89, 90, - /* 1020 */ 91, 92, 93, 94, 95, 152, 237, 152, 7, 8, - /* 1030 */ 50, 51, 237, 172, 173, 23, 23, 23, 26, 26, - /* 1040 */ 26, 23, 132, 133, 26, 172, 173, 172, 173, 23, - /* 1050 */ 163, 152, 26, 73, 74, 75, 76, 77, 78, 79, - /* 1060 */ 80, 81, 82, 83, 152, 85, 86, 87, 88, 89, - /* 1070 */ 90, 91, 92, 93, 94, 95, 19, 20, 27, 22, - /* 1080 */ 23, 210, 152, 196, 27, 28, 132, 133, 152, 19, - /* 1090 */ 20, 23, 22, 27, 26, 38, 152, 27, 28, 152, - /* 1100 */ 122, 152, 172, 173, 152, 163, 191, 23, 38, 152, - /* 1110 */ 26, 152, 163, 152, 57, 27, 172, 173, 163, 172, - /* 1120 */ 173, 172, 173, 66, 172, 173, 69, 57, 163, 172, - /* 1130 */ 173, 172, 173, 172, 173, 152, 66, 152, 196, 69, - /* 1140 */ 163, 101, 152, 152, 152, 196, 89, 90, 97, 152, - /* 1150 */ 152, 196, 112, 96, 97, 98, 207, 208, 101, 89, - /* 1160 */ 90, 196, 23, 97, 233, 26, 96, 97, 98, 172, - /* 1170 */ 173, 101, 152, 196, 152, 19, 20, 23, 22, 152, - /* 1180 */ 26, 152, 152, 27, 28, 97, 152, 152, 152, 132, - /* 1190 */ 133, 134, 135, 136, 38, 152, 152, 152, 152, 232, - /* 1200 */ 197, 214, 132, 133, 134, 135, 136, 198, 150, 210, - /* 1210 */ 210, 210, 201, 57, 238, 176, 214, 201, 180, 238, - /* 1220 */ 214, 184, 175, 19, 20, 69, 22, 175, 175, 198, - /* 1230 */ 226, 27, 28, 200, 155, 39, 242, 122, 41, 159, - /* 1240 */ 159, 159, 38, 22, 239, 89, 90, 91, 220, 239, - /* 1250 */ 71, 189, 96, 97, 98, 130, 201, 101, 18, 192, - /* 1260 */ 159, 57, 18, 192, 192, 192, 158, 189, 220, 159, - /* 1270 */ 201, 158, 189, 69, 137, 201, 235, 19, 20, 46, - /* 1280 */ 22, 159, 159, 234, 158, 27, 28, 22, 132, 133, - /* 1290 */ 134, 135, 136, 89, 90, 177, 38, 159, 158, 158, - /* 1300 */ 96, 97, 98, 159, 177, 101, 107, 174, 174, 174, - /* 1310 */ 48, 182, 106, 177, 182, 57, 174, 125, 216, 176, - /* 1320 */ 174, 174, 174, 107, 215, 159, 215, 69, 216, 159, - /* 1330 */ 216, 215, 137, 216, 215, 177, 132, 133, 134, 135, - /* 1340 */ 136, 95, 177, 129, 126, 225, 127, 89, 90, 228, - /* 1350 */ 205, 128, 228, 204, 96, 97, 98, 25, 203, 101, - /* 1360 */ 5, 202, 201, 162, 26, 10, 11, 12, 13, 14, - /* 1370 */ 161, 13, 17, 153, 6, 153, 151, 151, 151, 151, - /* 1380 */ 165, 178, 165, 178, 4, 3, 22, 32, 15, 34, - /* 1390 */ 132, 133, 134, 135, 136, 245, 165, 142, 43, 248, - /* 1400 */ 248, 68, 16, 120, 23, 131, 23, 111, 123, 20, - /* 1410 */ 16, 56, 125, 1, 123, 131, 79, 111, 63, 79, - /* 1420 */ 28, 66, 67, 36, 122, 1, 5, 22, 107, 140, - /* 1430 */ 54, 54, 26, 61, 44, 107, 20, 24, 19, 112, - /* 1440 */ 105, 53, 22, 40, 22, 22, 53, 30, 23, 22, - /* 1450 */ 22, 53, 23, 23, 23, 116, 22, 11, 23, 22, - /* 1460 */ 28, 23, 26, 122, 23, 22, 124, 122, 26, 114, - /* 1470 */ 26, 23, 23, 23, 22, 36, 36, 26, 23, 23, - /* 1480 */ 22, 36, 122, 24, 23, 22, 26, 22, 24, 23, - /* 1490 */ 23, 122, 23, 22, 15, 23, 141, 122, 1, + /* 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, }; -#define YY_SHIFT_USE_DFLT (-72) -#define YY_SHIFT_COUNT (439) -#define YY_SHIFT_MIN (-71) -#define YY_SHIFT_MAX (1497) +#define YY_SHIFT_USE_DFLT (1567) +#define YY_SHIFT_COUNT (455) +#define YY_SHIFT_MIN (-94) +#define YY_SHIFT_MAX (1549) static const short yy_shift_ofst[] = { - /* 0 */ 5, 1057, 1355, 1070, 1204, 1204, 1204, 138, -19, 58, - /* 10 */ 58, 186, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 67, - /* 20 */ 67, 90, 132, 336, 76, 135, 263, 340, 417, 494, - /* 30 */ 571, 622, 699, 776, 827, 827, 827, 827, 827, 827, - /* 40 */ 827, 827, 827, 827, 827, 827, 827, 827, 827, 878, - /* 50 */ 827, 929, 980, 980, 1156, 1204, 1204, 1204, 1204, 1204, - /* 60 */ 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, - /* 70 */ 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, - /* 80 */ 1204, 1204, 1204, 1258, 1204, 1204, 1204, 1204, 1204, 1204, - /* 90 */ 1204, 1204, 1204, 1204, 1204, 1204, 1204, -71, -47, -47, - /* 100 */ -47, -47, -47, -6, 88, -66, 23, 458, 505, 468, - /* 110 */ 468, 23, 201, 343, -58, -72, -72, -72, 11, 11, - /* 120 */ 11, 412, 412, 341, 537, 605, 23, 23, 23, 23, - /* 130 */ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - /* 140 */ 23, 23, 23, 23, 23, 23, 635, 298, 74, 74, - /* 150 */ 343, -1, -1, -1, -1, -1, -1, -72, -72, -72, - /* 160 */ 228, 101, 101, 203, 75, 71, 273, 284, 345, 23, - /* 170 */ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - /* 180 */ 23, 23, 23, 23, 23, 23, 421, 421, 421, 23, - /* 190 */ 23, 582, 23, 23, 23, 356, 23, 23, 585, 23, - /* 200 */ 23, 23, 23, 23, 23, 23, 23, 23, 23, 568, - /* 210 */ 575, 456, 456, 456, 704, 171, 645, 674, 858, 590, - /* 220 */ 590, 914, 858, 914, 370, 963, 886, 948, 590, 425, - /* 230 */ 948, 948, 864, 641, 527, 1196, 1115, 1115, 1197, 1197, - /* 240 */ 1115, 1221, 1179, 1125, 1240, 1240, 1240, 1240, 1115, 1244, - /* 250 */ 1125, 1221, 1179, 1179, 1125, 1115, 1244, 1137, 1233, 1115, - /* 260 */ 1115, 1244, 1265, 1115, 1244, 1115, 1244, 1265, 1199, 1199, - /* 270 */ 1199, 1262, 1265, 1199, 1206, 1199, 1262, 1199, 1199, 1192, - /* 280 */ 1216, 1192, 1216, 1192, 1216, 1192, 1216, 1115, 1115, 1195, - /* 290 */ 1265, 1246, 1246, 1265, 1214, 1218, 1223, 1219, 1125, 1332, - /* 300 */ 1338, 1358, 1358, 1368, 1368, 1368, 1368, -72, -72, -72, - /* 310 */ -72, -72, -72, -72, -72, 400, 623, 742, 816, 658, - /* 320 */ 697, 227, 1012, 664, 1013, 1014, 1018, 1026, 1051, 891, - /* 330 */ 1021, 1040, 1068, 1084, 1066, 1139, 910, 954, 1154, 1088, - /* 340 */ 978, 1380, 1382, 1364, 1255, 1373, 1333, 1386, 1381, 1383, - /* 350 */ 1283, 1274, 1296, 1285, 1389, 1287, 1394, 1412, 1291, 1284, - /* 360 */ 1337, 1340, 1306, 1392, 1387, 1302, 1424, 1421, 1405, 1321, - /* 370 */ 1289, 1376, 1406, 1377, 1372, 1390, 1328, 1413, 1416, 1419, - /* 380 */ 1327, 1335, 1420, 1388, 1422, 1423, 1425, 1427, 1393, 1417, - /* 390 */ 1428, 1398, 1403, 1429, 1430, 1431, 1339, 1434, 1435, 1437, - /* 400 */ 1436, 1341, 1438, 1441, 1432, 1439, 1443, 1342, 1442, 1440, - /* 410 */ 1444, 1445, 1442, 1448, 1449, 1450, 1451, 1455, 1452, 1446, - /* 420 */ 1456, 1458, 1459, 1460, 1461, 1463, 1464, 1460, 1466, 1465, - /* 430 */ 1467, 1469, 1471, 1345, 1360, 1369, 1375, 1472, 1479, 1497, + /* 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, }; -#define YY_REDUCE_USE_DFLT (-144) -#define YY_REDUCE_COUNT (314) -#define YY_REDUCE_MIN (-143) -#define YY_REDUCE_MAX (1231) +#define YY_REDUCE_USE_DFLT (-130) +#define YY_REDUCE_COUNT (324) +#define YY_REDUCE_MIN (-129) +#define YY_REDUCE_MAX (1300) static const short yy_reduce_ofst[] = { - /* 0 */ -143, 949, 136, 131, -48, -45, 158, 241, 22, 153, - /* 10 */ 226, 163, 362, 364, 366, 312, 314, 368, 237, 236, - /* 20 */ 300, 440, 114, 359, 319, 100, 100, 100, 100, 100, - /* 30 */ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - /* 40 */ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - /* 50 */ 100, 100, 100, 100, 374, 447, 461, 516, 518, 567, - /* 60 */ 569, 572, 574, 579, 581, 583, 586, 596, 631, 644, - /* 70 */ 646, 649, 657, 659, 661, 663, 671, 708, 720, 722, - /* 80 */ 759, 771, 773, 810, 822, 824, 861, 873, 875, 930, - /* 90 */ 944, 947, 952, 957, 959, 961, 997, 100, 100, 100, - /* 100 */ 100, 100, 100, 100, 100, 100, 486, -108, -83, 224, - /* 110 */ 286, 451, 100, 681, 100, 100, 100, 100, 354, 354, - /* 120 */ 354, 337, 352, 49, 482, 482, 503, 532, -60, 615, - /* 130 */ 647, 689, 690, 737, 782, -62, 517, 789, 474, 795, - /* 140 */ 580, 733, 32, 662, 488, 139, 678, 433, 769, 772, - /* 150 */ 396, 728, 887, 942, 955, 965, 977, 740, 766, 178, - /* 160 */ -46, -17, 59, 53, 118, 141, 167, 248, 255, 326, - /* 170 */ 441, 464, 519, 668, 693, 721, 736, 744, 775, 788, - /* 180 */ 846, 899, 912, 936, 983, 985, 72, 134, 542, 990, - /* 190 */ 991, 597, 992, 998, 1020, 871, 1022, 1027, 915, 1029, - /* 200 */ 1030, 1034, 118, 1035, 1036, 1043, 1044, 1045, 1046, 931, - /* 210 */ 967, 999, 1000, 1001, 597, 1003, 1009, 1058, 1011, 987, - /* 220 */ 1002, 976, 1016, 981, 1039, 1037, 1038, 1047, 1006, 1004, - /* 230 */ 1052, 1053, 1033, 1031, 1079, 994, 1080, 1081, 1005, 1010, - /* 240 */ 1082, 1028, 1062, 1055, 1067, 1071, 1072, 1073, 1101, 1108, - /* 250 */ 1069, 1048, 1078, 1083, 1074, 1110, 1113, 1041, 1049, 1122, - /* 260 */ 1123, 1126, 1118, 1138, 1140, 1144, 1141, 1127, 1133, 1134, - /* 270 */ 1135, 1129, 1136, 1142, 1143, 1146, 1132, 1147, 1148, 1102, - /* 280 */ 1109, 1112, 1111, 1114, 1116, 1117, 1119, 1166, 1170, 1120, - /* 290 */ 1158, 1121, 1124, 1165, 1145, 1149, 1155, 1159, 1161, 1201, - /* 300 */ 1209, 1220, 1222, 1225, 1226, 1227, 1228, 1151, 1152, 1150, - /* 310 */ 1215, 1217, 1203, 1205, 1231, + /* 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, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1250, 1240, 1240, 1240, 1174, 1174, 1174, 1240, 1071, 1100, - /* 10 */ 1100, 1224, 1301, 1301, 1301, 1301, 1301, 1301, 1173, 1301, - /* 20 */ 1301, 1301, 1301, 1240, 1075, 1106, 1301, 1301, 1301, 1301, - /* 30 */ 1301, 1301, 1301, 1301, 1223, 1225, 1114, 1113, 1206, 1087, - /* 40 */ 1111, 1104, 1108, 1175, 1169, 1170, 1168, 1172, 1176, 1301, - /* 50 */ 1107, 1138, 1153, 1137, 1301, 1301, 1301, 1301, 1301, 1301, - /* 60 */ 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, - /* 70 */ 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, - /* 80 */ 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, - /* 90 */ 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1147, 1152, 1159, - /* 100 */ 1151, 1148, 1140, 1139, 1141, 1142, 1301, 994, 1042, 1301, - /* 110 */ 1301, 1301, 1143, 1301, 1144, 1156, 1155, 1154, 1231, 1258, - /* 120 */ 1257, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, - /* 130 */ 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, - /* 140 */ 1301, 1301, 1301, 1301, 1301, 1301, 1250, 1240, 1000, 1000, - /* 150 */ 1301, 1240, 1240, 1240, 1240, 1240, 1240, 1236, 1075, 1066, - /* 160 */ 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, - /* 170 */ 1228, 1226, 1301, 1187, 1301, 1301, 1301, 1301, 1301, 1301, - /* 180 */ 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, - /* 190 */ 1301, 1301, 1301, 1301, 1301, 1071, 1301, 1301, 1301, 1301, - /* 200 */ 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1252, 1301, - /* 210 */ 1201, 1071, 1071, 1071, 1073, 1055, 1065, 979, 1110, 1089, - /* 220 */ 1089, 1290, 1110, 1290, 1017, 1272, 1014, 1100, 1089, 1171, - /* 230 */ 1100, 1100, 1072, 1065, 1301, 1293, 1080, 1080, 1292, 1292, - /* 240 */ 1080, 1119, 1045, 1110, 1051, 1051, 1051, 1051, 1080, 991, - /* 250 */ 1110, 1119, 1045, 1045, 1110, 1080, 991, 1205, 1287, 1080, - /* 260 */ 1080, 991, 1180, 1080, 991, 1080, 991, 1180, 1043, 1043, - /* 270 */ 1043, 1032, 1180, 1043, 1017, 1043, 1032, 1043, 1043, 1093, - /* 280 */ 1088, 1093, 1088, 1093, 1088, 1093, 1088, 1080, 1080, 1301, - /* 290 */ 1180, 1184, 1184, 1180, 1105, 1094, 1103, 1101, 1110, 997, - /* 300 */ 1035, 1255, 1255, 1251, 1251, 1251, 1251, 1298, 1298, 1236, - /* 310 */ 1267, 1267, 1019, 1019, 1267, 1301, 1301, 1301, 1301, 1301, - /* 320 */ 1301, 1262, 1301, 1189, 1301, 1301, 1301, 1301, 1301, 1301, - /* 330 */ 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, - /* 340 */ 1125, 1301, 975, 1233, 1301, 1301, 1232, 1301, 1301, 1301, - /* 350 */ 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, - /* 360 */ 1301, 1301, 1301, 1301, 1301, 1289, 1301, 1301, 1301, 1301, - /* 370 */ 1301, 1301, 1204, 1203, 1301, 1301, 1301, 1301, 1301, 1301, - /* 380 */ 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, - /* 390 */ 1301, 1301, 1301, 1301, 1301, 1301, 1057, 1301, 1301, 1301, - /* 400 */ 1276, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1102, 1301, - /* 410 */ 1095, 1301, 1280, 1301, 1301, 1301, 1301, 1301, 1301, 1301, - /* 420 */ 1301, 1301, 1301, 1242, 1301, 1301, 1301, 1241, 1301, 1301, - /* 430 */ 1301, 1301, 1301, 1127, 1301, 1126, 1130, 1301, 985, 1301, + /* 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, }; /********** End of lemon-generated parsing tables *****************************/ @@ -129132,74 +133677,100 @@ static const YYACTIONTYPE yy_default[] = { static const YYCODETYPE yyFallback[] = { 0, /* $ => nothing */ 0, /* SEMI => nothing */ - 27, /* EXPLAIN => ID */ - 27, /* QUERY => ID */ - 27, /* PLAN => ID */ - 27, /* BEGIN => ID */ + 55, /* EXPLAIN => ID */ + 55, /* QUERY => ID */ + 55, /* PLAN => ID */ + 55, /* BEGIN => ID */ 0, /* TRANSACTION => nothing */ - 27, /* DEFERRED => ID */ - 27, /* IMMEDIATE => ID */ - 27, /* EXCLUSIVE => ID */ + 55, /* DEFERRED => ID */ + 55, /* IMMEDIATE => ID */ + 55, /* EXCLUSIVE => ID */ 0, /* COMMIT => nothing */ - 27, /* END => ID */ - 27, /* ROLLBACK => ID */ - 27, /* SAVEPOINT => ID */ - 27, /* RELEASE => ID */ + 55, /* END => ID */ + 55, /* ROLLBACK => ID */ + 55, /* SAVEPOINT => ID */ + 55, /* RELEASE => ID */ 0, /* TO => nothing */ 0, /* TABLE => nothing */ 0, /* CREATE => nothing */ - 27, /* IF => ID */ + 55, /* IF => ID */ 0, /* NOT => nothing */ 0, /* EXISTS => nothing */ - 27, /* TEMP => ID */ + 55, /* TEMP => ID */ 0, /* LP => nothing */ 0, /* RP => nothing */ 0, /* AS => nothing */ - 27, /* WITHOUT => ID */ + 55, /* 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 */ - 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 */ + 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 */ }; #endif /* YYFALLBACK */ @@ -129231,9 +133802,9 @@ typedef struct yyStackEntry yyStackEntry; /* The state of the parser is completely contained in an instance of ** the following structure */ struct yyParser { - int yyidx; /* Index of top element in stack */ + yyStackEntry *yytos; /* Pointer to top element of the stack */ #ifdef YYTRACKMAXSTACKDEPTH - int yyidxMax; /* Maximum value of yyidx */ + int yyhwm; /* High-water mark of the stack */ #endif #ifndef YYNOERRORRECOVERY int yyerrcnt; /* Shifts left before out of the error */ @@ -129242,6 +133813,7 @@ struct yyParser { #if YYSTACKDEPTH<=0 int yystksz; /* Current side of the stack */ yyStackEntry *yystack; /* The parser's stack */ + yyStackEntry yystk0; /* First stack entry */ #else yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ #endif @@ -129290,25 +133862,25 @@ static const char *const yyTokenName[] = { "ROLLBACK", "SAVEPOINT", "RELEASE", "TO", "TABLE", "CREATE", "IF", "NOT", "EXISTS", "TEMP", "LP", "RP", - "AS", "WITHOUT", "COMMA", "ID", + "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", "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", "STRING", "JOIN_KW", "CONSTRAINT", + "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", "DEFAULT", "NULL", "PRIMARY", "UNIQUE", "CHECK", "REFERENCES", "AUTOINCR", "ON", "INSERT", "DELETE", "UPDATE", "SET", @@ -129317,7 +133889,7 @@ static const char *const yyTokenName[] = { "VALUES", "DISTINCT", "DOT", "FROM", "JOIN", "USING", "ORDER", "GROUP", "HAVING", "LIMIT", "WHERE", "INTO", - "INTEGER", "FLOAT", "BLOB", "VARIABLE", + "FLOAT", "BLOB", "INTEGER", "VARIABLE", "CASE", "WHEN", "THEN", "ELSE", "INDEX", "ALTER", "ADD", "error", "input", "cmdlist", "ecmd", "explain", @@ -129340,13 +133912,13 @@ static const char *const yyTokenName[] = { "stl_prefix", "joinop", "indexed_opt", "on_opt", "using_opt", "idlist", "setlist", "insert_cmd", "idlist_opt", "likeop", "between_op", "in_op", - "case_operand", "case_exprlist", "case_else", "uniqueflag", - "collate", "nmnum", "trigger_decl", "trigger_cmd_list", - "trigger_time", "trigger_event", "foreach_clause", "when_clause", - "trigger_cmd", "trnm", "tridxby", "database_kw_opt", - "key_opt", "add_column_fullname", "kwcolumn_opt", "create_vtab", - "vtabarglist", "vtabarg", "vtabargtoken", "lp", - "anylist", "wqlist", + "paren_exprlist", "case_operand", "case_exprlist", "case_else", + "uniqueflag", "collate", "nmnum", "trigger_decl", + "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause", + "when_clause", "trigger_cmd", "trnm", "tridxby", + "database_kw_opt", "key_opt", "add_column_fullname", "kwcolumn_opt", + "create_vtab", "vtabarglist", "vtabarg", "vtabargtoken", + "lp", "anylist", "wqlist", }; #endif /* NDEBUG */ @@ -129493,217 +134065,233 @@ static const char *const yyRuleName[] = { /* 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 ::= nm EQ expr", - /* 140 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select", - /* 141 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES", - /* 142 */ "insert_cmd ::= INSERT orconf", - /* 143 */ "insert_cmd ::= REPLACE", - /* 144 */ "idlist_opt ::=", - /* 145 */ "idlist_opt ::= LP idlist RP", - /* 146 */ "idlist ::= idlist COMMA nm", - /* 147 */ "idlist ::= nm", - /* 148 */ "expr ::= LP expr RP", - /* 149 */ "term ::= NULL", - /* 150 */ "expr ::= ID|INDEXED", - /* 151 */ "expr ::= JOIN_KW", - /* 152 */ "expr ::= nm DOT nm", - /* 153 */ "expr ::= nm DOT nm DOT nm", - /* 154 */ "term ::= INTEGER|FLOAT|BLOB", - /* 155 */ "term ::= STRING", - /* 156 */ "expr ::= VARIABLE", - /* 157 */ "expr ::= expr COLLATE ID|STRING", - /* 158 */ "expr ::= CAST LP expr AS typetoken RP", - /* 159 */ "expr ::= ID|INDEXED LP distinct exprlist RP", - /* 160 */ "expr ::= ID|INDEXED LP STAR RP", - /* 161 */ "term ::= CTIME_KW", - /* 162 */ "expr ::= expr AND expr", - /* 163 */ "expr ::= expr OR expr", - /* 164 */ "expr ::= expr LT|GT|GE|LE expr", - /* 165 */ "expr ::= expr EQ|NE expr", - /* 166 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", - /* 167 */ "expr ::= expr PLUS|MINUS expr", - /* 168 */ "expr ::= expr STAR|SLASH|REM expr", - /* 169 */ "expr ::= expr CONCAT expr", - /* 170 */ "likeop ::= LIKE_KW|MATCH", - /* 171 */ "likeop ::= NOT LIKE_KW|MATCH", - /* 172 */ "expr ::= expr likeop expr", - /* 173 */ "expr ::= expr likeop expr ESCAPE expr", - /* 174 */ "expr ::= expr ISNULL|NOTNULL", - /* 175 */ "expr ::= expr NOT NULL", - /* 176 */ "expr ::= expr IS expr", - /* 177 */ "expr ::= expr IS NOT expr", - /* 178 */ "expr ::= NOT expr", - /* 179 */ "expr ::= BITNOT expr", - /* 180 */ "expr ::= MINUS expr", - /* 181 */ "expr ::= PLUS expr", - /* 182 */ "between_op ::= BETWEEN", - /* 183 */ "between_op ::= NOT BETWEEN", - /* 184 */ "expr ::= expr between_op expr AND expr", - /* 185 */ "in_op ::= IN", - /* 186 */ "in_op ::= NOT IN", - /* 187 */ "expr ::= expr in_op LP exprlist RP", - /* 188 */ "expr ::= LP select RP", - /* 189 */ "expr ::= expr in_op LP select RP", - /* 190 */ "expr ::= expr in_op nm dbnm", - /* 191 */ "expr ::= EXISTS LP select RP", - /* 192 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 193 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 194 */ "case_exprlist ::= WHEN expr THEN expr", - /* 195 */ "case_else ::= ELSE expr", - /* 196 */ "case_else ::=", - /* 197 */ "case_operand ::= expr", - /* 198 */ "case_operand ::=", - /* 199 */ "exprlist ::=", - /* 200 */ "nexprlist ::= nexprlist COMMA expr", - /* 201 */ "nexprlist ::= expr", - /* 202 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", - /* 203 */ "uniqueflag ::= UNIQUE", - /* 204 */ "uniqueflag ::=", - /* 205 */ "eidlist_opt ::=", - /* 206 */ "eidlist_opt ::= LP eidlist RP", - /* 207 */ "eidlist ::= eidlist COMMA nm collate sortorder", - /* 208 */ "eidlist ::= nm collate sortorder", - /* 209 */ "collate ::=", - /* 210 */ "collate ::= COLLATE ID|STRING", - /* 211 */ "cmd ::= DROP INDEX ifexists fullname", - /* 212 */ "cmd ::= VACUUM", - /* 213 */ "cmd ::= VACUUM nm", - /* 214 */ "cmd ::= PRAGMA nm dbnm", - /* 215 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 216 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 217 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 218 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 219 */ "plus_num ::= PLUS INTEGER|FLOAT", - /* 220 */ "minus_num ::= MINUS INTEGER|FLOAT", - /* 221 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 222 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 223 */ "trigger_time ::= BEFORE", - /* 224 */ "trigger_time ::= AFTER", - /* 225 */ "trigger_time ::= INSTEAD OF", - /* 226 */ "trigger_time ::=", - /* 227 */ "trigger_event ::= DELETE|INSERT", - /* 228 */ "trigger_event ::= UPDATE", - /* 229 */ "trigger_event ::= UPDATE OF idlist", - /* 230 */ "when_clause ::=", - /* 231 */ "when_clause ::= WHEN expr", - /* 232 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 233 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 234 */ "trnm ::= nm DOT nm", - /* 235 */ "tridxby ::= INDEXED BY nm", - /* 236 */ "tridxby ::= NOT INDEXED", - /* 237 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", - /* 238 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", - /* 239 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", - /* 240 */ "trigger_cmd ::= select", - /* 241 */ "expr ::= RAISE LP IGNORE RP", - /* 242 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 243 */ "raisetype ::= ROLLBACK", - /* 244 */ "raisetype ::= ABORT", - /* 245 */ "raisetype ::= FAIL", - /* 246 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 247 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 248 */ "cmd ::= DETACH database_kw_opt expr", - /* 249 */ "key_opt ::=", - /* 250 */ "key_opt ::= KEY expr", - /* 251 */ "cmd ::= REINDEX", - /* 252 */ "cmd ::= REINDEX nm dbnm", - /* 253 */ "cmd ::= ANALYZE", - /* 254 */ "cmd ::= ANALYZE nm dbnm", - /* 255 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 256 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", - /* 257 */ "add_column_fullname ::= fullname", - /* 258 */ "cmd ::= create_vtab", - /* 259 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 260 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 261 */ "vtabarg ::=", - /* 262 */ "vtabargtoken ::= ANY", - /* 263 */ "vtabargtoken ::= lp anylist RP", - /* 264 */ "lp ::= LP", - /* 265 */ "with ::=", - /* 266 */ "with ::= WITH wqlist", - /* 267 */ "with ::= WITH RECURSIVE wqlist", - /* 268 */ "wqlist ::= nm eidlist_opt AS LP select RP", - /* 269 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", - /* 270 */ "input ::= cmdlist", - /* 271 */ "cmdlist ::= cmdlist ecmd", - /* 272 */ "cmdlist ::= ecmd", - /* 273 */ "ecmd ::= SEMI", - /* 274 */ "ecmd ::= explain cmdx SEMI", - /* 275 */ "explain ::=", - /* 276 */ "trans_opt ::=", - /* 277 */ "trans_opt ::= TRANSACTION", - /* 278 */ "trans_opt ::= TRANSACTION nm", - /* 279 */ "savepoint_opt ::= SAVEPOINT", - /* 280 */ "savepoint_opt ::=", - /* 281 */ "cmd ::= create_table create_table_args", - /* 282 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 283 */ "columnlist ::= columnname carglist", - /* 284 */ "nm ::= ID|INDEXED", - /* 285 */ "nm ::= STRING", - /* 286 */ "nm ::= JOIN_KW", - /* 287 */ "typetoken ::= typename", - /* 288 */ "typename ::= ID|STRING", - /* 289 */ "signed ::= plus_num", - /* 290 */ "signed ::= minus_num", - /* 291 */ "carglist ::= carglist ccons", - /* 292 */ "carglist ::=", - /* 293 */ "ccons ::= NULL onconf", - /* 294 */ "conslist_opt ::= COMMA conslist", - /* 295 */ "conslist ::= conslist tconscomma tcons", - /* 296 */ "conslist ::= tcons", - /* 297 */ "tconscomma ::=", - /* 298 */ "defer_subclause_opt ::= defer_subclause", - /* 299 */ "resolvetype ::= raisetype", - /* 300 */ "selectnowith ::= oneselect", - /* 301 */ "oneselect ::= values", - /* 302 */ "sclp ::= selcollist COMMA", - /* 303 */ "as ::= ID|STRING", - /* 304 */ "expr ::= term", - /* 305 */ "exprlist ::= nexprlist", - /* 306 */ "nmnum ::= plus_num", - /* 307 */ "nmnum ::= nm", - /* 308 */ "nmnum ::= ON", - /* 309 */ "nmnum ::= DELETE", - /* 310 */ "nmnum ::= DEFAULT", - /* 311 */ "plus_num ::= INTEGER|FLOAT", - /* 312 */ "foreach_clause ::=", - /* 313 */ "foreach_clause ::= FOR EACH ROW", - /* 314 */ "trnm ::= nm", - /* 315 */ "tridxby ::=", - /* 316 */ "database_kw_opt ::= DATABASE", - /* 317 */ "database_kw_opt ::=", - /* 318 */ "kwcolumn_opt ::=", - /* 319 */ "kwcolumn_opt ::= COLUMNKW", - /* 320 */ "vtabarglist ::= vtabarg", - /* 321 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 322 */ "vtabarg ::= vtabarg vtabargtoken", - /* 323 */ "anylist ::=", - /* 324 */ "anylist ::= anylist LP anylist RP", - /* 325 */ "anylist ::= anylist ANY", + /* 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", }; #endif /* NDEBUG */ #if YYSTACKDEPTH<=0 /* -** Try to increase the size of the parser stack. +** Try to increase the size of the parser stack. Return the number +** of errors. Return 0 on success. */ -static void yyGrowStack(yyParser *p){ +static int yyGrowStack(yyParser *p){ int newSize; + int idx; yyStackEntry *pNew; newSize = p->yystksz*2 + 100; - pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); + idx = p->yytos ? (int)(p->yytos - p->yystack) : 0; + if( p->yystack==&p->yystk0 ){ + pNew = malloc(newSize*sizeof(pNew[0])); + if( pNew ) pNew[0] = p->yystk0; + }else{ + pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); + } if( pNew ){ p->yystack = pNew; - p->yystksz = newSize; + p->yytos = &p->yystack[idx]; #ifndef NDEBUG if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sStack grows to %d entries!\n", - yyTracePrompt, p->yystksz); + fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n", + yyTracePrompt, p->yystksz, newSize); } #endif + p->yystksz = newSize; } + return pNew==0; } #endif @@ -129732,15 +134320,24 @@ SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ yyParser *pParser; pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); if( pParser ){ - pParser->yyidx = -1; #ifdef YYTRACKMAXSTACKDEPTH - pParser->yyidxMax = 0; + pParser->yyhwm = 0; #endif #if YYSTACKDEPTH<=0 + pParser->yytos = NULL; pParser->yystack = NULL; pParser->yystksz = 0; - yyGrowStack(pParser); + 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; } return pParser; } @@ -129775,13 +134372,13 @@ static void yy_destructor( case 195: /* oneselect */ case 206: /* values */ { -sqlite3SelectDelete(pParse->db, (yypminor->yy159)); +sqlite3SelectDelete(pParse->db, (yypminor->yy243)); } break; case 172: /* term */ case 173: /* expr */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy342).pExpr); +sqlite3ExprDelete(pParse->db, (yypminor->yy190).pExpr); } break; case 177: /* eidlist_opt */ @@ -129794,9 +134391,10 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy342).pExpr); case 208: /* exprlist */ case 209: /* sclp */ case 218: /* setlist */ - case 225: /* case_exprlist */ + case 224: /* paren_exprlist */ + case 226: /* case_exprlist */ { -sqlite3ExprListDelete(pParse->db, (yypminor->yy442)); +sqlite3ExprListDelete(pParse->db, (yypminor->yy148)); } break; case 193: /* fullname */ @@ -129804,42 +134402,42 @@ sqlite3ExprListDelete(pParse->db, (yypminor->yy442)); case 211: /* seltablist */ case 212: /* stl_prefix */ { -sqlite3SrcListDelete(pParse->db, (yypminor->yy347)); +sqlite3SrcListDelete(pParse->db, (yypminor->yy185)); } break; case 196: /* with */ - case 249: /* wqlist */ + case 250: /* wqlist */ { -sqlite3WithDelete(pParse->db, (yypminor->yy331)); +sqlite3WithDelete(pParse->db, (yypminor->yy285)); } break; case 201: /* where_opt */ case 203: /* having_opt */ case 215: /* on_opt */ - case 224: /* case_operand */ - case 226: /* case_else */ - case 235: /* when_clause */ - case 240: /* key_opt */ + case 225: /* case_operand */ + case 227: /* case_else */ + case 236: /* when_clause */ + case 241: /* key_opt */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy122)); +sqlite3ExprDelete(pParse->db, (yypminor->yy72)); } break; case 216: /* using_opt */ case 217: /* idlist */ case 220: /* idlist_opt */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy180)); +sqlite3IdListDelete(pParse->db, (yypminor->yy254)); } break; - case 231: /* trigger_cmd_list */ - case 236: /* trigger_cmd */ + case 232: /* trigger_cmd_list */ + case 237: /* trigger_cmd */ { -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy327)); +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy145)); } break; - case 233: /* trigger_event */ + case 234: /* trigger_event */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy410).b); +sqlite3IdListDelete(pParse->db, (yypminor->yy332).b); } break; /********* End destructor definitions *****************************************/ @@ -129855,8 +134453,9 @@ sqlite3IdListDelete(pParse->db, (yypminor->yy410).b); */ static void yy_pop_parser_stack(yyParser *pParser){ yyStackEntry *yytos; - assert( pParser->yyidx>=0 ); - yytos = &pParser->yystack[pParser->yyidx--]; + assert( pParser->yytos!=0 ); + assert( pParser->yytos > pParser->yystack ); + yytos = pParser->yytos--; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sPopping %s\n", @@ -129883,9 +134482,9 @@ SQLITE_PRIVATE void sqlite3ParserFree( #ifndef YYPARSEFREENEVERNULL if( pParser==0 ) return; #endif - while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); + while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser); #if YYSTACKDEPTH<=0 - free(pParser->yystack); + if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack); #endif (*freeProc)((void*)pParser); } @@ -129896,7 +134495,7 @@ SQLITE_PRIVATE void sqlite3ParserFree( #ifdef YYTRACKMAXSTACKDEPTH SQLITE_PRIVATE int sqlite3ParserStackPeak(void *p){ yyParser *pParser = (yyParser*)p; - return pParser->yyidxMax; + return pParser->yyhwm; } #endif @@ -129909,56 +134508,53 @@ static unsigned int yy_find_shift_action( YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; - int stateno = pParser->yystack[pParser->yyidx].stateno; + int stateno = pParser->yytos->stateno; if( stateno>=YY_MIN_REDUCE ) return stateno; assert( stateno <= YY_SHIFT_COUNT ); do{ i = yy_shift_ofst[stateno]; - if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno]; assert( iLookAhead!=YYNOCODE ); i += iLookAhead; if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ - if( iLookAhead>0 ){ #ifdef YYFALLBACK - YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); - } -#endif - assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ - iLookAhead = iFallback; - continue; + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); } +#endif + assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ + iLookAhead = iFallback; + continue; + } #endif #ifdef YYWILDCARD - { - int j = i - iLookAhead + YYWILDCARD; - if( + { + int j = i - iLookAhead + YYWILDCARD; + if( #if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && + j>=0 && #endif #if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j0 + ){ #ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", - yyTracePrompt, yyTokenName[iLookAhead], - yyTokenName[YYWILDCARD]); - } -#endif /* NDEBUG */ - return yy_action[j]; + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], + yyTokenName[YYWILDCARD]); } +#endif /* NDEBUG */ + return yy_action[j]; } -#endif /* YYWILDCARD */ } +#endif /* YYWILDCARD */ return yy_default[stateno]; }else{ return yy_action[i]; @@ -130002,13 +134598,13 @@ static int yy_find_reduce_action( */ static void yyStackOverflow(yyParser *yypParser){ sqlite3ParserARG_FETCH; - yypParser->yyidx--; + yypParser->yytos--; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); } #endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); + while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will execute if the parser ** stack every overflows */ /******** Begin %stack_overflow code ******************************************/ @@ -130026,11 +134622,11 @@ static void yyTraceShift(yyParser *yypParser, int yyNewState){ if( yyTraceFILE ){ if( yyNewStateyystack[yypParser->yyidx].major], + yyTracePrompt,yyTokenName[yypParser->yytos->major], yyNewState); }else{ fprintf(yyTraceFILE,"%sShift '%s'\n", - yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major]); + yyTracePrompt,yyTokenName[yypParser->yytos->major]); } } } @@ -130048,27 +134644,30 @@ static void yy_shift( sqlite3ParserTOKENTYPE yyMinor /* The minor token to shift in */ ){ yyStackEntry *yytos; - yypParser->yyidx++; + yypParser->yytos++; #ifdef YYTRACKMAXSTACKDEPTH - if( yypParser->yyidx>yypParser->yyidxMax ){ - yypParser->yyidxMax = yypParser->yyidx; + if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){ + yypParser->yyhwm++; + assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) ); } #endif #if YYSTACKDEPTH>0 - if( yypParser->yyidx>=YYSTACKDEPTH ){ + if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH] ){ yyStackOverflow(yypParser); return; } #else - if( yypParser->yyidx>=yypParser->yystksz ){ - yyGrowStack(yypParser); - if( yypParser->yyidx>=yypParser->yystksz ){ + if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){ + if( yyGrowStack(yypParser) ){ yyStackOverflow(yypParser); return; } } #endif - yytos = &yypParser->yystack[yypParser->yyidx]; + if( yyNewState > YY_MAX_SHIFT ){ + yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; + } + yytos = yypParser->yytos; yytos->stateno = (YYACTIONTYPE)yyNewState; yytos->major = (YYCODETYPE)yyMajor; yytos->minor.yy0 = yyMinor; @@ -130221,7 +134820,9 @@ static const struct { { 201, 2 }, { 149, 8 }, { 218, 5 }, + { 218, 7 }, { 218, 3 }, + { 218, 5 }, { 149, 6 }, { 149, 7 }, { 219, 2 }, @@ -130238,12 +134839,14 @@ static const struct { { 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 }, @@ -130272,27 +134875,29 @@ static const struct { { 173, 5 }, { 173, 3 }, { 173, 5 }, - { 173, 4 }, + { 173, 5 }, { 173, 4 }, { 173, 5 }, - { 225, 5 }, - { 225, 4 }, - { 226, 2 }, - { 226, 0 }, - { 224, 1 }, - { 224, 0 }, + { 226, 5 }, + { 226, 4 }, + { 227, 2 }, + { 227, 0 }, + { 225, 1 }, + { 225, 0 }, { 208, 0 }, { 207, 3 }, { 207, 1 }, + { 224, 0 }, + { 224, 3 }, { 149, 12 }, - { 227, 1 }, - { 227, 0 }, + { 228, 1 }, + { 228, 0 }, { 177, 0 }, { 177, 3 }, { 187, 5 }, { 187, 3 }, - { 228, 0 }, - { 228, 2 }, + { 229, 0 }, + { 229, 2 }, { 149, 4 }, { 149, 1 }, { 149, 2 }, @@ -130304,25 +134909,25 @@ static const struct { { 169, 2 }, { 170, 2 }, { 149, 5 }, - { 230, 11 }, - { 232, 1 }, - { 232, 1 }, - { 232, 2 }, - { 232, 0 }, + { 231, 11 }, { 233, 1 }, { 233, 1 }, - { 233, 3 }, - { 235, 0 }, - { 235, 2 }, - { 231, 3 }, - { 231, 2 }, - { 237, 3 }, + { 233, 2 }, + { 233, 0 }, + { 234, 1 }, + { 234, 1 }, + { 234, 3 }, + { 236, 0 }, + { 236, 2 }, + { 232, 3 }, + { 232, 2 }, { 238, 3 }, - { 238, 2 }, - { 236, 7 }, - { 236, 5 }, - { 236, 5 }, - { 236, 1 }, + { 239, 3 }, + { 239, 2 }, + { 237, 7 }, + { 237, 5 }, + { 237, 5 }, + { 237, 1 }, { 173, 4 }, { 173, 6 }, { 191, 1 }, @@ -130331,27 +134936,27 @@ static const struct { { 149, 4 }, { 149, 6 }, { 149, 3 }, - { 240, 0 }, - { 240, 2 }, + { 241, 0 }, + { 241, 2 }, { 149, 1 }, { 149, 3 }, { 149, 1 }, { 149, 3 }, { 149, 6 }, { 149, 7 }, - { 241, 1 }, + { 242, 1 }, { 149, 1 }, { 149, 4 }, - { 243, 8 }, - { 245, 0 }, - { 246, 1 }, - { 246, 3 }, + { 244, 8 }, + { 246, 0 }, { 247, 1 }, + { 247, 3 }, + { 248, 1 }, { 196, 0 }, { 196, 2 }, { 196, 3 }, - { 249, 6 }, - { 249, 8 }, + { 250, 6 }, + { 250, 8 }, { 144, 1 }, { 145, 2 }, { 145, 1 }, @@ -130388,26 +134993,26 @@ static const struct { { 210, 1 }, { 173, 1 }, { 208, 1 }, - { 229, 1 }, - { 229, 1 }, - { 229, 1 }, - { 229, 1 }, - { 229, 1 }, + { 230, 1 }, + { 230, 1 }, + { 230, 1 }, + { 230, 1 }, + { 230, 1 }, { 169, 1 }, - { 234, 0 }, - { 234, 3 }, - { 237, 1 }, - { 238, 0 }, - { 239, 1 }, + { 235, 0 }, + { 235, 3 }, + { 238, 1 }, { 239, 0 }, - { 242, 0 }, - { 242, 1 }, - { 244, 1 }, - { 244, 3 }, - { 245, 2 }, - { 248, 0 }, - { 248, 4 }, - { 248, 2 }, + { 240, 1 }, + { 240, 0 }, + { 243, 0 }, + { 243, 1 }, + { 245, 1 }, + { 245, 3 }, + { 246, 2 }, + { 249, 0 }, + { 249, 4 }, + { 249, 2 }, }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -130425,7 +135030,7 @@ static void yy_reduce( yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ sqlite3ParserARG_FETCH; - yymsp = &yypParser->yystack[yypParser->yyidx]; + yymsp = yypParser->yytos; #ifndef NDEBUG if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ yysize = yyRuleInfo[yyruleno].nrhs; @@ -130439,22 +135044,23 @@ static void yy_reduce( ** enough on the stack to push the LHS value */ if( yyRuleInfo[yyruleno].nrhs==0 ){ #ifdef YYTRACKMAXSTACKDEPTH - if( yypParser->yyidx>yypParser->yyidxMax ){ - yypParser->yyidxMax = yypParser->yyidx; + if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){ + yypParser->yyhwm++; + assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack)); } #endif #if YYSTACKDEPTH>0 - if( yypParser->yyidx>=YYSTACKDEPTH-1 ){ + if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH-1] ){ yyStackOverflow(yypParser); return; } #else - if( yypParser->yyidx>=yypParser->yystksz-1 ){ - yyGrowStack(yypParser); - if( yypParser->yyidx>=yypParser->yystksz-1 ){ + if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){ + if( yyGrowStack(yypParser) ){ yyStackOverflow(yypParser); return; } + yymsp = yypParser->yytos; } #endif } @@ -130480,15 +135086,15 @@ static void yy_reduce( { sqlite3FinishCoding(pParse); } break; case 3: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy392);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy194);} break; case 4: /* transtype ::= */ -{yymsp[1].minor.yy392 = TK_DEFERRED;} +{yymsp[1].minor.yy194 = TK_DEFERRED;} break; case 5: /* transtype ::= DEFERRED */ case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6); case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); -{yymsp[0].minor.yy392 = yymsp[0].major; /*A-overwrites-X*/} +{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); @@ -130514,7 +135120,7 @@ static void yy_reduce( break; case 14: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy392,0,0,yymsp[-2].minor.yy392); + 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 */ @@ -130528,33 +135134,33 @@ static void yy_reduce( case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); case 76: /* ifexists ::= */ yytestcase(yyruleno==76); case 90: /* distinct ::= */ yytestcase(yyruleno==90); - case 209: /* collate ::= */ yytestcase(yyruleno==209); -{yymsp[1].minor.yy392 = 0;} + case 215: /* collate ::= */ yytestcase(yyruleno==215); +{yymsp[1].minor.yy194 = 0;} break; case 17: /* ifnotexists ::= IF NOT EXISTS */ -{yymsp[-2].minor.yy392 = 1;} +{yymsp[-2].minor.yy194 = 1;} break; case 18: /* temp ::= TEMP */ case 43: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==43); -{yymsp[0].minor.yy392 = 1;} +{yymsp[0].minor.yy194 = 1;} break; case 20: /* create_table_args ::= LP columnlist conslist_opt RP table_options */ { - sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy392,0); + sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy194,0); } break; case 21: /* create_table_args ::= AS select */ { - sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy159); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159); + sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy243); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243); } break; case 23: /* table_options ::= WITHOUT nm */ { if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ - yymsp[-1].minor.yy392 = TF_WithoutRowid | TF_NoVisibleRowid; + yymsp[-1].minor.yy194 = TF_WithoutRowid | TF_NoVisibleRowid; }else{ - yymsp[-1].minor.yy392 = 0; + yymsp[-1].minor.yy194 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } @@ -130586,17 +135192,17 @@ static void yy_reduce( break; case 30: /* ccons ::= DEFAULT term */ case 32: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==32); -{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy342);} +{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy190);} break; case 31: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy342);} +{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy190);} break; case 33: /* ccons ::= DEFAULT MINUS term */ { ExprSpan v; - v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy342.pExpr, 0, 0); + v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy190.pExpr, 0, 0); v.zStart = yymsp[-1].minor.yy0.z; - v.zEnd = yymsp[0].minor.yy342.zEnd; + v.zEnd = yymsp[0].minor.yy190.zEnd; sqlite3AddDefaultValue(pParse,&v); } break; @@ -130608,147 +135214,149 @@ static void yy_reduce( } break; case 35: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy392);} +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy194);} break; case 36: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy392,yymsp[0].minor.yy392,yymsp[-2].minor.yy392);} +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy194,yymsp[0].minor.yy194,yymsp[-2].minor.yy194);} break; case 37: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy392,0,0,0,0);} +{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 */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy342.pExpr);} +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy190.pExpr);} break; case 39: /* ccons ::= REFERENCES nm eidlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy442,yymsp[0].minor.yy392);} +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy148,yymsp[0].minor.yy194);} break; case 40: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy392);} +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy194);} break; case 41: /* ccons ::= COLLATE ID|STRING */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; case 44: /* refargs ::= */ -{ yymsp[1].minor.yy392 = OE_None*0x0101; /* EV: R-19803-45884 */} +{ yymsp[1].minor.yy194 = OE_None*0x0101; /* EV: R-19803-45884 */} break; case 45: /* refargs ::= refargs refarg */ -{ yymsp[-1].minor.yy392 = (yymsp[-1].minor.yy392 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; } +{ yymsp[-1].minor.yy194 = (yymsp[-1].minor.yy194 & ~yymsp[0].minor.yy497.mask) | yymsp[0].minor.yy497.value; } break; case 46: /* refarg ::= MATCH nm */ -{ yymsp[-1].minor.yy207.value = 0; yymsp[-1].minor.yy207.mask = 0x000000; } +{ yymsp[-1].minor.yy497.value = 0; yymsp[-1].minor.yy497.mask = 0x000000; } break; case 47: /* refarg ::= ON INSERT refact */ -{ yymsp[-2].minor.yy207.value = 0; yymsp[-2].minor.yy207.mask = 0x000000; } +{ yymsp[-2].minor.yy497.value = 0; yymsp[-2].minor.yy497.mask = 0x000000; } break; case 48: /* refarg ::= ON DELETE refact */ -{ yymsp[-2].minor.yy207.value = yymsp[0].minor.yy392; yymsp[-2].minor.yy207.mask = 0x0000ff; } +{ yymsp[-2].minor.yy497.value = yymsp[0].minor.yy194; yymsp[-2].minor.yy497.mask = 0x0000ff; } break; case 49: /* refarg ::= ON UPDATE refact */ -{ yymsp[-2].minor.yy207.value = yymsp[0].minor.yy392<<8; yymsp[-2].minor.yy207.mask = 0x00ff00; } +{ yymsp[-2].minor.yy497.value = yymsp[0].minor.yy194<<8; yymsp[-2].minor.yy497.mask = 0x00ff00; } break; case 50: /* refact ::= SET NULL */ -{ yymsp[-1].minor.yy392 = OE_SetNull; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy194 = OE_SetNull; /* EV: R-33326-45252 */} break; case 51: /* refact ::= SET DEFAULT */ -{ yymsp[-1].minor.yy392 = OE_SetDflt; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy194 = OE_SetDflt; /* EV: R-33326-45252 */} break; case 52: /* refact ::= CASCADE */ -{ yymsp[0].minor.yy392 = OE_Cascade; /* EV: R-33326-45252 */} +{ yymsp[0].minor.yy194 = OE_Cascade; /* EV: R-33326-45252 */} break; case 53: /* refact ::= RESTRICT */ -{ yymsp[0].minor.yy392 = OE_Restrict; /* EV: R-33326-45252 */} +{ yymsp[0].minor.yy194 = OE_Restrict; /* EV: R-33326-45252 */} break; case 54: /* refact ::= NO ACTION */ -{ yymsp[-1].minor.yy392 = OE_None; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy194 = OE_None; /* EV: R-33326-45252 */} break; case 55: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ -{yymsp[-2].minor.yy392 = 0;} +{yymsp[-2].minor.yy194 = 0;} break; case 56: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ case 71: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==71); - case 142: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==142); -{yymsp[-1].minor.yy392 = yymsp[0].minor.yy392;} + case 144: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==144); +{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 183: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==183); - case 186: /* in_op ::= NOT IN */ yytestcase(yyruleno==186); - case 210: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==210); -{yymsp[-1].minor.yy392 = 1;} + 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); +{yymsp[-1].minor.yy194 = 1;} break; case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ -{yymsp[-1].minor.yy392 = 0;} +{yymsp[-1].minor.yy194 = 0;} break; case 61: /* tconscomma ::= COMMA */ {pParse->constraintName.n = 0;} break; case 63: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy442,yymsp[0].minor.yy392,yymsp[-2].minor.yy392,0);} +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy148,yymsp[0].minor.yy194,yymsp[-2].minor.yy194,0);} break; case 64: /* tcons ::= UNIQUE LP sortlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy442,yymsp[0].minor.yy392,0,0,0,0);} +{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 */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy342.pExpr);} +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy190.pExpr);} break; case 66: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy442, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy442, yymsp[-1].minor.yy392); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy392); + 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); -{yymsp[1].minor.yy392 = OE_Default;} +{yymsp[1].minor.yy194 = OE_Default;} break; case 69: /* onconf ::= ON CONFLICT resolvetype */ -{yymsp[-2].minor.yy392 = yymsp[0].minor.yy392;} +{yymsp[-2].minor.yy194 = yymsp[0].minor.yy194;} break; case 72: /* resolvetype ::= IGNORE */ -{yymsp[0].minor.yy392 = OE_Ignore;} +{yymsp[0].minor.yy194 = OE_Ignore;} break; case 73: /* resolvetype ::= REPLACE */ - case 143: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==143); -{yymsp[0].minor.yy392 = OE_Replace;} + case 145: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==145); +{yymsp[0].minor.yy194 = OE_Replace;} break; case 74: /* cmd ::= DROP TABLE ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy347, 0, yymsp[-1].minor.yy392); + 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 */ { - sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy442, yymsp[0].minor.yy159, yymsp[-7].minor.yy392, yymsp[-5].minor.yy392); + 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 */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy347, 1, yymsp[-1].minor.yy392); + sqlite3DropTable(pParse, yymsp[0].minor.yy185, 1, yymsp[-1].minor.yy194); } break; case 79: /* cmd ::= select */ { SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0}; - sqlite3Select(pParse, yymsp[0].minor.yy159, &dest); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159); + sqlite3Select(pParse, yymsp[0].minor.yy243, &dest); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243); } break; case 80: /* select ::= with selectnowith */ { - Select *p = yymsp[0].minor.yy159; + Select *p = yymsp[0].minor.yy243; if( p ){ - p->pWith = yymsp[-1].minor.yy331; + p->pWith = yymsp[-1].minor.yy285; parserDoubleLinkSelect(pParse, p); }else{ - sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy331); + sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy285); } - yymsp[-1].minor.yy159 = p; /*A-overwrites-W*/ + yymsp[-1].minor.yy243 = p; /*A-overwrites-W*/ } break; case 81: /* selectnowith ::= selectnowith multiselect_op oneselect */ { - Select *pRhs = yymsp[0].minor.yy159; - Select *pLhs = yymsp[-2].minor.yy159; + Select *pRhs = yymsp[0].minor.yy243; + Select *pLhs = yymsp[-2].minor.yy243; if( pRhs && pRhs->pPrior ){ SrcList *pFrom; Token x; @@ -130758,30 +135366,30 @@ static void yy_reduce( pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0); } if( pRhs ){ - pRhs->op = (u8)yymsp[-1].minor.yy392; + pRhs->op = (u8)yymsp[-1].minor.yy194; pRhs->pPrior = pLhs; if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue; pRhs->selFlags &= ~SF_MultiValue; - if( yymsp[-1].minor.yy392!=TK_ALL ) pParse->hasCompound = 1; + if( yymsp[-1].minor.yy194!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, pLhs); } - yymsp[-2].minor.yy159 = pRhs; + yymsp[-2].minor.yy243 = pRhs; } break; case 82: /* multiselect_op ::= UNION */ case 84: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==84); -{yymsp[0].minor.yy392 = yymsp[0].major; /*A-overwrites-OP*/} +{yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-OP*/} break; case 83: /* multiselect_op ::= UNION ALL */ -{yymsp[-1].minor.yy392 = TK_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 */ { #if SELECTTRACE_ENABLED Token s = yymsp[-8].minor.yy0; /*A-overwrites-S*/ #endif - yymsp[-8].minor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset); + yymsp[-8].minor.yy243 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy148,yymsp[-5].minor.yy185,yymsp[-4].minor.yy72,yymsp[-3].minor.yy148,yymsp[-2].minor.yy72,yymsp[-1].minor.yy148,yymsp[-7].minor.yy194,yymsp[0].minor.yy354.pLimit,yymsp[0].minor.yy354.pOffset); #if SELECTTRACE_ENABLED /* Populate the Select.zSelName[] string that is used to help with ** query planner debugging, to differentiate between multiple Select @@ -130792,17 +135400,17 @@ static void yy_reduce( ** comment to be the zSelName value. Otherwise, the label is #N where ** is an integer that is incremented with each SELECT statement seen. */ - if( yymsp[-8].minor.yy159!=0 ){ + if( yymsp[-8].minor.yy243!=0 ){ const char *z = s.z+6; int i; - sqlite3_snprintf(sizeof(yymsp[-8].minor.yy159->zSelName), yymsp[-8].minor.yy159->zSelName, "#%d", + sqlite3_snprintf(sizeof(yymsp[-8].minor.yy243->zSelName), yymsp[-8].minor.yy243->zSelName, "#%d", ++pParse->nSelect); while( z[0]==' ' ) z++; if( z[0]=='/' && z[1]=='*' ){ z += 2; while( z[0]==' ' ) z++; for(i=0; sqlite3Isalnum(z[i]); i++){} - sqlite3_snprintf(sizeof(yymsp[-8].minor.yy159->zSelName), yymsp[-8].minor.yy159->zSelName, "%.*s", i, z); + sqlite3_snprintf(sizeof(yymsp[-8].minor.yy243->zSelName), yymsp[-8].minor.yy243->zSelName, "%.*s", i, z); } } #endif /* SELECTRACE_ENABLED */ @@ -130810,118 +135418,119 @@ static void yy_reduce( break; case 86: /* values ::= VALUES LP nexprlist RP */ { - yymsp[-3].minor.yy159 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy442,0,0,0,0,0,SF_Values,0,0); + 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 */ { - Select *pRight, *pLeft = yymsp[-4].minor.yy159; - pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy442,0,0,0,0,0,SF_Values|SF_MultiValue,0,0); + 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); if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; if( pRight ){ pRight->op = TK_ALL; pRight->pPrior = pLeft; - yymsp[-4].minor.yy159 = pRight; + yymsp[-4].minor.yy243 = pRight; }else{ - yymsp[-4].minor.yy159 = pLeft; + yymsp[-4].minor.yy243 = pLeft; } } break; case 88: /* distinct ::= DISTINCT */ -{yymsp[0].minor.yy392 = SF_Distinct;} +{yymsp[0].minor.yy194 = SF_Distinct;} break; case 89: /* distinct ::= ALL */ -{yymsp[0].minor.yy392 = SF_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 199: /* exprlist ::= */ yytestcase(yyruleno==199); - case 205: /* eidlist_opt ::= */ yytestcase(yyruleno==205); -{yymsp[1].minor.yy442 = 0;} + case 203: /* exprlist ::= */ yytestcase(yyruleno==203); + case 206: /* paren_exprlist ::= */ yytestcase(yyruleno==206); + case 211: /* eidlist_opt ::= */ yytestcase(yyruleno==211); +{yymsp[1].minor.yy148 = 0;} break; case 92: /* selcollist ::= sclp expr as */ { - yymsp[-2].minor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy442, yymsp[-1].minor.yy342.pExpr); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-2].minor.yy442, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yymsp[-2].minor.yy442,&yymsp[-1].minor.yy342); + 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 */ { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); - yymsp[-1].minor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy442, p); + yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy148, p); } break; case 94: /* selcollist ::= sclp nm DOT STAR */ { - Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, &yymsp[0].minor.yy0); + 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); - yymsp[-3].minor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442, pDot); + 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 219: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==219); - case 220: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==220); + case 225: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==225); + case 226: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==226); {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} break; case 97: /* from ::= */ -{yymsp[1].minor.yy347 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy347));} +{yymsp[1].minor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy185));} break; case 98: /* from ::= FROM seltablist */ { - yymsp[-1].minor.yy347 = yymsp[0].minor.yy347; - sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy347); + yymsp[-1].minor.yy185 = yymsp[0].minor.yy185; + sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy185); } break; case 99: /* stl_prefix ::= seltablist joinop */ { - if( ALWAYS(yymsp[-1].minor.yy347 && yymsp[-1].minor.yy347->nSrc>0) ) yymsp[-1].minor.yy347->a[yymsp[-1].minor.yy347->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy392; + 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 ::= */ -{yymsp[1].minor.yy347 = 0;} +{yymsp[1].minor.yy185 = 0;} break; case 101: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ { - yymsp[-6].minor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); - sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy347, &yymsp[-2].minor.yy0); + 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 */ { - yymsp[-8].minor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy347,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); - sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy347, yymsp[-4].minor.yy442); + 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 */ { - yymsp[-6].minor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); + 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 */ { - if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){ - yymsp[-6].minor.yy347 = yymsp[-4].minor.yy347; - }else if( yymsp[-4].minor.yy347->nSrc==1 ){ - yymsp[-6].minor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); - if( yymsp[-6].minor.yy347 ){ - struct SrcList_item *pNew = &yymsp[-6].minor.yy347->a[yymsp[-6].minor.yy347->nSrc-1]; - struct SrcList_item *pOld = yymsp[-4].minor.yy347->a; + 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; + }else if( yymsp[-4].minor.yy185->nSrc==1 ){ + yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); + if( yymsp[-6].minor.yy185 ){ + struct SrcList_item *pNew = &yymsp[-6].minor.yy185->a[yymsp[-6].minor.yy185->nSrc-1]; + struct SrcList_item *pOld = yymsp[-4].minor.yy185->a; pNew->zName = pOld->zName; pNew->zDatabase = pOld->zDatabase; pNew->pSelect = pOld->pSelect; pOld->zName = pOld->zDatabase = 0; pOld->pSelect = 0; } - sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347); + sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy185); }else{ Select *pSubquery; - sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0); - yymsp[-6].minor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); + sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy185); + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy185,0,0,0,0,SF_NestedFrom,0,0); + yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); } } break; @@ -130930,32 +135539,32 @@ static void yy_reduce( {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;} break; case 107: /* fullname ::= nm dbnm */ -{yymsp[-1].minor.yy347 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} +{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 */ -{ yymsp[0].minor.yy392 = JT_INNER; } +{ yymsp[0].minor.yy194 = JT_INNER; } break; case 109: /* joinop ::= JOIN_KW JOIN */ -{yymsp[-1].minor.yy392 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} +{yymsp[-1].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} break; case 110: /* joinop ::= JOIN_KW nm JOIN */ -{yymsp[-2].minor.yy392 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} +{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 */ -{yymsp[-3].minor.yy392 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} +{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 195: /* case_else ::= ELSE expr */ yytestcase(yyruleno==195); -{yymsp[-1].minor.yy122 = yymsp[0].minor.yy342.pExpr;} + case 199: /* case_else ::= ELSE expr */ yytestcase(yyruleno==199); +{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 196: /* case_else ::= */ yytestcase(yyruleno==196); - case 198: /* case_operand ::= */ yytestcase(yyruleno==198); -{yymsp[1].minor.yy122 = 0;} + case 200: /* case_else ::= */ yytestcase(yyruleno==200); + case 202: /* case_operand ::= */ yytestcase(yyruleno==202); +{yymsp[1].minor.yy72 = 0;} break; case 115: /* indexed_opt ::= INDEXED BY nm */ {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} @@ -130964,276 +135573,314 @@ static void yy_reduce( {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;} break; case 117: /* using_opt ::= USING LP idlist RP */ -{yymsp[-3].minor.yy180 = yymsp[-1].minor.yy180;} +{yymsp[-3].minor.yy254 = yymsp[-1].minor.yy254;} break; case 118: /* using_opt ::= */ - case 144: /* idlist_opt ::= */ yytestcase(yyruleno==144); -{yymsp[1].minor.yy180 = 0;} + case 146: /* idlist_opt ::= */ yytestcase(yyruleno==146); +{yymsp[1].minor.yy254 = 0;} break; case 120: /* orderby_opt ::= ORDER BY sortlist */ case 127: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==127); -{yymsp[-2].minor.yy442 = yymsp[0].minor.yy442;} +{yymsp[-2].minor.yy148 = yymsp[0].minor.yy148;} break; case 121: /* sortlist ::= sortlist COMMA expr sortorder */ { - yymsp[-3].minor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442,yymsp[-1].minor.yy342.pExpr); - sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy442,yymsp[0].minor.yy392); + 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 */ { - yymsp[-1].minor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy342.pExpr); /*A-overwrites-Y*/ - sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy442,yymsp[0].minor.yy392); + 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 */ -{yymsp[0].minor.yy392 = SQLITE_SO_ASC;} +{yymsp[0].minor.yy194 = SQLITE_SO_ASC;} break; case 124: /* sortorder ::= DESC */ -{yymsp[0].minor.yy392 = SQLITE_SO_DESC;} +{yymsp[0].minor.yy194 = SQLITE_SO_DESC;} break; case 125: /* sortorder ::= */ -{yymsp[1].minor.yy392 = SQLITE_SO_UNDEFINED;} +{yymsp[1].minor.yy194 = SQLITE_SO_UNDEFINED;} break; case 130: /* limit_opt ::= */ -{yymsp[1].minor.yy64.pLimit = 0; yymsp[1].minor.yy64.pOffset = 0;} +{yymsp[1].minor.yy354.pLimit = 0; yymsp[1].minor.yy354.pOffset = 0;} break; case 131: /* limit_opt ::= LIMIT expr */ -{yymsp[-1].minor.yy64.pLimit = yymsp[0].minor.yy342.pExpr; yymsp[-1].minor.yy64.pOffset = 0;} +{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 */ -{yymsp[-3].minor.yy64.pLimit = yymsp[-2].minor.yy342.pExpr; yymsp[-3].minor.yy64.pOffset = yymsp[0].minor.yy342.pExpr;} +{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 */ -{yymsp[-3].minor.yy64.pOffset = yymsp[-2].minor.yy342.pExpr; yymsp[-3].minor.yy64.pLimit = yymsp[0].minor.yy342.pExpr;} +{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 */ { - sqlite3WithPush(pParse, yymsp[-5].minor.yy331, 1); - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy347, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy347,yymsp[0].minor.yy122); + 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 */ { - sqlite3WithPush(pParse, yymsp[-7].minor.yy331, 1); - sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy347, &yymsp[-3].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy442,"set list"); - sqlite3Update(pParse,yymsp[-4].minor.yy347,yymsp[-1].minor.yy442,yymsp[0].minor.yy122,yymsp[-5].minor.yy392); + sqlite3WithPush(pParse, yymsp[-7].minor.yy285, 1); + sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy185, &yymsp[-3].minor.yy0); + sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy148,"set list"); + 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 */ { - yymsp[-4].minor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy442, yymsp[0].minor.yy342.pExpr); - sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy442, &yymsp[-2].minor.yy0, 1); + 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 ::= nm EQ expr */ + case 139: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ { - yylhsminor.yy442 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy342.pExpr); - sqlite3ExprListSetName(pParse, yylhsminor.yy442, &yymsp[-2].minor.yy0, 1); + yymsp[-6].minor.yy148 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy148, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr); } - yymsp[-2].minor.yy442 = yylhsminor.yy442; break; - case 140: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */ + case 140: /* setlist ::= nm EQ expr */ { - sqlite3WithPush(pParse, yymsp[-5].minor.yy331, 1); - sqlite3Insert(pParse, yymsp[-2].minor.yy347, yymsp[0].minor.yy159, yymsp[-1].minor.yy180, yymsp[-4].minor.yy392); + 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: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ + case 141: /* setlist ::= LP idlist RP EQ expr */ { - sqlite3WithPush(pParse, yymsp[-6].minor.yy331, 1); - sqlite3Insert(pParse, yymsp[-3].minor.yy347, 0, yymsp[-2].minor.yy180, yymsp[-5].minor.yy392); + yymsp[-4].minor.yy148 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr); } break; - case 145: /* idlist_opt ::= LP idlist RP */ -{yymsp[-2].minor.yy180 = yymsp[-1].minor.yy180;} + case 142: /* 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 */ +{ + sqlite3WithPush(pParse, yymsp[-6].minor.yy285, 1); + sqlite3Insert(pParse, yymsp[-3].minor.yy185, 0, yymsp[-2].minor.yy254, yymsp[-5].minor.yy194); +} break; - case 146: /* idlist ::= idlist COMMA nm */ -{yymsp[-2].minor.yy180 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy180,&yymsp[0].minor.yy0);} + case 147: /* idlist_opt ::= LP idlist RP */ +{yymsp[-2].minor.yy254 = yymsp[-1].minor.yy254;} break; - case 147: /* idlist ::= nm */ -{yymsp[0].minor.yy180 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} + case 148: /* idlist ::= idlist COMMA nm */ +{yymsp[-2].minor.yy254 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);} break; - case 148: /* expr ::= LP expr RP */ -{spanSet(&yymsp[-2].minor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ yymsp[-2].minor.yy342.pExpr = yymsp[-1].minor.yy342.pExpr;} + case 149: /* idlist ::= nm */ +{yymsp[0].minor.yy254 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} break; - case 149: /* term ::= NULL */ - case 154: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==154); - case 155: /* term ::= STRING */ yytestcase(yyruleno==155); -{spanExpr(&yymsp[0].minor.yy342,pParse,yymsp[0].major,yymsp[0].minor.yy0);/*A-overwrites-X*/} + case 150: /* 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 150: /* expr ::= ID|INDEXED */ - case 151: /* expr ::= JOIN_KW */ yytestcase(yyruleno==151); -{spanExpr(&yymsp[0].minor.yy342,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} + 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 ::= nm DOT nm */ + case 152: /* expr ::= ID|INDEXED */ + case 153: /* expr ::= JOIN_KW */ yytestcase(yyruleno==153); +{spanExpr(&yymsp[0].minor.yy190,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} + break; + case 154: /* expr ::= nm DOT nm */ { - Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); - Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); - spanSet(&yymsp[-2].minor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-2].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); + 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); } break; - case 153: /* expr ::= nm DOT nm DOT nm */ + case 155: /* expr ::= nm DOT nm DOT nm */ { - Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0); - Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); - Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); + 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); - spanSet(&yymsp[-4].minor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-4].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); + 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); +} + break; + case 158: /* 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 156: /* expr ::= VARIABLE */ + case 159: /* expr ::= VARIABLE */ { - Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/ - if( t.n>=2 && t.z[0]=='#' && sqlite3Isdigit(t.z[1]) ){ + if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ + u32 n = yymsp[0].minor.yy0.n; + spanExpr(&yymsp[0].minor.yy190, pParse, TK_VARIABLE, yymsp[0].minor.yy0); + sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr, n); + }else{ /* When doing a nested parse, one can include terms in an expression ** that look like this: #1 #2 ... These terms refer to registers ** in the virtual machine. #N is the N-th register. */ - spanSet(&yymsp[0].minor.yy342, &t, &t); + Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/ + assert( t.n>=2 ); + spanSet(&yymsp[0].minor.yy190, &t, &t); if( pParse->nested==0 ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); - yymsp[0].minor.yy342.pExpr = 0; + yymsp[0].minor.yy190.pExpr = 0; }else{ - yymsp[0].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &t); - if( yymsp[0].minor.yy342.pExpr ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy342.pExpr->iTable); + yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, 0); + if( yymsp[0].minor.yy190.pExpr ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy190.pExpr->iTable); } - }else{ - spanExpr(&yymsp[0].minor.yy342, pParse, TK_VARIABLE, t); - sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy342.pExpr); } } break; - case 157: /* expr ::= expr COLLATE ID|STRING */ + case 160: /* expr ::= expr COLLATE ID|STRING */ { - yymsp[-2].minor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0, 1); - yymsp[-2].minor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + 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 158: /* expr ::= CAST LP expr AS typetoken RP */ + case 161: /* expr ::= CAST LP expr AS typetoken RP */ { - spanSet(&yymsp[-5].minor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-5].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy342.pExpr, 0, &yymsp[-1].minor.yy0); + 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); } break; - case 159: /* expr ::= ID|INDEXED LP distinct exprlist RP */ + case 162: /* expr ::= ID|INDEXED LP distinct exprlist RP */ { - if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ + 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); } - yylhsminor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0); - spanSet(&yylhsminor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); - if( yymsp[-2].minor.yy392==SF_Distinct && yylhsminor.yy342.pExpr ){ - yylhsminor.yy342.pExpr->flags |= EP_Distinct; + yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy148, &yymsp[-4].minor.yy0); + spanSet(&yylhsminor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); + if( yymsp[-2].minor.yy194==SF_Distinct && yylhsminor.yy190.pExpr ){ + yylhsminor.yy190.pExpr->flags |= EP_Distinct; } } - yymsp[-4].minor.yy342 = yylhsminor.yy342; + yymsp[-4].minor.yy190 = yylhsminor.yy190; break; - case 160: /* expr ::= ID|INDEXED LP STAR RP */ + case 163: /* expr ::= ID|INDEXED LP STAR RP */ { - yylhsminor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); - spanSet(&yylhsminor.yy342,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); + yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); + spanSet(&yylhsminor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } - yymsp[-3].minor.yy342 = yylhsminor.yy342; + yymsp[-3].minor.yy190 = yylhsminor.yy190; break; - case 161: /* term ::= CTIME_KW */ + case 164: /* term ::= CTIME_KW */ { - yylhsminor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); - spanSet(&yylhsminor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); + yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); + spanSet(&yylhsminor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy342 = yylhsminor.yy342; + yymsp[0].minor.yy190 = yylhsminor.yy190; break; - case 162: /* expr ::= expr AND expr */ - case 163: /* expr ::= expr OR expr */ yytestcase(yyruleno==163); - case 164: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==164); - case 165: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==165); - case 166: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==166); - case 167: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==167); - case 168: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==168); - case 169: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==169); -{spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);} + case 165: /* 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); + if( yylhsminor.yy190.pExpr ){ + yylhsminor.yy190.pExpr->x.pList = pList; + spanSet(&yylhsminor.yy190, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); + }else{ + sqlite3ExprListDelete(pParse->db, pList); + } +} + 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); +{spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);} break; - case 170: /* likeop ::= LIKE_KW|MATCH */ -{yymsp[0].minor.yy318.eOperator = yymsp[0].minor.yy0; yymsp[0].minor.yy318.bNot = 0;/*A-overwrites-X*/} + case 174: /* likeop ::= LIKE_KW|MATCH */ +{yymsp[0].minor.yy0=yymsp[0].minor.yy0;/*A-overwrites-X*/} break; - case 171: /* likeop ::= NOT LIKE_KW|MATCH */ -{yymsp[-1].minor.yy318.eOperator = yymsp[0].minor.yy0; yymsp[-1].minor.yy318.bNot = 1;} + case 175: /* 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 172: /* expr ::= expr likeop expr */ + case 176: /* expr ::= expr likeop expr */ { ExprList *pList; - pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy342.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy342.pExpr); - yymsp[-2].minor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy318.eOperator); - exprNot(pParse, yymsp[-1].minor.yy318.bNot, &yymsp[-2].minor.yy342); - yymsp[-2].minor.yy342.zEnd = yymsp[0].minor.yy342.zEnd; - if( yymsp[-2].minor.yy342.pExpr ) yymsp[-2].minor.yy342.pExpr->flags |= EP_InfixFunc; + int bNot = yymsp[-1].minor.yy0.n & 0x80000000; + yymsp[-1].minor.yy0.n &= 0x7fffffff; + pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy190.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy190.pExpr); + yymsp[-2].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0); + exprNot(pParse, bNot, &yymsp[-2].minor.yy190); + yymsp[-2].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; + if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc; } break; - case 173: /* expr ::= expr likeop expr ESCAPE expr */ + case 177: /* expr ::= expr likeop expr ESCAPE expr */ { ExprList *pList; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy342.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr); - yymsp[-4].minor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy318.eOperator); - exprNot(pParse, yymsp[-3].minor.yy318.bNot, &yymsp[-4].minor.yy342); - yymsp[-4].minor.yy342.zEnd = yymsp[0].minor.yy342.zEnd; - if( yymsp[-4].minor.yy342.pExpr ) yymsp[-4].minor.yy342.pExpr->flags |= EP_InfixFunc; + int bNot = yymsp[-3].minor.yy0.n & 0x80000000; + yymsp[-3].minor.yy0.n &= 0x7fffffff; + pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy190.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); + yymsp[-4].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0); + exprNot(pParse, bNot, &yymsp[-4].minor.yy190); + yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; + if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc; } break; - case 174: /* expr ::= expr ISNULL|NOTNULL */ -{spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy342,&yymsp[0].minor.yy0);} + case 178: /* expr ::= expr ISNULL|NOTNULL */ +{spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);} break; - case 175: /* expr ::= expr NOT NULL */ -{spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy0);} + case 179: /* expr ::= expr NOT NULL */ +{spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);} break; - case 176: /* expr ::= expr IS expr */ + case 180: /* expr ::= expr IS expr */ { - spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yymsp[-2].minor.yy342.pExpr, TK_ISNULL); + 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 177: /* expr ::= expr IS NOT expr */ + case 181: /* expr ::= expr IS NOT expr */ { - spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy342,&yymsp[0].minor.yy342); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yymsp[-3].minor.yy342.pExpr, TK_NOTNULL); + 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 178: /* expr ::= NOT expr */ - case 179: /* expr ::= BITNOT expr */ yytestcase(yyruleno==179); -{spanUnaryPrefix(&yymsp[-1].minor.yy342,pParse,yymsp[-1].major,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} + case 182: /* expr ::= NOT expr */ + case 183: /* expr ::= BITNOT expr */ yytestcase(yyruleno==183); +{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} break; - case 180: /* expr ::= MINUS expr */ -{spanUnaryPrefix(&yymsp[-1].minor.yy342,pParse,TK_UMINUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} + case 184: /* expr ::= MINUS expr */ +{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} break; - case 181: /* expr ::= PLUS expr */ -{spanUnaryPrefix(&yymsp[-1].minor.yy342,pParse,TK_UPLUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} + case 185: /* expr ::= PLUS expr */ +{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} break; - case 182: /* between_op ::= BETWEEN */ - case 185: /* in_op ::= IN */ yytestcase(yyruleno==185); -{yymsp[0].minor.yy392 = 0;} + case 186: /* between_op ::= BETWEEN */ + case 189: /* in_op ::= IN */ yytestcase(yyruleno==189); +{yymsp[0].minor.yy194 = 0;} break; - case 184: /* expr ::= expr between_op expr AND expr */ + case 188: /* expr ::= expr between_op expr AND expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr); - yymsp[-4].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy342.pExpr, 0, 0); - if( yymsp[-4].minor.yy342.pExpr ){ - yymsp[-4].minor.yy342.pExpr->x.pList = pList; + 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); + if( yymsp[-4].minor.yy190.pExpr ){ + yymsp[-4].minor.yy190.pExpr->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - exprNot(pParse, yymsp[-3].minor.yy392, &yymsp[-4].minor.yy342); - yymsp[-4].minor.yy342.zEnd = yymsp[0].minor.yy342.zEnd; + exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); + yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; } break; - case 187: /* expr ::= expr in_op LP exprlist RP */ + case 191: /* expr ::= expr in_op LP exprlist RP */ { - if( yymsp[-1].minor.yy442==0 ){ + if( yymsp[-1].minor.yy148==0 ){ /* Expressions of the form ** ** expr1 IN () @@ -131242,9 +135889,9 @@ static void yy_reduce( ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ - sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy342.pExpr); - yymsp[-4].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy392]); - }else if( yymsp[-1].minor.yy442->nExpr==1 ){ + sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy190.pExpr); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy194]); + }else if( yymsp[-1].minor.yy148->nExpr==1 ){ /* Expressions of the form: ** ** expr1 IN (?1) @@ -131261,223 +135908,204 @@ static void yy_reduce( ** affinity or the collating sequence to use for comparison. Otherwise, ** the semantics would be subtly different from IN or NOT IN. */ - Expr *pRHS = yymsp[-1].minor.yy442->a[0].pExpr; - yymsp[-1].minor.yy442->a[0].pExpr = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy442); + Expr *pRHS = yymsp[-1].minor.yy148->a[0].pExpr; + yymsp[-1].minor.yy148->a[0].pExpr = 0; + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy148); /* pRHS cannot be NULL because a malloc error would have been detected ** before now and control would have never reached this point */ if( ALWAYS(pRHS) ){ pRHS->flags &= ~EP_Collate; pRHS->flags |= EP_Generic; } - yymsp[-4].minor.yy342.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy392 ? TK_NE : TK_EQ, yymsp[-4].minor.yy342.pExpr, pRHS, 0); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy194 ? TK_NE : TK_EQ, yymsp[-4].minor.yy190.pExpr, pRHS, 0); }else{ - yymsp[-4].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0); - if( yymsp[-4].minor.yy342.pExpr ){ - yymsp[-4].minor.yy342.pExpr->x.pList = yymsp[-1].minor.yy442; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy342.pExpr); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 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); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy442); + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy148); } - exprNot(pParse, yymsp[-3].minor.yy392, &yymsp[-4].minor.yy342); + exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); } - yymsp[-4].minor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 188: /* expr ::= LP select RP */ + case 192: /* expr ::= LP select RP */ { - spanSet(&yymsp[-2].minor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ - yymsp[-2].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); - if( yymsp[-2].minor.yy342.pExpr ){ - yymsp[-2].minor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159; - ExprSetProperty(yymsp[-2].minor.yy342.pExpr, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-2].minor.yy342.pExpr); - }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159); - } + 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); + sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243); } break; - case 189: /* expr ::= expr in_op LP select RP */ + case 193: /* expr ::= expr in_op LP select RP */ { - yymsp[-4].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0); - if( yymsp[-4].minor.yy342.pExpr ){ - yymsp[-4].minor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159; - ExprSetProperty(yymsp[-4].minor.yy342.pExpr, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy342.pExpr); - }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159); - } - exprNot(pParse, yymsp[-3].minor.yy392, &yymsp[-4].minor.yy342); - yymsp[-4].minor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 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 190: /* expr ::= expr in_op nm dbnm */ + case 194: /* expr ::= expr in_op nm dbnm paren_exprlist */ { - SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); - yymsp[-3].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy342.pExpr, 0, 0); - if( yymsp[-3].minor.yy342.pExpr ){ - yymsp[-3].minor.yy342.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); - ExprSetProperty(yymsp[-3].minor.yy342.pExpr, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-3].minor.yy342.pExpr); - }else{ - sqlite3SrcListDelete(pParse->db, pSrc); - } - exprNot(pParse, yymsp[-2].minor.yy392, &yymsp[-3].minor.yy342); - yymsp[-3].minor.yy342.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]; + 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); + 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 191: /* expr ::= EXISTS LP select RP */ + case 195: /* expr ::= EXISTS LP select RP */ { Expr *p; - spanSet(&yymsp[-3].minor.yy342,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ - p = yymsp[-3].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); - if( p ){ - p->x.pSelect = yymsp[-1].minor.yy159; - ExprSetProperty(p, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeightAndFlags(pParse, p); - }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159); - } + 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); + sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243); } break; - case 192: /* expr ::= CASE case_operand case_exprlist case_else END */ + case 196: /* expr ::= CASE case_operand case_exprlist case_else END */ { - spanSet(&yymsp[-4].minor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/ - yymsp[-4].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy122, 0, 0); - if( yymsp[-4].minor.yy342.pExpr ){ - yymsp[-4].minor.yy342.pExpr->x.pList = yymsp[-1].minor.yy122 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy442,yymsp[-1].minor.yy122) : yymsp[-2].minor.yy442; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy342.pExpr); + 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); + 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); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy442); - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy122); + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy148); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy72); } } break; - case 193: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + case 197: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { - yymsp[-4].minor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, yymsp[-2].minor.yy342.pExpr); - yymsp[-4].minor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, yymsp[0].minor.yy342.pExpr); + 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 194: /* case_exprlist ::= WHEN expr THEN expr */ + case 198: /* case_exprlist ::= WHEN expr THEN expr */ { - yymsp[-3].minor.yy442 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr); - yymsp[-3].minor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442, yymsp[0].minor.yy342.pExpr); + 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 197: /* case_operand ::= expr */ -{yymsp[0].minor.yy122 = yymsp[0].minor.yy342.pExpr; /*A-overwrites-X*/} + case 201: /* case_operand ::= expr */ +{yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/} + break; + case 204: /* nexprlist ::= nexprlist COMMA expr */ +{yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);} break; - case 200: /* nexprlist ::= nexprlist COMMA expr */ -{yymsp[-2].minor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy442,yymsp[0].minor.yy342.pExpr);} + case 205: /* nexprlist ::= expr */ +{yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/} break; - case 201: /* nexprlist ::= expr */ -{yymsp[0].minor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy342.pExpr); /*A-overwrites-Y*/} + case 207: /* paren_exprlist ::= LP exprlist RP */ + case 212: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==212); +{yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;} break; - case 202: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + case 208: /* 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.yy442, yymsp[-10].minor.yy392, - &yymsp[-11].minor.yy0, yymsp[0].minor.yy122, SQLITE_SO_ASC, yymsp[-8].minor.yy392); + 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 203: /* uniqueflag ::= UNIQUE */ - case 244: /* raisetype ::= ABORT */ yytestcase(yyruleno==244); -{yymsp[0].minor.yy392 = OE_Abort;} + case 209: /* uniqueflag ::= UNIQUE */ + case 250: /* raisetype ::= ABORT */ yytestcase(yyruleno==250); +{yymsp[0].minor.yy194 = OE_Abort;} break; - case 204: /* uniqueflag ::= */ -{yymsp[1].minor.yy392 = OE_None;} + case 210: /* uniqueflag ::= */ +{yymsp[1].minor.yy194 = OE_None;} break; - case 206: /* eidlist_opt ::= LP eidlist RP */ -{yymsp[-2].minor.yy442 = yymsp[-1].minor.yy442;} - break; - case 207: /* eidlist ::= eidlist COMMA nm collate sortorder */ + case 213: /* eidlist ::= eidlist COMMA nm collate sortorder */ { - yymsp[-4].minor.yy442 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy442, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy392, yymsp[0].minor.yy392); + yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); } break; - case 208: /* eidlist ::= nm collate sortorder */ + case 214: /* eidlist ::= nm collate sortorder */ { - yymsp[-2].minor.yy442 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy392, yymsp[0].minor.yy392); /*A-overwrites-Y*/ + yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/ } break; - case 211: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy347, yymsp[-1].minor.yy392);} + case 217: /* cmd ::= DROP INDEX ifexists fullname */ +{sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} + break; + case 218: /* cmd ::= VACUUM */ +{sqlite3Vacuum(pParse,0);} break; - case 212: /* cmd ::= VACUUM */ - case 213: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==213); -{sqlite3Vacuum(pParse);} + case 219: /* cmd ::= VACUUM nm */ +{sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} break; - case 214: /* cmd ::= PRAGMA nm dbnm */ + case 220: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 215: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 221: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 216: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 222: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 217: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 223: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} break; - case 218: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + case 224: /* 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 221: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + case 227: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ { Token all; all.z = yymsp[-3].minor.yy0.z; all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy327, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); } break; - case 222: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 228: /* 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.yy392, yymsp[-4].minor.yy410.a, yymsp[-4].minor.yy410.b, yymsp[-2].minor.yy347, yymsp[0].minor.yy122, yymsp[-10].minor.yy392, yymsp[-8].minor.yy392); + 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 223: /* trigger_time ::= BEFORE */ -{ yymsp[0].minor.yy392 = TK_BEFORE; } + case 229: /* trigger_time ::= BEFORE */ +{ yymsp[0].minor.yy194 = TK_BEFORE; } break; - case 224: /* trigger_time ::= AFTER */ -{ yymsp[0].minor.yy392 = TK_AFTER; } + case 230: /* trigger_time ::= AFTER */ +{ yymsp[0].minor.yy194 = TK_AFTER; } break; - case 225: /* trigger_time ::= INSTEAD OF */ -{ yymsp[-1].minor.yy392 = TK_INSTEAD;} + case 231: /* trigger_time ::= INSTEAD OF */ +{ yymsp[-1].minor.yy194 = TK_INSTEAD;} break; - case 226: /* trigger_time ::= */ -{ yymsp[1].minor.yy392 = TK_BEFORE; } + case 232: /* trigger_time ::= */ +{ yymsp[1].minor.yy194 = TK_BEFORE; } break; - case 227: /* trigger_event ::= DELETE|INSERT */ - case 228: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==228); -{yymsp[0].minor.yy410.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy410.b = 0;} + case 233: /* trigger_event ::= DELETE|INSERT */ + case 234: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==234); +{yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;} break; - case 229: /* trigger_event ::= UPDATE OF idlist */ -{yymsp[-2].minor.yy410.a = TK_UPDATE; yymsp[-2].minor.yy410.b = yymsp[0].minor.yy180;} + case 235: /* trigger_event ::= UPDATE OF idlist */ +{yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;} break; - case 230: /* when_clause ::= */ - case 249: /* key_opt ::= */ yytestcase(yyruleno==249); -{ yymsp[1].minor.yy122 = 0; } + case 236: /* when_clause ::= */ + case 255: /* key_opt ::= */ yytestcase(yyruleno==255); +{ yymsp[1].minor.yy72 = 0; } break; - case 231: /* when_clause ::= WHEN expr */ - case 250: /* key_opt ::= KEY expr */ yytestcase(yyruleno==250); -{ yymsp[-1].minor.yy122 = yymsp[0].minor.yy342.pExpr; } + case 237: /* when_clause ::= WHEN expr */ + case 256: /* key_opt ::= KEY expr */ yytestcase(yyruleno==256); +{ yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; } break; - case 232: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 238: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { - assert( yymsp[-2].minor.yy327!=0 ); - yymsp[-2].minor.yy327->pLast->pNext = yymsp[-1].minor.yy327; - yymsp[-2].minor.yy327->pLast = yymsp[-1].minor.yy327; + 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 233: /* trigger_cmd_list ::= trigger_cmd SEMI */ + case 239: /* trigger_cmd_list ::= trigger_cmd SEMI */ { - assert( yymsp[-1].minor.yy327!=0 ); - yymsp[-1].minor.yy327->pLast = yymsp[-1].minor.yy327; + assert( yymsp[-1].minor.yy145!=0 ); + yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; } break; - case 234: /* trnm ::= nm DOT nm */ + case 240: /* trnm ::= nm DOT nm */ { yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; sqlite3ErrorMsg(pParse, @@ -131485,195 +136113,195 @@ static void yy_reduce( "statements within triggers"); } break; - case 235: /* tridxby ::= INDEXED BY nm */ + case 241: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 236: /* tridxby ::= NOT INDEXED */ + case 242: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 237: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ -{yymsp[-6].minor.yy327 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy442, yymsp[0].minor.yy122, yymsp[-5].minor.yy392);} + case 243: /* 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 238: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ -{yymsp[-4].minor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, yymsp[0].minor.yy159, yymsp[-4].minor.yy392);/*A-overwrites-R*/} + case 244: /* 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 239: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ -{yymsp[-4].minor.yy327 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy122);} + case 245: /* 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 240: /* trigger_cmd ::= select */ -{yymsp[0].minor.yy327 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy159); /*A-overwrites-X*/} + case 246: /* trigger_cmd ::= select */ +{yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/} break; - case 241: /* expr ::= RAISE LP IGNORE RP */ + case 247: /* expr ::= RAISE LP IGNORE RP */ { - spanSet(&yymsp[-3].minor.yy342,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-3].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); - if( yymsp[-3].minor.yy342.pExpr ){ - yymsp[-3].minor.yy342.pExpr->affinity = OE_Ignore; + 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); + if( yymsp[-3].minor.yy190.pExpr ){ + yymsp[-3].minor.yy190.pExpr->affinity = OE_Ignore; } } break; - case 242: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 248: /* expr ::= RAISE LP raisetype COMMA nm RP */ { - spanSet(&yymsp[-5].minor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-5].minor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); - if( yymsp[-5].minor.yy342.pExpr ) { - yymsp[-5].minor.yy342.pExpr->affinity = (char)yymsp[-3].minor.yy392; + 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); + if( yymsp[-5].minor.yy190.pExpr ) { + yymsp[-5].minor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194; } } break; - case 243: /* raisetype ::= ROLLBACK */ -{yymsp[0].minor.yy392 = OE_Rollback;} + case 249: /* raisetype ::= ROLLBACK */ +{yymsp[0].minor.yy194 = OE_Rollback;} break; - case 245: /* raisetype ::= FAIL */ -{yymsp[0].minor.yy392 = OE_Fail;} + case 251: /* raisetype ::= FAIL */ +{yymsp[0].minor.yy194 = OE_Fail;} break; - case 246: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 252: /* cmd ::= DROP TRIGGER ifexists fullname */ { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy347,yymsp[-1].minor.yy392); + sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); } break; - case 247: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 253: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { - sqlite3Attach(pParse, yymsp[-3].minor.yy342.pExpr, yymsp[-1].minor.yy342.pExpr, yymsp[0].minor.yy122); + sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72); } break; - case 248: /* cmd ::= DETACH database_kw_opt expr */ + case 254: /* cmd ::= DETACH database_kw_opt expr */ { - sqlite3Detach(pParse, yymsp[0].minor.yy342.pExpr); + sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr); } break; - case 251: /* cmd ::= REINDEX */ + case 257: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 252: /* cmd ::= REINDEX nm dbnm */ + case 258: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 253: /* cmd ::= ANALYZE */ + case 259: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 254: /* cmd ::= ANALYZE nm dbnm */ + case 260: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 255: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 261: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy347,&yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); } break; - case 256: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + case 262: /* 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 257: /* add_column_fullname ::= fullname */ + case 263: /* add_column_fullname ::= fullname */ { disableLookaside(pParse); - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy347); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); } break; - case 258: /* cmd ::= create_vtab */ + case 264: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 259: /* cmd ::= create_vtab LP vtabarglist RP */ + case 265: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 260: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 266: /* 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.yy392); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194); } break; - case 261: /* vtabarg ::= */ + case 267: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 262: /* vtabargtoken ::= ANY */ - case 263: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==263); - case 264: /* lp ::= LP */ yytestcase(yyruleno==264); + case 268: /* vtabargtoken ::= ANY */ + case 269: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==269); + case 270: /* lp ::= LP */ yytestcase(yyruleno==270); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; - case 265: /* with ::= */ -{yymsp[1].minor.yy331 = 0;} + case 271: /* with ::= */ +{yymsp[1].minor.yy285 = 0;} break; - case 266: /* with ::= WITH wqlist */ -{ yymsp[-1].minor.yy331 = yymsp[0].minor.yy331; } + case 272: /* with ::= WITH wqlist */ +{ yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; } break; - case 267: /* with ::= WITH RECURSIVE wqlist */ -{ yymsp[-2].minor.yy331 = yymsp[0].minor.yy331; } + case 273: /* with ::= WITH RECURSIVE wqlist */ +{ yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; } break; - case 268: /* wqlist ::= nm eidlist_opt AS LP select RP */ + case 274: /* wqlist ::= nm eidlist_opt AS LP select RP */ { - yymsp[-5].minor.yy331 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy442, yymsp[-1].minor.yy159); /*A-overwrites-X*/ + yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/ } break; - case 269: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ + case 275: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ { - yymsp[-7].minor.yy331 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy331, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy442, yymsp[-1].minor.yy159); + yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); } break; default: - /* (270) input ::= cmdlist */ yytestcase(yyruleno==270); - /* (271) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==271); - /* (272) cmdlist ::= ecmd */ yytestcase(yyruleno==272); - /* (273) ecmd ::= SEMI */ yytestcase(yyruleno==273); - /* (274) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==274); - /* (275) explain ::= */ yytestcase(yyruleno==275); - /* (276) trans_opt ::= */ yytestcase(yyruleno==276); - /* (277) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==277); - /* (278) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==278); - /* (279) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==279); - /* (280) savepoint_opt ::= */ yytestcase(yyruleno==280); - /* (281) cmd ::= create_table create_table_args */ yytestcase(yyruleno==281); - /* (282) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==282); - /* (283) columnlist ::= columnname carglist */ yytestcase(yyruleno==283); - /* (284) nm ::= ID|INDEXED */ yytestcase(yyruleno==284); - /* (285) nm ::= STRING */ yytestcase(yyruleno==285); - /* (286) nm ::= JOIN_KW */ yytestcase(yyruleno==286); - /* (287) typetoken ::= typename */ yytestcase(yyruleno==287); - /* (288) typename ::= ID|STRING */ yytestcase(yyruleno==288); - /* (289) signed ::= plus_num */ yytestcase(yyruleno==289); - /* (290) signed ::= minus_num */ yytestcase(yyruleno==290); - /* (291) carglist ::= carglist ccons */ yytestcase(yyruleno==291); - /* (292) carglist ::= */ yytestcase(yyruleno==292); - /* (293) ccons ::= NULL onconf */ yytestcase(yyruleno==293); - /* (294) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==294); - /* (295) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==295); - /* (296) conslist ::= tcons */ yytestcase(yyruleno==296); - /* (297) tconscomma ::= */ yytestcase(yyruleno==297); - /* (298) defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==298); - /* (299) resolvetype ::= raisetype */ yytestcase(yyruleno==299); - /* (300) selectnowith ::= oneselect */ yytestcase(yyruleno==300); - /* (301) oneselect ::= values */ yytestcase(yyruleno==301); - /* (302) sclp ::= selcollist COMMA */ yytestcase(yyruleno==302); - /* (303) as ::= ID|STRING */ yytestcase(yyruleno==303); - /* (304) expr ::= term */ yytestcase(yyruleno==304); - /* (305) exprlist ::= nexprlist */ yytestcase(yyruleno==305); - /* (306) nmnum ::= plus_num */ yytestcase(yyruleno==306); - /* (307) nmnum ::= nm */ yytestcase(yyruleno==307); - /* (308) nmnum ::= ON */ yytestcase(yyruleno==308); - /* (309) nmnum ::= DELETE */ yytestcase(yyruleno==309); - /* (310) nmnum ::= DEFAULT */ yytestcase(yyruleno==310); - /* (311) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==311); - /* (312) foreach_clause ::= */ yytestcase(yyruleno==312); - /* (313) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==313); - /* (314) trnm ::= nm */ yytestcase(yyruleno==314); - /* (315) tridxby ::= */ yytestcase(yyruleno==315); - /* (316) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==316); - /* (317) database_kw_opt ::= */ yytestcase(yyruleno==317); - /* (318) kwcolumn_opt ::= */ yytestcase(yyruleno==318); - /* (319) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==319); - /* (320) vtabarglist ::= vtabarg */ yytestcase(yyruleno==320); - /* (321) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==321); - /* (322) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==322); - /* (323) anylist ::= */ yytestcase(yyruleno==323); - /* (324) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==324); - /* (325) anylist ::= anylist ANY */ yytestcase(yyruleno==325); + /* (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); break; /********** End reduce actions ************************************************/ }; @@ -131682,15 +136310,17 @@ static void yy_reduce( yysize = yyRuleInfo[yyruleno].nrhs; yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); if( yyact <= YY_MAX_SHIFTREDUCE ){ - if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; - yypParser->yyidx -= yysize - 1; + if( yyact>YY_MAX_SHIFT ){ + yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; + } yymsp -= yysize-1; + yypParser->yytos = yymsp; yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; yyTraceShift(yypParser, yyact); }else{ assert( yyact == YY_ACCEPT_ACTION ); - yypParser->yyidx -= yysize; + yypParser->yytos -= yysize; yy_accept(yypParser); } } @@ -131708,7 +136338,7 @@ static void yy_parse_failed( fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); } #endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); + while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser fails */ /************ Begin %parse_failure code ***************************************/ @@ -131748,7 +136378,10 @@ static void yy_accept( fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); } #endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); +#ifndef YYNOERRORRECOVERY + yypParser->yyerrcnt = -1; +#endif + assert( yypParser->yytos==yypParser->yystack ); /* Here code is inserted which will be executed whenever the ** parser accepts */ /*********** Begin %parse_accept code *****************************************/ @@ -131791,28 +136424,8 @@ SQLITE_PRIVATE void sqlite3Parser( #endif yyParser *yypParser; /* The parser */ - /* (re)initialize the parser, if necessary */ yypParser = (yyParser*)yyp; - if( yypParser->yyidx<0 ){ -#if YYSTACKDEPTH<=0 - if( yypParser->yystksz <=0 ){ - yyStackOverflow(yypParser); - return; - } -#endif - yypParser->yyidx = 0; -#ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt = -1; -#endif - yypParser->yystack[0].stateno = 0; - yypParser->yystack[0].major = 0; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sInitialize. Empty stack. State 0\n", - yyTracePrompt); - } -#endif - } + assert( yypParser->yytos!=0 ); #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) yyendofinput = (yymajor==0); #endif @@ -131827,7 +136440,6 @@ SQLITE_PRIVATE void sqlite3Parser( do{ yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); if( yyact <= YY_MAX_SHIFTREDUCE ){ - if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; yy_shift(yypParser,yyact,yymajor,yyminor); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt--; @@ -131869,7 +136481,7 @@ SQLITE_PRIVATE void sqlite3Parser( if( yypParser->yyerrcnt<0 ){ yy_syntax_error(yypParser,yymajor,yyminor); } - yymx = yypParser->yystack[yypParser->yyidx].major; + yymx = yypParser->yytos->major; if( yymx==YYERRORSYMBOL || yyerrorhit ){ #ifndef NDEBUG if( yyTraceFILE ){ @@ -131880,18 +136492,20 @@ SQLITE_PRIVATE void sqlite3Parser( yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); yymajor = YYNOCODE; }else{ - while( - yypParser->yyidx >= 0 && - yymx != YYERRORSYMBOL && - (yyact = yy_find_reduce_action( - yypParser->yystack[yypParser->yyidx].stateno, + while( yypParser->yytos >= yypParser->yystack + && yymx != YYERRORSYMBOL + && (yyact = yy_find_reduce_action( + yypParser->yytos->stateno, YYERRORSYMBOL)) >= YY_MIN_REDUCE ){ yy_pop_parser_stack(yypParser); } - if( yypParser->yyidx < 0 || yymajor==0 ){ + if( yypParser->yytos < yypParser->yystack || yymajor==0 ){ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); yy_parse_failed(yypParser); +#ifndef YYNOERRORRECOVERY + yypParser->yyerrcnt = -1; +#endif yymajor = YYNOCODE; }else if( yymx!=YYERRORSYMBOL ){ yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor); @@ -131928,18 +136542,23 @@ SQLITE_PRIVATE void sqlite3Parser( yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); if( yyendofinput ){ yy_parse_failed(yypParser); +#ifndef YYNOERRORRECOVERY + yypParser->yyerrcnt = -1; +#endif } yymajor = YYNOCODE; #endif } - }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); + }while( yymajor!=YYNOCODE && yypParser->yytos>yypParser->yystack ); #ifndef NDEBUG if( yyTraceFILE ){ - int i; + yyStackEntry *i; + char cDiv = '['; fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt); - for(i=1; i<=yypParser->yyidx; i++) - fprintf(yyTraceFILE,"%c%s", i==1 ? '[' : ' ', - yyTokenName[yypParser->yystack[i].major]); + for(i=&yypParser->yystack[1]; i<=yypParser->yytos; i++){ + fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]); + cDiv = ' '; + } fprintf(yyTraceFILE,"]\n"); } #endif @@ -132741,14 +137360,26 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr assert( pParse->nVar==0 ); assert( pParse->nzVar==0 ); assert( pParse->azVar==0 ); - while( zSql[i]!=0 ){ + while( 1 ){ assert( i>=0 ); - pParse->sLastToken.z = &zSql[i]; - pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); - i += pParse->sLastToken.n; - if( i>mxSqlLen ){ - pParse->rc = SQLITE_TOOBIG; - break; + if( zSql[i]!=0 ){ + pParse->sLastToken.z = &zSql[i]; + pParse->sLastToken.n = sqlite3GetToken((u8*)&zSql[i],&tokenType); + i += pParse->sLastToken.n; + if( i>mxSqlLen ){ + pParse->rc = SQLITE_TOOBIG; + break; + } + }else{ + /* Upon reaching the end of input, call the parser two more times + ** with tokens TK_SEMI and 0, in that order. */ + if( lastTokenParsed==TK_SEMI ){ + tokenType = 0; + }else if( lastTokenParsed==0 ){ + break; + }else{ + tokenType = TK_SEMI; + } } if( tokenType>=TK_SPACE ){ assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); @@ -132769,15 +137400,6 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr } assert( nErr==0 ); pParse->zTail = &zSql[i]; - if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){ - assert( zSql[i]==0 ); - if( lastTokenParsed!=TK_SEMI ){ - sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse); - } - if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){ - sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); - } - } #ifdef YYTRACKMAXSTACKDEPTH sqlite3_mutex_enter(sqlite3MallocMutex()); sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK, @@ -132822,7 +137444,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr sqlite3DeleteTable(db, pParse->pNewTable); } - sqlite3WithDelete(db, pParse->pWithToFree); + 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); @@ -132945,7 +137567,7 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[]; ** to recognize the end of a trigger can be omitted. All we have to do ** is look for a semicolon that is not part of an string or comment. */ -SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *zSql){ +SQLITE_API int sqlite3_complete(const char *zSql){ u8 state = 0; /* Current state, using numbers defined in header comment */ u8 token; /* Value of the next token */ @@ -133110,7 +137732,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *zSql){ ** above, except that the parameter is required to be UTF-16 encoded, not ** UTF-8. */ -SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *zSql){ +SQLITE_API int sqlite3_complete16(const void *zSql){ sqlite3_value *pVal; char const *zSql8; int rc; @@ -133270,24 +137892,24 @@ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; /* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns ** a pointer to the to the sqlite3_version[] string constant. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void){ return sqlite3_version; } +SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; } /* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a ** pointer to a string constant whose value is the same as the ** SQLITE_SOURCE_ID C preprocessor macro. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } +SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } /* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function ** returns an integer equal to SQLITE_VERSION_NUMBER. */ -SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } +SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } /* IMPLEMENTATION-OF: R-20790-14025 The sqlite3_threadsafe() function returns ** zero if and only if SQLite was compiled with mutexing code omitted due to ** the SQLITE_THREADSAFE compile-time option being set to 0. */ -SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } +SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } /* ** When compiling the test fixture or with debugging enabled (on Win32), @@ -133360,7 +137982,7 @@ SQLITE_API char *sqlite3_data_directory = 0; ** * Recursive calls to this routine from thread X return immediately ** without blocking. */ -SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void){ +SQLITE_API int sqlite3_initialize(void){ MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ int rc; /* Result code */ #ifdef SQLITE_EXTRA_INIT @@ -133526,7 +138148,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void){ ** on when SQLite is already shut down. If SQLite is already shut down ** when this routine is invoked, then this routine is a harmless no-op. */ -SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void){ +SQLITE_API int sqlite3_shutdown(void){ #ifdef SQLITE_OMIT_WSD int rc = sqlite3_wsd_init(4096, 24); if( rc!=SQLITE_OK ){ @@ -133580,7 +138202,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void){ ** threadsafe. Failure to heed these warnings can lead to unpredictable ** behavior. */ -SQLITE_API int SQLITE_CDECL sqlite3_config(int op, ...){ +SQLITE_API int sqlite3_config(int op, ...){ va_list ap; int rc = SQLITE_OK; @@ -133945,7 +138567,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ /* ** Return the mutex associated with a database connection. */ -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3 *db){ +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -133959,7 +138581,7 @@ SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3 *db){ ** Free up as much memory as we can from the given database ** connection. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3 *db){ +SQLITE_API int sqlite3_db_release_memory(sqlite3 *db){ int i; #ifdef SQLITE_ENABLE_API_ARMOR @@ -133983,7 +138605,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3 *db){ ** Flush any dirty pages in the pager-cache for any attached database ** to disk. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3 *db){ +SQLITE_API int sqlite3_db_cacheflush(sqlite3 *db){ int i; int rc = SQLITE_OK; int bSeenBusy = 0; @@ -134012,11 +138634,16 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3 *db){ /* ** Configuration settings for an individual database connection */ -SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3 *db, int op, ...){ +SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ va_list ap; int rc; va_start(ap, op); switch( op ){ + case SQLITE_DBCONFIG_MAINDBNAME: { + db->aDb[0].zDbSName = va_arg(ap,char*); + rc = SQLITE_OK; + break; + } case SQLITE_DBCONFIG_LOOKASIDE: { void *pBuf = va_arg(ap, void*); /* IMP: R-26835-10964 */ int sz = va_arg(ap, int); /* IMP: R-47871-25994 */ @@ -134032,6 +138659,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3 *db, int op, ...){ { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, + { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ @@ -134132,7 +138760,7 @@ static int nocaseCollatingFunc( /* ** Return the ROWID of the most recent insert */ -SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3 *db){ +SQLITE_API sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -134145,7 +138773,7 @@ SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3 *db){ /* ** Return the number of changes in the most recent call to sqlite3_exec(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3 *db){ +SQLITE_API int sqlite3_changes(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -134158,7 +138786,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3 *db){ /* ** Return the number of changes since the database handle was opened. */ -SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3 *db){ +SQLITE_API int sqlite3_total_changes(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -134260,6 +138888,9 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){ return SQLITE_MISUSE_BKPT; } sqlite3_mutex_enter(db->mutex); + if( db->mTrace & SQLITE_TRACE_CLOSE ){ + db->xTrace(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0); + } /* Force xDisconnect calls on all virtual tables */ disconnectAllVtab(db); @@ -134306,8 +138937,8 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){ ** unclosed resources, and arranges for deallocation when the last ** prepare statement or sqlite3_backup closes. */ -SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); } -SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); } +SQLITE_API int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); } +SQLITE_API int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); } /* @@ -134714,7 +139345,7 @@ SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){ ** This routine sets the busy callback for an Sqlite database to the ** given callback function with the given argument. */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler( +SQLITE_API int sqlite3_busy_handler( sqlite3 *db, int (*xBusy)(void*,int), void *pArg @@ -134737,7 +139368,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler( ** given callback function with the given argument. The progress callback will ** be invoked every nOps opcodes. */ -SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler( +SQLITE_API void sqlite3_progress_handler( sqlite3 *db, int nOps, int (*xProgress)(void*), @@ -134768,7 +139399,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler( ** This routine installs a default busy handler that waits for the ** specified number of milliseconds before returning 0. */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3 *db, int ms){ +SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif @@ -134784,7 +139415,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3 *db, int ms){ /* ** Cause any pending operation to stop at its earliest opportunity. */ -SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3 *db){ +SQLITE_API void sqlite3_interrupt(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -134900,7 +139531,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc( /* ** Create new user functions. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_function( +SQLITE_API int sqlite3_create_function( sqlite3 *db, const char *zFunc, int nArg, @@ -134914,7 +139545,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function( xFinal, 0); } -SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( +SQLITE_API int sqlite3_create_function_v2( sqlite3 *db, const char *zFunc, int nArg, @@ -134957,7 +139588,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( +SQLITE_API int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, @@ -134997,7 +139628,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( ** A global function must exist in order for name resolution to work ** properly. */ -SQLITE_API int SQLITE_STDCALL sqlite3_overload_function( +SQLITE_API int sqlite3_overload_function( sqlite3 *db, const char *zName, int nArg @@ -135028,7 +139659,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_overload_function( ** trace is a pointer to a function that is invoked at the start of each ** SQL statement. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ +#ifndef SQLITE_OMIT_DEPRECATED +SQLITE_API void *sqlite3_trace(sqlite3 *db, void(*xTrace)(void*,const char*), void *pArg){ void *pOld; #ifdef SQLITE_ENABLE_API_ARMOR @@ -135039,11 +139671,38 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3 *db, void (*xTrace)(void*, #endif sqlite3_mutex_enter(db->mutex); pOld = db->pTraceArg; - db->xTrace = xTrace; + db->mTrace = xTrace ? SQLITE_TRACE_LEGACY : 0; + db->xTrace = (int(*)(u32,void*,void*,void*))xTrace; db->pTraceArg = pArg; sqlite3_mutex_leave(db->mutex); return pOld; } +#endif /* SQLITE_OMIT_DEPRECATED */ + +/* Register a trace callback using the version-2 interface. +*/ +SQLITE_API int sqlite3_trace_v2( + sqlite3 *db, /* Trace this connection */ + unsigned mTrace, /* Mask of events to be traced */ + int(*xTrace)(unsigned,void*,void*,void*), /* Callback to invoke */ + void *pArg /* Context */ +){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ){ + return SQLITE_MISUSE_BKPT; + } +#endif + sqlite3_mutex_enter(db->mutex); + if( mTrace==0 ) xTrace = 0; + if( xTrace==0 ) mTrace = 0; + db->mTrace = mTrace; + db->xTrace = xTrace; + db->pTraceArg = pArg; + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + +#ifndef SQLITE_OMIT_DEPRECATED /* ** Register a profile function. The pArg from the previously registered ** profile function is returned. @@ -135052,7 +139711,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3 *db, void (*xTrace)(void*, ** profile is a pointer to a function that is invoked at the conclusion of ** each SQL statement that is run. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_profile( +SQLITE_API void *sqlite3_profile( sqlite3 *db, void (*xProfile)(void*,const char*,sqlite_uint64), void *pArg @@ -135072,6 +139731,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_profile( sqlite3_mutex_leave(db->mutex); return pOld; } +#endif /* SQLITE_OMIT_DEPRECATED */ #endif /* SQLITE_OMIT_TRACE */ /* @@ -135079,7 +139739,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_profile( ** If the invoked function returns non-zero, then the commit becomes a ** rollback. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook( +SQLITE_API void *sqlite3_commit_hook( sqlite3 *db, /* Attach the hook to this database */ int (*xCallback)(void*), /* Function to invoke on each commit */ void *pArg /* Argument to the function */ @@ -135104,7 +139764,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook( ** Register a callback to be invoked each time a row is updated, ** inserted or deleted using this database connection. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( +SQLITE_API void *sqlite3_update_hook( sqlite3 *db, /* Attach the hook to this database */ void (*xCallback)(void*,int,char const *,char const *,sqlite_int64), void *pArg /* Argument to the function */ @@ -135129,7 +139789,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( ** Register a callback to be invoked each time a transaction is rolled ** back by this database connection. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook( +SQLITE_API void *sqlite3_rollback_hook( sqlite3 *db, /* Attach the hook to this database */ void (*xCallback)(void*), /* Callback function */ void *pArg /* Argument to the function */ @@ -135150,6 +139810,27 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook( return pRet; } +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK +/* +** Register a callback to be invoked each time a row is updated, +** inserted or deleted using this database connection. +*/ +SQLITE_API void *sqlite3_preupdate_hook( + sqlite3 *db, /* Attach the hook to this database */ + void(*xCallback)( /* Callback function */ + void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64), + void *pArg /* First callback argument */ +){ + void *pRet; + sqlite3_mutex_enter(db->mutex); + pRet = db->pPreUpdateArg; + db->xPreUpdateCallback = xCallback; + db->pPreUpdateArg = pArg; + sqlite3_mutex_leave(db->mutex); + return pRet; +} +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + #ifndef SQLITE_OMIT_WAL /* ** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). @@ -135183,7 +139864,7 @@ SQLITE_PRIVATE int sqlite3WalDefaultHook( ** using sqlite3_wal_hook() disables the automatic checkpoint mechanism ** configured by this function. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ +SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ #ifdef SQLITE_OMIT_WAL UNUSED_PARAMETER(db); UNUSED_PARAMETER(nFrame); @@ -135204,7 +139885,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame ** Register a callback to be invoked each time a transaction is written ** into the write-ahead-log by this database connection. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( +SQLITE_API void *sqlite3_wal_hook( sqlite3 *db, /* Attach the hook to this db handle */ int(*xCallback)(void *, sqlite3*, const char*, int), void *pArg /* First argument passed to xCallback() */ @@ -135231,7 +139912,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( /* ** Checkpoint database zDb. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( +SQLITE_API int sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of attached database (or NULL) */ int eMode, /* SQLITE_CHECKPOINT_* value */ @@ -135286,7 +139967,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( ** to contains a zero-length string, all attached databases are ** checkpointed. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ +SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ /* EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is equivalent to ** sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0). */ return sqlite3_wal_checkpoint_v2(db,zDb,SQLITE_CHECKPOINT_PASSIVE,0,0); @@ -135377,7 +140058,7 @@ SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3 *db){ ** Return UTF-8 encoded English language explanation of the most recent ** error. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3 *db){ +SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){ const char *z; if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM_BKPT); @@ -135405,7 +140086,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3 *db){ ** Return UTF-16 encoded English language explanation of the most recent ** error. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3 *db){ +SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){ static const u16 outOfMem[] = { 'o', 'u', 't', ' ', 'o', 'f', ' ', 'm', 'e', 'm', 'o', 'r', 'y', 0 }; @@ -135450,7 +140131,7 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3 *db){ ** Return the most recent error code generated by an SQLite routine. If NULL is ** passed to this function, we assume a malloc() failed during sqlite3_open(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db){ +SQLITE_API int sqlite3_errcode(sqlite3 *db){ if( db && !sqlite3SafetyCheckSickOrOk(db) ){ return SQLITE_MISUSE_BKPT; } @@ -135459,7 +140140,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db){ } return db->errCode & db->errMask; } -SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db){ +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){ if( db && !sqlite3SafetyCheckSickOrOk(db) ){ return SQLITE_MISUSE_BKPT; } @@ -135468,7 +140149,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db){ } return db->errCode; } -SQLITE_API int SQLITE_STDCALL sqlite3_system_errno(sqlite3 *db){ +SQLITE_API int sqlite3_system_errno(sqlite3 *db){ return db ? db->iSysErrno : 0; } @@ -135477,7 +140158,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_system_errno(sqlite3 *db){ ** argument. For now, this simply calls the internal sqlite3ErrStr() ** function. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int rc){ +SQLITE_API const char *sqlite3_errstr(int rc){ return sqlite3ErrStr(rc); } @@ -135625,7 +140306,7 @@ static const int aHardLimit[] = { ** It merely prevents new constructs that exceed the limit ** from forming. */ -SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ +SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ int oldLimit; #ifdef SQLITE_ENABLE_API_ARMOR @@ -136108,9 +140789,9 @@ static int openDatabase( /* The default safety_level for the main database is FULL; for the temp ** database it is OFF. This matches the pager layer defaults. */ - db->aDb[0].zName = "main"; + db->aDb[0].zDbSName = "main"; db->aDb[0].safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - db->aDb[1].zName = "temp"; + db->aDb[1].zDbSName = "temp"; db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF; db->magic = SQLITE_MAGIC_OPEN; @@ -136124,11 +140805,20 @@ static int openDatabase( */ sqlite3Error(db, SQLITE_OK); sqlite3RegisterPerConnectionBuiltinFunctions(db); + rc = sqlite3_errcode(db); + +#ifdef SQLITE_ENABLE_FTS5 + /* Register any built-in FTS5 module before loading the automatic + ** extensions. This allows automatic extensions to register FTS5 + ** tokenizers and auxiliary functions. */ + if( !db->mallocFailed && rc==SQLITE_OK ){ + rc = sqlite3Fts5Init(db); + } +#endif /* Load automatic extensions - extensions that have been registered ** using the sqlite3_automatic_extension() API. */ - rc = sqlite3_errcode(db); if( rc==SQLITE_OK ){ sqlite3AutoLoadExtensions(db); rc = sqlite3_errcode(db); @@ -136157,12 +140847,6 @@ static int openDatabase( } #endif -#ifdef SQLITE_ENABLE_FTS5 - if( !db->mallocFailed && rc==SQLITE_OK ){ - rc = sqlite3Fts5Init(db); - } -#endif - #ifdef SQLITE_ENABLE_ICU if( !db->mallocFailed && rc==SQLITE_OK ){ rc = sqlite3IcuInit(db); @@ -136249,14 +140933,14 @@ static int openDatabase( /* ** Open a new database handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_open( +SQLITE_API int sqlite3_open( const char *zFilename, sqlite3 **ppDb ){ return openDatabase(zFilename, ppDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); } -SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( +SQLITE_API int sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ @@ -136269,7 +140953,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( /* ** Open a new database handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_open16( +SQLITE_API int sqlite3_open16( const void *zFilename, sqlite3 **ppDb ){ @@ -136308,7 +140992,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_open16( /* ** Register a new collation sequence with the database handle db. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation( +SQLITE_API int sqlite3_create_collation( sqlite3* db, const char *zName, int enc, @@ -136321,7 +141005,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation( /* ** Register a new collation sequence with the database handle db. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( +SQLITE_API int sqlite3_create_collation_v2( sqlite3* db, const char *zName, int enc, @@ -136346,7 +141030,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( /* ** Register a new collation sequence with the database handle db. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( +SQLITE_API int sqlite3_create_collation16( sqlite3* db, const void *zName, int enc, @@ -136376,7 +141060,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( ** Register a collation sequence factory callback with the database handle ** db. Replace any previously installed collation sequence factory. */ -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( +SQLITE_API int sqlite3_collation_needed( sqlite3 *db, void *pCollNeededArg, void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*) @@ -136397,7 +141081,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( ** Register a collation sequence factory callback with the database handle ** db. Replace any previously installed collation sequence factory. */ -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( +SQLITE_API int sqlite3_collation_needed16( sqlite3 *db, void *pCollNeededArg, void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*) @@ -136419,7 +141103,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( ** This function is now an anachronism. It used to be used to recover from a ** malloc() failure, but SQLite now does this automatically. */ -SQLITE_API int SQLITE_STDCALL sqlite3_global_recover(void){ +SQLITE_API int sqlite3_global_recover(void){ return SQLITE_OK; } #endif @@ -136430,7 +141114,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_global_recover(void){ ** by default. Autocommit is disabled by a BEGIN statement and reenabled ** by the next COMMIT or ROLLBACK. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3 *db){ +SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -136487,7 +141171,7 @@ SQLITE_PRIVATE int sqlite3IoerrnomemError(int lineno){ ** SQLite no longer uses thread-specific data so this routine is now a ** no-op. It is retained for historical compatibility. */ -SQLITE_API void SQLITE_STDCALL sqlite3_thread_cleanup(void){ +SQLITE_API void sqlite3_thread_cleanup(void){ } #endif @@ -136495,7 +141179,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_thread_cleanup(void){ ** Return meta information about a specific column of a database table. ** See comment in sqlite3.h (sqlite.h.in) for details. */ -SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( +SQLITE_API int sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ @@ -136613,7 +141297,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( /* ** Sleep for a little while. Return the amount of time slept. */ -SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int ms){ +SQLITE_API int sqlite3_sleep(int ms){ sqlite3_vfs *pVfs; int rc; pVfs = sqlite3_vfs_find(0); @@ -136629,7 +141313,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int ms){ /* ** Enable or disable the extended result codes. */ -SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3 *db, int onoff){ +SQLITE_API int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif @@ -136642,7 +141326,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3 *db, int ono /* ** Invoke the xFileControl method on a particular database. */ -SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ +SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ int rc = SQLITE_ERROR; Btree *pBtree; @@ -136682,7 +141366,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3 *db, const char *zDbN /* ** Interface to the testing logic. */ -SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ +SQLITE_API int sqlite3_test_control(int op, ...){ int rc = 0; #ifdef SQLITE_OMIT_BUILTIN_TEST UNUSED_PARAMETER(op); @@ -136950,6 +141634,15 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ break; } + /* Set the threshold at which OP_Once counters reset back to zero. + ** By default this is 0x7ffffffe (over 2 billion), but that value is + ** too big to test in a reasonable amount of time, so this control is + ** provided to set a small and easily reachable reset value. + */ + case SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD: { + sqlite3GlobalConfig.iOnceResetThreshold = va_arg(ap, int); + break; + } /* sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, xCallback, ptr); ** @@ -137027,7 +141720,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ ** parameter if it exists. If the parameter does not exist, this routine ** returns a NULL pointer. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam){ +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){ if( zFilename==0 || zParam==0 ) return 0; zFilename += sqlite3Strlen30(zFilename) + 1; while( zFilename[0] ){ @@ -137042,7 +141735,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilenam /* ** Return a boolean value for a query parameter. */ -SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){ +SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){ const char *z = sqlite3_uri_parameter(zFilename, zParam); bDflt = bDflt!=0; return z ? sqlite3GetBoolean(z, bDflt) : bDflt; @@ -137051,7 +141744,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFilename, const c /* ** Return a 64-bit integer value for a query parameter. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64( +SQLITE_API sqlite3_int64 sqlite3_uri_int64( const char *zFilename, /* Filename as passed to xOpen */ const char *zParam, /* URI parameter sought */ sqlite3_int64 bDflt /* return if parameter is missing */ @@ -137071,7 +141764,7 @@ SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ int i; for(i=0; inDb; i++){ if( db->aDb[i].pBt - && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zName)==0) + && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zDbSName)==0) ){ return db->aDb[i].pBt; } @@ -137083,7 +141776,7 @@ SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ ** Return the filename of the database associated with a database ** connection. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName){ +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ Btree *pBt; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ @@ -137099,7 +141792,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const cha ** Return 1 if database is read-only or 0 if read/write. Return -1 if ** no such database exists. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ Btree *pBt; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ @@ -137116,7 +141809,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbNa ** Obtain a snapshot handle for the snapshot of database zDb currently ** being read by handle db. */ -SQLITE_API int SQLITE_STDCALL sqlite3_snapshot_get( +SQLITE_API int sqlite3_snapshot_get( sqlite3 *db, const char *zDb, sqlite3_snapshot **ppSnapshot @@ -137151,7 +141844,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_snapshot_get( /* ** Open a read-transaction on the snapshot idendified by pSnapshot. */ -SQLITE_API int SQLITE_STDCALL sqlite3_snapshot_open( +SQLITE_API int sqlite3_snapshot_open( sqlite3 *db, const char *zDb, sqlite3_snapshot *pSnapshot @@ -137188,7 +141881,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_snapshot_open( /* ** Free a snapshot handle obtained from sqlite3_snapshot_get(). */ -SQLITE_API void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){ +SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){ sqlite3_free(pSnapshot); } #endif /* SQLITE_ENABLE_SNAPSHOT */ @@ -137342,7 +142035,7 @@ static void leaveMutex(void){ ** on the same "db". If xNotify==0 then any prior callbacks are immediately ** cancelled. */ -SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( +SQLITE_API int sqlite3_unlock_notify( sqlite3 *db, void (*xNotify)(void **, int), void *pArg @@ -144345,7 +149038,7 @@ SQLITE_PRIVATE int sqlite3Fts3Corrupt(){ #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_fts3_init( +SQLITE_API int sqlite3_fts3_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -147501,7 +152194,11 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer( #ifdef SQLITE_TEST -#include +#if defined(INCLUDE_SQLITE_TCL_H) +# include "sqlite_tcl.h" +#else +# include "tcl.h" +#endif /* #include */ /* @@ -158182,7 +162879,7 @@ static int rtreeFilter( if( idxNum==1 ){ /* Special case - lookup by rowid. */ RtreeNode *pLeaf; /* Leaf on which the required cell resides */ - RtreeSearchPoint *p; /* Search point for the the leaf */ + RtreeSearchPoint *p; /* Search point for the leaf */ i64 iRowid = sqlite3_value_int64(argv[0]); i64 iNode = 0; rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); @@ -159440,6 +164137,53 @@ static RtreeValue rtreeValueUp(sqlite3_value *v){ } #endif /* !defined(SQLITE_RTREE_INT_ONLY) */ +/* +** A constraint has failed while inserting a row into an rtree table. +** Assuming no OOM error occurs, this function sets the error message +** (at pRtree->base.zErrMsg) to an appropriate value and returns +** SQLITE_CONSTRAINT. +** +** Parameter iCol is the index of the leftmost column involved in the +** constraint failure. If it is 0, then the constraint that failed is +** the unique constraint on the id column. Otherwise, it is the rtree +** (c1<=c2) constraint on columns iCol and iCol+1 that has failed. +** +** If an OOM occurs, SQLITE_NOMEM is returned instead of SQLITE_CONSTRAINT. +*/ +static int rtreeConstraintError(Rtree *pRtree, int iCol){ + sqlite3_stmt *pStmt = 0; + char *zSql; + int rc; + + assert( iCol==0 || iCol%2 ); + zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", pRtree->zDb, pRtree->zName); + if( zSql ){ + rc = sqlite3_prepare_v2(pRtree->db, zSql, -1, &pStmt, 0); + }else{ + rc = SQLITE_NOMEM; + } + sqlite3_free(zSql); + + if( rc==SQLITE_OK ){ + if( iCol==0 ){ + const char *zCol = sqlite3_column_name(pStmt, 0); + pRtree->base.zErrMsg = sqlite3_mprintf( + "UNIQUE constraint failed: %s.%s", pRtree->zName, zCol + ); + }else{ + const char *zCol1 = sqlite3_column_name(pStmt, iCol); + const char *zCol2 = sqlite3_column_name(pStmt, iCol+1); + pRtree->base.zErrMsg = sqlite3_mprintf( + "rtree constraint failed: %s.(%s<=%s)", pRtree->zName, zCol1, zCol2 + ); + } + } + + sqlite3_finalize(pStmt); + return (rc==SQLITE_OK ? SQLITE_CONSTRAINT : rc); +} + + /* ** The xUpdate method for rtree module virtual tables. @@ -159490,7 +164234,7 @@ static int rtreeUpdate( cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]); cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]); if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){ - rc = SQLITE_CONSTRAINT; + rc = rtreeConstraintError(pRtree, ii+1); goto constraint; } } @@ -159501,7 +164245,7 @@ static int rtreeUpdate( cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]); cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]); if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){ - rc = SQLITE_CONSTRAINT; + rc = rtreeConstraintError(pRtree, ii+1); goto constraint; } } @@ -159522,7 +164266,7 @@ static int rtreeUpdate( if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){ rc = rtreeDeleteRowid(pRtree, cell.iRowid); }else{ - rc = SQLITE_CONSTRAINT; + rc = rtreeConstraintError(pRtree, 0); goto constraint; } } @@ -159605,6 +164349,13 @@ static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){ int rc; i64 nRow = 0; + rc = sqlite3_table_column_metadata( + db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0 + ); + if( rc!=SQLITE_OK ){ + pRtree->nRowEst = RTREE_DEFAULT_ROWEST; + return rc==SQLITE_ERROR ? SQLITE_OK : rc; + } zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName); if( zSql==0 ){ rc = SQLITE_NOMEM; @@ -160090,7 +164841,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ /* ** Register a new geometry function for use with the r-tree MATCH operator. */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( +SQLITE_API int sqlite3_rtree_geometry_callback( sqlite3 *db, /* Register SQL function on this connection */ const char *zGeom, /* Name of the new SQL function */ int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*), /* Callback */ @@ -160114,7 +164865,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( ** Register a new 2nd-generation geometry function for use with the ** r-tree MATCH operator. */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( +SQLITE_API int sqlite3_rtree_query_callback( sqlite3 *db, /* Register SQL function on this connection */ const char *zQueryFunc, /* Name of new SQL function */ int (*xQueryFunc)(sqlite3_rtree_query_info*), /* Callback */ @@ -160139,7 +164890,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_init( +SQLITE_API int sqlite3_rtree_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -160504,20 +165255,22 @@ static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){ ** of upper() or lower(). ** ** lower('I', 'en_us') -> 'i' -** lower('I', 'tr_tr') -> 'ı' (small dotless i) +** lower('I', 'tr_tr') -> '\u131' (small dotless i) ** ** http://www.icu-project.org/userguide/posix.html#case_mappings */ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ - const UChar *zInput; - UChar *zOutput = 0; - int nInput; - int nOut; + const UChar *zInput; /* Pointer to input string */ + UChar *zOutput = 0; /* Pointer to output buffer */ + int nInput; /* Size of utf-16 input string in bytes */ + int nOut; /* Size of output buffer in bytes */ int cnt; + int bToUpper; /* True for toupper(), false for tolower() */ UErrorCode status; const char *zLocale = 0; assert(nArg==1 || nArg==2); + bToUpper = (sqlite3_user_data(p)!=0); if( nArg==2 ){ zLocale = (const char *)sqlite3_value_text(apArg[1]); } @@ -160541,19 +165294,23 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ } zOutput = zNew; status = U_ZERO_ERROR; - if( sqlite3_user_data(p) ){ + if( bToUpper ){ nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status); }else{ nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status); } - if( !U_SUCCESS(status) ){ - if( status==U_BUFFER_OVERFLOW_ERROR ) continue; - icuFunctionError(p, - sqlite3_user_data(p) ? "u_strToUpper" : "u_strToLower", status); - return; + + if( U_SUCCESS(status) ){ + sqlite3_result_text16(p, zOutput, nOut, xFree); + }else if( status==U_BUFFER_OVERFLOW_ERROR ){ + assert( cnt==0 ); + continue; + }else{ + icuFunctionError(p, bToUpper ? "u_strToUpper" : "u_strToLower", status); } + return; } - sqlite3_result_text16(p, zOutput, nOut, xFree); + assert( 0 ); /* Unreachable */ } /* @@ -160649,20 +165406,20 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){ void *pContext; /* sqlite3_user_data() context */ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); } scalars[] = { - {"regexp", 2, SQLITE_ANY, 0, icuRegexpFunc}, + {"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc}, - {"lower", 1, SQLITE_UTF16, 0, icuCaseFunc16}, - {"lower", 2, SQLITE_UTF16, 0, icuCaseFunc16}, - {"upper", 1, SQLITE_UTF16, (void*)1, icuCaseFunc16}, - {"upper", 2, SQLITE_UTF16, (void*)1, icuCaseFunc16}, + {"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, 0, icuCaseFunc16}, - {"lower", 2, SQLITE_UTF8, 0, icuCaseFunc16}, - {"upper", 1, SQLITE_UTF8, (void*)1, icuCaseFunc16}, - {"upper", 2, SQLITE_UTF8, (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, 0, icuLikeFunc}, - {"like", 3, SQLITE_UTF8, 0, icuLikeFunc}, + {"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}, }; @@ -160684,7 +165441,7 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){ #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_icu_init( +SQLITE_API int sqlite3_icu_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -161160,7 +165917,7 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule( ** may also be named data_, where is any sequence ** of zero or more numeric characters (0-9). This can be significant because ** tables within the RBU database are always processed in order sorted by -** name. By judicious selection of the the portion of the names +** name. By judicious selection of the portion of the names ** of the RBU tables the user can therefore control the order in which they ** are processed. This can be useful, for example, to ensure that "external ** content" FTS4 tables are updated before their underlying content tables. @@ -161364,12 +166121,50 @@ typedef struct sqlite3rbu sqlite3rbu; ** not work out of the box with zipvfs. Refer to the comment describing ** the zipvfs_create_vfs() API below for details on using RBU with zipvfs. */ -SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( +SQLITE_API sqlite3rbu *sqlite3rbu_open( const char *zTarget, const char *zRbu, const char *zState ); +/* +** Open an RBU handle to perform an RBU vacuum on database file zTarget. +** An RBU vacuum is similar to SQLite's built-in VACUUM command, except +** that it can be suspended and resumed like an RBU update. +** +** The second argument to this function identifies a database in which +** to store the state of the RBU vacuum operation if it is suspended. The +** first time sqlite3rbu_vacuum() is called, to start an RBU vacuum +** operation, the state database should either not exist or be empty +** (contain no tables). If an RBU vacuum is suspended by calling +** sqlite3rbu_close() on the RBU handle before sqlite3rbu_step() has +** returned SQLITE_DONE, the vacuum state is stored in the state database. +** The vacuum can be resumed by calling this function to open a new RBU +** handle specifying the same target and state databases. +** +** If the second argument passed to this function is NULL, then the +** name of the state database is "-vacuum", where +** is the name of the target database file. In this case, on UNIX, if the +** state database is not already present in the file-system, it is created +** with the same permissions as the target db is made. +** +** This function does not delete the state database after an RBU vacuum +** is completed, even if it created it. However, if the call to +** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents +** of the state tables within the state database are zeroed. This way, +** the next call to sqlite3rbu_vacuum() opens a handle that starts a +** new RBU vacuum operation. +** +** As with sqlite3rbu_open(), Zipvfs users should rever to the comment +** describing the sqlite3rbu_create_vfs() API function below for +** a description of the complications associated with using RBU with +** zipvfs databases. +*/ +SQLITE_API sqlite3rbu *sqlite3rbu_vacuum( + const char *zTarget, + const char *zState +); + /* ** Internally, each RBU connection uses a separate SQLite database ** connection to access the target and rbu update databases. This @@ -161401,7 +166196,7 @@ SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( ** Database handles returned by this function remain valid until the next ** call to any sqlite3rbu_xxx() function other than sqlite3rbu_db(). */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3rbu_db(sqlite3rbu*, int bRbu); +SQLITE_API sqlite3 *sqlite3rbu_db(sqlite3rbu*, int bRbu); /* ** Do some work towards applying the RBU update to the target db. @@ -161415,7 +166210,7 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3rbu_db(sqlite3rbu*, int bRbu); ** SQLITE_OK, all subsequent calls on the same RBU handle are no-ops ** that immediately return the same value. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_step(sqlite3rbu *pRbu); +SQLITE_API int sqlite3rbu_step(sqlite3rbu *pRbu); /* ** Force RBU to save its state to disk. @@ -161427,7 +166222,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_step(sqlite3rbu *pRbu); ** ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_savestate(sqlite3rbu *pRbu); +SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *pRbu); /* ** Close an RBU handle. @@ -161447,14 +166242,14 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_savestate(sqlite3rbu *pRbu); ** update has been partially applied, or SQLITE_DONE if it has been ** completely applied. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg); +SQLITE_API int sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg); /* ** Return the total number of key-value operations (inserts, deletes or ** updates) that have been performed on the target database since the ** current RBU update was started. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3rbu_progress(sqlite3rbu *pRbu); +SQLITE_API sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu); /* ** Obtain permyriadage (permyriadage is to 10000 as percentage is to 100) @@ -161496,7 +166291,45 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3rbu_progress(sqlite3rbu *pRbu); ** table exists but is not correctly populated, the value of the *pnOne ** output variable during stage 1 is undefined. */ -SQLITE_API void SQLITE_STDCALL sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int *pnTwo); +SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int *pnTwo); + +/* +** Obtain an indication as to the current stage of an RBU update or vacuum. +** This function always returns one of the SQLITE_RBU_STATE_XXX constants +** defined in this file. Return values should be interpreted as follows: +** +** SQLITE_RBU_STATE_OAL: +** RBU is currently building a *-oal file. The next call to sqlite3rbu_step() +** may either add further data to the *-oal file, or compute data that will +** be added by a subsequent call. +** +** SQLITE_RBU_STATE_MOVE: +** RBU has finished building the *-oal file. The next call to sqlite3rbu_step() +** will move the *-oal file to the equivalent *-wal path. If the current +** operation is an RBU update, then the updated version of the database +** file will become visible to ordinary SQLite clients following the next +** call to sqlite3rbu_step(). +** +** SQLITE_RBU_STATE_CHECKPOINT: +** RBU is currently performing an incremental checkpoint. The next call to +** sqlite3rbu_step() will copy a page of data from the *-wal file into +** the target database file. +** +** SQLITE_RBU_STATE_DONE: +** The RBU operation has finished. Any subsequent calls to sqlite3rbu_step() +** will immediately return SQLITE_DONE. +** +** SQLITE_RBU_STATE_ERROR: +** An error has occurred. Any subsequent calls to sqlite3rbu_step() will +** immediately return the SQLite error code associated with the error. +*/ +#define SQLITE_RBU_STATE_OAL 1 +#define SQLITE_RBU_STATE_MOVE 2 +#define SQLITE_RBU_STATE_CHECKPOINT 3 +#define SQLITE_RBU_STATE_DONE 4 +#define SQLITE_RBU_STATE_ERROR 5 + +SQLITE_API int sqlite3rbu_state(sqlite3rbu *pRbu); /* ** Create an RBU VFS named zName that accesses the underlying file-system @@ -161540,7 +166373,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnO ** file-system via "rbu" all the time, even if it only uses RBU functionality ** occasionally. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_create_vfs(const char *zName, const char *zParent); +SQLITE_API int sqlite3rbu_create_vfs(const char *zName, const char *zParent); /* ** Deregister and destroy an RBU vfs created by an earlier call to @@ -161550,7 +166383,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_create_vfs(const char *zName, const cha ** before all database handles that use it have been closed, the results ** are undefined. */ -SQLITE_API void SQLITE_STDCALL sqlite3rbu_destroy_vfs(const char *zName); +SQLITE_API void sqlite3rbu_destroy_vfs(const char *zName); #if 0 } /* end of the 'extern "C"' block */ @@ -161648,6 +166481,7 @@ typedef struct RbuUpdateStmt RbuUpdateStmt; #if !defined(SQLITE_AMALGAMATION) typedef unsigned int u32; +typedef unsigned short u16; typedef unsigned char u8; typedef sqlite3_int64 i64; #endif @@ -161661,6 +166495,8 @@ typedef sqlite3_int64 i64; #define WAL_LOCK_CKPT 1 #define WAL_LOCK_READ0 3 +#define SQLITE_FCNTL_RBUCNT 5149216 + /* ** A structure to store values read from the rbu_state table in memory. */ @@ -161839,6 +166675,10 @@ struct sqlite3rbu { int pgsz; u8 *aBuf; i64 iWalCksum; + + /* Used in RBU vacuum mode only */ + int nRbu; /* Number of RBU VFS in the stack */ + rbu_file *pRbuFd; /* Fd for main db of dbRbu */ }; /* @@ -161864,6 +166704,7 @@ struct rbu_file { int openFlags; /* Flags this file was opened with */ u32 iCookie; /* Cookie value for main db files */ u8 iWriteVer; /* "write-version" value for main db files */ + u8 bNolock; /* True to fail EXCLUSIVE locks */ int nShm; /* Number of entries in apShm[] array */ char **apShm; /* Array of mmap'd *-shm regions */ @@ -161874,6 +166715,11 @@ struct rbu_file { rbu_file *pMainNext; /* Next MAIN_DB file */ }; +/* +** True for an RBU vacuum handle, or false otherwise. +*/ +#define rbuIsVacuum(p) ((p)->zTarget==0) + /************************************************************************* ** The following three functions, found below: @@ -162322,8 +167168,11 @@ static int rbuObjIterNext(sqlite3rbu *p, RbuObjIter *pIter){ /* ** The implementation of the rbu_target_name() SQL function. This function -** accepts one argument - the name of a table in the RBU database. If the -** table name matches the pattern: +** accepts one or two arguments. The first argument is the name of a table - +** the name of a table in the RBU database. The second, if it is present, is 1 +** for a view or 0 for a table. +** +** For a non-vacuum RBU handle, if the table name matches the pattern: ** ** data[0-9]_ ** @@ -162334,21 +167183,33 @@ static int rbuObjIterNext(sqlite3rbu *p, RbuObjIter *pIter){ ** "data_t1" -> "t1" ** "data0123_t2" -> "t2" ** "dataAB_t3" -> NULL +** +** For an rbu vacuum handle, a copy of the first argument is returned if +** the second argument is either missing or 0 (not a view). */ static void rbuTargetNameFunc( - sqlite3_context *context, + sqlite3_context *pCtx, int argc, sqlite3_value **argv ){ + sqlite3rbu *p = sqlite3_user_data(pCtx); const char *zIn; - assert( argc==1 ); + assert( argc==1 || argc==2 ); zIn = (const char*)sqlite3_value_text(argv[0]); - if( zIn && strlen(zIn)>4 && memcmp("data", zIn, 4)==0 ){ - int i; - for(i=4; zIn[i]>='0' && zIn[i]<='9'; i++); - if( zIn[i]=='_' && zIn[i+1] ){ - sqlite3_result_text(context, &zIn[i+1], -1, SQLITE_STATIC); + if( zIn ){ + if( rbuIsVacuum(p) ){ + if( argc==1 || 0==sqlite3_value_int(argv[1]) ){ + sqlite3_result_text(pCtx, zIn, -1, SQLITE_STATIC); + } + }else{ + if( strlen(zIn)>4 && memcmp("data", zIn, 4)==0 ){ + int i; + for(i=4; zIn[i]>='0' && zIn[i]<='9'; i++); + if( zIn[i]=='_' && zIn[i+1] ){ + sqlite3_result_text(pCtx, &zIn[i+1], -1, SQLITE_STATIC); + } + } } } } @@ -162365,11 +167226,14 @@ static int rbuObjIterFirst(sqlite3rbu *p, RbuObjIter *pIter){ int rc; memset(pIter, 0, sizeof(RbuObjIter)); - rc = prepareAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg, - "SELECT rbu_target_name(name) AS target, name FROM sqlite_master " + rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg, + sqlite3_mprintf( + "SELECT rbu_target_name(name, type='view') AS target, name " + "FROM sqlite_master " "WHERE type IN ('table', 'view') AND target IS NOT NULL " + " %s " "ORDER BY name" - ); + , rbuIsVacuum(p) ? "AND rootpage!=0 AND rootpage IS NOT NULL" : "")); if( rc==SQLITE_OK ){ rc = prepareAndCollectError(p->dbMain, &pIter->pIdxIter, &p->zErrmsg, @@ -162742,6 +167606,7 @@ static int rbuObjIterCacheTableInfo(sqlite3rbu *p, RbuObjIter *pIter){ pStmt = 0; if( p->rc==SQLITE_OK + && rbuIsVacuum(p)==0 && bRbuRowid!=(pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) ){ p->rc = SQLITE_ERROR; @@ -162881,6 +167746,8 @@ static char *rbuObjIterGetIndexCols( for(i=0; pIter->abTblPk[i]==0; i++); assert( inTblCol ); zCol = pIter->azTblCol[i]; + }else if( rbuIsVacuum(p) ){ + zCol = "_rowid_"; }else{ zCol = "rbu_rowid"; } @@ -163421,7 +168288,7 @@ static int rbuObjIterPrepareAll( } /* And to delete index entries */ - if( p->rc==SQLITE_OK ){ + if( rbuIsVacuum(p)==0 && p->rc==SQLITE_OK ){ p->rc = prepareFreeAndCollectError( p->dbMain, &pIter->pDelete, &p->zErrmsg, sqlite3_mprintf("DELETE FROM \"rbu_imp_%w\" WHERE %s", zTbl, zWhere) @@ -163431,6 +168298,15 @@ static int rbuObjIterPrepareAll( /* Create the SELECT statement to read keys in sorted order */ if( p->rc==SQLITE_OK ){ char *zSql; + if( rbuIsVacuum(p) ){ + zSql = sqlite3_mprintf( + "SELECT %s, 0 AS rbu_control FROM '%q' ORDER BY %s%s", + zCollist, + pIter->zDataTbl, + zCollist, zLimit + ); + }else + if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ zSql = sqlite3_mprintf( "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' ORDER BY %s%s", @@ -163457,7 +168333,9 @@ static int rbuObjIterPrepareAll( sqlite3_free(zWhere); sqlite3_free(zBind); }else{ - int bRbuRowid = (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE); + int bRbuRowid = (pIter->eType==RBU_PK_VTAB) + ||(pIter->eType==RBU_PK_NONE) + ||(pIter->eType==RBU_PK_EXTERNAL && rbuIsVacuum(p)); const char *zTbl = pIter->zTbl; /* Table this step applies to */ const char *zWrite; /* Imposter table name */ @@ -163484,8 +168362,10 @@ static int rbuObjIterPrepareAll( ); } - /* Create the DELETE statement to write to the target PK b-tree */ - if( p->rc==SQLITE_OK ){ + /* Create the DELETE statement to write to the target PK b-tree. + ** Because it only performs INSERT operations, this is not required for + ** an rbu vacuum handle. */ + if( rbuIsVacuum(p)==0 && p->rc==SQLITE_OK ){ p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pDelete, pz, sqlite3_mprintf( "DELETE FROM \"%s%w\" WHERE %s", zWrite, zTbl, zWhere @@ -163493,7 +168373,7 @@ static int rbuObjIterPrepareAll( ); } - if( pIter->abIndexed ){ + if( rbuIsVacuum(p)==0 && pIter->abIndexed ){ const char *zRbuRowid = ""; if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ zRbuRowid = ", rbu_rowid"; @@ -163543,10 +168423,16 @@ static int rbuObjIterPrepareAll( /* Create the SELECT statement to read keys from data_xxx */ if( p->rc==SQLITE_OK ){ + const char *zRbuRowid = ""; + if( bRbuRowid ){ + zRbuRowid = rbuIsVacuum(p) ? ",_rowid_ " : ",rbu_rowid"; + } p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, sqlite3_mprintf( - "SELECT %s, rbu_control%s FROM '%q'%s", - zCollist, (bRbuRowid ? ", rbu_rowid" : ""), + "SELECT %s,%s rbu_control%s FROM '%q'%s", + zCollist, + (rbuIsVacuum(p) ? "0 AS " : ""), + zRbuRowid, pIter->zDataTbl, zLimit ) ); @@ -163641,11 +168527,15 @@ static int rbuGetUpdateStmt( return p->rc; } -static sqlite3 *rbuOpenDbhandle(sqlite3rbu *p, const char *zName){ +static sqlite3 *rbuOpenDbhandle( + sqlite3rbu *p, + const char *zName, + int bUseVfs +){ sqlite3 *db = 0; if( p->rc==SQLITE_OK ){ const int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_URI; - p->rc = sqlite3_open_v2(zName, &db, flags, p->zVfsName); + p->rc = sqlite3_open_v2(zName, &db, flags, bUseVfs ? p->zVfsName : 0); if( p->rc ){ p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); sqlite3_close(db); @@ -163655,17 +168545,113 @@ static sqlite3 *rbuOpenDbhandle(sqlite3rbu *p, const char *zName){ return db; } +/* +** Free an RbuState object allocated by rbuLoadState(). +*/ +static void rbuFreeState(RbuState *p){ + if( p ){ + sqlite3_free(p->zTbl); + sqlite3_free(p->zIdx); + sqlite3_free(p); + } +} + +/* +** Allocate an RbuState object and load the contents of the rbu_state +** table into it. Return a pointer to the new object. It is the +** responsibility of the caller to eventually free the object using +** sqlite3_free(). +** +** If an error occurs, leave an error code and message in the rbu handle +** and return NULL. +*/ +static RbuState *rbuLoadState(sqlite3rbu *p){ + RbuState *pRet = 0; + sqlite3_stmt *pStmt = 0; + int rc; + int rc2; + + pRet = (RbuState*)rbuMalloc(p, sizeof(RbuState)); + if( pRet==0 ) return 0; + + rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, + sqlite3_mprintf("SELECT k, v FROM %s.rbu_state", p->zStateDb) + ); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + switch( sqlite3_column_int(pStmt, 0) ){ + case RBU_STATE_STAGE: + pRet->eStage = sqlite3_column_int(pStmt, 1); + if( pRet->eStage!=RBU_STAGE_OAL + && pRet->eStage!=RBU_STAGE_MOVE + && pRet->eStage!=RBU_STAGE_CKPT + ){ + p->rc = SQLITE_CORRUPT; + } + break; + + case RBU_STATE_TBL: + pRet->zTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); + break; + + case RBU_STATE_IDX: + pRet->zIdx = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); + break; + + case RBU_STATE_ROW: + pRet->nRow = sqlite3_column_int(pStmt, 1); + break; + + case RBU_STATE_PROGRESS: + pRet->nProgress = sqlite3_column_int64(pStmt, 1); + break; + + case RBU_STATE_CKPT: + pRet->iWalCksum = sqlite3_column_int64(pStmt, 1); + break; + + case RBU_STATE_COOKIE: + pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1); + break; + + case RBU_STATE_OALSZ: + pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1); + break; + + case RBU_STATE_PHASEONESTEP: + pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1); + break; + + default: + rc = SQLITE_CORRUPT; + break; + } + } + rc2 = sqlite3_finalize(pStmt); + if( rc==SQLITE_OK ) rc = rc2; + + p->rc = rc; + return pRet; +} + + /* ** 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){ - assert( p->rc==SQLITE_OK ); - assert( p->dbMain==0 && p->dbRbu==0 ); + assert( p->rc || (p->dbMain==0 && p->dbRbu==0) ); + assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 ); - p->eStage = 0; - p->dbMain = rbuOpenDbhandle(p, p->zTarget); - p->dbRbu = rbuOpenDbhandle(p, p->zRbu); + /* Open the RBU database */ + p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1); + + if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ + sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); + if( p->zState==0 ){ + const char *zFile = sqlite3_db_filename(p->dbRbu, "main"); + p->zState = rbuMPrintf(p, "file://%s-vacuum?modeof=%s", zFile, zFile); + } + } /* If using separate RBU and state databases, attach the state database to ** the RBU db handle now. */ @@ -163676,6 +168662,96 @@ static void rbuOpenDatabase(sqlite3rbu *p){ memcpy(p->zStateDb, "main", 4); } +#if 0 + if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ + p->rc = sqlite3_exec(p->dbRbu, "BEGIN", 0, 0, 0); + } +#endif + + /* If it has not already been created, create the rbu_state table */ + rbuMPrintfExec(p, p->dbRbu, RBU_CREATE_STATE, p->zStateDb); + +#if 0 + if( rbuIsVacuum(p) ){ + if( p->rc==SQLITE_OK ){ + int rc2; + int bOk = 0; + sqlite3_stmt *pCnt = 0; + p->rc = prepareAndCollectError(p->dbRbu, &pCnt, &p->zErrmsg, + "SELECT count(*) FROM stat.sqlite_master" + ); + if( p->rc==SQLITE_OK + && sqlite3_step(pCnt)==SQLITE_ROW + && 1==sqlite3_column_int(pCnt, 0) + ){ + bOk = 1; + } + rc2 = sqlite3_finalize(pCnt); + if( p->rc==SQLITE_OK ) p->rc = rc2; + + if( p->rc==SQLITE_OK && bOk==0 ){ + p->rc = SQLITE_ERROR; + p->zErrmsg = sqlite3_mprintf("invalid state database"); + } + + if( p->rc==SQLITE_OK ){ + p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0); + } + } + } +#endif + + if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ + int bOpen = 0; + int rc; + p->nRbu = 0; + p->pRbuFd = 0; + rc = sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); + if( rc!=SQLITE_NOTFOUND ) p->rc = rc; + if( p->eStage>=RBU_STAGE_MOVE ){ + bOpen = 1; + }else{ + RbuState *pState = rbuLoadState(p); + if( pState ){ + bOpen = (pState->eStage>RBU_STAGE_MOVE); + rbuFreeState(pState); + } + } + if( bOpen ) p->dbMain = rbuOpenDbhandle(p, p->zRbu, p->nRbu<=1); + } + + p->eStage = 0; + if( p->rc==SQLITE_OK && p->dbMain==0 ){ + if( !rbuIsVacuum(p) ){ + p->dbMain = rbuOpenDbhandle(p, p->zTarget, 1); + }else if( p->pRbuFd->pWalFd ){ + p->rc = SQLITE_ERROR; + p->zErrmsg = sqlite3_mprintf("cannot vacuum wal mode database"); + }else{ + char *zTarget; + char *zExtra = 0; + if( strlen(p->zRbu)>=5 && 0==memcmp("file:", p->zRbu, 5) ){ + zExtra = &p->zRbu[5]; + while( *zExtra ){ + if( *zExtra++=='?' ) break; + } + if( *zExtra=='\0' ) zExtra = 0; + } + + zTarget = sqlite3_mprintf("file:%s-vacuum?rbu_memory=1%s%s", + sqlite3_db_filename(p->dbRbu, "main"), + (zExtra==0 ? "" : "&"), (zExtra==0 ? "" : zExtra) + ); + + if( zTarget==0 ){ + p->rc = SQLITE_NOMEM; + return; + } + p->dbMain = rbuOpenDbhandle(p, zTarget, p->nRbu<=1); + sqlite3_free(zTarget); + } + } + if( p->rc==SQLITE_OK ){ p->rc = sqlite3_create_function(p->dbMain, "rbu_tmp_insert", -1, SQLITE_UTF8, (void*)p, rbuTmpInsertFunc, 0, 0 @@ -163690,7 +168766,7 @@ static void rbuOpenDatabase(sqlite3rbu *p){ if( p->rc==SQLITE_OK ){ p->rc = sqlite3_create_function(p->dbRbu, - "rbu_target_name", 1, SQLITE_UTF8, (void*)p, rbuTargetNameFunc, 0, 0 + "rbu_target_name", -1, SQLITE_UTF8, (void*)p, rbuTargetNameFunc, 0, 0 ); } @@ -163739,9 +168815,9 @@ static void rbuFileSuffix3(const char *zBase, char *z){ #endif { int i, sz; - sz = sqlite3Strlen30(z); + sz = (int)strlen(z)&0xffffff; for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} - if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4); + if( z[i]=='.' && sz>i+4 ) memmove(&z[i+1], &z[sz-3], 4); } #endif } @@ -163949,9 +169025,15 @@ static LPWSTR rbuWinUtf8ToUnicode(const char *zFilename){ */ static void rbuMoveOalFile(sqlite3rbu *p){ const char *zBase = sqlite3_db_filename(p->dbMain, "main"); + const char *zMove = zBase; + char *zOal; + char *zWal; - char *zWal = sqlite3_mprintf("%s-wal", zBase); - char *zOal = sqlite3_mprintf("%s-oal", zBase); + if( rbuIsVacuum(p) ){ + zMove = sqlite3_db_filename(p->dbRbu, "main"); + } + zOal = sqlite3_mprintf("%s-oal", zMove); + zWal = sqlite3_mprintf("%s-wal", zMove); assert( p->eStage==RBU_STAGE_MOVE ); assert( p->rc==SQLITE_OK && p->zErrmsg==0 ); @@ -163972,8 +169054,8 @@ static void rbuMoveOalFile(sqlite3rbu *p){ /* Re-open the databases. */ rbuObjIterFinalize(&p->objiter); - sqlite3_close(p->dbMain); sqlite3_close(p->dbRbu); + sqlite3_close(p->dbMain); p->dbMain = 0; p->dbRbu = 0; @@ -164135,19 +169217,24 @@ static void rbuStepOneOp(sqlite3rbu *p, int eType){ p->rc = sqlite3_bind_value(pWriter, i+1, pVal); if( p->rc ) return; } - if( pIter->zIdx==0 - && (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) - ){ - /* For a virtual table, or a table with no primary key, the - ** SELECT statement is: - ** - ** SELECT , rbu_control, rbu_rowid FROM .... - ** - ** Hence column_value(pIter->nCol+1). - */ - assertColumnName(pIter->pSelect, pIter->nCol+1, "rbu_rowid"); - pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); - p->rc = sqlite3_bind_value(pWriter, pIter->nCol+1, pVal); + if( pIter->zIdx==0 ){ + if( pIter->eType==RBU_PK_VTAB + || pIter->eType==RBU_PK_NONE + || (pIter->eType==RBU_PK_EXTERNAL && rbuIsVacuum(p)) + ){ + /* For a virtual table, or a table with no primary key, the + ** SELECT statement is: + ** + ** SELECT , rbu_control, rbu_rowid FROM .... + ** + ** Hence column_value(pIter->nCol+1). + */ + assertColumnName(pIter->pSelect, pIter->nCol+1, + rbuIsVacuum(p) ? "rowid" : "rbu_rowid" + ); + pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); + p->rc = sqlite3_bind_value(pWriter, pIter->nCol+1, pVal); + } } if( p->rc==SQLITE_OK ){ sqlite3_step(pWriter); @@ -164226,13 +169313,18 @@ static int rbuStep(sqlite3rbu *p){ /* ** Increment the schema cookie of the main database opened by p->dbMain. +** +** Or, if this is an RBU vacuum, set the schema cookie of the main db +** opened by p->dbMain to one more than the schema cookie of the main +** db opened by p->dbRbu. */ static void rbuIncrSchemaCookie(sqlite3rbu *p){ if( p->rc==SQLITE_OK ){ + sqlite3 *dbread = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain); int iCookie = 1000000; sqlite3_stmt *pStmt; - p->rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, + p->rc = prepareAndCollectError(dbread, &pStmt, &p->zErrmsg, "PRAGMA schema_version" ); if( p->rc==SQLITE_OK ){ @@ -164260,6 +169352,7 @@ static void rbuIncrSchemaCookie(sqlite3rbu *p){ static void rbuSaveState(sqlite3rbu *p, int eStage){ if( p->rc==SQLITE_OK || p->rc==SQLITE_DONE ){ sqlite3_stmt *pInsert = 0; + rbu_file *pFd = (rbuIsVacuum(p) ? p->pRbuFd : p->pTargetFd); int rc; assert( p->zErrmsg==0 ); @@ -164282,7 +169375,7 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){ RBU_STATE_ROW, p->nStep, RBU_STATE_PROGRESS, p->nProgress, RBU_STATE_CKPT, p->iWalCksum, - RBU_STATE_COOKIE, (i64)p->pTargetFd->iCookie, + RBU_STATE_COOKIE, (i64)pFd->iCookie, RBU_STATE_OALSZ, p->iOalSz, RBU_STATE_PHASEONESTEP, p->nPhaseOneStep ) @@ -164298,21 +169391,116 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){ } +/* +** The second argument passed to this function is the name of a PRAGMA +** setting - "page_size", "auto_vacuum", "user_version" or "application_id". +** This function executes the following on sqlite3rbu.dbRbu: +** +** "PRAGMA main.$zPragma" +** +** where $zPragma is the string passed as the second argument, then +** on sqlite3rbu.dbMain: +** +** "PRAGMA main.$zPragma = $val" +** +** where $val is the value returned by the first PRAGMA invocation. +** +** In short, it copies the value of the specified PRAGMA setting from +** dbRbu to dbMain. +*/ +static void rbuCopyPragma(sqlite3rbu *p, const char *zPragma){ + if( p->rc==SQLITE_OK ){ + sqlite3_stmt *pPragma = 0; + p->rc = prepareFreeAndCollectError(p->dbRbu, &pPragma, &p->zErrmsg, + sqlite3_mprintf("PRAGMA main.%s", zPragma) + ); + if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPragma) ){ + p->rc = rbuMPrintfExec(p, p->dbMain, "PRAGMA main.%s = %d", + zPragma, sqlite3_column_int(pPragma, 0) + ); + } + rbuFinalize(p, pPragma); + } +} + +/* +** The RBU handle passed as the only argument has just been opened and +** the state database is empty. If this RBU handle was opened for an +** RBU vacuum operation, create the schema in the target db. +*/ +static void rbuCreateTargetSchema(sqlite3rbu *p){ + sqlite3_stmt *pSql = 0; + sqlite3_stmt *pInsert = 0; + + assert( rbuIsVacuum(p) ); + p->rc = sqlite3_exec(p->dbMain, "PRAGMA writable_schema=1", 0,0, &p->zErrmsg); + if( p->rc==SQLITE_OK ){ + p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg, + "SELECT sql FROM sqlite_master WHERE sql!='' AND rootpage!=0" + " AND name!='sqlite_sequence' " + " ORDER BY type DESC" + ); + } + + while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){ + const char *zSql = (const char*)sqlite3_column_text(pSql, 0); + p->rc = sqlite3_exec(p->dbMain, zSql, 0, 0, &p->zErrmsg); + } + rbuFinalize(p, pSql); + if( p->rc!=SQLITE_OK ) return; + + if( p->rc==SQLITE_OK ){ + p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg, + "SELECT * FROM sqlite_master WHERE rootpage=0 OR rootpage IS NULL" + ); + } + + if( p->rc==SQLITE_OK ){ + p->rc = prepareAndCollectError(p->dbMain, &pInsert, &p->zErrmsg, + "INSERT INTO sqlite_master VALUES(?,?,?,?,?)" + ); + } + + while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){ + int i; + for(i=0; i<5; i++){ + sqlite3_bind_value(pInsert, i+1, sqlite3_column_value(pSql, i)); + } + sqlite3_step(pInsert); + p->rc = sqlite3_reset(pInsert); + } + if( p->rc==SQLITE_OK ){ + p->rc = sqlite3_exec(p->dbMain, "PRAGMA writable_schema=0",0,0,&p->zErrmsg); + } + + rbuFinalize(p, pSql); + rbuFinalize(p, pInsert); +} + /* ** Step the RBU object. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_step(sqlite3rbu *p){ +SQLITE_API int sqlite3rbu_step(sqlite3rbu *p){ if( p ){ switch( p->eStage ){ case RBU_STAGE_OAL: { RbuObjIter *pIter = &p->objiter; + + /* If this is an RBU vacuum operation and the state table was empty + ** when this handle was opened, create the target database schema. */ + if( rbuIsVacuum(p) && p->nProgress==0 && p->rc==SQLITE_OK ){ + rbuCreateTargetSchema(p); + rbuCopyPragma(p, "user_version"); + rbuCopyPragma(p, "application_id"); + } + while( p->rc==SQLITE_OK && pIter->zTbl ){ if( pIter->bCleanup ){ /* Clean up the rbu_tmp_xxx table for the previous table. It ** cannot be dropped as there are currently active SQL statements. ** But the contents can be deleted. */ - if( pIter->abIndexed ){ + if( rbuIsVacuum(p)==0 && pIter->abIndexed ){ rbuMPrintfExec(p, p->dbRbu, "DELETE FROM %s.'rbu_tmp_%q'", p->zStateDb, pIter->zDataTbl ); @@ -164399,94 +169587,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_step(sqlite3rbu *p){ } } -/* -** Free an RbuState object allocated by rbuLoadState(). -*/ -static void rbuFreeState(RbuState *p){ - if( p ){ - sqlite3_free(p->zTbl); - sqlite3_free(p->zIdx); - sqlite3_free(p); - } -} - -/* -** Allocate an RbuState object and load the contents of the rbu_state -** table into it. Return a pointer to the new object. It is the -** responsibility of the caller to eventually free the object using -** sqlite3_free(). -** -** If an error occurs, leave an error code and message in the rbu handle -** and return NULL. -*/ -static RbuState *rbuLoadState(sqlite3rbu *p){ - RbuState *pRet = 0; - sqlite3_stmt *pStmt = 0; - int rc; - int rc2; - - pRet = (RbuState*)rbuMalloc(p, sizeof(RbuState)); - if( pRet==0 ) return 0; - - rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, - sqlite3_mprintf("SELECT k, v FROM %s.rbu_state", p->zStateDb) - ); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - switch( sqlite3_column_int(pStmt, 0) ){ - case RBU_STATE_STAGE: - pRet->eStage = sqlite3_column_int(pStmt, 1); - if( pRet->eStage!=RBU_STAGE_OAL - && pRet->eStage!=RBU_STAGE_MOVE - && pRet->eStage!=RBU_STAGE_CKPT - ){ - p->rc = SQLITE_CORRUPT; - } - break; - - case RBU_STATE_TBL: - pRet->zTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); - break; - - case RBU_STATE_IDX: - pRet->zIdx = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); - break; - - case RBU_STATE_ROW: - pRet->nRow = sqlite3_column_int(pStmt, 1); - break; - - case RBU_STATE_PROGRESS: - pRet->nProgress = sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_CKPT: - pRet->iWalCksum = sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_COOKIE: - pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_OALSZ: - pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_PHASEONESTEP: - pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1); - break; - - default: - rc = SQLITE_CORRUPT; - break; - } - } - rc2 = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ) rc = rc2; - - p->rc = rc; - return pRet; -} - /* ** Compare strings z1 and z2, returning 0 if they are identical, or non-zero ** otherwise. Either or both argument may be NULL. Two NULL values are @@ -164676,19 +169776,16 @@ static void rbuInitPhaseOneSteps(sqlite3rbu *p){ } } -/* -** Open and return a new RBU handle. -*/ -SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( + +static sqlite3rbu *openRbuHandle( const char *zTarget, const char *zRbu, const char *zState ){ sqlite3rbu *p; - size_t nTarget = strlen(zTarget); + size_t nTarget = zTarget ? strlen(zTarget) : 0; size_t nRbu = strlen(zRbu); - size_t nState = zState ? strlen(zState) : 0; - size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1+ nState+1; + size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1; p = (sqlite3rbu*)sqlite3_malloc64(nByte); if( p ){ @@ -164698,22 +169795,23 @@ SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( memset(p, 0, sizeof(sqlite3rbu)); rbuCreateVfs(p); - /* Open the target database */ + /* Open the target, RBU and state databases */ if( p->rc==SQLITE_OK ){ - p->zTarget = (char*)&p[1]; - memcpy(p->zTarget, zTarget, nTarget+1); - p->zRbu = &p->zTarget[nTarget+1]; + char *pCsr = (char*)&p[1]; + if( zTarget ){ + p->zTarget = pCsr; + memcpy(p->zTarget, zTarget, nTarget+1); + pCsr += nTarget+1; + } + p->zRbu = pCsr; memcpy(p->zRbu, zRbu, nRbu+1); + pCsr += nRbu+1; if( zState ){ - p->zState = &p->zRbu[nRbu+1]; - memcpy(p->zState, zState, nState+1); + p->zState = rbuMPrintf(p, "%s", zState); } rbuOpenDatabase(p); } - /* If it has not already been created, create the rbu_state table */ - rbuMPrintfExec(p, p->dbRbu, RBU_CREATE_STATE, p->zStateDb); - if( p->rc==SQLITE_OK ){ pState = rbuLoadState(p); assert( pState || p->rc!=SQLITE_OK ); @@ -164743,38 +169841,27 @@ SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( } } - if( p->rc==SQLITE_OK + if( p->rc==SQLITE_OK && (p->eStage==RBU_STAGE_OAL || p->eStage==RBU_STAGE_MOVE) - && pState->eStage!=0 && p->pTargetFd->iCookie!=pState->iCookie - ){ - /* At this point (pTargetFd->iCookie) contains the value of the - ** change-counter cookie (the thing that gets incremented when a - ** transaction is committed in rollback mode) currently stored on - ** page 1 of the database file. */ - p->rc = SQLITE_BUSY; - p->zErrmsg = sqlite3_mprintf("database modified during rbu update"); + && pState->eStage!=0 + ){ + rbu_file *pFd = (rbuIsVacuum(p) ? p->pRbuFd : p->pTargetFd); + if( pFd->iCookie!=pState->iCookie ){ + /* At this point (pTargetFd->iCookie) contains the value of the + ** change-counter cookie (the thing that gets incremented when a + ** transaction is committed in rollback mode) currently stored on + ** page 1 of the database file. */ + p->rc = SQLITE_BUSY; + p->zErrmsg = sqlite3_mprintf("database modified during rbu %s", + (rbuIsVacuum(p) ? "vacuum" : "update") + ); + } } if( p->rc==SQLITE_OK ){ if( p->eStage==RBU_STAGE_OAL ){ sqlite3 *db = p->dbMain; - - /* Open transactions both databases. The *-oal file is opened or - ** created at this point. */ - p->rc = sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_exec(p->dbRbu, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); - } - - /* Check if the main database is a zipvfs db. If it is, set the upper - ** level pager to use "journal_mode=off". This prevents it from - ** generating a large journal using a temp file. */ - if( p->rc==SQLITE_OK ){ - int frc = sqlite3_file_control(db, "main", SQLITE_FCNTL_ZIPVFS, 0); - if( frc==SQLITE_OK ){ - p->rc = sqlite3_exec(db, "PRAGMA journal_mode=off",0,0,&p->zErrmsg); - } - } + p->rc = sqlite3_exec(p->dbRbu, "BEGIN", 0, 0, &p->zErrmsg); /* Point the object iterator at the first object */ if( p->rc==SQLITE_OK ){ @@ -164785,12 +169872,34 @@ SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( ** update finished. */ if( p->rc==SQLITE_OK && p->objiter.zTbl==0 ){ p->rc = SQLITE_DONE; - } + p->eStage = RBU_STAGE_DONE; + }else{ + if( p->rc==SQLITE_OK && pState->eStage==0 && rbuIsVacuum(p) ){ + rbuCopyPragma(p, "page_size"); + rbuCopyPragma(p, "auto_vacuum"); + } - if( p->rc==SQLITE_OK ){ - rbuSetupOal(p, pState); - } + /* Open transactions both databases. The *-oal file is opened or + ** created at this point. */ + if( p->rc==SQLITE_OK ){ + p->rc = sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); + } + + /* Check if the main database is a zipvfs db. If it is, set the upper + ** level pager to use "journal_mode=off". This prevents it from + ** generating a large journal using a temp file. */ + if( p->rc==SQLITE_OK ){ + int frc = sqlite3_file_control(db, "main", SQLITE_FCNTL_ZIPVFS, 0); + if( frc==SQLITE_OK ){ + p->rc = sqlite3_exec( + db, "PRAGMA journal_mode=off",0,0,&p->zErrmsg); + } + } + if( p->rc==SQLITE_OK ){ + rbuSetupOal(p, pState); + } + } }else if( p->eStage==RBU_STAGE_MOVE ){ /* no-op */ }else if( p->eStage==RBU_STAGE_CKPT ){ @@ -164808,11 +169917,49 @@ SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( return p; } +/* +** Allocate and return an RBU handle with all fields zeroed except for the +** error code, which is set to SQLITE_MISUSE. +*/ +static sqlite3rbu *rbuMisuseError(void){ + sqlite3rbu *pRet; + pRet = sqlite3_malloc64(sizeof(sqlite3rbu)); + if( pRet ){ + memset(pRet, 0, sizeof(sqlite3rbu)); + pRet->rc = SQLITE_MISUSE; + } + return pRet; +} + +/* +** Open and return a new RBU handle. +*/ +SQLITE_API sqlite3rbu *sqlite3rbu_open( + const char *zTarget, + const char *zRbu, + const char *zState +){ + if( zTarget==0 || zRbu==0 ){ return rbuMisuseError(); } + /* TODO: Check that zTarget and zRbu are non-NULL */ + return openRbuHandle(zTarget, zRbu, zState); +} + +/* +** Open a handle to begin or resume an RBU VACUUM operation. +*/ +SQLITE_API sqlite3rbu *sqlite3rbu_vacuum( + const char *zTarget, + const char *zState +){ + if( zTarget==0 ){ return rbuMisuseError(); } + /* TODO: Check that both arguments are non-NULL */ + return openRbuHandle(0, zTarget, zState); +} /* ** Return the database handle used by pRbu. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3rbu_db(sqlite3rbu *pRbu, int bRbu){ +SQLITE_API sqlite3 *sqlite3rbu_db(sqlite3rbu *pRbu, int bRbu){ sqlite3 *db = 0; if( pRbu ){ db = (bRbu ? pRbu->dbRbu : pRbu->dbMain); @@ -164828,7 +169975,7 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3rbu_db(sqlite3rbu *pRbu, int bRbu){ */ static void rbuEditErrmsg(sqlite3rbu *p){ if( p->rc==SQLITE_CONSTRAINT && p->zErrmsg ){ - int i; + unsigned int i; size_t nErrmsg = strlen(p->zErrmsg); for(i=0; i<(nErrmsg-8); i++){ if( memcmp(&p->zErrmsg[i], "rbu_imp_", 8)==0 ){ @@ -164844,7 +169991,7 @@ static void rbuEditErrmsg(sqlite3rbu *p){ /* ** Close the RBU handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){ +SQLITE_API int sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){ int rc; if( p ){ @@ -164862,9 +170009,19 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){ /* Close any open statement handles. */ rbuObjIterFinalize(&p->objiter); + /* If this is an RBU vacuum handle and the vacuum has either finished + ** successfully or encountered an error, delete the contents of the + ** state table. This causes the next call to sqlite3rbu_vacuum() + ** specifying the current target and state databases to start a new + ** vacuum from scratch. */ + if( rbuIsVacuum(p) && p->rc!=SQLITE_OK && p->dbRbu ){ + int rc2 = sqlite3_exec(p->dbRbu, "DELETE FROM stat.rbu_state", 0, 0, 0); + if( p->rc==SQLITE_DONE && rc2!=SQLITE_OK ) p->rc = rc2; + } + /* Close the open database handle and VFS object. */ - sqlite3_close(p->dbMain); sqlite3_close(p->dbRbu); + sqlite3_close(p->dbMain); rbuDeleteVfs(p); sqlite3_free(p->aBuf); sqlite3_free(p->aFrame); @@ -164872,6 +170029,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){ rbuEditErrmsg(p); rc = p->rc; *pzErrmsg = p->zErrmsg; + sqlite3_free(p->zState); sqlite3_free(p); }else{ rc = SQLITE_NOMEM; @@ -164885,7 +170043,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){ ** updates) that have been performed on the target database since the ** current RBU update was started. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3rbu_progress(sqlite3rbu *pRbu){ +SQLITE_API sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu){ return pRbu->nProgress; } @@ -164893,7 +170051,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3rbu_progress(sqlite3rbu *pRbu){ ** Return permyriadage progress indications for the two main stages of ** an RBU update. */ -SQLITE_API void SQLITE_STDCALL sqlite3rbu_bp_progress(sqlite3rbu *p, int *pnOne, int *pnTwo){ +SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *p, int *pnOne, int *pnTwo){ const int MAX_PROGRESS = 10000; switch( p->eStage ){ case RBU_STAGE_OAL: @@ -164925,9 +170083,39 @@ SQLITE_API void SQLITE_STDCALL sqlite3rbu_bp_progress(sqlite3rbu *p, int *pnOne, } } -SQLITE_API int SQLITE_STDCALL sqlite3rbu_savestate(sqlite3rbu *p){ +/* +** Return the current state of the RBU vacuum or update operation. +*/ +SQLITE_API int sqlite3rbu_state(sqlite3rbu *p){ + int aRes[] = { + 0, SQLITE_RBU_STATE_OAL, SQLITE_RBU_STATE_MOVE, + 0, SQLITE_RBU_STATE_CHECKPOINT, SQLITE_RBU_STATE_DONE + }; + + assert( RBU_STAGE_OAL==1 ); + assert( RBU_STAGE_MOVE==2 ); + assert( RBU_STAGE_CKPT==4 ); + assert( RBU_STAGE_DONE==5 ); + assert( aRes[RBU_STAGE_OAL]==SQLITE_RBU_STATE_OAL ); + assert( aRes[RBU_STAGE_MOVE]==SQLITE_RBU_STATE_MOVE ); + assert( aRes[RBU_STAGE_CKPT]==SQLITE_RBU_STATE_CHECKPOINT ); + assert( aRes[RBU_STAGE_DONE]==SQLITE_RBU_STATE_DONE ); + + if( p->rc!=SQLITE_OK && p->rc!=SQLITE_DONE ){ + return SQLITE_RBU_STATE_ERROR; + }else{ + assert( p->rc!=SQLITE_DONE || p->eStage==RBU_STAGE_DONE ); + assert( p->eStage==RBU_STAGE_OAL + || p->eStage==RBU_STAGE_MOVE + || p->eStage==RBU_STAGE_CKPT + || p->eStage==RBU_STAGE_DONE + ); + return aRes[p->eStage]; + } +} + +SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *p){ int rc = p->rc; - if( rc==SQLITE_DONE ) return SQLITE_OK; assert( p->eStage>=RBU_STAGE_OAL && p->eStage<=RBU_STAGE_DONE ); @@ -165066,6 +170254,22 @@ static u32 rbuGetU32(u8 *aBuf){ + ((u32)aBuf[3]); } +/* +** Write an unsigned 32-bit value in big-endian format to the supplied +** buffer. +*/ +static void rbuPutU32(u8 *aBuf, u32 iVal){ + aBuf[0] = (iVal >> 24) & 0xFF; + aBuf[1] = (iVal >> 16) & 0xFF; + aBuf[2] = (iVal >> 8) & 0xFF; + aBuf[3] = (iVal >> 0) & 0xFF; +} + +static void rbuPutU16(u8 *aBuf, u16 iVal){ + aBuf[0] = (iVal >> 8) & 0xFF; + aBuf[1] = (iVal >> 0) & 0xFF; +} + /* ** Read data from an rbuVfs-file. */ @@ -165091,6 +170295,35 @@ static int rbuVfsRead( memset(zBuf, 0, iAmt); }else{ rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); +#if 1 + /* If this is being called to read the first page of the target + ** database as part of an rbu vacuum operation, synthesize the + ** contents of the first page if it does not yet exist. Otherwise, + ** SQLite will not check for a *-wal file. */ + if( pRbu && rbuIsVacuum(pRbu) + && rc==SQLITE_IOERR_SHORT_READ && iOfst==0 + && (p->openFlags & SQLITE_OPEN_MAIN_DB) + && pRbu->rc==SQLITE_OK + ){ + sqlite3_file *pFd = (sqlite3_file*)pRbu->pRbuFd; + rc = pFd->pMethods->xRead(pFd, zBuf, iAmt, iOfst); + if( rc==SQLITE_OK ){ + u8 *aBuf = (u8*)zBuf; + u32 iRoot = rbuGetU32(&aBuf[52]) ? 1 : 0; + rbuPutU32(&aBuf[52], iRoot); /* largest root page number */ + rbuPutU32(&aBuf[36], 0); /* number of free pages */ + rbuPutU32(&aBuf[32], 0); /* first page on free list trunk */ + rbuPutU32(&aBuf[28], 1); /* size of db file in pages */ + rbuPutU32(&aBuf[24], pRbu->pRbuFd->iCookie+1); /* Change counter */ + + if( iAmt>100 ){ + memset(&aBuf[100], 0, iAmt-100); + rbuPutU16(&aBuf[105], iAmt & 0xFFFF); + aBuf[100] = 0x0D; + } + } + } +#endif } if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){ /* These look like magic numbers. But they are stable, as they are part @@ -165165,7 +170398,20 @@ static int rbuVfsSync(sqlite3_file *pFile, int flags){ */ static int rbuVfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ rbu_file *p = (rbu_file *)pFile; - return p->pReal->pMethods->xFileSize(p->pReal, pSize); + int rc; + rc = p->pReal->pMethods->xFileSize(p->pReal, pSize); + + /* If this is an RBU vacuum operation and this is the target database, + ** pretend that it has at least one page. Otherwise, SQLite will not + ** check for the existance of a *-wal file. rbuVfsRead() contains + ** similar logic. */ + if( rc==SQLITE_OK && *pSize==0 + && p->pRbu && rbuIsVacuum(p->pRbu) + && (p->openFlags & SQLITE_OPEN_MAIN_DB) + ){ + *pSize = 1024; + } + return rc; } /* @@ -165177,7 +170423,9 @@ static int rbuVfsLock(sqlite3_file *pFile, int eLock){ int rc = SQLITE_OK; assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); - if( pRbu && eLock==SQLITE_LOCK_EXCLUSIVE && pRbu->eStage!=RBU_STAGE_DONE ){ + if( eLock==SQLITE_LOCK_EXCLUSIVE + && (p->bNolock || (pRbu && pRbu->eStage!=RBU_STAGE_DONE)) + ){ /* Do not allow EXCLUSIVE locks. Preventing SQLite from taking this ** prevents it from checkpointing the database from sqlite3_close(). */ rc = SQLITE_BUSY; @@ -165240,6 +170488,12 @@ static int rbuVfsFileControl(sqlite3_file *pFile, int op, void *pArg){ } return rc; } + else if( op==SQLITE_FCNTL_RBUCNT ){ + sqlite3rbu *pRbu = (sqlite3rbu*)pArg; + pRbu->nRbu++; + pRbu->pRbuFd = p; + p->bNolock = 1; + } rc = xControl(p->pReal, op, pArg); if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){ @@ -165403,6 +170657,33 @@ static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){ return pDb; } +/* +** A main database named zName has just been opened. The following +** function returns a pointer to a buffer owned by SQLite that contains +** the name of the *-wal file this db connection will use. SQLite +** happens to pass a pointer to this buffer when using xAccess() +** or xOpen() to operate on the *-wal file. +*/ +static const char *rbuMainToWal(const char *zName, int flags){ + int n = (int)strlen(zName); + const char *z = &zName[n]; + if( flags & SQLITE_OPEN_URI ){ + int odd = 0; + while( 1 ){ + if( z[0]==0 ){ + odd = 1 - odd; + if( odd && z[1]==0 ) break; + } + z++; + } + z += 2; + }else{ + while( *z==0 ) z++; + } + z += (n + 8 + 1); + return z; +} + /* ** Open an rbu file handle. */ @@ -165438,6 +170719,7 @@ static int rbuVfsOpen( rbu_file *pFd = (rbu_file *)pFile; int rc = SQLITE_OK; const char *zOpen = zName; + int oflags = flags; memset(pFd, 0, sizeof(rbu_file)); pFd->pReal = (sqlite3_file*)&pFd[1]; @@ -165450,23 +170732,7 @@ static int rbuVfsOpen( ** the name of the *-wal file this db connection will use. SQLite ** happens to pass a pointer to this buffer when using xAccess() ** or xOpen() to operate on the *-wal file. */ - int n = (int)strlen(zName); - const char *z = &zName[n]; - if( flags & SQLITE_OPEN_URI ){ - int odd = 0; - while( 1 ){ - if( z[0]==0 ){ - odd = 1 - odd; - if( odd && z[1]==0 ) break; - } - z++; - } - z += 2; - }else{ - while( *z==0 ) z++; - } - z += (n + 8 + 1); - pFd->zWal = z; + pFd->zWal = rbuMainToWal(zName, flags); } else if( flags & SQLITE_OPEN_WAL ){ rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName); @@ -165476,10 +170742,17 @@ static int rbuVfsOpen( ** code ensures that the string passed to xOpen() is terminated by a ** pair of '\0' bytes in case the VFS attempts to extract a URI ** parameter from it. */ - size_t nCopy = strlen(zName); - char *zCopy = sqlite3_malloc64(nCopy+2); + const char *zBase = zName; + size_t nCopy; + char *zCopy; + if( rbuIsVacuum(pDb->pRbu) ){ + zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main"); + zBase = rbuMainToWal(zBase, SQLITE_OPEN_URI); + } + nCopy = strlen(zBase); + zCopy = sqlite3_malloc64(nCopy+2); if( zCopy ){ - memcpy(zCopy, zName, nCopy); + memcpy(zCopy, zBase, nCopy); zCopy[nCopy-3] = 'o'; zCopy[nCopy] = '\0'; zCopy[nCopy+1] = '\0'; @@ -165494,8 +170767,17 @@ static int rbuVfsOpen( } } + if( oflags & SQLITE_OPEN_MAIN_DB + && sqlite3_uri_boolean(zName, "rbu_memory", 0) + ){ + assert( oflags & SQLITE_OPEN_MAIN_DB ); + oflags = SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | + SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE; + zOpen = 0; + } + if( rc==SQLITE_OK ){ - rc = pRealVfs->xOpen(pRealVfs, zOpen, pFd->pReal, flags, pOutFlags); + rc = pRealVfs->xOpen(pRealVfs, zOpen, pFd->pReal, oflags, pOutFlags); } if( pFd->pReal->pMethods ){ /* The xOpen() operation has succeeded. Set the sqlite3_file.pMethods @@ -165659,7 +170941,7 @@ static int rbuVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){ ** Deregister and destroy an RBU vfs created by an earlier call to ** sqlite3rbu_create_vfs(). */ -SQLITE_API void SQLITE_STDCALL sqlite3rbu_destroy_vfs(const char *zName){ +SQLITE_API void sqlite3rbu_destroy_vfs(const char *zName){ sqlite3_vfs *pVfs = sqlite3_vfs_find(zName); if( pVfs && pVfs->xOpen==rbuVfsOpen ){ sqlite3_mutex_free(((rbu_vfs*)pVfs)->mutex); @@ -165673,7 +170955,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3rbu_destroy_vfs(const char *zName){ ** via existing VFS zParent. The new object is registered as a non-default ** VFS with SQLite before returning. */ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_create_vfs(const char *zName, const char *zParent){ +SQLITE_API int sqlite3rbu_create_vfs(const char *zName, const char *zParent){ /* Template for VFS */ static sqlite3_vfs vfs_template = { @@ -165815,10 +171097,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3rbu_create_vfs(const char *zName, const cha */ #define VTAB_SCHEMA \ "CREATE TABLE xx( " \ - " name STRING, /* Name of table or index */" \ - " path INTEGER, /* Path to page from root */" \ + " name TEXT, /* Name of table or index */" \ + " path TEXT, /* Path to page from root */" \ " pageno INTEGER, /* Page number */" \ - " pagetype STRING, /* 'internal', 'leaf' or 'overflow' */" \ + " pagetype TEXT, /* 'internal', 'leaf' or 'overflow' */" \ " ncell INTEGER, /* Cells on page (0 for overflow) */" \ " payload INTEGER, /* Bytes of payload on this page */" \ " unused INTEGER, /* Bytes of unused space on this page */" \ @@ -166359,7 +171641,7 @@ static int statFilter( " UNION ALL " "SELECT name, rootpage, type" " FROM \"%w\".%s WHERE rootpage!=0" - " ORDER BY name", pTab->db->aDb[pCsr->iDb].zName, zMaster); + " ORDER BY name", pTab->db->aDb[pCsr->iDb].zDbSName, zMaster); if( zSql==0 ){ return SQLITE_NOMEM_BKPT; }else{ @@ -166413,7 +171695,7 @@ static int statColumn( default: { /* schema */ sqlite3 *db = sqlite3_context_db_handle(ctx); int iDb = pCsr->iDb; - sqlite3_result_text(ctx, db->aDb[iDb].zName, -1, SQLITE_STATIC); + sqlite3_result_text(ctx, db->aDb[iDb].zDbSName, -1, SQLITE_STATIC); break; } } @@ -166459,6 +171741,4650 @@ SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3 *db){ return SQLITE_OK; } #endif /* SQLITE_ENABLE_DBSTAT_VTAB */ /************** End of dbstat.c **********************************************/ +/************** Begin file sqlite3session.c **********************************/ + +#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK) +/* #include "sqlite3session.h" */ +/* #include */ +/* #include */ + +#ifndef SQLITE_AMALGAMATION +/* # include "sqliteInt.h" */ +/* # include "vdbeInt.h" */ +#endif + +typedef struct SessionTable SessionTable; +typedef struct SessionChange SessionChange; +typedef struct SessionBuffer SessionBuffer; +typedef struct SessionInput SessionInput; + +/* +** Minimum chunk size used by streaming versions of functions. +*/ +#ifndef SESSIONS_STRM_CHUNK_SIZE +# ifdef SQLITE_TEST +# define SESSIONS_STRM_CHUNK_SIZE 64 +# else +# define SESSIONS_STRM_CHUNK_SIZE 1024 +# endif +#endif + +typedef struct SessionHook SessionHook; +struct SessionHook { + void *pCtx; + int (*xOld)(void*,int,sqlite3_value**); + int (*xNew)(void*,int,sqlite3_value**); + int (*xCount)(void*); + int (*xDepth)(void*); +}; + +/* +** Session handle structure. +*/ +struct sqlite3_session { + sqlite3 *db; /* Database handle session is attached to */ + char *zDb; /* Name of database session is attached to */ + int bEnable; /* True if currently recording */ + int bIndirect; /* True if all changes are indirect */ + int bAutoAttach; /* True to auto-attach tables */ + int rc; /* Non-zero if an error has occurred */ + void *pFilterCtx; /* First argument to pass to xTableFilter */ + int (*xTableFilter)(void *pCtx, const char *zTab); + sqlite3_session *pNext; /* Next session object on same db. */ + SessionTable *pTable; /* List of attached tables */ + SessionHook hook; /* APIs to grab new and old data with */ +}; + +/* +** Instances of this structure are used to build strings or binary records. +*/ +struct SessionBuffer { + u8 *aBuf; /* Pointer to changeset buffer */ + int nBuf; /* Size of buffer aBuf */ + int nAlloc; /* Size of allocation containing aBuf */ +}; + +/* +** An object of this type is used internally as an abstraction for +** input data. Input data may be supplied either as a single large buffer +** (e.g. sqlite3changeset_start()) or using a stream function (e.g. +** sqlite3changeset_start_strm()). +*/ +struct SessionInput { + int bNoDiscard; /* If true, discard no data */ + int iCurrent; /* Offset in aData[] of current change */ + int iNext; /* Offset in aData[] of next change */ + u8 *aData; /* Pointer to buffer containing changeset */ + int nData; /* Number of bytes in aData */ + + SessionBuffer buf; /* Current read buffer */ + int (*xInput)(void*, void*, int*); /* Input stream call (or NULL) */ + void *pIn; /* First argument to xInput */ + int bEof; /* Set to true after xInput finished */ +}; + +/* +** Structure for changeset iterators. +*/ +struct sqlite3_changeset_iter { + SessionInput in; /* Input buffer or stream */ + SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */ + int bPatchset; /* True if this is a patchset */ + int rc; /* Iterator error code */ + sqlite3_stmt *pConflict; /* Points to conflicting row, if any */ + char *zTab; /* Current table */ + int nCol; /* Number of columns in zTab */ + int op; /* Current operation */ + int bIndirect; /* True if current change was indirect */ + u8 *abPK; /* Primary key array */ + sqlite3_value **apValue; /* old.* and new.* values */ +}; + +/* +** Each session object maintains a set of the following structures, one +** for each table the session object is monitoring. The structures are +** stored in a linked list starting at sqlite3_session.pTable. +** +** The keys of the SessionTable.aChange[] hash table are all rows that have +** been modified in any way since the session object was attached to the +** table. +** +** The data associated with each hash-table entry is a structure containing +** a subset of the initial values that the modified row contained at the +** start of the session. Or no initial values if the row was inserted. +*/ +struct SessionTable { + SessionTable *pNext; + char *zName; /* Local name of table */ + int nCol; /* Number of columns in table zName */ + const char **azCol; /* Column names */ + u8 *abPK; /* Array of primary key flags */ + int nEntry; /* Total number of entries in hash table */ + int nChange; /* Size of apChange[] array */ + SessionChange **apChange; /* Hash table buckets */ +}; + +/* +** RECORD FORMAT: +** +** The following record format is similar to (but not compatible with) that +** used in SQLite database files. This format is used as part of the +** change-set binary format, and so must be architecture independent. +** +** Unlike the SQLite database record format, each field is self-contained - +** there is no separation of header and data. Each field begins with a +** single byte describing its type, as follows: +** +** 0x00: Undefined value. +** 0x01: Integer value. +** 0x02: Real value. +** 0x03: Text value. +** 0x04: Blob value. +** 0x05: SQL NULL value. +** +** Note that the above match the definitions of SQLITE_INTEGER, SQLITE_TEXT +** and so on in sqlite3.h. For undefined and NULL values, the field consists +** only of the single type byte. For other types of values, the type byte +** is followed by: +** +** Text values: +** A varint containing the number of bytes in the value (encoded using +** UTF-8). Followed by a buffer containing the UTF-8 representation +** of the text value. There is no nul terminator. +** +** Blob values: +** A varint containing the number of bytes in the value, followed by +** a buffer containing the value itself. +** +** Integer values: +** An 8-byte big-endian integer value. +** +** Real values: +** An 8-byte big-endian IEEE 754-2008 real value. +** +** Varint values are encoded in the same way as varints in the SQLite +** record format. +** +** CHANGESET FORMAT: +** +** A changeset is a collection of DELETE, UPDATE and INSERT operations on +** one or more tables. Operations on a single table are grouped together, +** but may occur in any order (i.e. deletes, updates and inserts are all +** mixed together). +** +** Each group of changes begins with a table header: +** +** 1 byte: Constant 0x54 (capital 'T') +** Varint: Number of columns in the table. +** nCol bytes: 0x01 for PK columns, 0x00 otherwise. +** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. +** +** Followed by one or more changes to the table. +** +** 1 byte: Either SQLITE_INSERT (0x12), UPDATE (0x17) or DELETE (0x09). +** 1 byte: The "indirect-change" flag. +** old.* record: (delete and update only) +** new.* record: (insert and update only) +** +** The "old.*" and "new.*" records, if present, are N field records in the +** format described above under "RECORD FORMAT", where N is the number of +** columns in the table. The i'th field of each record is associated with +** the i'th column of the table, counting from left to right in the order +** in which columns were declared in the CREATE TABLE statement. +** +** The new.* record that is part of each INSERT change contains the values +** that make up the new row. Similarly, the old.* record that is part of each +** DELETE change contains the values that made up the row that was deleted +** from the database. In the changeset format, the records that are part +** of INSERT or DELETE changes never contain any undefined (type byte 0x00) +** fields. +** +** Within the old.* record associated with an UPDATE change, all fields +** associated with table columns that are not PRIMARY KEY columns and are +** not modified by the UPDATE change are set to "undefined". Other fields +** are set to the values that made up the row before the UPDATE that the +** change records took place. Within the new.* record, fields associated +** with table columns modified by the UPDATE change contain the new +** values. Fields associated with table columns that are not modified +** are set to "undefined". +** +** PATCHSET FORMAT: +** +** A patchset is also a collection of changes. It is similar to a changeset, +** but leaves undefined those fields that are not useful if no conflict +** resolution is required when applying the changeset. +** +** Each group of changes begins with a table header: +** +** 1 byte: Constant 0x50 (capital 'P') +** Varint: Number of columns in the table. +** nCol bytes: 0x01 for PK columns, 0x00 otherwise. +** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. +** +** Followed by one or more changes to the table. +** +** 1 byte: Either SQLITE_INSERT (0x12), UPDATE (0x17) or DELETE (0x09). +** 1 byte: The "indirect-change" flag. +** single record: (PK fields for DELETE, PK and modified fields for UPDATE, +** full record for INSERT). +** +** As in the changeset format, each field of the single record that is part +** of a patchset change is associated with the correspondingly positioned +** table column, counting from left to right within the CREATE TABLE +** statement. +** +** For a DELETE change, all fields within the record except those associated +** with PRIMARY KEY columns are set to "undefined". The PRIMARY KEY fields +** contain the values identifying the row to delete. +** +** For an UPDATE change, all fields except those associated with PRIMARY KEY +** columns and columns that are modified by the UPDATE are set to "undefined". +** PRIMARY KEY fields contain the values identifying the table row to update, +** and fields associated with modified columns contain the new column values. +** +** The records associated with INSERT changes are in the same format as for +** changesets. It is not possible for a record associated with an INSERT +** change to contain a field set to "undefined". +*/ + +/* +** For each row modified during a session, there exists a single instance of +** this structure stored in a SessionTable.aChange[] hash table. +*/ +struct SessionChange { + int op; /* One of UPDATE, DELETE, INSERT */ + int bIndirect; /* True if this change is "indirect" */ + int nRecord; /* Number of bytes in buffer aRecord[] */ + u8 *aRecord; /* Buffer containing old.* record */ + SessionChange *pNext; /* For hash-table collisions */ +}; + +/* +** Write a varint with value iVal into the buffer at aBuf. Return the +** number of bytes written. +*/ +static int sessionVarintPut(u8 *aBuf, int iVal){ + return putVarint32(aBuf, iVal); +} + +/* +** Return the number of bytes required to store value iVal as a varint. +*/ +static int sessionVarintLen(int iVal){ + return sqlite3VarintLen(iVal); +} + +/* +** Read a varint value from aBuf[] into *piVal. Return the number of +** bytes read. +*/ +static int sessionVarintGet(u8 *aBuf, int *piVal){ + return getVarint32(aBuf, *piVal); +} + +/* Load an unaligned and unsigned 32-bit integer */ +#define SESSION_UINT32(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) + +/* +** Read a 64-bit big-endian integer value from buffer aRec[]. Return +** the value read. +*/ +static sqlite3_int64 sessionGetI64(u8 *aRec){ + u64 x = SESSION_UINT32(aRec); + u32 y = SESSION_UINT32(aRec+4); + x = (x<<32) + y; + return (sqlite3_int64)x; +} + +/* +** Write a 64-bit big-endian integer value to the buffer aBuf[]. +*/ +static void sessionPutI64(u8 *aBuf, sqlite3_int64 i){ + aBuf[0] = (i>>56) & 0xFF; + aBuf[1] = (i>>48) & 0xFF; + aBuf[2] = (i>>40) & 0xFF; + aBuf[3] = (i>>32) & 0xFF; + aBuf[4] = (i>>24) & 0xFF; + aBuf[5] = (i>>16) & 0xFF; + aBuf[6] = (i>> 8) & 0xFF; + aBuf[7] = (i>> 0) & 0xFF; +} + +/* +** This function is used to serialize the contents of value pValue (see +** comment titled "RECORD FORMAT" above). +** +** If it is non-NULL, the serialized form of the value is written to +** buffer aBuf. *pnWrite is set to the number of bytes written before +** returning. Or, if aBuf is NULL, the only thing this function does is +** set *pnWrite. +** +** If no error occurs, SQLITE_OK is returned. Or, if an OOM error occurs +** within a call to sqlite3_value_text() (may fail if the db is utf-16)) +** SQLITE_NOMEM is returned. +*/ +static int sessionSerializeValue( + u8 *aBuf, /* If non-NULL, write serialized value here */ + sqlite3_value *pValue, /* Value to serialize */ + int *pnWrite /* IN/OUT: Increment by bytes written */ +){ + int nByte; /* Size of serialized value in bytes */ + + if( pValue ){ + int eType; /* Value type (SQLITE_NULL, TEXT etc.) */ + + eType = sqlite3_value_type(pValue); + if( aBuf ) aBuf[0] = eType; + + switch( eType ){ + case SQLITE_NULL: + nByte = 1; + break; + + case SQLITE_INTEGER: + case SQLITE_FLOAT: + if( aBuf ){ + /* TODO: SQLite does something special to deal with mixed-endian + ** floating point values (e.g. ARM7). This code probably should + ** too. */ + u64 i; + if( eType==SQLITE_INTEGER ){ + i = (u64)sqlite3_value_int64(pValue); + }else{ + double r; + assert( sizeof(double)==8 && sizeof(u64)==8 ); + r = sqlite3_value_double(pValue); + memcpy(&i, &r, 8); + } + sessionPutI64(&aBuf[1], i); + } + nByte = 9; + break; + + default: { + u8 *z; + int n; + int nVarint; + + assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); + if( eType==SQLITE_TEXT ){ + z = (u8 *)sqlite3_value_text(pValue); + }else{ + z = (u8 *)sqlite3_value_blob(pValue); + } + n = sqlite3_value_bytes(pValue); + if( z==0 && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM; + nVarint = sessionVarintLen(n); + + if( aBuf ){ + sessionVarintPut(&aBuf[1], n); + memcpy(&aBuf[nVarint + 1], eType==SQLITE_TEXT ? + sqlite3_value_text(pValue) : sqlite3_value_blob(pValue), n + ); + } + + nByte = 1 + nVarint + n; + break; + } + } + }else{ + nByte = 1; + if( aBuf ) aBuf[0] = '\0'; + } + + if( pnWrite ) *pnWrite += nByte; + return SQLITE_OK; +} + + +/* +** This macro is used to calculate hash key values for data structures. In +** order to use this macro, the entire data structure must be represented +** as a series of unsigned integers. In order to calculate a hash-key value +** for a data structure represented as three such integers, the macro may +** then be used as follows: +** +** int hash_key_value; +** hash_key_value = HASH_APPEND(0, ); +** hash_key_value = HASH_APPEND(hash_key_value, ); +** hash_key_value = HASH_APPEND(hash_key_value, ); +** +** In practice, the data structures this macro is used for are the primary +** key values of modified rows. +*/ +#define HASH_APPEND(hash, add) ((hash) << 3) ^ (hash) ^ (unsigned int)(add) + +/* +** Append the hash of the 64-bit integer passed as the second argument to the +** hash-key value passed as the first. Return the new hash-key value. +*/ +static unsigned int sessionHashAppendI64(unsigned int h, i64 i){ + h = HASH_APPEND(h, i & 0xFFFFFFFF); + return HASH_APPEND(h, (i>>32)&0xFFFFFFFF); +} + +/* +** Append the hash of the blob passed via the second and third arguments to +** the hash-key value passed as the first. Return the new hash-key value. +*/ +static unsigned int sessionHashAppendBlob(unsigned int h, int n, const u8 *z){ + int i; + for(i=0; inCol==pSession->hook.xCount(pSession->hook.pCtx) ); + for(i=0; inCol; i++){ + if( pTab->abPK[i] ){ + int rc; + int eType; + sqlite3_value *pVal; + + if( bNew ){ + rc = pSession->hook.xNew(pSession->hook.pCtx, i, &pVal); + }else{ + rc = pSession->hook.xOld(pSession->hook.pCtx, i, &pVal); + } + if( rc!=SQLITE_OK ) return rc; + + eType = sqlite3_value_type(pVal); + h = sessionHashAppendType(h, eType); + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + i64 iVal; + if( eType==SQLITE_INTEGER ){ + iVal = sqlite3_value_int64(pVal); + }else{ + double rVal = sqlite3_value_double(pVal); + assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); + memcpy(&iVal, &rVal, 8); + } + h = sessionHashAppendI64(h, iVal); + }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ + const u8 *z; + int n; + if( eType==SQLITE_TEXT ){ + z = (const u8 *)sqlite3_value_text(pVal); + }else{ + z = (const u8 *)sqlite3_value_blob(pVal); + } + n = sqlite3_value_bytes(pVal); + if( !z && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM; + h = sessionHashAppendBlob(h, n, z); + }else{ + assert( eType==SQLITE_NULL ); + *pbNullPK = 1; + } + } + } + + *piHash = (h % pTab->nChange); + return SQLITE_OK; +} + +/* +** The buffer that the argument points to contains a serialized SQL value. +** Return the number of bytes of space occupied by the value (including +** the type byte). +*/ +static int sessionSerialLen(u8 *a){ + int e = *a; + int n; + if( e==0 ) return 1; + if( e==SQLITE_NULL ) return 1; + if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; + return sessionVarintGet(&a[1], &n) + 1 + n; +} + +/* +** Based on the primary key values stored in change aRecord, calculate a +** hash key. Assume the has table has nBucket buckets. The hash keys +** calculated by this function are compatible with those calculated by +** sessionPreupdateHash(). +** +** The bPkOnly argument is non-zero if the record at aRecord[] is from +** a patchset DELETE. In this case the non-PK fields are omitted entirely. +*/ +static unsigned int sessionChangeHash( + SessionTable *pTab, /* Table handle */ + int bPkOnly, /* Record consists of PK fields only */ + u8 *aRecord, /* Change record */ + int nBucket /* Assume this many buckets in hash table */ +){ + unsigned int h = 0; /* Value to return */ + int i; /* Used to iterate through columns */ + u8 *a = aRecord; /* Used to iterate through change record */ + + for(i=0; inCol; i++){ + int eType = *a; + int isPK = pTab->abPK[i]; + if( bPkOnly && isPK==0 ) continue; + + /* It is not possible for eType to be SQLITE_NULL here. The session + ** module does not record changes for rows with NULL values stored in + ** primary key columns. */ + assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT + || eType==SQLITE_TEXT || eType==SQLITE_BLOB + || eType==SQLITE_NULL || eType==0 + ); + assert( !isPK || (eType!=0 && eType!=SQLITE_NULL) ); + + if( isPK ){ + a++; + h = sessionHashAppendType(h, eType); + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + h = sessionHashAppendI64(h, sessionGetI64(a)); + a += 8; + }else{ + int n; + a += sessionVarintGet(a, &n); + h = sessionHashAppendBlob(h, n, a); + a += n; + } + }else{ + a += sessionSerialLen(a); + } + } + return (h % nBucket); +} + +/* +** Arguments aLeft and aRight are pointers to change records for table pTab. +** This function returns true if the two records apply to the same row (i.e. +** have the same values stored in the primary key columns), or false +** otherwise. +*/ +static int sessionChangeEqual( + SessionTable *pTab, /* Table used for PK definition */ + int bLeftPkOnly, /* True if aLeft[] contains PK fields only */ + u8 *aLeft, /* Change record */ + int bRightPkOnly, /* True if aRight[] contains PK fields only */ + u8 *aRight /* Change record */ +){ + u8 *a1 = aLeft; /* Cursor to iterate through aLeft */ + u8 *a2 = aRight; /* Cursor to iterate through aRight */ + int iCol; /* Used to iterate through table columns */ + + for(iCol=0; iColnCol; iCol++){ + if( pTab->abPK[iCol] ){ + int n1 = sessionSerialLen(a1); + int n2 = sessionSerialLen(a2); + + if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){ + return 0; + } + a1 += n1; + a2 += n2; + }else{ + if( bLeftPkOnly==0 ) a1 += sessionSerialLen(a1); + if( bRightPkOnly==0 ) a2 += sessionSerialLen(a2); + } + } + + return 1; +} + +/* +** Arguments aLeft and aRight both point to buffers containing change +** records with nCol columns. This function "merges" the two records into +** a single records which is written to the buffer at *paOut. *paOut is +** then set to point to one byte after the last byte written before +** returning. +** +** The merging of records is done as follows: For each column, if the +** aRight record contains a value for the column, copy the value from +** their. Otherwise, if aLeft contains a value, copy it. If neither +** record contains a value for a given column, then neither does the +** output record. +*/ +static void sessionMergeRecord( + u8 **paOut, + int nCol, + u8 *aLeft, + u8 *aRight +){ + u8 *a1 = aLeft; /* Cursor used to iterate through aLeft */ + u8 *a2 = aRight; /* Cursor used to iterate through aRight */ + u8 *aOut = *paOut; /* Output cursor */ + int iCol; /* Used to iterate from 0 to nCol */ + + for(iCol=0; iColnCol; i++){ + int nOld; + u8 *aOld; + int nNew; + u8 *aNew; + + aOld = sessionMergeValue(&aOld1, &aOld2, &nOld); + aNew = sessionMergeValue(&aNew1, &aNew2, &nNew); + if( pTab->abPK[i] || nOld!=nNew || memcmp(aOld, aNew, nNew) ){ + if( pTab->abPK[i]==0 ) bRequired = 1; + memcpy(aOut, aOld, nOld); + aOut += nOld; + }else{ + *(aOut++) = '\0'; + } + } + + if( !bRequired ) return 0; + } + + /* Write the new.* vector */ + aOld1 = aOldRecord1; + aOld2 = aOldRecord2; + aNew1 = aNewRecord1; + aNew2 = aNewRecord2; + for(i=0; inCol; i++){ + int nOld; + u8 *aOld; + int nNew; + u8 *aNew; + + aOld = sessionMergeValue(&aOld1, &aOld2, &nOld); + aNew = sessionMergeValue(&aNew1, &aNew2, &nNew); + if( bPatchset==0 + && (pTab->abPK[i] || (nOld==nNew && 0==memcmp(aOld, aNew, nNew))) + ){ + *(aOut++) = '\0'; + }else{ + memcpy(aOut, aNew, nNew); + aOut += nNew; + } + } + + *paOut = aOut; + return 1; +} + +/* +** This function is only called from within a pre-update-hook callback. +** It determines if the current pre-update-hook change affects the same row +** as the change stored in argument pChange. If so, it returns true. Otherwise +** if the pre-update-hook does not affect the same row as pChange, it returns +** false. +*/ +static int sessionPreupdateEqual( + sqlite3_session *pSession, /* Session object that owns SessionTable */ + SessionTable *pTab, /* Table associated with change */ + SessionChange *pChange, /* Change to compare to */ + int op /* Current pre-update operation */ +){ + int iCol; /* Used to iterate through columns */ + u8 *a = pChange->aRecord; /* Cursor used to scan change record */ + + assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE ); + for(iCol=0; iColnCol; iCol++){ + if( !pTab->abPK[iCol] ){ + a += sessionSerialLen(a); + }else{ + sqlite3_value *pVal; /* Value returned by preupdate_new/old */ + int rc; /* Error code from preupdate_new/old */ + int eType = *a++; /* Type of value from change record */ + + /* The following calls to preupdate_new() and preupdate_old() can not + ** fail. This is because they cache their return values, and by the + ** time control flows to here they have already been called once from + ** within sessionPreupdateHash(). The first two asserts below verify + ** this (that the method has already been called). */ + if( op==SQLITE_INSERT ){ + /* assert( db->pPreUpdate->pNewUnpacked || db->pPreUpdate->aNew ); */ + rc = pSession->hook.xNew(pSession->hook.pCtx, iCol, &pVal); + }else{ + /* assert( db->pPreUpdate->pUnpacked ); */ + rc = pSession->hook.xOld(pSession->hook.pCtx, iCol, &pVal); + } + assert( rc==SQLITE_OK ); + if( sqlite3_value_type(pVal)!=eType ) return 0; + + /* A SessionChange object never has a NULL value in a PK column */ + assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT + || eType==SQLITE_BLOB || eType==SQLITE_TEXT + ); + + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + i64 iVal = sessionGetI64(a); + a += 8; + if( eType==SQLITE_INTEGER ){ + if( sqlite3_value_int64(pVal)!=iVal ) return 0; + }else{ + double rVal; + assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); + memcpy(&rVal, &iVal, 8); + if( sqlite3_value_double(pVal)!=rVal ) return 0; + } + }else{ + int n; + const u8 *z; + a += sessionVarintGet(a, &n); + if( sqlite3_value_bytes(pVal)!=n ) return 0; + if( eType==SQLITE_TEXT ){ + z = sqlite3_value_text(pVal); + }else{ + z = sqlite3_value_blob(pVal); + } + if( memcmp(a, z, n) ) return 0; + a += n; + break; + } + } + } + + return 1; +} + +/* +** If required, grow the hash table used to store changes on table pTab +** (part of the session pSession). If a fatal OOM error occurs, set the +** session object to failed and return SQLITE_ERROR. Otherwise, return +** SQLITE_OK. +** +** It is possible that a non-fatal OOM error occurs in this function. In +** that case the hash-table does not grow, but SQLITE_OK is returned anyway. +** Growing the hash table in this case is a performance optimization only, +** it is not required for correct operation. +*/ +static int sessionGrowHash(int bPatchset, SessionTable *pTab){ + if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){ + int i; + SessionChange **apNew; + int nNew = (pTab->nChange ? pTab->nChange : 128) * 2; + + apNew = (SessionChange **)sqlite3_malloc(sizeof(SessionChange *) * nNew); + if( apNew==0 ){ + if( pTab->nChange==0 ){ + return SQLITE_ERROR; + } + return SQLITE_OK; + } + memset(apNew, 0, sizeof(SessionChange *) * nNew); + + for(i=0; inChange; i++){ + SessionChange *p; + SessionChange *pNext; + for(p=pTab->apChange[i]; p; p=pNext){ + int bPkOnly = (p->op==SQLITE_DELETE && bPatchset); + int iHash = sessionChangeHash(pTab, bPkOnly, p->aRecord, nNew); + pNext = p->pNext; + p->pNext = apNew[iHash]; + apNew[iHash] = p; + } + } + + sqlite3_free(pTab->apChange); + pTab->nChange = nNew; + pTab->apChange = apNew; + } + + return SQLITE_OK; +} + +/* +** This function queries the database for the names of the columns of table +** zThis, in schema zDb. It is expected that the table has nCol columns. If +** not, SQLITE_SCHEMA is returned and none of the output variables are +** populated. +** +** Otherwise, if they are not NULL, variable *pnCol is set to the number +** of columns in the database table and variable *pzTab is set to point to a +** nul-terminated copy of the table name. *pazCol (if not NULL) is set to +** point to an array of pointers to column names. And *pabPK (again, if not +** NULL) is set to point to an array of booleans - true if the corresponding +** column is part of the primary key. +** +** For example, if the table is declared as: +** +** CREATE TABLE tbl1(w, x, y, z, PRIMARY KEY(w, z)); +** +** Then the four output variables are populated as follows: +** +** *pnCol = 4 +** *pzTab = "tbl1" +** *pazCol = {"w", "x", "y", "z"} +** *pabPK = {1, 0, 0, 1} +** +** All returned buffers are part of the same single allocation, which must +** be freed using sqlite3_free() by the caller. If pazCol was not NULL, then +** pointer *pazCol should be freed to release all memory. Otherwise, pointer +** *pabPK. It is illegal for both pazCol and pabPK to be NULL. +*/ +static int sessionTableInfo( + sqlite3 *db, /* Database connection */ + const char *zDb, /* Name of attached database (e.g. "main") */ + const char *zThis, /* Table name */ + int *pnCol, /* OUT: number of columns */ + const char **pzTab, /* OUT: Copy of zThis */ + const char ***pazCol, /* OUT: Array of column names for table */ + u8 **pabPK /* OUT: Array of booleans - true for PK col */ +){ + char *zPragma; + sqlite3_stmt *pStmt; + int rc; + int nByte; + int nDbCol = 0; + int nThis; + int i; + u8 *pAlloc = 0; + char **azCol = 0; + u8 *abPK = 0; + + assert( pazCol && pabPK ); + + nThis = sqlite3Strlen30(zThis); + zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis); + if( !zPragma ) return SQLITE_NOMEM; + + rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0); + sqlite3_free(zPragma); + if( rc!=SQLITE_OK ) return rc; + + nByte = nThis + 1; + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + nByte += sqlite3_column_bytes(pStmt, 1); + nDbCol++; + } + rc = sqlite3_reset(pStmt); + + if( rc==SQLITE_OK ){ + nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1); + pAlloc = sqlite3_malloc(nByte); + if( pAlloc==0 ){ + rc = SQLITE_NOMEM; + } + } + if( rc==SQLITE_OK ){ + azCol = (char **)pAlloc; + pAlloc = (u8 *)&azCol[nDbCol]; + abPK = (u8 *)pAlloc; + pAlloc = &abPK[nDbCol]; + if( pzTab ){ + memcpy(pAlloc, zThis, nThis+1); + *pzTab = (char *)pAlloc; + pAlloc += nThis+1; + } + + i = 0; + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + int nName = sqlite3_column_bytes(pStmt, 1); + const unsigned char *zName = sqlite3_column_text(pStmt, 1); + if( zName==0 ) break; + memcpy(pAlloc, zName, nName+1); + azCol[i] = (char *)pAlloc; + pAlloc += nName+1; + abPK[i] = sqlite3_column_int(pStmt, 5); + i++; + } + rc = sqlite3_reset(pStmt); + + } + + /* If successful, populate the output variables. Otherwise, zero them and + ** free any allocation made. An error code will be returned in this case. + */ + if( rc==SQLITE_OK ){ + *pazCol = (const char **)azCol; + *pabPK = abPK; + *pnCol = nDbCol; + }else{ + *pazCol = 0; + *pabPK = 0; + *pnCol = 0; + if( pzTab ) *pzTab = 0; + sqlite3_free(azCol); + } + sqlite3_finalize(pStmt); + return rc; +} + +/* +** This function is only called from within a pre-update handler for a +** write to table pTab, part of session pSession. If this is the first +** write to this table, initalize the SessionTable.nCol, azCol[] and +** abPK[] arrays accordingly. +** +** If an error occurs, an error code is stored in sqlite3_session.rc and +** non-zero returned. Or, if no error occurs but the table has no primary +** key, sqlite3_session.rc is left set to SQLITE_OK and non-zero returned to +** indicate that updates on this table should be ignored. SessionTable.abPK +** is set to NULL in this case. +*/ +static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ + if( pTab->nCol==0 ){ + u8 *abPK; + assert( pTab->azCol==0 || pTab->abPK==0 ); + pSession->rc = sessionTableInfo(pSession->db, pSession->zDb, + pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK + ); + if( pSession->rc==SQLITE_OK ){ + int i; + for(i=0; inCol; i++){ + if( abPK[i] ){ + pTab->abPK = abPK; + break; + } + } + } + } + return (pSession->rc || pTab->abPK==0); +} + +/* +** This function is only called from with a pre-update-hook reporting a +** change on table pTab (attached to session pSession). The type of change +** (UPDATE, INSERT, DELETE) is specified by the first argument. +** +** Unless one is already present or an error occurs, an entry is added +** to the changed-rows hash table associated with table pTab. +*/ +static void sessionPreupdateOneChange( + int op, /* One of SQLITE_UPDATE, INSERT, DELETE */ + sqlite3_session *pSession, /* Session object pTab is attached to */ + SessionTable *pTab /* Table that change applies to */ +){ + int iHash; + int bNull = 0; + int rc = SQLITE_OK; + + if( pSession->rc ) return; + + /* Load table details if required */ + if( sessionInitTable(pSession, pTab) ) return; + + /* Check the number of columns in this xPreUpdate call matches the + ** number of columns in the table. */ + if( pTab->nCol!=pSession->hook.xCount(pSession->hook.pCtx) ){ + pSession->rc = SQLITE_SCHEMA; + return; + } + + /* Grow the hash table if required */ + if( sessionGrowHash(0, pTab) ){ + pSession->rc = SQLITE_NOMEM; + return; + } + + /* Calculate the hash-key for this change. If the primary key of the row + ** includes a NULL value, exit early. Such changes are ignored by the + ** session module. */ + rc = sessionPreupdateHash(pSession, pTab, op==SQLITE_INSERT, &iHash, &bNull); + if( rc!=SQLITE_OK ) goto error_out; + + if( bNull==0 ){ + /* Search the hash table for an existing record for this row. */ + SessionChange *pC; + for(pC=pTab->apChange[iHash]; pC; pC=pC->pNext){ + if( sessionPreupdateEqual(pSession, pTab, pC, op) ) break; + } + + if( pC==0 ){ + /* Create a new change object containing all the old values (if + ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK + ** values (if this is an INSERT). */ + SessionChange *pChange; /* New change object */ + int nByte; /* Number of bytes to allocate */ + int i; /* Used to iterate through columns */ + + assert( rc==SQLITE_OK ); + pTab->nEntry++; + + /* Figure out how large an allocation is required */ + nByte = sizeof(SessionChange); + for(i=0; inCol; i++){ + sqlite3_value *p = 0; + if( op!=SQLITE_INSERT ){ + TESTONLY(int trc = ) pSession->hook.xOld(pSession->hook.pCtx, i, &p); + assert( trc==SQLITE_OK ); + }else if( pTab->abPK[i] ){ + TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx, i, &p); + assert( trc==SQLITE_OK ); + } + + /* This may fail if SQLite value p contains a utf-16 string that must + ** be converted to utf-8 and an OOM error occurs while doing so. */ + rc = sessionSerializeValue(0, p, &nByte); + if( rc!=SQLITE_OK ) goto error_out; + } + + /* Allocate the change object */ + pChange = (SessionChange *)sqlite3_malloc(nByte); + if( !pChange ){ + rc = SQLITE_NOMEM; + goto error_out; + }else{ + memset(pChange, 0, sizeof(SessionChange)); + pChange->aRecord = (u8 *)&pChange[1]; + } + + /* Populate the change object. None of the preupdate_old(), + ** preupdate_new() or SerializeValue() calls below may fail as all + ** required values and encodings have already been cached in memory. + ** It is not possible for an OOM to occur in this block. */ + nByte = 0; + for(i=0; inCol; i++){ + sqlite3_value *p = 0; + if( op!=SQLITE_INSERT ){ + pSession->hook.xOld(pSession->hook.pCtx, i, &p); + }else if( pTab->abPK[i] ){ + pSession->hook.xNew(pSession->hook.pCtx, i, &p); + } + sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte); + } + + /* Add the change to the hash-table */ + if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){ + pChange->bIndirect = 1; + } + pChange->nRecord = nByte; + pChange->op = op; + pChange->pNext = pTab->apChange[iHash]; + pTab->apChange[iHash] = pChange; + + }else if( pC->bIndirect ){ + /* If the existing change is considered "indirect", but this current + ** change is "direct", mark the change object as direct. */ + if( pSession->hook.xDepth(pSession->hook.pCtx)==0 + && pSession->bIndirect==0 + ){ + pC->bIndirect = 0; + } + } + } + + /* If an error has occurred, mark the session object as failed. */ + error_out: + if( rc!=SQLITE_OK ){ + pSession->rc = rc; + } +} + +static int sessionFindTable( + sqlite3_session *pSession, + const char *zName, + SessionTable **ppTab +){ + int rc = SQLITE_OK; + int nName = sqlite3Strlen30(zName); + SessionTable *pRet; + + /* Search for an existing table */ + for(pRet=pSession->pTable; pRet; pRet=pRet->pNext){ + if( 0==sqlite3_strnicmp(pRet->zName, zName, nName+1) ) break; + } + + if( pRet==0 && pSession->bAutoAttach ){ + /* If there is a table-filter configured, invoke it. If it returns 0, + ** do not automatically add the new table. */ + if( pSession->xTableFilter==0 + || pSession->xTableFilter(pSession->pFilterCtx, zName) + ){ + rc = sqlite3session_attach(pSession, zName); + if( rc==SQLITE_OK ){ + for(pRet=pSession->pTable; pRet->pNext; pRet=pRet->pNext); + assert( 0==sqlite3_strnicmp(pRet->zName, zName, nName+1) ); + } + } + } + + assert( rc==SQLITE_OK || pRet==0 ); + *ppTab = pRet; + return rc; +} + +/* +** The 'pre-update' hook registered by this module with SQLite databases. +*/ +static void xPreUpdate( + void *pCtx, /* Copy of third arg to preupdate_hook() */ + sqlite3 *db, /* Database handle */ + int op, /* SQLITE_UPDATE, DELETE or INSERT */ + char const *zDb, /* Database name */ + char const *zName, /* Table name */ + sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ + sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ +){ + sqlite3_session *pSession; + int nDb = sqlite3Strlen30(zDb); + + assert( sqlite3_mutex_held(db->mutex) ); + + for(pSession=(sqlite3_session *)pCtx; pSession; pSession=pSession->pNext){ + SessionTable *pTab; + + /* If this session is attached to a different database ("main", "temp" + ** etc.), or if it is not currently enabled, there is nothing to do. Skip + ** to the next session object attached to this database. */ + if( pSession->bEnable==0 ) continue; + if( pSession->rc ) continue; + if( sqlite3_strnicmp(zDb, pSession->zDb, nDb+1) ) continue; + + pSession->rc = sessionFindTable(pSession, zName, &pTab); + if( pTab ){ + assert( pSession->rc==SQLITE_OK ); + sessionPreupdateOneChange(op, pSession, pTab); + if( op==SQLITE_UPDATE ){ + sessionPreupdateOneChange(SQLITE_INSERT, pSession, pTab); + } + } + } +} + +/* +** The pre-update hook implementations. +*/ +static int sessionPreupdateOld(void *pCtx, int iVal, sqlite3_value **ppVal){ + return sqlite3_preupdate_old((sqlite3*)pCtx, iVal, ppVal); +} +static int sessionPreupdateNew(void *pCtx, int iVal, sqlite3_value **ppVal){ + return sqlite3_preupdate_new((sqlite3*)pCtx, iVal, ppVal); +} +static int sessionPreupdateCount(void *pCtx){ + return sqlite3_preupdate_count((sqlite3*)pCtx); +} +static int sessionPreupdateDepth(void *pCtx){ + return sqlite3_preupdate_depth((sqlite3*)pCtx); +} + +/* +** Install the pre-update hooks on the session object passed as the only +** argument. +*/ +static void sessionPreupdateHooks( + sqlite3_session *pSession +){ + pSession->hook.pCtx = (void*)pSession->db; + pSession->hook.xOld = sessionPreupdateOld; + pSession->hook.xNew = sessionPreupdateNew; + pSession->hook.xCount = sessionPreupdateCount; + pSession->hook.xDepth = sessionPreupdateDepth; +} + +typedef struct SessionDiffCtx SessionDiffCtx; +struct SessionDiffCtx { + sqlite3_stmt *pStmt; + int nOldOff; +}; + +/* +** The diff hook implementations. +*/ +static int sessionDiffOld(void *pCtx, int iVal, sqlite3_value **ppVal){ + SessionDiffCtx *p = (SessionDiffCtx*)pCtx; + *ppVal = sqlite3_column_value(p->pStmt, iVal+p->nOldOff); + return SQLITE_OK; +} +static int sessionDiffNew(void *pCtx, int iVal, sqlite3_value **ppVal){ + SessionDiffCtx *p = (SessionDiffCtx*)pCtx; + *ppVal = sqlite3_column_value(p->pStmt, iVal); + return SQLITE_OK; +} +static int sessionDiffCount(void *pCtx){ + SessionDiffCtx *p = (SessionDiffCtx*)pCtx; + return p->nOldOff ? p->nOldOff : sqlite3_column_count(p->pStmt); +} +static int sessionDiffDepth(void *pCtx){ + return 0; +} + +/* +** Install the diff hooks on the session object passed as the only +** argument. +*/ +static void sessionDiffHooks( + sqlite3_session *pSession, + SessionDiffCtx *pDiffCtx +){ + pSession->hook.pCtx = (void*)pDiffCtx; + pSession->hook.xOld = sessionDiffOld; + pSession->hook.xNew = sessionDiffNew; + pSession->hook.xCount = sessionDiffCount; + pSession->hook.xDepth = sessionDiffDepth; +} + +static char *sessionExprComparePK( + int nCol, + const char *zDb1, const char *zDb2, + const char *zTab, + const char **azCol, u8 *abPK +){ + int i; + const char *zSep = ""; + char *zRet = 0; + + for(i=0; inCol, zDb1, zDb2, pTab->zName,zExpr); + + if( zStmt==0 ){ + rc = SQLITE_NOMEM; + }else{ + sqlite3_stmt *pStmt; + rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0); + if( rc==SQLITE_OK ){ + SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx; + pDiffCtx->pStmt = pStmt; + pDiffCtx->nOldOff = 0; + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + sessionPreupdateOneChange(op, pSession, pTab); + } + rc = sqlite3_finalize(pStmt); + } + sqlite3_free(zStmt); + } + + return rc; +} + +static int sessionDiffFindModified( + sqlite3_session *pSession, + SessionTable *pTab, + const char *zFrom, + const char *zExpr +){ + int rc = SQLITE_OK; + + char *zExpr2 = sessionExprCompareOther(pTab->nCol, + pSession->zDb, zFrom, pTab->zName, pTab->azCol, pTab->abPK + ); + if( zExpr2==0 ){ + rc = SQLITE_NOMEM; + }else{ + char *zStmt = sqlite3_mprintf( + "SELECT * FROM \"%w\".\"%w\", \"%w\".\"%w\" WHERE %s AND (%z)", + pSession->zDb, pTab->zName, zFrom, pTab->zName, zExpr, zExpr2 + ); + if( zStmt==0 ){ + rc = SQLITE_NOMEM; + }else{ + sqlite3_stmt *pStmt; + rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0); + + if( rc==SQLITE_OK ){ + SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx; + pDiffCtx->pStmt = pStmt; + pDiffCtx->nOldOff = pTab->nCol; + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + sessionPreupdateOneChange(SQLITE_UPDATE, pSession, pTab); + } + rc = sqlite3_finalize(pStmt); + } + sqlite3_free(zStmt); + } + } + + return rc; +} + +SQLITE_API int sqlite3session_diff( + sqlite3_session *pSession, + const char *zFrom, + const char *zTbl, + char **pzErrMsg +){ + const char *zDb = pSession->zDb; + int rc = pSession->rc; + SessionDiffCtx d; + + memset(&d, 0, sizeof(d)); + sessionDiffHooks(pSession, &d); + + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); + if( pzErrMsg ) *pzErrMsg = 0; + if( rc==SQLITE_OK ){ + char *zExpr = 0; + sqlite3 *db = pSession->db; + SessionTable *pTo; /* Table zTbl */ + + /* Locate and if necessary initialize the target table object */ + rc = sessionFindTable(pSession, zTbl, &pTo); + if( pTo==0 ) goto diff_out; + if( sessionInitTable(pSession, pTo) ){ + rc = pSession->rc; + goto diff_out; + } + + /* Check the table schemas match */ + if( rc==SQLITE_OK ){ + int bHasPk = 0; + int bMismatch = 0; + int nCol; /* Columns in zFrom.zTbl */ + u8 *abPK; + const char **azCol = 0; + rc = sessionTableInfo(db, zFrom, zTbl, &nCol, 0, &azCol, &abPK); + if( rc==SQLITE_OK ){ + if( pTo->nCol!=nCol ){ + bMismatch = 1; + }else{ + int i; + for(i=0; iabPK[i]!=abPK[i] ) bMismatch = 1; + if( sqlite3_stricmp(azCol[i], pTo->azCol[i]) ) bMismatch = 1; + if( abPK[i] ) bHasPk = 1; + } + } + + } + sqlite3_free((char*)azCol); + if( bMismatch ){ + *pzErrMsg = sqlite3_mprintf("table schemas do not match"); + rc = SQLITE_SCHEMA; + } + if( bHasPk==0 ){ + /* Ignore tables with no primary keys */ + goto diff_out; + } + } + + if( rc==SQLITE_OK ){ + zExpr = sessionExprComparePK(pTo->nCol, + zDb, zFrom, pTo->zName, pTo->azCol, pTo->abPK + ); + } + + /* Find new rows */ + if( rc==SQLITE_OK ){ + rc = sessionDiffFindNew(SQLITE_INSERT, pSession, pTo, zDb, zFrom, zExpr); + } + + /* Find old rows */ + if( rc==SQLITE_OK ){ + rc = sessionDiffFindNew(SQLITE_DELETE, pSession, pTo, zFrom, zDb, zExpr); + } + + /* Find modified rows */ + if( rc==SQLITE_OK ){ + rc = sessionDiffFindModified(pSession, pTo, zFrom, zExpr); + } + + sqlite3_free(zExpr); + } + + diff_out: + sessionPreupdateHooks(pSession); + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); + return rc; +} + +/* +** Create a session object. This session object will record changes to +** database zDb attached to connection db. +*/ +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 */ +){ + sqlite3_session *pNew; /* Newly allocated session object */ + sqlite3_session *pOld; /* Session object already attached to db */ + int nDb = sqlite3Strlen30(zDb); /* Length of zDb in bytes */ + + /* Zero the output value in case an error occurs. */ + *ppSession = 0; + + /* Allocate and populate the new session object. */ + pNew = (sqlite3_session *)sqlite3_malloc(sizeof(sqlite3_session) + nDb + 1); + if( !pNew ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(sqlite3_session)); + pNew->db = db; + pNew->zDb = (char *)&pNew[1]; + pNew->bEnable = 1; + memcpy(pNew->zDb, zDb, nDb+1); + sessionPreupdateHooks(pNew); + + /* Add the new session object to the linked list of session objects + ** attached to database handle $db. Do this under the cover of the db + ** handle mutex. */ + sqlite3_mutex_enter(sqlite3_db_mutex(db)); + pOld = (sqlite3_session*)sqlite3_preupdate_hook(db, xPreUpdate, (void*)pNew); + pNew->pNext = pOld; + sqlite3_mutex_leave(sqlite3_db_mutex(db)); + + *ppSession = pNew; + return SQLITE_OK; +} + +/* +** Free the list of table objects passed as the first argument. The contents +** of the changed-rows hash tables are also deleted. +*/ +static void sessionDeleteTable(SessionTable *pList){ + SessionTable *pNext; + SessionTable *pTab; + + for(pTab=pList; pTab; pTab=pNext){ + int i; + pNext = pTab->pNext; + for(i=0; inChange; i++){ + SessionChange *p; + SessionChange *pNextChange; + for(p=pTab->apChange[i]; p; p=pNextChange){ + pNextChange = p->pNext; + sqlite3_free(p); + } + } + sqlite3_free((char*)pTab->azCol); /* cast works around VC++ bug */ + sqlite3_free(pTab->apChange); + sqlite3_free(pTab); + } +} + +/* +** Delete a session object previously allocated using sqlite3session_create(). +*/ +SQLITE_API void sqlite3session_delete(sqlite3_session *pSession){ + sqlite3 *db = pSession->db; + sqlite3_session *pHead; + sqlite3_session **pp; + + /* Unlink the session from the linked list of sessions attached to the + ** database handle. Hold the db mutex while doing so. */ + sqlite3_mutex_enter(sqlite3_db_mutex(db)); + pHead = (sqlite3_session*)sqlite3_preupdate_hook(db, 0, 0); + for(pp=&pHead; ALWAYS((*pp)!=0); pp=&((*pp)->pNext)){ + if( (*pp)==pSession ){ + *pp = (*pp)->pNext; + if( pHead ) sqlite3_preupdate_hook(db, xPreUpdate, (void*)pHead); + break; + } + } + sqlite3_mutex_leave(sqlite3_db_mutex(db)); + + /* Delete all attached table objects. And the contents of their + ** associated hash-tables. */ + sessionDeleteTable(pSession->pTable); + + /* Free the session object itself. */ + sqlite3_free(pSession); +} + +/* +** Set a table filter on a Session Object. +*/ +SQLITE_API void sqlite3session_table_filter( + sqlite3_session *pSession, + int(*xFilter)(void*, const char*), + void *pCtx /* First argument passed to xFilter */ +){ + pSession->bAutoAttach = 1; + pSession->pFilterCtx = pCtx; + pSession->xTableFilter = xFilter; +} + +/* +** Attach a table to a session. All subsequent changes made to the table +** while the session object is enabled will be recorded. +** +** Only tables that have a PRIMARY KEY defined may be attached. It does +** not matter if the PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) +** or not. +*/ +SQLITE_API int sqlite3session_attach( + sqlite3_session *pSession, /* Session object */ + const char *zName /* Table name */ +){ + int rc = SQLITE_OK; + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); + + if( !zName ){ + pSession->bAutoAttach = 1; + }else{ + SessionTable *pTab; /* New table object (if required) */ + int nName; /* Number of bytes in string zName */ + + /* First search for an existing entry. If one is found, this call is + ** a no-op. Return early. */ + nName = sqlite3Strlen30(zName); + for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){ + if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ) break; + } + + if( !pTab ){ + /* Allocate new SessionTable object. */ + pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1); + if( !pTab ){ + rc = SQLITE_NOMEM; + }else{ + /* Populate the new SessionTable object and link it into the list. + ** The new object must be linked onto the end of the list, not + ** simply added to the start of it in order to ensure that tables + ** appear in the correct order when a changeset or patchset is + ** eventually generated. */ + SessionTable **ppTab; + memset(pTab, 0, sizeof(SessionTable)); + pTab->zName = (char *)&pTab[1]; + memcpy(pTab->zName, zName, nName+1); + for(ppTab=&pSession->pTable; *ppTab; ppTab=&(*ppTab)->pNext); + *ppTab = pTab; + } + } + } + + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); + return rc; +} + +/* +** Ensure that there is room in the buffer to append nByte bytes of data. +** If not, use sqlite3_realloc() to grow the buffer so that there is. +** +** If successful, return zero. Otherwise, if an OOM condition is encountered, +** set *pRc to SQLITE_NOMEM and return non-zero. +*/ +static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ + if( *pRc==SQLITE_OK && p->nAlloc-p->nBufnAlloc ? p->nAlloc : 128; + do { + nNew = nNew*2; + }while( nNew<(p->nBuf+nByte) ); + + aNew = (u8 *)sqlite3_realloc(p->aBuf, nNew); + if( 0==aNew ){ + *pRc = SQLITE_NOMEM; + }else{ + p->aBuf = aNew; + p->nAlloc = nNew; + } + } + return (*pRc!=SQLITE_OK); +} + +/* +** Append the value passed as the second argument to the buffer passed +** as the first. +** +** This function is a no-op if *pRc is non-zero when it is called. +** Otherwise, if an error occurs, *pRc is set to an SQLite error code +** before returning. +*/ +static void sessionAppendValue(SessionBuffer *p, sqlite3_value *pVal, int *pRc){ + int rc = *pRc; + if( rc==SQLITE_OK ){ + int nByte = 0; + rc = sessionSerializeValue(0, pVal, &nByte); + sessionBufferGrow(p, nByte, &rc); + if( rc==SQLITE_OK ){ + rc = sessionSerializeValue(&p->aBuf[p->nBuf], pVal, 0); + p->nBuf += nByte; + }else{ + *pRc = rc; + } + } +} + +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append a single byte to the buffer. +** +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before +** returning. +*/ +static void sessionAppendByte(SessionBuffer *p, u8 v, int *pRc){ + if( 0==sessionBufferGrow(p, 1, pRc) ){ + p->aBuf[p->nBuf++] = v; + } +} + +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append a single varint to the buffer. +** +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before +** returning. +*/ +static void sessionAppendVarint(SessionBuffer *p, int v, int *pRc){ + if( 0==sessionBufferGrow(p, 9, pRc) ){ + p->nBuf += sessionVarintPut(&p->aBuf[p->nBuf], v); + } +} + +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append a blob of data to the buffer. +** +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before +** returning. +*/ +static void sessionAppendBlob( + SessionBuffer *p, + const u8 *aBlob, + int nBlob, + int *pRc +){ + if( 0==sessionBufferGrow(p, nBlob, pRc) ){ + memcpy(&p->aBuf[p->nBuf], aBlob, nBlob); + p->nBuf += nBlob; + } +} + +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append a string to the buffer. All bytes in the string +** up to (but not including) the nul-terminator are written to the buffer. +** +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before +** returning. +*/ +static void sessionAppendStr( + SessionBuffer *p, + const char *zStr, + int *pRc +){ + int nStr = sqlite3Strlen30(zStr); + if( 0==sessionBufferGrow(p, nStr, pRc) ){ + memcpy(&p->aBuf[p->nBuf], zStr, nStr); + p->nBuf += nStr; + } +} + +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append the string representation of integer iVal +** to the buffer. No nul-terminator is written. +** +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before +** returning. +*/ +static void sessionAppendInteger( + SessionBuffer *p, /* Buffer to append to */ + int iVal, /* Value to write the string rep. of */ + int *pRc /* IN/OUT: Error code */ +){ + char aBuf[24]; + sqlite3_snprintf(sizeof(aBuf)-1, aBuf, "%d", iVal); + sessionAppendStr(p, aBuf, pRc); +} + +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append the string zStr enclosed in quotes (") and +** with any embedded quote characters escaped to the buffer. No +** nul-terminator byte is written. +** +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before +** returning. +*/ +static void sessionAppendIdent( + SessionBuffer *p, /* Buffer to a append to */ + const char *zStr, /* String to quote, escape and append */ + int *pRc /* IN/OUT: Error code */ +){ + int nStr = sqlite3Strlen30(zStr)*2 + 2 + 1; + if( 0==sessionBufferGrow(p, nStr, pRc) ){ + char *zOut = (char *)&p->aBuf[p->nBuf]; + const char *zIn = zStr; + *zOut++ = '"'; + while( *zIn ){ + if( *zIn=='"' ) *zOut++ = '"'; + *zOut++ = *(zIn++); + } + *zOut++ = '"'; + p->nBuf = (int)((u8 *)zOut - p->aBuf); + } +} + +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwse, it appends the serialized version of the value stored +** in column iCol of the row that SQL statement pStmt currently points +** to to the buffer. +*/ +static void sessionAppendCol( + SessionBuffer *p, /* Buffer to append to */ + sqlite3_stmt *pStmt, /* Handle pointing to row containing value */ + int iCol, /* Column to read value from */ + int *pRc /* IN/OUT: Error code */ +){ + if( *pRc==SQLITE_OK ){ + int eType = sqlite3_column_type(pStmt, iCol); + sessionAppendByte(p, (u8)eType, pRc); + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + sqlite3_int64 i; + u8 aBuf[8]; + if( eType==SQLITE_INTEGER ){ + i = sqlite3_column_int64(pStmt, iCol); + }else{ + double r = sqlite3_column_double(pStmt, iCol); + memcpy(&i, &r, 8); + } + sessionPutI64(aBuf, i); + sessionAppendBlob(p, aBuf, 8, pRc); + } + if( eType==SQLITE_BLOB || eType==SQLITE_TEXT ){ + u8 *z; + int nByte; + if( eType==SQLITE_BLOB ){ + z = (u8 *)sqlite3_column_blob(pStmt, iCol); + }else{ + z = (u8 *)sqlite3_column_text(pStmt, iCol); + } + nByte = sqlite3_column_bytes(pStmt, iCol); + if( z || (eType==SQLITE_BLOB && nByte==0) ){ + sessionAppendVarint(p, nByte, pRc); + sessionAppendBlob(p, z, nByte, pRc); + }else{ + *pRc = SQLITE_NOMEM; + } + } + } +} + +/* +** +** This function appends an update change to the buffer (see the comments +** under "CHANGESET FORMAT" at the top of the file). An update change +** consists of: +** +** 1 byte: SQLITE_UPDATE (0x17) +** n bytes: old.* record (see RECORD FORMAT) +** m bytes: new.* record (see RECORD FORMAT) +** +** The SessionChange object passed as the third argument contains the +** values that were stored in the row when the session began (the old.* +** values). The statement handle passed as the second argument points +** at the current version of the row (the new.* values). +** +** If all of the old.* values are equal to their corresponding new.* value +** (i.e. nothing has changed), then no data at all is appended to the buffer. +** +** Otherwise, the old.* record contains all primary key values and the +** original values of any fields that have been modified. The new.* record +** contains the new values of only those fields that have been modified. +*/ +static int sessionAppendUpdate( + SessionBuffer *pBuf, /* Buffer to append to */ + int bPatchset, /* True for "patchset", 0 for "changeset" */ + sqlite3_stmt *pStmt, /* Statement handle pointing at new row */ + SessionChange *p, /* Object containing old values */ + u8 *abPK /* Boolean array - true for PK columns */ +){ + int rc = SQLITE_OK; + SessionBuffer buf2 = {0,0,0}; /* Buffer to accumulate new.* record in */ + int bNoop = 1; /* Set to zero if any values are modified */ + int nRewind = pBuf->nBuf; /* Set to zero if any values are modified */ + int i; /* Used to iterate through columns */ + u8 *pCsr = p->aRecord; /* Used to iterate through old.* values */ + + sessionAppendByte(pBuf, SQLITE_UPDATE, &rc); + sessionAppendByte(pBuf, p->bIndirect, &rc); + for(i=0; inBuf = nRewind; + }else{ + sessionAppendBlob(pBuf, buf2.aBuf, buf2.nBuf, &rc); + } + sqlite3_free(buf2.aBuf); + + return rc; +} + +/* +** Append a DELETE change to the buffer passed as the first argument. Use +** the changeset format if argument bPatchset is zero, or the patchset +** format otherwise. +*/ +static int sessionAppendDelete( + SessionBuffer *pBuf, /* Buffer to append to */ + int bPatchset, /* True for "patchset", 0 for "changeset" */ + SessionChange *p, /* Object containing old values */ + int nCol, /* Number of columns in table */ + u8 *abPK /* Boolean array - true for PK columns */ +){ + int rc = SQLITE_OK; + + sessionAppendByte(pBuf, SQLITE_DELETE, &rc); + sessionAppendByte(pBuf, p->bIndirect, &rc); + + if( bPatchset==0 ){ + sessionAppendBlob(pBuf, p->aRecord, p->nRecord, &rc); + }else{ + int i; + u8 *a = p->aRecord; + for(i=0; iaRecord)==p->nRecord ); + } + + return rc; +} + +/* +** Formulate and prepare a SELECT statement to retrieve a row from table +** zTab in database zDb based on its primary key. i.e. +** +** SELECT * FROM zDb.zTab WHERE pk1 = ? AND pk2 = ? AND ... +*/ +static int sessionSelectStmt( + sqlite3 *db, /* Database handle */ + const char *zDb, /* Database name */ + const char *zTab, /* Table name */ + int nCol, /* Number of columns in table */ + const char **azCol, /* Names of table columns */ + u8 *abPK, /* PRIMARY KEY array */ + sqlite3_stmt **ppStmt /* OUT: Prepared SELECT statement */ +){ + int rc = SQLITE_OK; + int i; + const char *zSep = ""; + SessionBuffer buf = {0, 0, 0}; + + sessionAppendStr(&buf, "SELECT * FROM ", &rc); + sessionAppendIdent(&buf, zDb, &rc); + sessionAppendStr(&buf, ".", &rc); + sessionAppendIdent(&buf, zTab, &rc); + sessionAppendStr(&buf, " WHERE ", &rc); + for(i=0; iaRecord; + + for(i=0; inCol, pRc); + sessionAppendBlob(pBuf, pTab->abPK, pTab->nCol, pRc); + sessionAppendBlob(pBuf, (u8 *)pTab->zName, (int)strlen(pTab->zName)+1, pRc); +} + +/* +** Generate either a changeset (if argument bPatchset is zero) or a patchset +** (if it is non-zero) based on the current contents of the session object +** passed as the first argument. +** +** If no error occurs, SQLITE_OK is returned and the new changeset/patchset +** stored in output variables *pnChangeset and *ppChangeset. Or, if an error +** occurs, an SQLite error code is returned and both output variables set +** to 0. +*/ +static int sessionGenerateChangeset( + sqlite3_session *pSession, /* Session object */ + int bPatchset, /* True for patchset, false for changeset */ + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut, /* First argument for xOutput */ + int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ + void **ppChangeset /* OUT: Buffer containing changeset */ +){ + sqlite3 *db = pSession->db; /* Source database handle */ + SessionTable *pTab; /* Used to iterate through attached tables */ + SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */ + int rc; /* Return code */ + + assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0 ) ); + + /* Zero the output variables in case an error occurs. If this session + ** object is already in the error state (sqlite3_session.rc != SQLITE_OK), + ** this call will be a no-op. */ + if( xOutput==0 ){ + *pnChangeset = 0; + *ppChangeset = 0; + } + + if( pSession->rc ) return pSession->rc; + rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0); + if( rc!=SQLITE_OK ) return rc; + + sqlite3_mutex_enter(sqlite3_db_mutex(db)); + + for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ + if( pTab->nEntry ){ + const char *zName = pTab->zName; + int nCol; /* Number of columns in table */ + u8 *abPK; /* Primary key array */ + const char **azCol = 0; /* Table columns */ + int i; /* Used to iterate through hash buckets */ + sqlite3_stmt *pSel = 0; /* SELECT statement to query table pTab */ + int nRewind = buf.nBuf; /* Initial size of write buffer */ + int nNoop; /* Size of buffer after writing tbl header */ + + /* Check the table schema is still Ok. */ + rc = sessionTableInfo(db, pSession->zDb, zName, &nCol, 0, &azCol, &abPK); + if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){ + rc = SQLITE_SCHEMA; + } + + /* Write a table header */ + sessionAppendTableHdr(&buf, bPatchset, pTab, &rc); + + /* Build and compile a statement to execute: */ + if( rc==SQLITE_OK ){ + rc = sessionSelectStmt( + db, pSession->zDb, zName, nCol, azCol, abPK, &pSel); + } + + nNoop = buf.nBuf; + for(i=0; inChange && rc==SQLITE_OK; i++){ + SessionChange *p; /* Used to iterate through changes */ + + for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ + rc = sessionSelectBind(pSel, nCol, abPK, p); + if( rc!=SQLITE_OK ) continue; + if( sqlite3_step(pSel)==SQLITE_ROW ){ + if( p->op==SQLITE_INSERT ){ + int iCol; + sessionAppendByte(&buf, SQLITE_INSERT, &rc); + sessionAppendByte(&buf, p->bIndirect, &rc); + for(iCol=0; iColop!=SQLITE_INSERT ){ + rc = sessionAppendDelete(&buf, bPatchset, p, nCol, abPK); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_reset(pSel); + } + + /* If the buffer is now larger than SESSIONS_STRM_CHUNK_SIZE, pass + ** its contents to the xOutput() callback. */ + if( xOutput + && rc==SQLITE_OK + && buf.nBuf>nNoop + && buf.nBuf>SESSIONS_STRM_CHUNK_SIZE + ){ + rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf); + nNoop = -1; + buf.nBuf = 0; + } + + } + } + + sqlite3_finalize(pSel); + if( buf.nBuf==nNoop ){ + buf.nBuf = nRewind; + } + sqlite3_free((char*)azCol); /* cast works around VC++ bug */ + } + } + + if( rc==SQLITE_OK ){ + if( xOutput==0 ){ + *pnChangeset = buf.nBuf; + *ppChangeset = buf.aBuf; + buf.aBuf = 0; + }else if( buf.nBuf>0 ){ + rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf); + } + } + + sqlite3_free(buf.aBuf); + sqlite3_exec(db, "RELEASE changeset", 0, 0, 0); + sqlite3_mutex_leave(sqlite3_db_mutex(db)); + return rc; +} + +/* +** Obtain a changeset object containing all changes recorded by the +** session object passed as the first argument. +** +** It is the responsibility of the caller to eventually free the buffer +** using sqlite3_free(). +*/ +SQLITE_API int sqlite3session_changeset( + sqlite3_session *pSession, /* Session object */ + int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ + void **ppChangeset /* OUT: Buffer containing changeset */ +){ + return sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset, ppChangeset); +} + +/* +** Streaming version of sqlite3session_changeset(). +*/ +SQLITE_API int sqlite3session_changeset_strm( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +){ + return sessionGenerateChangeset(pSession, 0, xOutput, pOut, 0, 0); +} + +/* +** Streaming version of sqlite3session_patchset(). +*/ +SQLITE_API int sqlite3session_patchset_strm( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +){ + return sessionGenerateChangeset(pSession, 1, xOutput, pOut, 0, 0); +} + +/* +** Obtain a patchset object containing all changes recorded by the +** session object passed as the first argument. +** +** It is the responsibility of the caller to eventually free the buffer +** using sqlite3_free(). +*/ +SQLITE_API int sqlite3session_patchset( + sqlite3_session *pSession, /* Session object */ + int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ + void **ppPatchset /* OUT: Buffer containing changeset */ +){ + return sessionGenerateChangeset(pSession, 1, 0, 0, pnPatchset, ppPatchset); +} + +/* +** Enable or disable the session object passed as the first argument. +*/ +SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable){ + int ret; + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); + if( bEnable>=0 ){ + pSession->bEnable = bEnable; + } + ret = pSession->bEnable; + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); + return ret; +} + +/* +** Enable or disable the session object passed as the first argument. +*/ +SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect){ + int ret; + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); + if( bIndirect>=0 ){ + pSession->bIndirect = bIndirect; + } + ret = pSession->bIndirect; + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); + return ret; +} + +/* +** Return true if there have been no changes to monitored tables recorded +** by the session object passed as the only argument. +*/ +SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession){ + int ret = 0; + SessionTable *pTab; + + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); + for(pTab=pSession->pTable; pTab && ret==0; pTab=pTab->pNext){ + ret = (pTab->nEntry>0); + } + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); + + return (ret==0); +} + +/* +** Do the work for either sqlite3changeset_start() or start_strm(). +*/ +static int sessionChangesetStart( + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int nChangeset, /* Size of buffer pChangeset in bytes */ + void *pChangeset /* Pointer to buffer containing changeset */ +){ + sqlite3_changeset_iter *pRet; /* Iterator to return */ + int nByte; /* Number of bytes to allocate for iterator */ + + assert( xInput==0 || (pChangeset==0 && nChangeset==0) ); + + /* Zero the output variable in case an error occurs. */ + *pp = 0; + + /* Allocate and initialize the iterator structure. */ + nByte = sizeof(sqlite3_changeset_iter); + pRet = (sqlite3_changeset_iter *)sqlite3_malloc(nByte); + if( !pRet ) return SQLITE_NOMEM; + memset(pRet, 0, sizeof(sqlite3_changeset_iter)); + pRet->in.aData = (u8 *)pChangeset; + pRet->in.nData = nChangeset; + pRet->in.xInput = xInput; + pRet->in.pIn = pIn; + pRet->in.bEof = (xInput ? 0 : 1); + + /* Populate the output variable and return success. */ + *pp = pRet; + return SQLITE_OK; +} + +/* +** Create an iterator used to iterate through the contents of a changeset. +*/ +SQLITE_API int sqlite3changeset_start( + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ + int nChangeset, /* Size of buffer pChangeset in bytes */ + void *pChangeset /* Pointer to buffer containing changeset */ +){ + return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset); +} + +/* +** Streaming version of sqlite3changeset_start(). +*/ +SQLITE_API int sqlite3changeset_start_strm( + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn +){ + return sessionChangesetStart(pp, xInput, pIn, 0, 0); +} + +/* +** If the SessionInput object passed as the only argument is a streaming +** object and the buffer is full, discard some data to free up space. +*/ +static void sessionDiscardData(SessionInput *pIn){ + if( pIn->bEof && pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ + int nMove = pIn->buf.nBuf - pIn->iNext; + assert( nMove>=0 ); + if( nMove>0 ){ + memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove); + } + pIn->buf.nBuf -= pIn->iNext; + pIn->iNext = 0; + pIn->nData = pIn->buf.nBuf; + } +} + +/* +** Ensure that there are at least nByte bytes available in the buffer. Or, +** if there are not nByte bytes remaining in the input, that all available +** data is in the buffer. +** +** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise. +*/ +static int sessionInputBuffer(SessionInput *pIn, int nByte){ + int rc = SQLITE_OK; + if( pIn->xInput ){ + while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){ + int nNew = SESSIONS_STRM_CHUNK_SIZE; + + if( pIn->bNoDiscard==0 ) sessionDiscardData(pIn); + if( SQLITE_OK==sessionBufferGrow(&pIn->buf, nNew, &rc) ){ + rc = pIn->xInput(pIn->pIn, &pIn->buf.aBuf[pIn->buf.nBuf], &nNew); + if( nNew==0 ){ + pIn->bEof = 1; + }else{ + pIn->buf.nBuf += nNew; + } + } + + pIn->aData = pIn->buf.aBuf; + pIn->nData = pIn->buf.nBuf; + } + } + return rc; +} + +/* +** When this function is called, *ppRec points to the start of a record +** that contains nCol values. This function advances the pointer *ppRec +** until it points to the byte immediately following that record. +*/ +static void sessionSkipRecord( + u8 **ppRec, /* IN/OUT: Record pointer */ + int nCol /* Number of values in record */ +){ + u8 *aRec = *ppRec; + int i; + for(i=0; iaData[pIn->iNext++]; + } + + assert( apOut[i]==0 ); + if( eType ){ + apOut[i] = sqlite3ValueNew(0); + if( !apOut[i] ) rc = SQLITE_NOMEM; + } + + if( rc==SQLITE_OK ){ + u8 *aVal = &pIn->aData[pIn->iNext]; + if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ + int nByte; + pIn->iNext += sessionVarintGet(aVal, &nByte); + rc = sessionInputBuffer(pIn, nByte); + if( rc==SQLITE_OK ){ + u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); + rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc); + } + pIn->iNext += nByte; + } + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + sqlite3_int64 v = sessionGetI64(aVal); + if( eType==SQLITE_INTEGER ){ + sqlite3VdbeMemSetInt64(apOut[i], v); + }else{ + double d; + memcpy(&d, &v, 8); + sqlite3VdbeMemSetDouble(apOut[i], d); + } + pIn->iNext += 8; + } + } + } + + return rc; +} + +/* +** The input pointer currently points to the second byte of a table-header. +** Specifically, to the following: +** +** + number of columns in table (varint) +** + array of PK flags (1 byte per column), +** + table name (nul terminated). +** +** This function ensures that all of the above is present in the input +** buffer (i.e. that it can be accessed without any calls to xInput()). +** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. +** The input pointer is not moved. +*/ +static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ + int rc = SQLITE_OK; + int nCol = 0; + int nRead = 0; + + rc = sessionInputBuffer(pIn, 9); + if( rc==SQLITE_OK ){ + nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol); + rc = sessionInputBuffer(pIn, nRead+nCol+100); + nRead += nCol; + } + + while( rc==SQLITE_OK ){ + while( (pIn->iNext + nRead)nData && pIn->aData[pIn->iNext + nRead] ){ + nRead++; + } + if( (pIn->iNext + nRead)nData ) break; + rc = sessionInputBuffer(pIn, nRead + 100); + } + *pnByte = nRead+1; + return rc; +} + +/* +** The input pointer currently points to the first byte of the first field +** of a record consisting of nCol columns. This function ensures the entire +** record is buffered. It does not move the input pointer. +** +** If successful, SQLITE_OK is returned and *pnByte is set to the size of +** the record in bytes. Otherwise, an SQLite error code is returned. The +** final value of *pnByte is undefined in this case. +*/ +static int sessionChangesetBufferRecord( + SessionInput *pIn, /* Input data */ + int nCol, /* Number of columns in record */ + int *pnByte /* OUT: Size of record in bytes */ +){ + int rc = SQLITE_OK; + int nByte = 0; + int i; + for(i=0; rc==SQLITE_OK && iaData[pIn->iNext + nByte++]; + if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ + int n; + nByte += sessionVarintGet(&pIn->aData[pIn->iNext+nByte], &n); + nByte += n; + rc = sessionInputBuffer(pIn, nByte); + }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + nByte += 8; + } + } + } + *pnByte = nByte; + return rc; +} + +/* +** The input pointer currently points to the second byte of a table-header. +** Specifically, to the following: +** +** + number of columns in table (varint) +** + array of PK flags (1 byte per column), +** + table name (nul terminated). +** +** This function decodes the table-header and populates the p->nCol, +** p->zTab and p->abPK[] variables accordingly. The p->apValue[] array is +** also allocated or resized according to the new value of p->nCol. The +** input pointer is left pointing to the byte following the table header. +** +** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code +** is returned and the final values of the various fields enumerated above +** are undefined. +*/ +static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){ + int rc; + int nCopy; + assert( p->rc==SQLITE_OK ); + + rc = sessionChangesetBufferTblhdr(&p->in, &nCopy); + if( rc==SQLITE_OK ){ + int nByte; + int nVarint; + nVarint = sessionVarintGet(&p->in.aData[p->in.iNext], &p->nCol); + nCopy -= nVarint; + p->in.iNext += nVarint; + nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy; + p->tblhdr.nBuf = 0; + sessionBufferGrow(&p->tblhdr, nByte, &rc); + } + + if( rc==SQLITE_OK ){ + int iPK = sizeof(sqlite3_value*)*p->nCol*2; + memset(p->tblhdr.aBuf, 0, iPK); + memcpy(&p->tblhdr.aBuf[iPK], &p->in.aData[p->in.iNext], nCopy); + p->in.iNext += nCopy; + } + + p->apValue = (sqlite3_value**)p->tblhdr.aBuf; + p->abPK = (u8*)&p->apValue[p->nCol*2]; + p->zTab = (char*)&p->abPK[p->nCol]; + return (p->rc = rc); +} + +/* +** Advance the changeset iterator to the next change. +** +** If both paRec and pnRec are NULL, then this function works like the public +** API sqlite3changeset_next(). If SQLITE_ROW is returned, then the +** sqlite3changeset_new() and old() APIs may be used to query for values. +** +** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change +** record is written to *paRec before returning and the number of bytes in +** the record to *pnRec. +** +** Either way, this function returns SQLITE_ROW if the iterator is +** successfully advanced to the next change in the changeset, an SQLite +** error code if an error occurs, or SQLITE_DONE if there are no further +** changes in the changeset. +*/ +static int sessionChangesetNext( + sqlite3_changeset_iter *p, /* Changeset iterator */ + u8 **paRec, /* If non-NULL, store record pointer here */ + int *pnRec /* If non-NULL, store size of record here */ +){ + int i; + u8 op; + + assert( (paRec==0 && pnRec==0) || (paRec && pnRec) ); + + /* If the iterator is in the error-state, return immediately. */ + if( p->rc!=SQLITE_OK ) return p->rc; + + /* Free the current contents of p->apValue[], if any. */ + if( p->apValue ){ + for(i=0; inCol*2; i++){ + sqlite3ValueFree(p->apValue[i]); + } + memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2); + } + + /* Make sure the buffer contains at least 10 bytes of input data, or all + ** remaining data if there are less than 10 bytes available. This is + ** sufficient either for the 'T' or 'P' byte and the varint that follows + ** it, or for the two single byte values otherwise. */ + p->rc = sessionInputBuffer(&p->in, 2); + if( p->rc!=SQLITE_OK ) return p->rc; + + /* If the iterator is already at the end of the changeset, return DONE. */ + if( p->in.iNext>=p->in.nData ){ + return SQLITE_DONE; + } + + sessionDiscardData(&p->in); + p->in.iCurrent = p->in.iNext; + + op = p->in.aData[p->in.iNext++]; + if( 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; + op = p->in.aData[p->in.iNext++]; + } + + p->op = op; + p->bIndirect = p->in.aData[p->in.iNext++]; + if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){ + return (p->rc = SQLITE_CORRUPT_BKPT); + } + + if( paRec ){ + int nVal; /* Number of values to buffer */ + if( p->bPatchset==0 && op==SQLITE_UPDATE ){ + nVal = p->nCol * 2; + }else if( p->bPatchset && op==SQLITE_DELETE ){ + nVal = 0; + for(i=0; inCol; i++) if( p->abPK[i] ) nVal++; + }else{ + nVal = p->nCol; + } + p->rc = sessionChangesetBufferRecord(&p->in, nVal, pnRec); + if( p->rc!=SQLITE_OK ) return p->rc; + *paRec = &p->in.aData[p->in.iNext]; + p->in.iNext += *pnRec; + }else{ + + /* If this is an UPDATE or DELETE, read the old.* record. */ + if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){ + u8 *abPK = p->bPatchset ? p->abPK : 0; + p->rc = sessionReadRecord(&p->in, p->nCol, abPK, p->apValue); + if( p->rc!=SQLITE_OK ) return p->rc; + } + + /* If this is an INSERT or UPDATE, read the new.* record. */ + if( p->op!=SQLITE_DELETE ){ + p->rc = sessionReadRecord(&p->in, p->nCol, 0, &p->apValue[p->nCol]); + if( p->rc!=SQLITE_OK ) return p->rc; + } + + if( p->bPatchset && p->op==SQLITE_UPDATE ){ + /* If this is an UPDATE that is part of a patchset, then all PK and + ** modified fields are present in the new.* record. The old.* record + ** is currently completely empty. This block shifts the PK fields from + ** new.* to old.*, to accommodate the code that reads these arrays. */ + for(i=0; inCol; i++){ + assert( p->apValue[i]==0 ); + assert( p->abPK[i]==0 || p->apValue[i+p->nCol] ); + if( p->abPK[i] ){ + p->apValue[i] = p->apValue[i+p->nCol]; + p->apValue[i+p->nCol] = 0; + } + } + } + } + + return SQLITE_ROW; +} + +/* +** Advance an iterator created by sqlite3changeset_start() to the next +** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE +** or SQLITE_CORRUPT. +** +** This function may not be called on iterators passed to a conflict handler +** callback by changeset_apply(). +*/ +SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *p){ + return sessionChangesetNext(p, 0, 0); +} + +/* +** The following function extracts information on the current change +** from a changeset iterator. It may only be called after changeset_next() +** has returned SQLITE_ROW. +*/ +SQLITE_API int sqlite3changeset_op( + sqlite3_changeset_iter *pIter, /* Iterator handle */ + const char **pzTab, /* OUT: Pointer to table name */ + int *pnCol, /* OUT: Number of columns in table */ + int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */ + int *pbIndirect /* OUT: True if change is indirect */ +){ + *pOp = pIter->op; + *pnCol = pIter->nCol; + *pzTab = pIter->zTab; + if( pbIndirect ) *pbIndirect = pIter->bIndirect; + return SQLITE_OK; +} + +/* +** Return information regarding the PRIMARY KEY and number of columns in +** the database table affected by the change that pIter currently points +** to. This function may only be called after changeset_next() returns +** SQLITE_ROW. +*/ +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 */ +){ + *pabPK = pIter->abPK; + if( pnCol ) *pnCol = pIter->nCol; + return SQLITE_OK; +} + +/* +** This function may only be called while the iterator is pointing to an +** SQLITE_UPDATE or SQLITE_DELETE change (see sqlite3changeset_op()). +** Otherwise, SQLITE_MISUSE is returned. +** +** It sets *ppValue to point to an sqlite3_value structure containing the +** iVal'th value in the old.* record. Or, if that particular value is not +** included in the record (because the change is an UPDATE and the field +** was not modified and is not a PK column), set *ppValue to NULL. +** +** If value iVal is out-of-range, SQLITE_RANGE is returned and *ppValue is +** not modified. Otherwise, SQLITE_OK. +*/ +SQLITE_API int sqlite3changeset_old( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Index of old.* value to retrieve */ + sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ +){ + if( pIter->op!=SQLITE_UPDATE && pIter->op!=SQLITE_DELETE ){ + return SQLITE_MISUSE; + } + if( iVal<0 || iVal>=pIter->nCol ){ + return SQLITE_RANGE; + } + *ppValue = pIter->apValue[iVal]; + return SQLITE_OK; +} + +/* +** This function may only be called while the iterator is pointing to an +** SQLITE_UPDATE or SQLITE_INSERT change (see sqlite3changeset_op()). +** Otherwise, SQLITE_MISUSE is returned. +** +** It sets *ppValue to point to an sqlite3_value structure containing the +** iVal'th value in the new.* record. Or, if that particular value is not +** included in the record (because the change is an UPDATE and the field +** was not modified), set *ppValue to NULL. +** +** If value iVal is out-of-range, SQLITE_RANGE is returned and *ppValue is +** not modified. Otherwise, SQLITE_OK. +*/ +SQLITE_API int sqlite3changeset_new( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Index of new.* value to retrieve */ + sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ +){ + if( pIter->op!=SQLITE_UPDATE && pIter->op!=SQLITE_INSERT ){ + return SQLITE_MISUSE; + } + if( iVal<0 || iVal>=pIter->nCol ){ + return SQLITE_RANGE; + } + *ppValue = pIter->apValue[pIter->nCol+iVal]; + return SQLITE_OK; +} + +/* +** The following two macros are used internally. They are similar to the +** sqlite3changeset_new() and sqlite3changeset_old() functions, except that +** they omit all error checking and return a pointer to the requested value. +*/ +#define sessionChangesetNew(pIter, iVal) (pIter)->apValue[(pIter)->nCol+(iVal)] +#define sessionChangesetOld(pIter, iVal) (pIter)->apValue[(iVal)] + +/* +** This function may only be called with a changeset iterator that has been +** passed to an SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT +** conflict-handler function. Otherwise, SQLITE_MISUSE is returned. +** +** If successful, *ppValue is set to point to an sqlite3_value structure +** containing the iVal'th value of the conflicting record. +** +** If value iVal is out-of-range or some other error occurs, an SQLite error +** code is returned. Otherwise, SQLITE_OK. +*/ +SQLITE_API int sqlite3changeset_conflict( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Index of conflict record value to fetch */ + sqlite3_value **ppValue /* OUT: Value from conflicting row */ +){ + if( !pIter->pConflict ){ + return SQLITE_MISUSE; + } + if( iVal<0 || iVal>=sqlite3_column_count(pIter->pConflict) ){ + return SQLITE_RANGE; + } + *ppValue = sqlite3_column_value(pIter->pConflict, iVal); + return SQLITE_OK; +} + +/* +** This function may only be called with an iterator passed to an +** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case +** it sets the output variable to the total number of known foreign key +** violations in the destination database and returns SQLITE_OK. +** +** In all other cases this function returns SQLITE_MISUSE. +*/ +SQLITE_API int sqlite3changeset_fk_conflicts( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int *pnOut /* OUT: Number of FK violations */ +){ + if( pIter->pConflict || pIter->apValue ){ + return SQLITE_MISUSE; + } + *pnOut = pIter->nCol; + return SQLITE_OK; +} + + +/* +** Finalize an iterator allocated with sqlite3changeset_start(). +** +** This function may not be called on iterators passed to a conflict handler +** callback by changeset_apply(). +*/ +SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *p){ + int rc = SQLITE_OK; + if( p ){ + int i; /* Used to iterate through p->apValue[] */ + rc = p->rc; + if( p->apValue ){ + for(i=0; inCol*2; i++) sqlite3ValueFree(p->apValue[i]); + } + sqlite3_free(p->tblhdr.aBuf); + sqlite3_free(p->in.buf.aBuf); + sqlite3_free(p); + } + return rc; +} + +static int sessionChangesetInvert( + SessionInput *pInput, /* Input changeset */ + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut, + int *pnInverted, /* OUT: Number of bytes in output changeset */ + void **ppInverted /* OUT: Inverse of pChangeset */ +){ + int rc = SQLITE_OK; /* Return value */ + SessionBuffer sOut; /* Output buffer */ + int nCol = 0; /* Number of cols in current table */ + u8 *abPK = 0; /* PK array for current table */ + sqlite3_value **apVal = 0; /* Space for values for UPDATE inversion */ + SessionBuffer sPK = {0, 0, 0}; /* PK array for current table */ + + /* Initialize the output buffer */ + memset(&sOut, 0, sizeof(SessionBuffer)); + + /* Zero the output variables in case an error occurs. */ + if( ppInverted ){ + *ppInverted = 0; + *pnInverted = 0; + } + + while( 1 ){ + u8 eType; + + /* Test for EOF. */ + if( (rc = sessionInputBuffer(pInput, 2)) ) goto finished_invert; + if( pInput->iNext>=pInput->nData ) break; + eType = pInput->aData[pInput->iNext]; + + switch( eType ){ + case 'T': { + /* A 'table' record consists of: + ** + ** * A constant 'T' character, + ** * Number of columns in said table (a varint), + ** * An array of nCol bytes (sPK), + ** * A nul-terminated table name. + */ + int nByte; + int nVar; + pInput->iNext++; + if( (rc = sessionChangesetBufferTblhdr(pInput, &nByte)) ){ + goto finished_invert; + } + nVar = sessionVarintGet(&pInput->aData[pInput->iNext], &nCol); + sPK.nBuf = 0; + sessionAppendBlob(&sPK, &pInput->aData[pInput->iNext+nVar], nCol, &rc); + sessionAppendByte(&sOut, eType, &rc); + sessionAppendBlob(&sOut, &pInput->aData[pInput->iNext], nByte, &rc); + if( rc ) goto finished_invert; + + pInput->iNext += nByte; + sqlite3_free(apVal); + apVal = 0; + abPK = sPK.aBuf; + break; + } + + case SQLITE_INSERT: + case SQLITE_DELETE: { + int nByte; + int bIndirect = pInput->aData[pInput->iNext+1]; + int eType2 = (eType==SQLITE_DELETE ? SQLITE_INSERT : SQLITE_DELETE); + pInput->iNext += 2; + assert( rc==SQLITE_OK ); + rc = sessionChangesetBufferRecord(pInput, nCol, &nByte); + sessionAppendByte(&sOut, eType2, &rc); + sessionAppendByte(&sOut, bIndirect, &rc); + sessionAppendBlob(&sOut, &pInput->aData[pInput->iNext], nByte, &rc); + pInput->iNext += nByte; + if( rc ) goto finished_invert; + break; + } + + case SQLITE_UPDATE: { + int iCol; + + if( 0==apVal ){ + apVal = (sqlite3_value **)sqlite3_malloc(sizeof(apVal[0])*nCol*2); + if( 0==apVal ){ + rc = SQLITE_NOMEM; + goto finished_invert; + } + memset(apVal, 0, sizeof(apVal[0])*nCol*2); + } + + /* Write the header for the new UPDATE change. Same as the original. */ + sessionAppendByte(&sOut, eType, &rc); + sessionAppendByte(&sOut, pInput->aData[pInput->iNext+1], &rc); + + /* Read the old.* and new.* records for the update change. */ + pInput->iNext += 2; + rc = sessionReadRecord(pInput, nCol, 0, &apVal[0]); + if( rc==SQLITE_OK ){ + rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol]); + } + + /* Write the new old.* record. Consists of the PK columns from the + ** original old.* record, and the other values from the original + ** new.* record. */ + for(iCol=0; iCol=SESSIONS_STRM_CHUNK_SIZE ){ + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); + sOut.nBuf = 0; + if( rc!=SQLITE_OK ) goto finished_invert; + } + } + + assert( rc==SQLITE_OK ); + if( pnInverted ){ + *pnInverted = sOut.nBuf; + *ppInverted = sOut.aBuf; + sOut.aBuf = 0; + }else if( sOut.nBuf>0 ){ + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); + } + + finished_invert: + sqlite3_free(sOut.aBuf); + sqlite3_free(apVal); + sqlite3_free(sPK.aBuf); + return rc; +} + + +/* +** Invert a changeset object. +*/ +SQLITE_API int sqlite3changeset_invert( + int nChangeset, /* Number of bytes in input */ + const void *pChangeset, /* Input changeset */ + int *pnInverted, /* OUT: Number of bytes in output changeset */ + void **ppInverted /* OUT: Inverse of pChangeset */ +){ + SessionInput sInput; + + /* Set up the input stream */ + memset(&sInput, 0, sizeof(SessionInput)); + sInput.nData = nChangeset; + sInput.aData = (u8*)pChangeset; + + return sessionChangesetInvert(&sInput, 0, 0, pnInverted, ppInverted); +} + +/* +** Streaming version of sqlite3changeset_invert(). +*/ +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 +){ + SessionInput sInput; + int rc; + + /* Set up the input stream */ + memset(&sInput, 0, sizeof(SessionInput)); + sInput.xInput = xInput; + sInput.pIn = pIn; + + rc = sessionChangesetInvert(&sInput, xOutput, pOut, 0, 0); + sqlite3_free(sInput.buf.aBuf); + return rc; +} + +typedef struct SessionApplyCtx SessionApplyCtx; +struct SessionApplyCtx { + sqlite3 *db; + sqlite3_stmt *pDelete; /* DELETE statement */ + sqlite3_stmt *pUpdate; /* UPDATE statement */ + sqlite3_stmt *pInsert; /* INSERT statement */ + sqlite3_stmt *pSelect; /* SELECT statement */ + int nCol; /* Size of azCol[] and abPK[] arrays */ + const char **azCol; /* Array of column names */ + u8 *abPK; /* Boolean array - true if column is in PK */ + + int bDeferConstraints; /* True to defer constraints */ + SessionBuffer constraints; /* Deferred constraints are stored here */ +}; + +/* +** Formulate a statement to DELETE a row from database db. Assuming a table +** structure like this: +** +** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c)); +** +** The DELETE statement looks like this: +** +** DELETE FROM x WHERE a = :1 AND c = :3 AND (:5 OR b IS :2 AND d IS :4) +** +** Variable :5 (nCol+1) is a boolean. It should be set to 0 if we require +** matching b and d values, or 1 otherwise. The second case comes up if the +** conflict handler is invoked with NOTFOUND and returns CHANGESET_REPLACE. +** +** If successful, SQLITE_OK is returned and SessionApplyCtx.pDelete is left +** pointing to the prepared version of the SQL statement. +*/ +static int sessionDeleteRow( + sqlite3 *db, /* Database handle */ + const char *zTab, /* Table name */ + SessionApplyCtx *p /* Session changeset-apply context */ +){ + int i; + const char *zSep = ""; + int rc = SQLITE_OK; + SessionBuffer buf = {0, 0, 0}; + int nPk = 0; + + sessionAppendStr(&buf, "DELETE FROM ", &rc); + sessionAppendIdent(&buf, zTab, &rc); + sessionAppendStr(&buf, " WHERE ", &rc); + + for(i=0; inCol; i++){ + if( p->abPK[i] ){ + nPk++; + sessionAppendStr(&buf, zSep, &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " = ?", &rc); + sessionAppendInteger(&buf, i+1, &rc); + zSep = " AND "; + } + } + + if( nPknCol ){ + sessionAppendStr(&buf, " AND (?", &rc); + sessionAppendInteger(&buf, p->nCol+1, &rc); + sessionAppendStr(&buf, " OR ", &rc); + + zSep = ""; + for(i=0; inCol; i++){ + if( !p->abPK[i] ){ + sessionAppendStr(&buf, zSep, &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " IS ?", &rc); + sessionAppendInteger(&buf, i+1, &rc); + zSep = "AND "; + } + } + sessionAppendStr(&buf, ")", &rc); + } + + if( rc==SQLITE_OK ){ + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pDelete, 0); + } + sqlite3_free(buf.aBuf); + + return rc; +} + +/* +** Formulate and prepare a statement to UPDATE a row from database db. +** Assuming a table structure like this: +** +** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c)); +** +** The UPDATE statement looks like this: +** +** UPDATE x SET +** a = CASE WHEN ?2 THEN ?3 ELSE a END, +** b = CASE WHEN ?5 THEN ?6 ELSE b END, +** c = CASE WHEN ?8 THEN ?9 ELSE c END, +** d = CASE WHEN ?11 THEN ?12 ELSE d END +** WHERE a = ?1 AND c = ?7 AND (?13 OR +** (?5==0 OR b IS ?4) AND (?11==0 OR d IS ?10) AND +** ) +** +** For each column in the table, there are three variables to bind: +** +** ?(i*3+1) The old.* value of the column, if any. +** ?(i*3+2) A boolean flag indicating that the value is being modified. +** ?(i*3+3) The new.* value of the column, if any. +** +** Also, a boolean flag that, if set to true, causes the statement to update +** a row even if the non-PK values do not match. This is required if the +** conflict-handler is invoked with CHANGESET_DATA and returns +** CHANGESET_REPLACE. This is variable "?(nCol*3+1)". +** +** If successful, SQLITE_OK is returned and SessionApplyCtx.pUpdate is left +** pointing to the prepared version of the SQL statement. +*/ +static int sessionUpdateRow( + sqlite3 *db, /* Database handle */ + const char *zTab, /* Table name */ + SessionApplyCtx *p /* Session changeset-apply context */ +){ + int rc = SQLITE_OK; + int i; + const char *zSep = ""; + SessionBuffer buf = {0, 0, 0}; + + /* Append "UPDATE tbl SET " */ + sessionAppendStr(&buf, "UPDATE ", &rc); + sessionAppendIdent(&buf, zTab, &rc); + sessionAppendStr(&buf, " SET ", &rc); + + /* Append the assignments */ + for(i=0; inCol; i++){ + sessionAppendStr(&buf, zSep, &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " = CASE WHEN ?", &rc); + sessionAppendInteger(&buf, i*3+2, &rc); + sessionAppendStr(&buf, " THEN ?", &rc); + sessionAppendInteger(&buf, i*3+3, &rc); + sessionAppendStr(&buf, " ELSE ", &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " END", &rc); + zSep = ", "; + } + + /* Append the PK part of the WHERE clause */ + sessionAppendStr(&buf, " WHERE ", &rc); + for(i=0; inCol; i++){ + if( p->abPK[i] ){ + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " = ?", &rc); + sessionAppendInteger(&buf, i*3+1, &rc); + sessionAppendStr(&buf, " AND ", &rc); + } + } + + /* Append the non-PK part of the WHERE clause */ + sessionAppendStr(&buf, " (?", &rc); + sessionAppendInteger(&buf, p->nCol*3+1, &rc); + sessionAppendStr(&buf, " OR 1", &rc); + for(i=0; inCol; i++){ + if( !p->abPK[i] ){ + sessionAppendStr(&buf, " AND (?", &rc); + sessionAppendInteger(&buf, i*3+2, &rc); + sessionAppendStr(&buf, "=0 OR ", &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " IS ?", &rc); + sessionAppendInteger(&buf, i*3+1, &rc); + sessionAppendStr(&buf, ")", &rc); + } + } + sessionAppendStr(&buf, ")", &rc); + + if( rc==SQLITE_OK ){ + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pUpdate, 0); + } + sqlite3_free(buf.aBuf); + + return rc; +} + +/* +** Formulate and prepare an SQL statement to query table zTab by primary +** key. Assuming the following table structure: +** +** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c)); +** +** The SELECT statement looks like this: +** +** SELECT * FROM x WHERE a = ?1 AND c = ?3 +** +** If successful, SQLITE_OK is returned and SessionApplyCtx.pSelect is left +** pointing to the prepared version of the SQL statement. +*/ +static int sessionSelectRow( + sqlite3 *db, /* Database handle */ + const char *zTab, /* Table name */ + SessionApplyCtx *p /* Session changeset-apply context */ +){ + return sessionSelectStmt( + db, "main", zTab, p->nCol, p->azCol, p->abPK, &p->pSelect); +} + +/* +** Formulate and prepare an INSERT statement to add a record to table zTab. +** For example: +** +** INSERT INTO main."zTab" VALUES(?1, ?2, ?3 ...); +** +** If successful, SQLITE_OK is returned and SessionApplyCtx.pInsert is left +** pointing to the prepared version of the SQL statement. +*/ +static int sessionInsertRow( + sqlite3 *db, /* Database handle */ + const char *zTab, /* Table name */ + SessionApplyCtx *p /* Session changeset-apply context */ +){ + int rc = SQLITE_OK; + int i; + SessionBuffer buf = {0, 0, 0}; + + sessionAppendStr(&buf, "INSERT INTO main.", &rc); + sessionAppendIdent(&buf, zTab, &rc); + sessionAppendStr(&buf, " VALUES(?", &rc); + for(i=1; inCol; i++){ + sessionAppendStr(&buf, ", ?", &rc); + } + sessionAppendStr(&buf, ")", &rc); + + if( rc==SQLITE_OK ){ + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pInsert, 0); + } + sqlite3_free(buf.aBuf); + return rc; +} + +/* +** A wrapper around sqlite3_bind_value() that detects an extra problem. +** See comments in the body of this function for details. +*/ +static int sessionBindValue( + sqlite3_stmt *pStmt, /* Statement to bind value to */ + int i, /* Parameter number to bind to */ + sqlite3_value *pVal /* Value to bind */ +){ + int eType = sqlite3_value_type(pVal); + /* COVERAGE: The (pVal->z==0) branch is never true using current versions + ** of SQLite. If a malloc fails in an sqlite3_value_xxx() function, either + ** the (pVal->z) variable remains as it was or the type of the value is + ** set to SQLITE_NULL. */ + if( (eType==SQLITE_TEXT || eType==SQLITE_BLOB) && pVal->z==0 ){ + /* This condition occurs when an earlier OOM in a call to + ** sqlite3_value_text() or sqlite3_value_blob() (perhaps from within + ** a conflict-handler) has zeroed the pVal->z pointer. Return NOMEM. */ + return SQLITE_NOMEM; + } + return sqlite3_bind_value(pStmt, i, pVal); +} + +/* +** Iterator pIter must point to an SQLITE_INSERT entry. This function +** transfers new.* values from the current iterator entry to statement +** pStmt. The table being inserted into has nCol columns. +** +** New.* value $i from the iterator is bound to variable ($i+1) of +** statement pStmt. If parameter abPK is NULL, all values from 0 to (nCol-1) +** are transfered to the statement. Otherwise, if abPK is not NULL, it points +** to an array nCol elements in size. In this case only those values for +** which abPK[$i] is true are read from the iterator and bound to the +** statement. +** +** An SQLite error code is returned if an error occurs. Otherwise, SQLITE_OK. +*/ +static int sessionBindRow( + sqlite3_changeset_iter *pIter, /* Iterator to read values from */ + int(*xValue)(sqlite3_changeset_iter *, int, sqlite3_value **), + int nCol, /* Number of columns */ + u8 *abPK, /* If not NULL, bind only if true */ + sqlite3_stmt *pStmt /* Bind values to this statement */ +){ + int i; + int rc = SQLITE_OK; + + /* Neither sqlite3changeset_old or sqlite3changeset_new can fail if the + ** argument iterator points to a suitable entry. Make sure that xValue + ** is one of these to guarantee that it is safe to ignore the return + ** in the code below. */ + assert( xValue==sqlite3changeset_old || xValue==sqlite3changeset_new ); + + for(i=0; rc==SQLITE_OK && idb, pIter, p->abPK, p->pSelect); + }else{ + rc = SQLITE_OK; + } + + if( rc==SQLITE_ROW ){ + /* There exists another row with the new.* primary key. */ + pIter->pConflict = p->pSelect; + res = xConflict(pCtx, eType, pIter); + pIter->pConflict = 0; + rc = sqlite3_reset(p->pSelect); + }else if( rc==SQLITE_OK ){ + if( p->bDeferConstraints && eType==SQLITE_CHANGESET_CONFLICT ){ + /* Instead of invoking the conflict handler, append the change blob + ** to the SessionApplyCtx.constraints buffer. */ + u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent]; + int nBlob = pIter->in.iNext - pIter->in.iCurrent; + sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc); + res = SQLITE_CHANGESET_OMIT; + }else{ + /* No other row with the new.* primary key. */ + res = xConflict(pCtx, eType+1, pIter); + if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE; + } + } + + if( rc==SQLITE_OK ){ + switch( res ){ + case SQLITE_CHANGESET_REPLACE: + assert( pbReplace ); + *pbReplace = 1; + break; + + case SQLITE_CHANGESET_OMIT: + break; + + case SQLITE_CHANGESET_ABORT: + rc = SQLITE_ABORT; + break; + + default: + rc = SQLITE_MISUSE; + break; + } + } + + return rc; +} + +/* +** Attempt to apply the change that the iterator passed as the first argument +** currently points to to the database. If a conflict is encountered, invoke +** the conflict handler callback. +** +** If argument pbRetry is NULL, then ignore any CHANGESET_DATA conflict. If +** one is encountered, update or delete the row with the matching primary key +** instead. Or, if pbRetry is not NULL and a CHANGESET_DATA conflict occurs, +** invoke the conflict handler. If it returns CHANGESET_REPLACE, set *pbRetry +** to true before returning. In this case the caller will invoke this function +** again, this time with pbRetry set to NULL. +** +** If argument pbReplace is NULL and a CHANGESET_CONFLICT conflict is +** encountered invoke the conflict handler with CHANGESET_CONSTRAINT instead. +** Or, if pbReplace is not NULL, invoke it with CHANGESET_CONFLICT. If such +** an invocation returns SQLITE_CHANGESET_REPLACE, set *pbReplace to true +** before retrying. In this case the caller attempts to remove the conflicting +** row before invoking this function again, this time with pbReplace set +** to NULL. +** +** If any conflict handler returns SQLITE_CHANGESET_ABORT, this function +** returns SQLITE_ABORT. Otherwise, if no error occurs, SQLITE_OK is +** returned. +*/ +static int sessionApplyOneOp( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + SessionApplyCtx *p, /* changeset_apply() context */ + int(*xConflict)(void *, int, sqlite3_changeset_iter *), + void *pCtx, /* First argument for the conflict handler */ + int *pbReplace, /* OUT: True to remove PK row and retry */ + int *pbRetry /* OUT: True to retry. */ +){ + const char *zDummy; + int op; + int nCol; + int rc = SQLITE_OK; + + assert( p->pDelete && p->pUpdate && p->pInsert && p->pSelect ); + assert( p->azCol && p->abPK ); + assert( !pbReplace || *pbReplace==0 ); + + sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0); + + if( op==SQLITE_DELETE ){ + + /* Bind values to the DELETE statement. If conflict handling is required, + ** bind values for all columns and set bound variable (nCol+1) to true. + ** Or, if conflict handling is not required, bind just the PK column + ** values and, if it exists, set (nCol+1) to false. Conflict handling + ** is not required if: + ** + ** * this is a patchset, or + ** * (pbRetry==0), or + ** * all columns of the table are PK columns (in this case there is + ** no (nCol+1) variable to bind to). + */ + u8 *abPK = (pIter->bPatchset ? p->abPK : 0); + rc = sessionBindRow(pIter, sqlite3changeset_old, nCol, abPK, p->pDelete); + if( rc==SQLITE_OK && sqlite3_bind_parameter_count(p->pDelete)>nCol ){ + rc = sqlite3_bind_int(p->pDelete, nCol+1, (pbRetry==0 || abPK)); + } + if( rc!=SQLITE_OK ) return rc; + + sqlite3_step(p->pDelete); + rc = sqlite3_reset(p->pDelete); + if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){ + rc = sessionConflictHandler( + SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry + ); + }else if( (rc&0xff)==SQLITE_CONSTRAINT ){ + rc = sessionConflictHandler( + SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0 + ); + } + + }else if( op==SQLITE_UPDATE ){ + int i; + + /* Bind values to the UPDATE statement. */ + for(i=0; rc==SQLITE_OK && ipUpdate, i*3+2, !!pNew); + if( pOld ){ + rc = sessionBindValue(p->pUpdate, i*3+1, pOld); + } + if( rc==SQLITE_OK && pNew ){ + rc = sessionBindValue(p->pUpdate, i*3+3, pNew); + } + } + if( rc==SQLITE_OK ){ + sqlite3_bind_int(p->pUpdate, nCol*3+1, pbRetry==0 || pIter->bPatchset); + } + if( rc!=SQLITE_OK ) return rc; + + /* Attempt the UPDATE. In the case of a NOTFOUND or DATA conflict, + ** the result will be SQLITE_OK with 0 rows modified. */ + sqlite3_step(p->pUpdate); + rc = sqlite3_reset(p->pUpdate); + + if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){ + /* A NOTFOUND or DATA error. Search the table to see if it contains + ** a row with a matching primary key. If so, this is a DATA conflict. + ** Otherwise, if there is no primary key match, it is a NOTFOUND. */ + + rc = sessionConflictHandler( + SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry + ); + + }else if( (rc&0xff)==SQLITE_CONSTRAINT ){ + /* This is always a CONSTRAINT conflict. */ + rc = sessionConflictHandler( + SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0 + ); + } + + }else{ + assert( op==SQLITE_INSERT ); + rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert); + if( rc!=SQLITE_OK ) return rc; + + sqlite3_step(p->pInsert); + rc = sqlite3_reset(p->pInsert); + if( (rc&0xff)==SQLITE_CONSTRAINT ){ + rc = sessionConflictHandler( + SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, pbReplace + ); + } + } + + return rc; +} + +/* +** Attempt to apply the change that the iterator passed as the first argument +** currently points to to the database. If a conflict is encountered, invoke +** the conflict handler callback. +** +** The difference between this function and sessionApplyOne() is that this +** function handles the case where the conflict-handler is invoked and +** returns SQLITE_CHANGESET_REPLACE - indicating that the change should be +** retried in some manner. +*/ +static int sessionApplyOneWithRetry( + sqlite3 *db, /* Apply change to "main" db of this handle */ + sqlite3_changeset_iter *pIter, /* Changeset iterator to read change from */ + SessionApplyCtx *pApply, /* Apply context */ + int(*xConflict)(void*, int, sqlite3_changeset_iter*), + void *pCtx /* First argument passed to xConflict */ +){ + int bReplace = 0; + int bRetry = 0; + int rc; + + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry); + assert( rc==SQLITE_OK || (bRetry==0 && bReplace==0) ); + + /* If the bRetry flag is set, the change has not been applied due to an + ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and + ** a row with the correct PK is present in the db, but one or more other + ** fields do not contain the expected values) and the conflict handler + ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation, + ** but pass NULL as the final argument so that sessionApplyOneOp() ignores + ** the SQLITE_CHANGESET_DATA problem. */ + if( bRetry ){ + assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE ); + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); + } + + /* If the bReplace flag is set, the change is an INSERT that has not + ** been performed because the database already contains a row with the + ** specified primary key and the conflict handler returned + ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row + ** before reattempting the INSERT. */ + else if( bReplace ){ + assert( pIter->op==SQLITE_INSERT ); + rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); + if( rc==SQLITE_OK ){ + rc = sessionBindRow(pIter, + sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete); + sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1); + } + if( rc==SQLITE_OK ){ + sqlite3_step(pApply->pDelete); + rc = sqlite3_reset(pApply->pDelete); + } + if( rc==SQLITE_OK ){ + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); + } + } + + return rc; +} + +/* +** Retry the changes accumulated in the pApply->constraints buffer. +*/ +static int sessionRetryConstraints( + sqlite3 *db, + int bPatchset, + const char *zTab, + SessionApplyCtx *pApply, + int(*xConflict)(void*, int, sqlite3_changeset_iter*), + void *pCtx /* First argument passed to xConflict */ +){ + int rc = SQLITE_OK; + + while( pApply->constraints.nBuf ){ + sqlite3_changeset_iter *pIter2 = 0; + SessionBuffer cons = pApply->constraints; + memset(&pApply->constraints, 0, sizeof(SessionBuffer)); + + rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf); + if( rc==SQLITE_OK ){ + int nByte = 2*pApply->nCol*sizeof(sqlite3_value*); + int rc2; + pIter2->bPatchset = bPatchset; + pIter2->zTab = (char*)zTab; + pIter2->nCol = pApply->nCol; + pIter2->abPK = pApply->abPK; + sessionBufferGrow(&pIter2->tblhdr, nByte, &rc); + pIter2->apValue = (sqlite3_value**)pIter2->tblhdr.aBuf; + if( rc==SQLITE_OK ) memset(pIter2->apValue, 0, nByte); + + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter2) ){ + rc = sessionApplyOneWithRetry(db, pIter2, pApply, xConflict, pCtx); + } + + rc2 = sqlite3changeset_finalize(pIter2); + if( rc==SQLITE_OK ) rc = rc2; + } + assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 ); + + sqlite3_free(cons.aBuf); + if( rc!=SQLITE_OK ) break; + if( pApply->constraints.nBuf>=cons.nBuf ){ + /* No progress was made on the last round. */ + pApply->bDeferConstraints = 0; + } + } + + return rc; +} + +/* +** Argument pIter is a changeset iterator that has been initialized, but +** not yet passed to sqlite3changeset_next(). This function applies the +** changeset to the main database attached to handle "db". The supplied +** conflict handler callback is invoked to resolve any conflicts encountered +** while applying the change. +*/ +static int sessionChangesetApply( + sqlite3 *db, /* Apply change to "main" db of this handle */ + sqlite3_changeset_iter *pIter, /* Changeset to apply */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of fifth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx /* First argument passed to xConflict */ +){ + int schemaMismatch = 0; + int rc; /* Return code */ + const char *zTab = 0; /* Name of current table */ + int nTab = 0; /* Result of sqlite3Strlen30(zTab) */ + SessionApplyCtx sApply; /* changeset_apply() context object */ + int bPatchset; + + assert( xConflict!=0 ); + + pIter->in.bNoDiscard = 1; + memset(&sApply, 0, sizeof(sApply)); + sqlite3_mutex_enter(sqlite3_db_mutex(db)); + rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 1", 0, 0, 0); + } + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){ + int nCol; + int op; + const char *zNew; + + sqlite3changeset_op(pIter, &zNew, &nCol, &op, 0); + + if( zTab==0 || sqlite3_strnicmp(zNew, zTab, nTab+1) ){ + u8 *abPK; + + rc = sessionRetryConstraints( + db, pIter->bPatchset, zTab, &sApply, xConflict, pCtx + ); + if( rc!=SQLITE_OK ) break; + + sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ + sqlite3_finalize(sApply.pDelete); + sqlite3_finalize(sApply.pUpdate); + sqlite3_finalize(sApply.pInsert); + sqlite3_finalize(sApply.pSelect); + memset(&sApply, 0, sizeof(sApply)); + sApply.db = db; + sApply.bDeferConstraints = 1; + + /* If an xFilter() callback was specified, invoke it now. If the + ** xFilter callback returns zero, skip this table. If it returns + ** non-zero, proceed. */ + schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew))); + if( schemaMismatch ){ + zTab = sqlite3_mprintf("%s", zNew); + if( zTab==0 ){ + rc = SQLITE_NOMEM; + break; + } + nTab = (int)strlen(zTab); + sApply.azCol = (const char **)zTab; + }else{ + sqlite3changeset_pk(pIter, &abPK, 0); + rc = sessionTableInfo( + db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK + ); + if( rc!=SQLITE_OK ) break; + + if( sApply.nCol==0 ){ + schemaMismatch = 1; + sqlite3_log(SQLITE_SCHEMA, + "sqlite3changeset_apply(): no such table: %s", zTab + ); + } + else if( sApply.nCol!=nCol ){ + schemaMismatch = 1; + sqlite3_log(SQLITE_SCHEMA, + "sqlite3changeset_apply(): table %s has %d columns, expected %d", + zTab, sApply.nCol, nCol + ); + } + else if( memcmp(sApply.abPK, abPK, nCol)!=0 ){ + schemaMismatch = 1; + sqlite3_log(SQLITE_SCHEMA, "sqlite3changeset_apply(): " + "primary key mismatch for table %s", zTab + ); + } + else if( + (rc = sessionSelectRow(db, zTab, &sApply)) + || (rc = sessionUpdateRow(db, zTab, &sApply)) + || (rc = sessionDeleteRow(db, zTab, &sApply)) + || (rc = sessionInsertRow(db, zTab, &sApply)) + ){ + break; + } + nTab = sqlite3Strlen30(zTab); + } + } + + /* If there is a schema mismatch on the current table, proceed to the + ** next change. A log message has already been issued. */ + if( schemaMismatch ) continue; + + rc = sessionApplyOneWithRetry(db, pIter, &sApply, xConflict, pCtx); + } + + bPatchset = pIter->bPatchset; + if( rc==SQLITE_OK ){ + rc = sqlite3changeset_finalize(pIter); + }else{ + sqlite3changeset_finalize(pIter); + } + + if( rc==SQLITE_OK ){ + rc = sessionRetryConstraints(db, bPatchset, zTab, &sApply, xConflict, pCtx); + } + + if( rc==SQLITE_OK ){ + int nFk, notUsed; + sqlite3_db_status(db, SQLITE_DBSTATUS_DEFERRED_FKS, &nFk, ¬Used, 0); + if( nFk!=0 ){ + int res = SQLITE_CHANGESET_ABORT; + sqlite3_changeset_iter sIter; + memset(&sIter, 0, sizeof(sIter)); + sIter.nCol = nFk; + res = xConflict(pCtx, SQLITE_CHANGESET_FOREIGN_KEY, &sIter); + if( res!=SQLITE_CHANGESET_OMIT ){ + rc = SQLITE_CONSTRAINT; + } + } + } + sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0); + + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); + }else{ + sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0); + sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); + } + + sqlite3_finalize(sApply.pInsert); + sqlite3_finalize(sApply.pDelete); + sqlite3_finalize(sApply.pUpdate); + sqlite3_finalize(sApply.pSelect); + sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ + sqlite3_free((char*)sApply.constraints.aBuf); + sqlite3_mutex_leave(sqlite3_db_mutex(db)); + return rc; +} + +/* +** Apply the changeset passed via pChangeset/nChangeset to the main database +** attached to handle "db". Invoke the supplied conflict handler callback +** to resolve any conflicts encountered while applying the change. +*/ +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 */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of fifth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx /* First argument passed to xConflict */ +){ + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ + int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + if( rc==SQLITE_OK ){ + rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); + } + return rc; +} + +/* +** Apply the changeset passed via xInput/pIn to the main database +** attached to handle "db". Invoke the supplied conflict handler callback +** to resolve any conflicts encountered while applying the change. +*/ +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 */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx /* First argument passed to xConflict */ +){ + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ + int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); + if( rc==SQLITE_OK ){ + rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); + } + return rc; +} + +/* +** sqlite3_changegroup handle. +*/ +struct sqlite3_changegroup { + int rc; /* Error code */ + int bPatch; /* True to accumulate patchsets */ + SessionTable *pList; /* List of tables in current patch */ +}; + +/* +** This function is called to merge two changes to the same row together as +** part of an sqlite3changeset_concat() operation. A new change object is +** allocated and a pointer to it stored in *ppNew. +*/ +static int sessionChangeMerge( + SessionTable *pTab, /* Table structure */ + int bPatchset, /* True for patchsets */ + SessionChange *pExist, /* Existing change */ + int op2, /* Second change operation */ + int bIndirect, /* True if second change is indirect */ + u8 *aRec, /* Second change record */ + int nRec, /* Number of bytes in aRec */ + SessionChange **ppNew /* OUT: Merged change */ +){ + SessionChange *pNew = 0; + + if( !pExist ){ + pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec); + if( !pNew ){ + return SQLITE_NOMEM; + } + memset(pNew, 0, sizeof(SessionChange)); + pNew->op = op2; + pNew->bIndirect = bIndirect; + pNew->nRecord = nRec; + pNew->aRecord = (u8*)&pNew[1]; + memcpy(pNew->aRecord, aRec, nRec); + }else{ + int op1 = pExist->op; + + /* + ** op1=INSERT, op2=INSERT -> Unsupported. Discard op2. + ** op1=INSERT, op2=UPDATE -> INSERT. + ** op1=INSERT, op2=DELETE -> (none) + ** + ** op1=UPDATE, op2=INSERT -> Unsupported. Discard op2. + ** op1=UPDATE, op2=UPDATE -> UPDATE. + ** op1=UPDATE, op2=DELETE -> DELETE. + ** + ** op1=DELETE, op2=INSERT -> UPDATE. + ** op1=DELETE, op2=UPDATE -> Unsupported. Discard op2. + ** op1=DELETE, op2=DELETE -> Unsupported. Discard op2. + */ + if( (op1==SQLITE_INSERT && op2==SQLITE_INSERT) + || (op1==SQLITE_UPDATE && op2==SQLITE_INSERT) + || (op1==SQLITE_DELETE && op2==SQLITE_UPDATE) + || (op1==SQLITE_DELETE && op2==SQLITE_DELETE) + ){ + pNew = pExist; + }else if( op1==SQLITE_INSERT && op2==SQLITE_DELETE ){ + sqlite3_free(pExist); + assert( pNew==0 ); + }else{ + u8 *aExist = pExist->aRecord; + int nByte; + u8 *aCsr; + + /* Allocate a new SessionChange object. Ensure that the aRecord[] + ** buffer of the new object is large enough to hold any record that + ** may be generated by combining the input records. */ + nByte = sizeof(SessionChange) + pExist->nRecord + nRec; + pNew = (SessionChange *)sqlite3_malloc(nByte); + if( !pNew ){ + sqlite3_free(pExist); + return SQLITE_NOMEM; + } + memset(pNew, 0, sizeof(SessionChange)); + pNew->bIndirect = (bIndirect && pExist->bIndirect); + aCsr = pNew->aRecord = (u8 *)&pNew[1]; + + if( op1==SQLITE_INSERT ){ /* INSERT + UPDATE */ + u8 *a1 = aRec; + assert( op2==SQLITE_UPDATE ); + pNew->op = SQLITE_INSERT; + if( bPatchset==0 ) sessionSkipRecord(&a1, pTab->nCol); + sessionMergeRecord(&aCsr, pTab->nCol, aExist, a1); + }else if( op1==SQLITE_DELETE ){ /* DELETE + INSERT */ + assert( op2==SQLITE_INSERT ); + pNew->op = SQLITE_UPDATE; + if( bPatchset ){ + memcpy(aCsr, aRec, nRec); + aCsr += nRec; + }else{ + if( 0==sessionMergeUpdate(&aCsr, pTab, bPatchset, aExist, 0,aRec,0) ){ + sqlite3_free(pNew); + pNew = 0; + } + } + }else if( op2==SQLITE_UPDATE ){ /* UPDATE + UPDATE */ + u8 *a1 = aExist; + u8 *a2 = aRec; + assert( op1==SQLITE_UPDATE ); + if( bPatchset==0 ){ + sessionSkipRecord(&a1, pTab->nCol); + sessionSkipRecord(&a2, pTab->nCol); + } + pNew->op = SQLITE_UPDATE; + if( 0==sessionMergeUpdate(&aCsr, pTab, bPatchset, aRec, aExist,a1,a2) ){ + sqlite3_free(pNew); + pNew = 0; + } + }else{ /* UPDATE + DELETE */ + assert( op1==SQLITE_UPDATE && op2==SQLITE_DELETE ); + pNew->op = SQLITE_DELETE; + if( bPatchset ){ + memcpy(aCsr, aRec, nRec); + aCsr += nRec; + }else{ + sessionMergeRecord(&aCsr, pTab->nCol, aRec, aExist); + } + } + + if( pNew ){ + pNew->nRecord = (int)(aCsr - pNew->aRecord); + } + sqlite3_free(pExist); + } + } + + *ppNew = pNew; + return SQLITE_OK; +} + +/* +** Add all changes in the changeset traversed by the iterator passed as +** the first argument to the changegroup hash tables. +*/ +static int sessionChangesetToHash( + sqlite3_changeset_iter *pIter, /* Iterator to read from */ + sqlite3_changegroup *pGrp /* Changegroup object to add changeset to */ +){ + u8 *aRec; + int nRec; + int rc = SQLITE_OK; + SessionTable *pTab = 0; + + + while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec) ){ + const char *zNew; + int nCol; + int op; + int iHash; + int bIndirect; + SessionChange *pChange; + SessionChange *pExist = 0; + SessionChange **pp; + + if( pGrp->pList==0 ){ + pGrp->bPatch = pIter->bPatchset; + }else if( pIter->bPatchset!=pGrp->bPatch ){ + rc = SQLITE_ERROR; + break; + } + + sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect); + if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){ + /* Search the list for a matching table */ + int nNew = (int)strlen(zNew); + u8 *abPK; + + sqlite3changeset_pk(pIter, &abPK, 0); + for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){ + if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break; + } + if( !pTab ){ + SessionTable **ppTab; + + pTab = sqlite3_malloc(sizeof(SessionTable) + nCol + nNew+1); + if( !pTab ){ + rc = SQLITE_NOMEM; + break; + } + memset(pTab, 0, sizeof(SessionTable)); + pTab->nCol = nCol; + pTab->abPK = (u8*)&pTab[1]; + memcpy(pTab->abPK, abPK, nCol); + pTab->zName = (char*)&pTab->abPK[nCol]; + memcpy(pTab->zName, zNew, nNew+1); + + /* The new object must be linked on to the end of the list, not + ** simply added to the start of it. This is to ensure that the + ** tables within the output of sqlite3changegroup_output() are in + ** the right order. */ + for(ppTab=&pGrp->pList; *ppTab; ppTab=&(*ppTab)->pNext); + *ppTab = pTab; + }else if( pTab->nCol!=nCol || memcmp(pTab->abPK, abPK, nCol) ){ + rc = SQLITE_SCHEMA; + break; + } + } + + if( sessionGrowHash(pIter->bPatchset, pTab) ){ + rc = SQLITE_NOMEM; + break; + } + iHash = sessionChangeHash( + pTab, (pIter->bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange + ); + + /* Search for existing entry. If found, remove it from the hash table. + ** Code below may link it back in. + */ + for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){ + int bPkOnly1 = 0; + int bPkOnly2 = 0; + if( pIter->bPatchset ){ + bPkOnly1 = (*pp)->op==SQLITE_DELETE; + bPkOnly2 = op==SQLITE_DELETE; + } + if( sessionChangeEqual(pTab, bPkOnly1, (*pp)->aRecord, bPkOnly2, aRec) ){ + pExist = *pp; + *pp = (*pp)->pNext; + pTab->nEntry--; + break; + } + } + + rc = sessionChangeMerge(pTab, + pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange + ); + if( rc ) break; + if( pChange ){ + pChange->pNext = pTab->apChange[iHash]; + pTab->apChange[iHash] = pChange; + pTab->nEntry++; + } + } + + if( rc==SQLITE_OK ) rc = pIter->rc; + return rc; +} + +/* +** Serialize a changeset (or patchset) based on all changesets (or patchsets) +** added to the changegroup object passed as the first argument. +** +** If xOutput is not NULL, then the changeset/patchset is returned to the +** user via one or more calls to xOutput, as with the other streaming +** interfaces. +** +** Or, if xOutput is NULL, then (*ppOut) is populated with a pointer to a +** buffer containing the output changeset before this function returns. In +** this case (*pnOut) is set to the size of the output buffer in bytes. It +** is the responsibility of the caller to free the output buffer using +** sqlite3_free() when it is no longer required. +** +** If successful, SQLITE_OK is returned. Or, if an error occurs, an SQLite +** error code. If an error occurs and xOutput is NULL, (*ppOut) and (*pnOut) +** are both set to 0 before returning. +*/ +static int sessionChangegroupOutput( + sqlite3_changegroup *pGrp, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut, + int *pnOut, + void **ppOut +){ + int rc = SQLITE_OK; + SessionBuffer buf = {0, 0, 0}; + SessionTable *pTab; + assert( xOutput==0 || (ppOut==0 && pnOut==0) ); + + /* Create the serialized output changeset based on the contents of the + ** hash tables attached to the SessionTable objects in list p->pList. + */ + for(pTab=pGrp->pList; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ + int i; + if( pTab->nEntry==0 ) continue; + + sessionAppendTableHdr(&buf, pGrp->bPatch, pTab, &rc); + for(i=0; inChange; i++){ + SessionChange *p; + for(p=pTab->apChange[i]; p; p=p->pNext){ + sessionAppendByte(&buf, p->op, &rc); + sessionAppendByte(&buf, p->bIndirect, &rc); + sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); + } + } + + if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ + rc = xOutput(pOut, buf.aBuf, buf.nBuf); + buf.nBuf = 0; + } + } + + if( rc==SQLITE_OK ){ + if( xOutput ){ + if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf); + }else{ + *ppOut = buf.aBuf; + *pnOut = buf.nBuf; + buf.aBuf = 0; + } + } + sqlite3_free(buf.aBuf); + + return rc; +} + +/* +** Allocate a new, empty, sqlite3_changegroup. +*/ +SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp){ + int rc = SQLITE_OK; /* Return code */ + sqlite3_changegroup *p; /* New object */ + p = (sqlite3_changegroup*)sqlite3_malloc(sizeof(sqlite3_changegroup)); + if( p==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(p, 0, sizeof(sqlite3_changegroup)); + } + *pp = p; + return rc; +} + +/* +** Add the changeset currently stored in buffer pData, size nData bytes, +** to changeset-group p. +*/ +SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void *pData){ + sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ + int rc; /* Return code */ + + rc = sqlite3changeset_start(&pIter, nData, pData); + if( rc==SQLITE_OK ){ + rc = sessionChangesetToHash(pIter, pGrp); + } + sqlite3changeset_finalize(pIter); + return rc; +} + +/* +** Obtain a buffer containing a changeset representing the concatenation +** of all changesets added to the group so far. +*/ +SQLITE_API int sqlite3changegroup_output( + sqlite3_changegroup *pGrp, + int *pnData, + void **ppData +){ + return sessionChangegroupOutput(pGrp, 0, 0, pnData, ppData); +} + +/* +** Streaming versions of changegroup_add(). +*/ +SQLITE_API int sqlite3changegroup_add_strm( + sqlite3_changegroup *pGrp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn +){ + sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ + int rc; /* Return code */ + + rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); + if( rc==SQLITE_OK ){ + rc = sessionChangesetToHash(pIter, pGrp); + } + sqlite3changeset_finalize(pIter); + return rc; +} + +/* +** Streaming versions of changegroup_output(). +*/ +SQLITE_API int sqlite3changegroup_output_strm( + sqlite3_changegroup *pGrp, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +){ + return sessionChangegroupOutput(pGrp, xOutput, pOut, 0, 0); +} + +/* +** Delete a changegroup object. +*/ +SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){ + if( pGrp ){ + sessionDeleteTable(pGrp->pList); + sqlite3_free(pGrp); + } +} + +/* +** Combine two changesets together. +*/ +SQLITE_API int sqlite3changeset_concat( + int nLeft, /* Number of bytes in lhs input */ + void *pLeft, /* Lhs input changeset */ + int nRight /* Number of bytes in rhs input */, + void *pRight, /* Rhs input changeset */ + int *pnOut, /* OUT: Number of bytes in output changeset */ + void **ppOut /* OUT: changeset (left right) */ +){ + sqlite3_changegroup *pGrp; + int rc; + + rc = sqlite3changegroup_new(&pGrp); + if( rc==SQLITE_OK ){ + rc = sqlite3changegroup_add(pGrp, nLeft, pLeft); + } + if( rc==SQLITE_OK ){ + rc = sqlite3changegroup_add(pGrp, nRight, pRight); + } + if( rc==SQLITE_OK ){ + rc = sqlite3changegroup_output(pGrp, pnOut, ppOut); + } + sqlite3changegroup_delete(pGrp); + + return rc; +} + +/* +** Streaming version of sqlite3changeset_concat(). +*/ +SQLITE_API int sqlite3changeset_concat_strm( + int (*xInputA)(void *pIn, void *pData, int *pnData), + void *pInA, + int (*xInputB)(void *pIn, void *pData, int *pnData), + void *pInB, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +){ + sqlite3_changegroup *pGrp; + int rc; + + rc = sqlite3changegroup_new(&pGrp); + if( rc==SQLITE_OK ){ + rc = sqlite3changegroup_add_strm(pGrp, xInputA, pInA); + } + if( rc==SQLITE_OK ){ + rc = sqlite3changegroup_add_strm(pGrp, xInputB, pInB); + } + if( rc==SQLITE_OK ){ + rc = sqlite3changegroup_output_strm(pGrp, xOutput, pOut); + } + sqlite3changegroup_delete(pGrp); + + return rc; +} + +#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ + +/************** End of sqlite3session.c **************************************/ /************** Begin file json1.c *******************************************/ /* ** 2015-08-12 @@ -166511,13 +176437,15 @@ SQLITE_EXTENSION_INIT1 #ifdef sqlite3Isdigit /* Use the SQLite core versions if this routine is part of the ** SQLite amalgamation */ -# define safe_isdigit(x) sqlite3Isdigit(x) -# define safe_isalnum(x) sqlite3Isalnum(x) +# define safe_isdigit(x) sqlite3Isdigit(x) +# define safe_isalnum(x) sqlite3Isalnum(x) +# define safe_isxdigit(x) sqlite3Isxdigit(x) #else /* Use the standard library for separate compilation */ #include /* amalgamator: keep */ -# define safe_isdigit(x) isdigit((unsigned char)(x)) -# define safe_isalnum(x) isalnum((unsigned char)(x)) +# define safe_isdigit(x) isdigit((unsigned char)(x)) +# define safe_isalnum(x) isalnum((unsigned char)(x)) +# define safe_isxdigit(x) isxdigit((unsigned char)(x)) #endif /* @@ -167164,6 +177092,15 @@ static int jsonParseAddNode( return pParse->nNode++; } +/* +** Return true if z[] begins with 4 (or more) hexadecimal digits +*/ +static int jsonIs4Hex(const char *z){ + int i; + for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0; + return 1; +} + /* ** Parse a single JSON value which begins at pParse->zJson[i]. Return the ** index of the first character past the end of the value parsed. @@ -167238,8 +177175,13 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ if( c==0 ) return -1; if( c=='\\' ){ c = pParse->zJson[++j]; - if( c==0 ) return -1; - jnFlags = JNODE_ESCAPE; + if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f' + || c=='n' || c=='r' || c=='t' + || (c=='u' && jsonIs4Hex(pParse->zJson+j+1)) ){ + jnFlags = JNODE_ESCAPE; + }else{ + return -1; + } }else if( c=='"' ){ break; } @@ -167673,6 +177615,26 @@ static void jsonTest1Func( ** Scalar SQL function implementations ****************************************************************************/ +/* +** Implementation of the json_QUOTE(VALUE) function. Return a JSON value +** corresponding to the SQL value input. Mostly this means putting +** double-quotes around strings and returning the unquoted string "null" +** when given a NULL input. +*/ +static void jsonQuoteFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonString jx; + UNUSED_PARAM(argc); + + jsonInit(&jx, ctx); + jsonAppendValue(&jx, argv[0]); + jsonResult(&jx); + sqlite3_result_subtype(ctx, JSON_SUBTYPE); +} + /* ** Implementation of the json_array(VALUE,...) function. Return a JSON ** array that contains all values given in arguments. Or if any argument @@ -168087,7 +178049,7 @@ static void jsonObjectFinal(sqlite3_context *ctx){ if( pStr ){ jsonAppendChar(pStr, '}'); if( pStr->bErr ){ - if( pStr->bErr==0 ) sqlite3_result_error_nomem(ctx); + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); assert( pStr->bStatic ); }else{ sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, @@ -168365,9 +178327,9 @@ static int jsonEachColumn( /* For json_each() path and root are the same so fall through ** into the root case */ } - case JEACH_ROOT: { + default: { const char *zRoot = p->zRoot; - if( zRoot==0 ) zRoot = "$"; + if( zRoot==0 ) zRoot = "$"; sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC); break; } @@ -168586,6 +178548,7 @@ SQLITE_PRIVATE int sqlite3Json1Init(sqlite3 *db){ { "json_extract", -1, 0, jsonExtractFunc }, { "json_insert", -1, 0, jsonSetFunc }, { "json_object", -1, 0, jsonObjectFunc }, + { "json_quote", 1, 0, jsonQuoteFunc }, { "json_remove", -1, 0, jsonRemoveFunc }, { "json_replace", -1, 0, jsonReplaceFunc }, { "json_set", -1, 1, jsonSetFunc }, @@ -168641,7 +178604,7 @@ SQLITE_PRIVATE int sqlite3Json1Init(sqlite3 *db){ #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_json_init( +SQLITE_API int sqlite3_json_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -168811,11 +178774,13 @@ struct Fts5PhraseIter { ** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid ** ** with $p set to a phrase equivalent to the phrase iPhrase of the -** current query is executed. For each row visited, the callback function -** passed as the fourth argument is invoked. The context and API objects -** passed to the callback function may be used to access the properties of -** each matched row. Invoking Api.xUserData() returns a copy of the pointer -** passed as the third argument to pUserData. +** current query is executed. Any column filter that applies to +** phrase iPhrase of the current query is included in $p. For each +** row visited, the callback function passed as the fourth argument +** is invoked. The context and API objects passed to the callback +** function may be used to access the properties of each matched row. +** Invoking Api.xUserData() returns a copy of the pointer passed as +** the third argument to pUserData. ** ** If the callback function returns any value other than SQLITE_OK, the ** query is abandoned and the xQueryPhrase function returns immediately. @@ -168984,7 +178949,7 @@ struct Fts5ExtensionApi { ** behaviour. The structure methods are expected to function as follows: ** ** xCreate: -** This function is used to allocate and inititalize a tokenizer instance. +** This function is used to allocate and initialize a tokenizer instance. ** A tokenizer instance is required to actually tokenize text. ** ** The first argument passed to this function is a copy of the (void*) @@ -169244,7 +179209,6 @@ struct fts5_api { #endif /* _FTS5_H */ - /* ** 2014 May 31 ** @@ -169933,7 +179897,6 @@ static int sqlite3Fts5ExprPopulatePoslists( Fts5Config*, Fts5Expr*, Fts5PoslistPopulator*, int, const char*, int ); static void sqlite3Fts5ExprCheckPoslists(Fts5Expr*, i64); -static void sqlite3Fts5ExprClearEof(Fts5Expr*); static int sqlite3Fts5ExprClonePhrase(Fts5Expr*, int, Fts5Expr**); @@ -169985,6 +179948,7 @@ static void sqlite3Fts5ParseNodeFree(Fts5ExprNode*); static void sqlite3Fts5ParseSetDistance(Fts5Parse*, Fts5ExprNearset*, Fts5Token*); static void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNearset*, Fts5Colset*); +static Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse*, Fts5Colset*); static void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p); static void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token*); @@ -170042,12 +180006,13 @@ static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic); #define FTS5_COLON 5 #define FTS5_LP 6 #define FTS5_RP 7 -#define FTS5_LCP 8 -#define FTS5_RCP 9 -#define FTS5_STRING 10 -#define FTS5_COMMA 11 -#define FTS5_PLUS 12 -#define FTS5_STAR 13 +#define FTS5_MINUS 8 +#define FTS5_LCP 9 +#define FTS5_RCP 10 +#define FTS5_STRING 11 +#define FTS5_COMMA 12 +#define FTS5_PLUS 13 +#define FTS5_STAR 14 /* ** 2000-05-29 @@ -170161,17 +180126,17 @@ static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic); #endif /************* Begin control #defines *****************************************/ #define fts5YYCODETYPE unsigned char -#define fts5YYNOCODE 27 +#define fts5YYNOCODE 28 #define fts5YYACTIONTYPE unsigned char #define sqlite3Fts5ParserFTS5TOKENTYPE Fts5Token typedef union { int fts5yyinit; sqlite3Fts5ParserFTS5TOKENTYPE fts5yy0; - Fts5Colset* fts5yy3; - Fts5ExprPhrase* fts5yy11; - Fts5ExprNode* fts5yy18; - int fts5yy20; - Fts5ExprNearset* fts5yy26; + int fts5yy4; + Fts5Colset* fts5yy11; + Fts5ExprNode* fts5yy24; + Fts5ExprNearset* fts5yy46; + Fts5ExprPhrase* fts5yy53; } fts5YYMINORTYPE; #ifndef fts5YYSTACKDEPTH #define fts5YYSTACKDEPTH 100 @@ -170180,16 +180145,16 @@ typedef union { #define sqlite3Fts5ParserARG_PDECL ,Fts5Parse *pParse #define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse = fts5yypParser->pParse #define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse = pParse -#define fts5YYNSTATE 26 -#define fts5YYNRULE 24 -#define fts5YY_MAX_SHIFT 25 -#define fts5YY_MIN_SHIFTREDUCE 40 -#define fts5YY_MAX_SHIFTREDUCE 63 -#define fts5YY_MIN_REDUCE 64 -#define fts5YY_MAX_REDUCE 87 -#define fts5YY_ERROR_ACTION 88 -#define fts5YY_ACCEPT_ACTION 89 -#define fts5YY_NO_ACTION 90 +#define fts5YYNSTATE 29 +#define fts5YYNRULE 26 +#define fts5YY_MAX_SHIFT 28 +#define fts5YY_MIN_SHIFTREDUCE 45 +#define fts5YY_MAX_SHIFTREDUCE 70 +#define fts5YY_MIN_REDUCE 71 +#define fts5YY_MAX_REDUCE 96 +#define fts5YY_ERROR_ACTION 97 +#define fts5YY_ACCEPT_ACTION 98 +#define fts5YY_NO_ACTION 99 /************* End control #defines *******************************************/ /* Define the fts5yytestcase() macro to be a no-op if is not already defined @@ -170221,7 +180186,7 @@ typedef union { ** ** N between fts5YY_MIN_REDUCE Reduce by rule N-fts5YY_MIN_REDUCE ** and fts5YY_MAX_REDUCE - +** ** N == fts5YY_ERROR_ACTION A syntax error has occurred. ** ** N == fts5YY_ACCEPT_ACTION The parser accepts its input. @@ -170230,16 +180195,20 @@ typedef union { ** slots in the fts5yy_action[] table. ** ** The action table is constructed as a single large table named fts5yy_action[]. -** Given state S and lookahead X, the action is computed as +** Given state S and lookahead X, the action is computed as either: ** -** fts5yy_action[ fts5yy_shift_ofst[S] + X ] +** (A) N = fts5yy_action[ fts5yy_shift_ofst[S] + X ] +** (B) N = fts5yy_default[S] ** -** If the index value fts5yy_shift_ofst[S]+X is out of range or if the value -** fts5yy_lookahead[fts5yy_shift_ofst[S]+X] is not equal to X or if fts5yy_shift_ofst[S] -** is equal to fts5YY_SHIFT_USE_DFLT, it means that the action is not in the table -** and that fts5yy_default[S] should be used instead. +** The (A) formula is preferred. The B formula is used instead if: +** (1) The fts5yy_shift_ofst[S]+X value is out of range, or +** (2) fts5yy_lookahead[fts5yy_shift_ofst[S]+X] is not equal to X, or +** (3) fts5yy_shift_ofst[S] equal fts5YY_SHIFT_USE_DFLT. +** (Implementation note: fts5YY_SHIFT_USE_DFLT is chosen so that +** fts5YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. +** Hence only tests (1) and (2) need to be evaluated.) ** -** The formula above is for computing the action when the lookahead is +** The formulas above are for computing the action when the lookahead is ** a terminal symbol. If the lookahead is a non-terminal (as occurs after ** a reduce action) then the fts5yy_reduce_ofst[] array is used in place of ** the fts5yy_shift_ofst[] array and fts5YY_REDUCE_USE_DFLT is used in place of @@ -170257,48 +180226,50 @@ typedef union { ** fts5yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define fts5YY_ACTTAB_COUNT (78) +#define fts5YY_ACTTAB_COUNT (85) static const fts5YYACTIONTYPE fts5yy_action[] = { - /* 0 */ 89, 15, 46, 5, 48, 24, 12, 19, 23, 14, - /* 10 */ 46, 5, 48, 24, 20, 21, 23, 43, 46, 5, - /* 20 */ 48, 24, 6, 18, 23, 17, 46, 5, 48, 24, - /* 30 */ 75, 7, 23, 25, 46, 5, 48, 24, 62, 47, - /* 40 */ 23, 48, 24, 7, 11, 23, 9, 3, 4, 2, - /* 50 */ 62, 50, 52, 44, 64, 3, 4, 2, 49, 4, - /* 60 */ 2, 1, 23, 11, 16, 9, 12, 2, 10, 61, - /* 70 */ 53, 59, 62, 60, 22, 13, 55, 8, + /* 0 */ 98, 16, 51, 5, 53, 27, 83, 7, 26, 15, + /* 10 */ 51, 5, 53, 27, 13, 69, 26, 48, 51, 5, + /* 20 */ 53, 27, 19, 11, 26, 9, 20, 51, 5, 53, + /* 30 */ 27, 13, 22, 26, 28, 51, 5, 53, 27, 68, + /* 40 */ 1, 26, 19, 11, 17, 9, 52, 10, 53, 27, + /* 50 */ 23, 24, 26, 54, 3, 4, 2, 26, 6, 21, + /* 60 */ 49, 71, 3, 4, 2, 7, 56, 59, 55, 59, + /* 70 */ 4, 2, 12, 69, 58, 60, 18, 67, 62, 69, + /* 80 */ 25, 66, 8, 14, 2, }; static const fts5YYCODETYPE fts5yy_lookahead[] = { - /* 0 */ 15, 16, 17, 18, 19, 20, 10, 11, 23, 16, - /* 10 */ 17, 18, 19, 20, 23, 24, 23, 16, 17, 18, - /* 20 */ 19, 20, 22, 23, 23, 16, 17, 18, 19, 20, - /* 30 */ 5, 6, 23, 16, 17, 18, 19, 20, 13, 17, - /* 40 */ 23, 19, 20, 6, 8, 23, 10, 1, 2, 3, - /* 50 */ 13, 9, 10, 7, 0, 1, 2, 3, 19, 2, - /* 60 */ 3, 6, 23, 8, 21, 10, 10, 3, 10, 25, - /* 70 */ 10, 10, 13, 25, 12, 10, 7, 5, + /* 0 */ 16, 17, 18, 19, 20, 21, 5, 6, 24, 17, + /* 10 */ 18, 19, 20, 21, 11, 14, 24, 17, 18, 19, + /* 20 */ 20, 21, 8, 9, 24, 11, 17, 18, 19, 20, + /* 30 */ 21, 11, 12, 24, 17, 18, 19, 20, 21, 26, + /* 40 */ 6, 24, 8, 9, 22, 11, 18, 11, 20, 21, + /* 50 */ 24, 25, 24, 20, 1, 2, 3, 24, 23, 24, + /* 60 */ 7, 0, 1, 2, 3, 6, 10, 11, 10, 11, + /* 70 */ 2, 3, 9, 14, 11, 11, 22, 26, 7, 14, + /* 80 */ 13, 11, 5, 11, 3, }; -#define fts5YY_SHIFT_USE_DFLT (-5) -#define fts5YY_SHIFT_COUNT (25) -#define fts5YY_SHIFT_MIN (-4) -#define fts5YY_SHIFT_MAX (72) -static const signed char fts5yy_shift_ofst[] = { - /* 0 */ 55, 55, 55, 55, 55, 36, -4, 56, 58, 25, - /* 10 */ 37, 60, 59, 59, 46, 54, 42, 57, 62, 61, - /* 20 */ 62, 69, 65, 62, 72, 64, +#define fts5YY_SHIFT_USE_DFLT (85) +#define fts5YY_SHIFT_COUNT (28) +#define fts5YY_SHIFT_MIN (0) +#define fts5YY_SHIFT_MAX (81) +static const unsigned char fts5yy_shift_ofst[] = { + /* 0 */ 34, 34, 34, 34, 34, 14, 20, 3, 36, 1, + /* 10 */ 59, 64, 64, 65, 65, 53, 61, 56, 58, 63, + /* 20 */ 68, 67, 70, 67, 71, 72, 67, 77, 81, }; -#define fts5YY_REDUCE_USE_DFLT (-16) -#define fts5YY_REDUCE_COUNT (13) -#define fts5YY_REDUCE_MIN (-15) -#define fts5YY_REDUCE_MAX (48) +#define fts5YY_REDUCE_USE_DFLT (-17) +#define fts5YY_REDUCE_COUNT (14) +#define fts5YY_REDUCE_MIN (-16) +#define fts5YY_REDUCE_MAX (54) static const signed char fts5yy_reduce_ofst[] = { - /* 0 */ -15, -7, 1, 9, 17, 22, -9, 0, 39, 44, - /* 10 */ 44, 43, 44, 48, + /* 0 */ -16, -8, 0, 9, 17, 28, 26, 35, 33, 13, + /* 10 */ 13, 22, 54, 13, 51, }; static const fts5YYACTIONTYPE fts5yy_default[] = { - /* 0 */ 88, 88, 88, 88, 88, 69, 82, 88, 88, 87, - /* 10 */ 87, 88, 87, 87, 88, 88, 88, 66, 80, 88, - /* 20 */ 81, 88, 88, 78, 88, 65, + /* 0 */ 97, 97, 97, 97, 97, 76, 91, 97, 97, 96, + /* 10 */ 96, 97, 97, 96, 96, 97, 97, 97, 97, 97, + /* 20 */ 73, 89, 97, 90, 97, 97, 87, 97, 72, }; /********** End of lemon-generated parsing tables *****************************/ @@ -170349,9 +180320,9 @@ typedef struct fts5yyStackEntry fts5yyStackEntry; /* The state of the parser is completely contained in an instance of ** the following structure */ struct fts5yyParser { - int fts5yyidx; /* Index of top element in stack */ + fts5yyStackEntry *fts5yytos; /* Pointer to top element of the stack */ #ifdef fts5YYTRACKMAXSTACKDEPTH - int fts5yyidxMax; /* Maximum value of fts5yyidx */ + int fts5yyhwm; /* High-water mark of the stack */ #endif #ifndef fts5YYNOERRORRECOVERY int fts5yyerrcnt; /* Shifts left before out of the error */ @@ -170360,6 +180331,7 @@ struct fts5yyParser { #if fts5YYSTACKDEPTH<=0 int fts5yystksz; /* Current side of the stack */ fts5yyStackEntry *fts5yystack; /* The parser's stack */ + fts5yyStackEntry fts5yystk0; /* First stack entry */ #else fts5yyStackEntry fts5yystack[fts5YYSTACKDEPTH]; /* The parser's stack */ #endif @@ -170404,11 +180376,11 @@ static void sqlite3Fts5ParserTrace(FILE *TraceFILE, char *zTracePrompt){ static const char *const fts5yyTokenName[] = { "$", "OR", "AND", "NOT", "TERM", "COLON", "LP", "RP", - "LCP", "RCP", "STRING", "COMMA", - "PLUS", "STAR", "error", "input", - "expr", "cnearset", "exprlist", "nearset", - "colset", "colsetlist", "nearphrases", "phrase", - "neardist_opt", "star_opt", + "MINUS", "LCP", "RCP", "STRING", + "COMMA", "PLUS", "STAR", "error", + "input", "expr", "cnearset", "exprlist", + "nearset", "colset", "colsetlist", "nearphrases", + "phrase", "neardist_opt", "star_opt", }; #endif /* NDEBUG */ @@ -170426,44 +180398,56 @@ static const char *const fts5yyRuleName[] = { /* 7 */ "exprlist ::= exprlist cnearset", /* 8 */ "cnearset ::= nearset", /* 9 */ "cnearset ::= colset COLON nearset", - /* 10 */ "colset ::= LCP colsetlist RCP", - /* 11 */ "colset ::= STRING", - /* 12 */ "colsetlist ::= colsetlist STRING", - /* 13 */ "colsetlist ::= STRING", - /* 14 */ "nearset ::= phrase", - /* 15 */ "nearset ::= STRING LP nearphrases neardist_opt RP", - /* 16 */ "nearphrases ::= phrase", - /* 17 */ "nearphrases ::= nearphrases phrase", - /* 18 */ "neardist_opt ::=", - /* 19 */ "neardist_opt ::= COMMA STRING", - /* 20 */ "phrase ::= phrase PLUS STRING star_opt", - /* 21 */ "phrase ::= STRING star_opt", - /* 22 */ "star_opt ::= STAR", - /* 23 */ "star_opt ::=", + /* 10 */ "colset ::= MINUS LCP colsetlist RCP", + /* 11 */ "colset ::= LCP colsetlist RCP", + /* 12 */ "colset ::= STRING", + /* 13 */ "colset ::= MINUS STRING", + /* 14 */ "colsetlist ::= colsetlist STRING", + /* 15 */ "colsetlist ::= STRING", + /* 16 */ "nearset ::= phrase", + /* 17 */ "nearset ::= STRING LP nearphrases neardist_opt RP", + /* 18 */ "nearphrases ::= phrase", + /* 19 */ "nearphrases ::= nearphrases phrase", + /* 20 */ "neardist_opt ::=", + /* 21 */ "neardist_opt ::= COMMA STRING", + /* 22 */ "phrase ::= phrase PLUS STRING star_opt", + /* 23 */ "phrase ::= STRING star_opt", + /* 24 */ "star_opt ::= STAR", + /* 25 */ "star_opt ::=", }; #endif /* NDEBUG */ #if fts5YYSTACKDEPTH<=0 /* -** Try to increase the size of the parser stack. +** Try to increase the size of the parser stack. Return the number +** of errors. Return 0 on success. */ -static void fts5yyGrowStack(fts5yyParser *p){ +static int fts5yyGrowStack(fts5yyParser *p){ int newSize; + int idx; fts5yyStackEntry *pNew; newSize = p->fts5yystksz*2 + 100; - pNew = realloc(p->fts5yystack, newSize*sizeof(pNew[0])); + idx = p->fts5yytos ? (int)(p->fts5yytos - p->fts5yystack) : 0; + if( p->fts5yystack==&p->fts5yystk0 ){ + pNew = malloc(newSize*sizeof(pNew[0])); + if( pNew ) pNew[0] = p->fts5yystk0; + }else{ + pNew = realloc(p->fts5yystack, newSize*sizeof(pNew[0])); + } if( pNew ){ p->fts5yystack = pNew; - p->fts5yystksz = newSize; + p->fts5yytos = &p->fts5yystack[idx]; #ifndef NDEBUG if( fts5yyTraceFILE ){ - fprintf(fts5yyTraceFILE,"%sStack grows to %d entries!\n", - fts5yyTracePrompt, p->fts5yystksz); + fprintf(fts5yyTraceFILE,"%sStack grows from %d to %d entries.\n", + fts5yyTracePrompt, p->fts5yystksz, newSize); } #endif + p->fts5yystksz = newSize; } + return pNew==0; } #endif @@ -170492,15 +180476,24 @@ static void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(fts5YYMALLOCARGTYPE)){ fts5yyParser *pParser; pParser = (fts5yyParser*)(*mallocProc)( (fts5YYMALLOCARGTYPE)sizeof(fts5yyParser) ); if( pParser ){ - pParser->fts5yyidx = -1; #ifdef fts5YYTRACKMAXSTACKDEPTH - pParser->fts5yyidxMax = 0; + pParser->fts5yyhwm = 0; #endif #if fts5YYSTACKDEPTH<=0 + pParser->fts5yytos = NULL; pParser->fts5yystack = NULL; pParser->fts5yystksz = 0; - fts5yyGrowStack(pParser); + if( fts5yyGrowStack(pParser) ){ + pParser->fts5yystack = &pParser->fts5yystk0; + pParser->fts5yystksz = 1; + } +#endif +#ifndef fts5YYNOERRORRECOVERY + pParser->fts5yyerrcnt = -1; #endif + pParser->fts5yytos = pParser->fts5yystack; + pParser->fts5yystack[0].stateno = 0; + pParser->fts5yystack[0].major = 0; } return pParser; } @@ -170530,33 +180523,33 @@ static void fts5yy_destructor( ** inside the C code. */ /********* Begin destructor definitions ***************************************/ - case 15: /* input */ + case 16: /* input */ { (void)pParse; } break; - case 16: /* expr */ - case 17: /* cnearset */ - case 18: /* exprlist */ + case 17: /* expr */ + case 18: /* cnearset */ + case 19: /* exprlist */ { - sqlite3Fts5ParseNodeFree((fts5yypminor->fts5yy18)); + sqlite3Fts5ParseNodeFree((fts5yypminor->fts5yy24)); } break; - case 19: /* nearset */ - case 22: /* nearphrases */ + case 20: /* nearset */ + case 23: /* nearphrases */ { - sqlite3Fts5ParseNearsetFree((fts5yypminor->fts5yy26)); + sqlite3Fts5ParseNearsetFree((fts5yypminor->fts5yy46)); } break; - case 20: /* colset */ - case 21: /* colsetlist */ + case 21: /* colset */ + case 22: /* colsetlist */ { - sqlite3_free((fts5yypminor->fts5yy3)); + sqlite3_free((fts5yypminor->fts5yy11)); } break; - case 23: /* phrase */ + case 24: /* phrase */ { - sqlite3Fts5ParsePhraseFree((fts5yypminor->fts5yy11)); + sqlite3Fts5ParsePhraseFree((fts5yypminor->fts5yy53)); } break; /********* End destructor definitions *****************************************/ @@ -170572,8 +180565,9 @@ static void fts5yy_destructor( */ static void fts5yy_pop_parser_stack(fts5yyParser *pParser){ fts5yyStackEntry *fts5yytos; - assert( pParser->fts5yyidx>=0 ); - fts5yytos = &pParser->fts5yystack[pParser->fts5yyidx--]; + assert( pParser->fts5yytos!=0 ); + assert( pParser->fts5yytos > pParser->fts5yystack ); + fts5yytos = pParser->fts5yytos--; #ifndef NDEBUG if( fts5yyTraceFILE ){ fprintf(fts5yyTraceFILE,"%sPopping %s\n", @@ -170600,9 +180594,9 @@ static void sqlite3Fts5ParserFree( #ifndef fts5YYPARSEFREENEVERNULL if( pParser==0 ) return; #endif - while( pParser->fts5yyidx>=0 ) fts5yy_pop_parser_stack(pParser); + while( pParser->fts5yytos>pParser->fts5yystack ) fts5yy_pop_parser_stack(pParser); #if fts5YYSTACKDEPTH<=0 - free(pParser->fts5yystack); + if( pParser->fts5yystack!=&pParser->fts5yystk0 ) free(pParser->fts5yystack); #endif (*freeProc)((void*)pParser); } @@ -170613,7 +180607,7 @@ static void sqlite3Fts5ParserFree( #ifdef fts5YYTRACKMAXSTACKDEPTH static int sqlite3Fts5ParserStackPeak(void *p){ fts5yyParser *pParser = (fts5yyParser*)p; - return pParser->fts5yyidxMax; + return pParser->fts5yyhwm; } #endif @@ -170626,56 +180620,53 @@ static unsigned int fts5yy_find_shift_action( fts5YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; - int stateno = pParser->fts5yystack[pParser->fts5yyidx].stateno; + int stateno = pParser->fts5yytos->stateno; if( stateno>=fts5YY_MIN_REDUCE ) return stateno; assert( stateno <= fts5YY_SHIFT_COUNT ); do{ i = fts5yy_shift_ofst[stateno]; - if( i==fts5YY_SHIFT_USE_DFLT ) return fts5yy_default[stateno]; assert( iLookAhead!=fts5YYNOCODE ); i += iLookAhead; if( i<0 || i>=fts5YY_ACTTAB_COUNT || fts5yy_lookahead[i]!=iLookAhead ){ - if( iLookAhead>0 ){ #ifdef fts5YYFALLBACK - fts5YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", - fts5yyTracePrompt, fts5yyTokenName[iLookAhead], fts5yyTokenName[iFallback]); - } -#endif - assert( fts5yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ - iLookAhead = iFallback; - continue; + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE, "%sFALLBACK %s => %s\n", + fts5yyTracePrompt, fts5yyTokenName[iLookAhead], fts5yyTokenName[iFallback]); } +#endif + assert( fts5yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ + iLookAhead = iFallback; + continue; + } #endif #ifdef fts5YYWILDCARD - { - int j = i - iLookAhead + fts5YYWILDCARD; - if( + { + int j = i - iLookAhead + fts5YYWILDCARD; + if( #if fts5YY_SHIFT_MIN+fts5YYWILDCARD<0 - j>=0 && + j>=0 && #endif #if fts5YY_SHIFT_MAX+fts5YYWILDCARD>=fts5YY_ACTTAB_COUNT - j0 + ){ #ifndef NDEBUG - if( fts5yyTraceFILE ){ - fprintf(fts5yyTraceFILE, "%sWILDCARD %s => %s\n", - fts5yyTracePrompt, fts5yyTokenName[iLookAhead], - fts5yyTokenName[fts5YYWILDCARD]); - } -#endif /* NDEBUG */ - return fts5yy_action[j]; + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE, "%sWILDCARD %s => %s\n", + fts5yyTracePrompt, fts5yyTokenName[iLookAhead], + fts5yyTokenName[fts5YYWILDCARD]); } +#endif /* NDEBUG */ + return fts5yy_action[j]; } -#endif /* fts5YYWILDCARD */ } +#endif /* fts5YYWILDCARD */ return fts5yy_default[stateno]; }else{ return fts5yy_action[i]; @@ -170719,13 +180710,13 @@ static int fts5yy_find_reduce_action( */ static void fts5yyStackOverflow(fts5yyParser *fts5yypParser){ sqlite3Fts5ParserARG_FETCH; - fts5yypParser->fts5yyidx--; + fts5yypParser->fts5yytos--; #ifndef NDEBUG if( fts5yyTraceFILE ){ fprintf(fts5yyTraceFILE,"%sStack Overflow!\n",fts5yyTracePrompt); } #endif - while( fts5yypParser->fts5yyidx>=0 ) fts5yy_pop_parser_stack(fts5yypParser); + while( fts5yypParser->fts5yytos>fts5yypParser->fts5yystack ) fts5yy_pop_parser_stack(fts5yypParser); /* Here code is inserted which will execute if the parser ** stack every overflows */ /******** Begin %stack_overflow code ******************************************/ @@ -170743,11 +180734,11 @@ static void fts5yyTraceShift(fts5yyParser *fts5yypParser, int fts5yyNewState){ if( fts5yyTraceFILE ){ if( fts5yyNewStatefts5yystack[fts5yypParser->fts5yyidx].major], + fts5yyTracePrompt,fts5yyTokenName[fts5yypParser->fts5yytos->major], fts5yyNewState); }else{ fprintf(fts5yyTraceFILE,"%sShift '%s'\n", - fts5yyTracePrompt,fts5yyTokenName[fts5yypParser->fts5yystack[fts5yypParser->fts5yyidx].major]); + fts5yyTracePrompt,fts5yyTokenName[fts5yypParser->fts5yytos->major]); } } } @@ -170765,27 +180756,30 @@ static void fts5yy_shift( sqlite3Fts5ParserFTS5TOKENTYPE fts5yyMinor /* The minor token to shift in */ ){ fts5yyStackEntry *fts5yytos; - fts5yypParser->fts5yyidx++; + fts5yypParser->fts5yytos++; #ifdef fts5YYTRACKMAXSTACKDEPTH - if( fts5yypParser->fts5yyidx>fts5yypParser->fts5yyidxMax ){ - fts5yypParser->fts5yyidxMax = fts5yypParser->fts5yyidx; + if( (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack)>fts5yypParser->fts5yyhwm ){ + fts5yypParser->fts5yyhwm++; + assert( fts5yypParser->fts5yyhwm == (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack) ); } #endif #if fts5YYSTACKDEPTH>0 - if( fts5yypParser->fts5yyidx>=fts5YYSTACKDEPTH ){ + if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5YYSTACKDEPTH] ){ fts5yyStackOverflow(fts5yypParser); return; } #else - if( fts5yypParser->fts5yyidx>=fts5yypParser->fts5yystksz ){ - fts5yyGrowStack(fts5yypParser); - if( fts5yypParser->fts5yyidx>=fts5yypParser->fts5yystksz ){ + if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz] ){ + if( fts5yyGrowStack(fts5yypParser) ){ fts5yyStackOverflow(fts5yypParser); return; } } #endif - fts5yytos = &fts5yypParser->fts5yystack[fts5yypParser->fts5yyidx]; + if( fts5yyNewState > fts5YY_MAX_SHIFT ){ + fts5yyNewState += fts5YY_MIN_REDUCE - fts5YY_MIN_SHIFTREDUCE; + } + fts5yytos = fts5yypParser->fts5yytos; fts5yytos->stateno = (fts5YYACTIONTYPE)fts5yyNewState; fts5yytos->major = (fts5YYCODETYPE)fts5yyMajor; fts5yytos->minor.fts5yy0 = fts5yyMinor; @@ -170799,30 +180793,32 @@ static const struct { fts5YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ unsigned char nrhs; /* Number of right-hand side symbols in the rule */ } fts5yyRuleInfo[] = { - { 15, 1 }, - { 16, 3 }, - { 16, 3 }, - { 16, 3 }, - { 16, 3 }, { 16, 1 }, - { 18, 1 }, - { 18, 2 }, - { 17, 1 }, { 17, 3 }, - { 20, 3 }, - { 20, 1 }, - { 21, 2 }, - { 21, 1 }, + { 17, 3 }, + { 17, 3 }, + { 17, 3 }, + { 17, 1 }, { 19, 1 }, - { 19, 5 }, - { 22, 1 }, + { 19, 2 }, + { 18, 1 }, + { 18, 3 }, + { 21, 4 }, + { 21, 3 }, + { 21, 1 }, + { 21, 2 }, { 22, 2 }, - { 24, 0 }, - { 24, 2 }, - { 23, 4 }, + { 22, 1 }, + { 20, 1 }, + { 20, 5 }, + { 23, 1 }, { 23, 2 }, - { 25, 1 }, { 25, 0 }, + { 25, 2 }, + { 24, 4 }, + { 24, 2 }, + { 26, 1 }, + { 26, 0 }, }; static void fts5yy_accept(fts5yyParser*); /* Forward Declaration */ @@ -170840,7 +180836,7 @@ static void fts5yy_reduce( fts5yyStackEntry *fts5yymsp; /* The top of the parser's stack */ int fts5yysize; /* Amount to pop the stack */ sqlite3Fts5ParserARG_FETCH; - fts5yymsp = &fts5yypParser->fts5yystack[fts5yypParser->fts5yyidx]; + fts5yymsp = fts5yypParser->fts5yytos; #ifndef NDEBUG if( fts5yyTraceFILE && fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) ){ fts5yysize = fts5yyRuleInfo[fts5yyruleno].nrhs; @@ -170854,22 +180850,23 @@ static void fts5yy_reduce( ** enough on the stack to push the LHS value */ if( fts5yyRuleInfo[fts5yyruleno].nrhs==0 ){ #ifdef fts5YYTRACKMAXSTACKDEPTH - if( fts5yypParser->fts5yyidx>fts5yypParser->fts5yyidxMax ){ - fts5yypParser->fts5yyidxMax = fts5yypParser->fts5yyidx; + if( (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack)>fts5yypParser->fts5yyhwm ){ + fts5yypParser->fts5yyhwm++; + assert( fts5yypParser->fts5yyhwm == (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack)); } #endif #if fts5YYSTACKDEPTH>0 - if( fts5yypParser->fts5yyidx>=fts5YYSTACKDEPTH-1 ){ + if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5YYSTACKDEPTH-1] ){ fts5yyStackOverflow(fts5yypParser); return; } #else - if( fts5yypParser->fts5yyidx>=fts5yypParser->fts5yystksz-1 ){ - fts5yyGrowStack(fts5yypParser); - if( fts5yypParser->fts5yyidx>=fts5yypParser->fts5yystksz-1 ){ + if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz-1] ){ + if( fts5yyGrowStack(fts5yypParser) ){ fts5yyStackOverflow(fts5yypParser); return; } + fts5yymsp = fts5yypParser->fts5yytos; } #endif } @@ -170886,120 +180883,131 @@ static void fts5yy_reduce( /********** Begin reduce actions **********************************************/ fts5YYMINORTYPE fts5yylhsminor; case 0: /* input ::= expr */ -{ sqlite3Fts5ParseFinished(pParse, fts5yymsp[0].minor.fts5yy18); } +{ sqlite3Fts5ParseFinished(pParse, fts5yymsp[0].minor.fts5yy24); } break; case 1: /* expr ::= expr AND expr */ { - fts5yylhsminor.fts5yy18 = sqlite3Fts5ParseNode(pParse, FTS5_AND, fts5yymsp[-2].minor.fts5yy18, fts5yymsp[0].minor.fts5yy18, 0); + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_AND, fts5yymsp[-2].minor.fts5yy24, fts5yymsp[0].minor.fts5yy24, 0); } - fts5yymsp[-2].minor.fts5yy18 = fts5yylhsminor.fts5yy18; + fts5yymsp[-2].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 2: /* expr ::= expr OR expr */ { - fts5yylhsminor.fts5yy18 = sqlite3Fts5ParseNode(pParse, FTS5_OR, fts5yymsp[-2].minor.fts5yy18, fts5yymsp[0].minor.fts5yy18, 0); + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_OR, fts5yymsp[-2].minor.fts5yy24, fts5yymsp[0].minor.fts5yy24, 0); } - fts5yymsp[-2].minor.fts5yy18 = fts5yylhsminor.fts5yy18; + fts5yymsp[-2].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 3: /* expr ::= expr NOT expr */ { - fts5yylhsminor.fts5yy18 = sqlite3Fts5ParseNode(pParse, FTS5_NOT, fts5yymsp[-2].minor.fts5yy18, fts5yymsp[0].minor.fts5yy18, 0); + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_NOT, fts5yymsp[-2].minor.fts5yy24, fts5yymsp[0].minor.fts5yy24, 0); } - fts5yymsp[-2].minor.fts5yy18 = fts5yylhsminor.fts5yy18; + fts5yymsp[-2].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 4: /* expr ::= LP expr RP */ -{fts5yymsp[-2].minor.fts5yy18 = fts5yymsp[-1].minor.fts5yy18;} +{fts5yymsp[-2].minor.fts5yy24 = fts5yymsp[-1].minor.fts5yy24;} break; case 5: /* expr ::= exprlist */ case 6: /* exprlist ::= cnearset */ fts5yytestcase(fts5yyruleno==6); -{fts5yylhsminor.fts5yy18 = fts5yymsp[0].minor.fts5yy18;} - fts5yymsp[0].minor.fts5yy18 = fts5yylhsminor.fts5yy18; +{fts5yylhsminor.fts5yy24 = fts5yymsp[0].minor.fts5yy24;} + fts5yymsp[0].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 7: /* exprlist ::= exprlist cnearset */ { - fts5yylhsminor.fts5yy18 = sqlite3Fts5ParseImplicitAnd(pParse, fts5yymsp[-1].minor.fts5yy18, fts5yymsp[0].minor.fts5yy18); + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseImplicitAnd(pParse, fts5yymsp[-1].minor.fts5yy24, fts5yymsp[0].minor.fts5yy24); } - fts5yymsp[-1].minor.fts5yy18 = fts5yylhsminor.fts5yy18; + fts5yymsp[-1].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 8: /* cnearset ::= nearset */ { - fts5yylhsminor.fts5yy18 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy26); + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy46); } - fts5yymsp[0].minor.fts5yy18 = fts5yylhsminor.fts5yy18; + fts5yymsp[0].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 9: /* cnearset ::= colset COLON nearset */ { - sqlite3Fts5ParseSetColset(pParse, fts5yymsp[0].minor.fts5yy26, fts5yymsp[-2].minor.fts5yy3); - fts5yylhsminor.fts5yy18 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy26); + sqlite3Fts5ParseSetColset(pParse, fts5yymsp[0].minor.fts5yy46, fts5yymsp[-2].minor.fts5yy11); + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy46); +} + fts5yymsp[-2].minor.fts5yy24 = fts5yylhsminor.fts5yy24; + break; + case 10: /* colset ::= MINUS LCP colsetlist RCP */ +{ + fts5yymsp[-3].minor.fts5yy11 = sqlite3Fts5ParseColsetInvert(pParse, fts5yymsp[-1].minor.fts5yy11); } - fts5yymsp[-2].minor.fts5yy18 = fts5yylhsminor.fts5yy18; break; - case 10: /* colset ::= LCP colsetlist RCP */ -{ fts5yymsp[-2].minor.fts5yy3 = fts5yymsp[-1].minor.fts5yy3; } + case 11: /* colset ::= LCP colsetlist RCP */ +{ fts5yymsp[-2].minor.fts5yy11 = fts5yymsp[-1].minor.fts5yy11; } break; - case 11: /* colset ::= STRING */ + case 12: /* colset ::= STRING */ { - fts5yylhsminor.fts5yy3 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); + fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); } - fts5yymsp[0].minor.fts5yy3 = fts5yylhsminor.fts5yy3; + fts5yymsp[0].minor.fts5yy11 = fts5yylhsminor.fts5yy11; break; - case 12: /* colsetlist ::= colsetlist STRING */ + case 13: /* colset ::= MINUS STRING */ +{ + fts5yymsp[-1].minor.fts5yy11 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); + fts5yymsp[-1].minor.fts5yy11 = sqlite3Fts5ParseColsetInvert(pParse, fts5yymsp[-1].minor.fts5yy11); +} + break; + case 14: /* colsetlist ::= colsetlist STRING */ { - fts5yylhsminor.fts5yy3 = sqlite3Fts5ParseColset(pParse, fts5yymsp[-1].minor.fts5yy3, &fts5yymsp[0].minor.fts5yy0); } - fts5yymsp[-1].minor.fts5yy3 = fts5yylhsminor.fts5yy3; + fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseColset(pParse, fts5yymsp[-1].minor.fts5yy11, &fts5yymsp[0].minor.fts5yy0); } + fts5yymsp[-1].minor.fts5yy11 = fts5yylhsminor.fts5yy11; break; - case 13: /* colsetlist ::= STRING */ + case 15: /* colsetlist ::= STRING */ { - fts5yylhsminor.fts5yy3 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); + fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); } - fts5yymsp[0].minor.fts5yy3 = fts5yylhsminor.fts5yy3; + fts5yymsp[0].minor.fts5yy11 = fts5yylhsminor.fts5yy11; break; - case 14: /* nearset ::= phrase */ -{ fts5yylhsminor.fts5yy26 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy11); } - fts5yymsp[0].minor.fts5yy26 = fts5yylhsminor.fts5yy26; + case 16: /* nearset ::= phrase */ +{ fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); } + fts5yymsp[0].minor.fts5yy46 = fts5yylhsminor.fts5yy46; break; - case 15: /* nearset ::= STRING LP nearphrases neardist_opt RP */ + case 17: /* nearset ::= STRING LP nearphrases neardist_opt RP */ { sqlite3Fts5ParseNear(pParse, &fts5yymsp[-4].minor.fts5yy0); - sqlite3Fts5ParseSetDistance(pParse, fts5yymsp[-2].minor.fts5yy26, &fts5yymsp[-1].minor.fts5yy0); - fts5yylhsminor.fts5yy26 = fts5yymsp[-2].minor.fts5yy26; + sqlite3Fts5ParseSetDistance(pParse, fts5yymsp[-2].minor.fts5yy46, &fts5yymsp[-1].minor.fts5yy0); + fts5yylhsminor.fts5yy46 = fts5yymsp[-2].minor.fts5yy46; } - fts5yymsp[-4].minor.fts5yy26 = fts5yylhsminor.fts5yy26; + fts5yymsp[-4].minor.fts5yy46 = fts5yylhsminor.fts5yy46; break; - case 16: /* nearphrases ::= phrase */ + case 18: /* nearphrases ::= phrase */ { - fts5yylhsminor.fts5yy26 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy11); + fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); } - fts5yymsp[0].minor.fts5yy26 = fts5yylhsminor.fts5yy26; + fts5yymsp[0].minor.fts5yy46 = fts5yylhsminor.fts5yy46; break; - case 17: /* nearphrases ::= nearphrases phrase */ + case 19: /* nearphrases ::= nearphrases phrase */ { - fts5yylhsminor.fts5yy26 = sqlite3Fts5ParseNearset(pParse, fts5yymsp[-1].minor.fts5yy26, fts5yymsp[0].minor.fts5yy11); + fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, fts5yymsp[-1].minor.fts5yy46, fts5yymsp[0].minor.fts5yy53); } - fts5yymsp[-1].minor.fts5yy26 = fts5yylhsminor.fts5yy26; + fts5yymsp[-1].minor.fts5yy46 = fts5yylhsminor.fts5yy46; break; - case 18: /* neardist_opt ::= */ + case 20: /* neardist_opt ::= */ { fts5yymsp[1].minor.fts5yy0.p = 0; fts5yymsp[1].minor.fts5yy0.n = 0; } break; - case 19: /* neardist_opt ::= COMMA STRING */ + case 21: /* neardist_opt ::= COMMA STRING */ { fts5yymsp[-1].minor.fts5yy0 = fts5yymsp[0].minor.fts5yy0; } break; - case 20: /* phrase ::= phrase PLUS STRING star_opt */ + case 22: /* phrase ::= phrase PLUS STRING star_opt */ { - fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseTerm(pParse, fts5yymsp[-3].minor.fts5yy11, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy20); + fts5yylhsminor.fts5yy53 = sqlite3Fts5ParseTerm(pParse, fts5yymsp[-3].minor.fts5yy53, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); } - fts5yymsp[-3].minor.fts5yy11 = fts5yylhsminor.fts5yy11; + fts5yymsp[-3].minor.fts5yy53 = fts5yylhsminor.fts5yy53; break; - case 21: /* phrase ::= STRING star_opt */ + case 23: /* phrase ::= STRING star_opt */ { - fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseTerm(pParse, 0, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy20); + fts5yylhsminor.fts5yy53 = sqlite3Fts5ParseTerm(pParse, 0, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); } - fts5yymsp[-1].minor.fts5yy11 = fts5yylhsminor.fts5yy11; + fts5yymsp[-1].minor.fts5yy53 = fts5yylhsminor.fts5yy53; break; - case 22: /* star_opt ::= STAR */ -{ fts5yymsp[0].minor.fts5yy20 = 1; } + case 24: /* star_opt ::= STAR */ +{ fts5yymsp[0].minor.fts5yy4 = 1; } break; - case 23: /* star_opt ::= */ -{ fts5yymsp[1].minor.fts5yy20 = 0; } + case 25: /* star_opt ::= */ +{ fts5yymsp[1].minor.fts5yy4 = 0; } break; default: break; @@ -171010,15 +181018,17 @@ static void fts5yy_reduce( fts5yysize = fts5yyRuleInfo[fts5yyruleno].nrhs; fts5yyact = fts5yy_find_reduce_action(fts5yymsp[-fts5yysize].stateno,(fts5YYCODETYPE)fts5yygoto); if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){ - if( fts5yyact>fts5YY_MAX_SHIFT ) fts5yyact += fts5YY_MIN_REDUCE - fts5YY_MIN_SHIFTREDUCE; - fts5yypParser->fts5yyidx -= fts5yysize - 1; + if( fts5yyact>fts5YY_MAX_SHIFT ){ + fts5yyact += fts5YY_MIN_REDUCE - fts5YY_MIN_SHIFTREDUCE; + } fts5yymsp -= fts5yysize-1; + fts5yypParser->fts5yytos = fts5yymsp; fts5yymsp->stateno = (fts5YYACTIONTYPE)fts5yyact; fts5yymsp->major = (fts5YYCODETYPE)fts5yygoto; fts5yyTraceShift(fts5yypParser, fts5yyact); }else{ assert( fts5yyact == fts5YY_ACCEPT_ACTION ); - fts5yypParser->fts5yyidx -= fts5yysize; + fts5yypParser->fts5yytos -= fts5yysize; fts5yy_accept(fts5yypParser); } } @@ -171036,7 +181046,7 @@ static void fts5yy_parse_failed( fprintf(fts5yyTraceFILE,"%sFail!\n",fts5yyTracePrompt); } #endif - while( fts5yypParser->fts5yyidx>=0 ) fts5yy_pop_parser_stack(fts5yypParser); + while( fts5yypParser->fts5yytos>fts5yypParser->fts5yystack ) fts5yy_pop_parser_stack(fts5yypParser); /* Here code is inserted which will be executed whenever the ** parser fails */ /************ Begin %parse_failure code ***************************************/ @@ -171077,7 +181087,10 @@ static void fts5yy_accept( fprintf(fts5yyTraceFILE,"%sAccept!\n",fts5yyTracePrompt); } #endif - while( fts5yypParser->fts5yyidx>=0 ) fts5yy_pop_parser_stack(fts5yypParser); +#ifndef fts5YYNOERRORRECOVERY + fts5yypParser->fts5yyerrcnt = -1; +#endif + assert( fts5yypParser->fts5yytos==fts5yypParser->fts5yystack ); /* Here code is inserted which will be executed whenever the ** parser accepts */ /*********** Begin %parse_accept code *****************************************/ @@ -171120,28 +181133,8 @@ static void sqlite3Fts5Parser( #endif fts5yyParser *fts5yypParser; /* The parser */ - /* (re)initialize the parser, if necessary */ fts5yypParser = (fts5yyParser*)fts5yyp; - if( fts5yypParser->fts5yyidx<0 ){ -#if fts5YYSTACKDEPTH<=0 - if( fts5yypParser->fts5yystksz <=0 ){ - fts5yyStackOverflow(fts5yypParser); - return; - } -#endif - fts5yypParser->fts5yyidx = 0; -#ifndef fts5YYNOERRORRECOVERY - fts5yypParser->fts5yyerrcnt = -1; -#endif - fts5yypParser->fts5yystack[0].stateno = 0; - fts5yypParser->fts5yystack[0].major = 0; -#ifndef NDEBUG - if( fts5yyTraceFILE ){ - fprintf(fts5yyTraceFILE,"%sInitialize. Empty stack. State 0\n", - fts5yyTracePrompt); - } -#endif - } + assert( fts5yypParser->fts5yytos!=0 ); #if !defined(fts5YYERRORSYMBOL) && !defined(fts5YYNOERRORRECOVERY) fts5yyendofinput = (fts5yymajor==0); #endif @@ -171156,7 +181149,6 @@ static void sqlite3Fts5Parser( do{ fts5yyact = fts5yy_find_shift_action(fts5yypParser,(fts5YYCODETYPE)fts5yymajor); if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){ - if( fts5yyact > fts5YY_MAX_SHIFT ) fts5yyact += fts5YY_MIN_REDUCE - fts5YY_MIN_SHIFTREDUCE; fts5yy_shift(fts5yypParser,fts5yyact,fts5yymajor,fts5yyminor); #ifndef fts5YYNOERRORRECOVERY fts5yypParser->fts5yyerrcnt--; @@ -171198,7 +181190,7 @@ static void sqlite3Fts5Parser( if( fts5yypParser->fts5yyerrcnt<0 ){ fts5yy_syntax_error(fts5yypParser,fts5yymajor,fts5yyminor); } - fts5yymx = fts5yypParser->fts5yystack[fts5yypParser->fts5yyidx].major; + fts5yymx = fts5yypParser->fts5yytos->major; if( fts5yymx==fts5YYERRORSYMBOL || fts5yyerrorhit ){ #ifndef NDEBUG if( fts5yyTraceFILE ){ @@ -171209,18 +181201,20 @@ static void sqlite3Fts5Parser( fts5yy_destructor(fts5yypParser, (fts5YYCODETYPE)fts5yymajor, &fts5yyminorunion); fts5yymajor = fts5YYNOCODE; }else{ - while( - fts5yypParser->fts5yyidx >= 0 && - fts5yymx != fts5YYERRORSYMBOL && - (fts5yyact = fts5yy_find_reduce_action( - fts5yypParser->fts5yystack[fts5yypParser->fts5yyidx].stateno, + while( fts5yypParser->fts5yytos >= fts5yypParser->fts5yystack + && fts5yymx != fts5YYERRORSYMBOL + && (fts5yyact = fts5yy_find_reduce_action( + fts5yypParser->fts5yytos->stateno, fts5YYERRORSYMBOL)) >= fts5YY_MIN_REDUCE ){ fts5yy_pop_parser_stack(fts5yypParser); } - if( fts5yypParser->fts5yyidx < 0 || fts5yymajor==0 ){ + if( fts5yypParser->fts5yytos < fts5yypParser->fts5yystack || fts5yymajor==0 ){ fts5yy_destructor(fts5yypParser,(fts5YYCODETYPE)fts5yymajor,&fts5yyminorunion); fts5yy_parse_failed(fts5yypParser); +#ifndef fts5YYNOERRORRECOVERY + fts5yypParser->fts5yyerrcnt = -1; +#endif fts5yymajor = fts5YYNOCODE; }else if( fts5yymx!=fts5YYERRORSYMBOL ){ fts5yy_shift(fts5yypParser,fts5yyact,fts5YYERRORSYMBOL,fts5yyminor); @@ -171257,18 +181251,23 @@ static void sqlite3Fts5Parser( fts5yy_destructor(fts5yypParser,(fts5YYCODETYPE)fts5yymajor,&fts5yyminorunion); if( fts5yyendofinput ){ fts5yy_parse_failed(fts5yypParser); +#ifndef fts5YYNOERRORRECOVERY + fts5yypParser->fts5yyerrcnt = -1; +#endif } fts5yymajor = fts5YYNOCODE; #endif } - }while( fts5yymajor!=fts5YYNOCODE && fts5yypParser->fts5yyidx>=0 ); + }while( fts5yymajor!=fts5YYNOCODE && fts5yypParser->fts5yytos>fts5yypParser->fts5yystack ); #ifndef NDEBUG if( fts5yyTraceFILE ){ - int i; + fts5yyStackEntry *i; + char cDiv = '['; fprintf(fts5yyTraceFILE,"%sReturn. Stack=",fts5yyTracePrompt); - for(i=1; i<=fts5yypParser->fts5yyidx; i++) - fprintf(fts5yyTraceFILE,"%c%s", i==1 ? '[' : ' ', - fts5yyTokenName[fts5yypParser->fts5yystack[i].major]); + for(i=&fts5yypParser->fts5yystack[1]; i<=fts5yypParser->fts5yytos; i++){ + fprintf(fts5yyTraceFILE,"%c%s", cDiv, fts5yyTokenName[i->major]); + cDiv = ' '; + } fprintf(fts5yyTraceFILE,"]\n"); } #endif @@ -171466,7 +181465,7 @@ static int fts5HighlightCb( if( p->iRangeEnd>0 && iPos==p->iRangeEnd ){ fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); p->iOff = iEndOff; - if( iPositer.iEnd ){ + if( iPos>=p->iter.iStart && iPositer.iEnd ){ fts5HighlightAppend(&rc, p, p->zClose, -1); } } @@ -171523,6 +181522,118 @@ static void fts5HighlightFunction( ** End of highlight() implementation. **************************************************************************/ +/* +** Context object passed to the fts5SentenceFinderCb() function. +*/ +typedef struct Fts5SFinder Fts5SFinder; +struct Fts5SFinder { + int iPos; /* Current token position */ + int nFirstAlloc; /* Allocated size of aFirst[] */ + int nFirst; /* Number of entries in aFirst[] */ + int *aFirst; /* Array of first token in each sentence */ + const char *zDoc; /* Document being tokenized */ +}; + +/* +** Add an entry to the Fts5SFinder.aFirst[] array. Grow the array if +** necessary. Return SQLITE_OK if successful, or SQLITE_NOMEM if an +** error occurs. +*/ +static int fts5SentenceFinderAdd(Fts5SFinder *p, int iAdd){ + if( p->nFirstAlloc==p->nFirst ){ + int nNew = p->nFirstAlloc ? p->nFirstAlloc*2 : 64; + int *aNew; + + aNew = (int*)sqlite3_realloc(p->aFirst, nNew*sizeof(int)); + if( aNew==0 ) return SQLITE_NOMEM; + p->aFirst = aNew; + p->nFirstAlloc = nNew; + } + p->aFirst[p->nFirst++] = iAdd; + return SQLITE_OK; +} + +/* +** This function is an xTokenize() callback used by the auxiliary snippet() +** function. Its job is to identify tokens that are the first in a sentence. +** For each such token, an entry is added to the SFinder.aFirst[] array. +*/ +static int fts5SentenceFinderCb( + void *pContext, /* Pointer to HighlightContext object */ + int tflags, /* Mask of FTS5_TOKEN_* flags */ + const char *pToken, /* Buffer containing token */ + int nToken, /* Size of token in bytes */ + int iStartOff, /* Start offset of token */ + int iEndOff /* End offset of token */ +){ + int rc = SQLITE_OK; + + UNUSED_PARAM2(pToken, nToken); + UNUSED_PARAM(iEndOff); + + if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){ + Fts5SFinder *p = (Fts5SFinder*)pContext; + if( p->iPos>0 ){ + int i; + char c = 0; + for(i=iStartOff-1; i>=0; i--){ + c = p->zDoc[i]; + if( c!=' ' && c!='\t' && c!='\n' && c!='\r' ) break; + } + if( i!=iStartOff-1 && (c=='.' || c==':') ){ + rc = fts5SentenceFinderAdd(p, p->iPos); + } + }else{ + rc = fts5SentenceFinderAdd(p, 0); + } + p->iPos++; + } + return rc; +} + +static int fts5SnippetScore( + const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ + Fts5Context *pFts, /* First arg to pass to pApi functions */ + int nDocsize, /* Size of column in tokens */ + unsigned char *aSeen, /* Array with one element per query phrase */ + int iCol, /* Column to score */ + int iPos, /* Starting offset to score */ + int nToken, /* Max tokens per snippet */ + int *pnScore, /* OUT: Score */ + int *piPos /* OUT: Adjusted offset */ +){ + int rc; + int i; + int ip = 0; + int ic = 0; + int iOff = 0; + int iFirst = -1; + int nInst; + int nScore = 0; + int iLast = 0; + + rc = pApi->xInstCount(pFts, &nInst); + for(i=0; ixInst(pFts, i, &ip, &ic, &iOff); + if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<(iPos+nToken) ){ + nScore += (aSeen[ip] ? 1 : 1000); + aSeen[ip] = 1; + if( iFirst<0 ) iFirst = iOff; + iLast = iOff + pApi->xPhraseSize(pFts, ip); + } + } + + *pnScore = nScore; + if( piPos ){ + int iAdj = iFirst - (nToken - (iLast-iFirst)) / 2; + if( (iAdj+nToken)>nDocsize ) iAdj = nDocsize - nToken; + if( iAdj<0 ) iAdj = 0; + *piPos = iAdj; + } + + return rc; +} + /* ** Implementation of snippet() function. */ @@ -171544,9 +181655,10 @@ static void fts5SnippetFunction( unsigned char *aSeen; /* Array of "seen instance" flags */ int iBestCol; /* Column containing best snippet */ int iBestStart = 0; /* First token of best snippet */ - int iBestLast; /* Last token of best snippet */ int nBestScore = 0; /* Score of best snippet */ int nColSize = 0; /* Total size of iBestCol in tokens */ + Fts5SFinder sFinder; /* Used to find the beginnings of sentences */ + int nCol; if( nVal!=5 ){ const char *zErr = "wrong number of arguments to function snippet()"; @@ -171554,13 +181666,13 @@ static void fts5SnippetFunction( return; } + nCol = pApi->xColumnCount(pFts); memset(&ctx, 0, sizeof(HighlightContext)); iCol = sqlite3_value_int(apVal[0]); ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]); ctx.zClose = (const char*)sqlite3_value_text(apVal[2]); zEllips = (const char*)sqlite3_value_text(apVal[3]); nToken = sqlite3_value_int(apVal[4]); - iBestLast = nToken-1; iBestCol = (iCol>=0 ? iCol : 0); nPhrase = pApi->xPhraseCount(pFts); @@ -171568,65 +181680,94 @@ static void fts5SnippetFunction( if( aSeen==0 ){ rc = SQLITE_NOMEM; } - if( rc==SQLITE_OK ){ rc = pApi->xInstCount(pFts, &nInst); } - for(i=0; rc==SQLITE_OK && ixInst(pFts, i, &ip, &iSnippetCol, &iStart); - if( rc==SQLITE_OK && (iCol<0 || iSnippetCol==iCol) ){ - int nScore = 1000; - int iLast = iStart - 1 + pApi->xPhraseSize(pFts, ip); - int j; - aSeen[ip] = 1; - for(j=i+1; rc==SQLITE_OK && jxInst(pFts, j, &ip, &ic, &io); - iFinal = io + pApi->xPhraseSize(pFts, ip) - 1; - if( rc==SQLITE_OK && ic==iSnippetCol && iLastiLast ) iLast = iFinal; + memset(&sFinder, 0, sizeof(Fts5SFinder)); + for(i=0; ixColumnText(pFts, i, &sFinder.zDoc, &nDoc); + if( rc!=SQLITE_OK ) break; + rc = pApi->xTokenize(pFts, + sFinder.zDoc, nDoc, (void*)&sFinder,fts5SentenceFinderCb + ); + if( rc!=SQLITE_OK ) break; + rc = pApi->xColumnSize(pFts, i, &nDocsize); + if( rc!=SQLITE_OK ) break; + + for(ii=0; rc==SQLITE_OK && iixInst(pFts, ii, &ip, &ic, &io); + if( ic!=i || rc!=SQLITE_OK ) continue; + memset(aSeen, 0, nPhrase); + rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i, + io, nToken, &nScore, &iAdj + ); + if( rc==SQLITE_OK && nScore>nBestScore ){ + nBestScore = nScore; + iBestCol = i; + iBestStart = iAdj; + nColSize = nDocsize; } - } - if( rc==SQLITE_OK && nScore>nBestScore ){ - iBestCol = iSnippetCol; - iBestStart = iStart; - iBestLast = iLast; - nBestScore = nScore; + if( rc==SQLITE_OK && sFinder.nFirst && nDocsize>nToken ){ + for(jj=0; jj<(sFinder.nFirst-1); jj++){ + if( sFinder.aFirst[jj+1]>io ) break; + } + + if( sFinder.aFirst[jj]nBestScore ){ + nBestScore = nScore; + iBestCol = i; + iBestStart = sFinder.aFirst[jj]; + nColSize = nDocsize; + } + } + } } } } - if( rc==SQLITE_OK ){ - rc = pApi->xColumnSize(pFts, iBestCol, &nColSize); - } if( rc==SQLITE_OK ){ rc = pApi->xColumnText(pFts, iBestCol, &ctx.zIn, &ctx.nIn); } + if( rc==SQLITE_OK && nColSize==0 ){ + rc = pApi->xColumnSize(pFts, iBestCol, &nColSize); + } if( ctx.zIn ){ if( rc==SQLITE_OK ){ rc = fts5CInstIterInit(pApi, pFts, iBestCol, &ctx.iter); } - if( (iBestStart+nToken-1)>iBestLast ){ - iBestStart -= (iBestStart+nToken-1-iBestLast) / 2; - } - if( iBestStart+nToken>nColSize ){ - iBestStart = nColSize - nToken; - } - if( iBestStart<0 ) iBestStart = 0; - ctx.iRangeStart = iBestStart; ctx.iRangeEnd = iBestStart + nToken - 1; if( iBestStart>0 ){ fts5HighlightAppend(&rc, &ctx, zEllips, -1); } + + /* Advance iterator ctx.iter so that it points to the first coalesced + ** phrase instance at or following position iBestStart. */ + while( ctx.iter.iStart>=0 && ctx.iter.iStartxTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); } @@ -171635,15 +181776,15 @@ static void fts5SnippetFunction( }else{ fts5HighlightAppend(&rc, &ctx, zEllips, -1); } - - if( rc==SQLITE_OK ){ - sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT); - }else{ - sqlite3_result_error_code(pCtx, rc); - } - sqlite3_free(ctx.zOut); } + if( rc==SQLITE_OK ){ + sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT); + }else{ + sqlite3_result_error_code(pCtx, rc); + } + sqlite3_free(ctx.zOut); sqlite3_free(aSeen); + sqlite3_free(sFinder.aFirst); } /************************************************************************/ @@ -173362,6 +183503,7 @@ static int fts5ExprGetToken( case ',': tok = FTS5_COMMA; break; case '+': tok = FTS5_PLUS; break; case '*': tok = FTS5_STAR; break; + case '-': tok = FTS5_MINUS; break; case '\0': tok = FTS5_EOF; break; case '"': { @@ -173948,6 +184090,7 @@ static int fts5ExprNearInitAll( Fts5ExprNearset *pNear = pNode->pNear; int i, j; int rc = SQLITE_OK; + int bEof = 1; assert( pNode->bNomatch==0 ); for(i=0; rc==SQLITE_OK && inPhrase; i++){ @@ -173955,7 +184098,6 @@ static int fts5ExprNearInitAll( for(j=0; jnTerm; j++){ Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; Fts5ExprTerm *p; - int bEof = 1; for(p=pTerm; p && rc==SQLITE_OK; p=p->pSynonym){ if( p->pIter ){ @@ -173975,13 +184117,12 @@ static int fts5ExprNearInitAll( } } - if( bEof ){ - pNode->bEof = 1; - return rc; - } + if( bEof ) break; } + if( bEof ) break; } + pNode->bEof = bEof; return rc; } @@ -174115,7 +184256,7 @@ static int fts5ExprNodeTest_STRING( } }else{ Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; - if( pIter->iRowid==iLast ) continue; + if( pIter->iRowid==iLast || pIter->bEof ) continue; bMatch = 0; if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){ return rc; @@ -174832,7 +184973,6 @@ static int sqlite3Fts5ExprClonePhrase( ){ int rc = SQLITE_OK; /* Return code */ Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */ - int i; /* Used to iterate through phrase terms */ Fts5Expr *pNew = 0; /* Expression to return via *ppNew */ TokenCtx sCtx = {0,0}; /* Context object for fts5ParseTokenize */ @@ -174850,19 +184990,37 @@ static int sqlite3Fts5ExprClonePhrase( pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*)); } - - for(i=0; rc==SQLITE_OK && inTerm; i++){ - int tflags = 0; - Fts5ExprTerm *p; - for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){ - const char *zTerm = p->zTerm; - rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm), - 0, 0); - tflags = FTS5_TOKEN_COLOCATED; + if( rc==SQLITE_OK ){ + Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset; + if( pColsetOrig ){ + int nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int); + Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte); + if( pColset ){ + memcpy(pColset, pColsetOrig, nByte); + } + pNew->pRoot->pNear->pColset = pColset; } - if( rc==SQLITE_OK ){ - sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; + } + + if( pOrig->nTerm ){ + int i; /* Used to iterate through phrase terms */ + for(i=0; rc==SQLITE_OK && inTerm; i++){ + int tflags = 0; + Fts5ExprTerm *p; + for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){ + const char *zTerm = p->zTerm; + rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm), + 0, 0); + tflags = FTS5_TOKEN_COLOCATED; + } + if( rc==SQLITE_OK ){ + sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; + } } + }else{ + /* This happens when parsing a token or quoted phrase that contains + ** no token characters at all. (e.g ... MATCH '""'). */ + sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase)); } if( rc==SQLITE_OK ){ @@ -174977,6 +185135,34 @@ static Fts5Colset *fts5ParseColset( return pNew; } +/* +** Allocate and return an Fts5Colset object specifying the inverse of +** the colset passed as the second argument. Free the colset passed +** as the second argument before returning. +*/ +static Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){ + Fts5Colset *pRet; + int nCol = pParse->pConfig->nCol; + + pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc, + sizeof(Fts5Colset) + sizeof(int)*nCol + ); + if( pRet ){ + int i; + int iOld = 0; + for(i=0; i=p->nCol || p->aiCol[iOld]!=i ){ + pRet->aiCol[pRet->nCol++] = i; + }else{ + iOld++; + } + } + } + + sqlite3_free(p); + return pRet; +} + static Fts5Colset *sqlite3Fts5ParseColset( Fts5Parse *pParse, /* Store SQLITE_NOMEM here if required */ Fts5Colset *pColset, /* Existing colset object */ @@ -175801,17 +185987,6 @@ static void sqlite3Fts5ExprCheckPoslists(Fts5Expr *pExpr, i64 iRowid){ fts5ExprCheckPoslists(pExpr->pRoot, iRowid); } -static void fts5ExprClearEof(Fts5ExprNode *pNode){ - int i; - for(i=0; inChild; i++){ - fts5ExprClearEof(pNode->apChild[i]); - } - pNode->bEof = 0; -} -static void sqlite3Fts5ExprClearEof(Fts5Expr *pExpr){ - fts5ExprClearEof(pExpr->pRoot); -} - /* ** This function is only called for detail=columns tables. */ @@ -176198,11 +186373,11 @@ static int sqlite3Fts5HashWrite( if( pHash->eDetail==FTS5_DETAIL_FULL ){ pPtr[p->nData++] = 0x01; p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iCol); - p->iCol = iCol; + p->iCol = (i16)iCol; p->iPos = 0; }else{ bNew = 1; - p->iCol = iPos = iCol; + p->iCol = (i16)(iPos = iCol); } } @@ -177083,7 +187258,6 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){ return pRet; } - /* ** Release a reference to data record returned by an earlier call to ** fts5DataRead(). @@ -177092,6 +187266,18 @@ static void fts5DataRelease(Fts5Data *pData){ sqlite3_free(pData); } +static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){ + Fts5Data *pRet = fts5DataRead(p, iRowid); + if( pRet ){ + if( pRet->szLeaf>pRet->nn ){ + p->rc = FTS5_CORRUPT; + fts5DataRelease(pRet); + pRet = 0; + } + } + return pRet; +} + static int fts5IndexPrepareStmt( Fts5Index *p, sqlite3_stmt **ppStmt, @@ -177900,7 +188086,7 @@ static void fts5SegIterNextPage( pIter->pLeaf = pIter->pNextLeaf; pIter->pNextLeaf = 0; }else if( pIter->iLeafPgno<=pSeg->pgnoLast ){ - pIter->pLeaf = fts5DataRead(p, + pIter->pLeaf = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, pIter->iLeafPgno) ); }else{ @@ -178403,9 +188589,8 @@ static void fts5SegIterNext( if( pLeaf->nn>pLeaf->szLeaf ){ pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32( &pLeaf->p[pLeaf->szLeaf], pIter->iEndofDoclist - ); + ); } - } else if( pLeaf->nn>pLeaf->szLeaf ){ pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32( @@ -178650,6 +188835,11 @@ static void fts5LeafSeek( iTermOff += nKeep; iOff = iTermOff; + if( iOff>=n ){ + p->rc = FTS5_CORRUPT; + return; + } + /* Read the nKeep field of the next term. */ fts5FastGetVarint32(a, iOff, nKeep); } @@ -179206,6 +189396,7 @@ static void fts5MultiIterNext( i64 iFrom /* Advance at least as far as this */ ){ int bUseFrom = bFrom; + assert( pIter->base.bEof==0 ); while( p->rc==SQLITE_OK ){ int iFirst = pIter->aFirst[1].iFirst; int bNewTerm = 0; @@ -179576,6 +189767,15 @@ static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){ } } +/* +** xSetOutputs callback used when the Fts5Colset object has nCol==0 (match +** against no columns at all). +*/ +static void fts5IterSetOutputs_ZeroColset(Fts5Iter *pIter, Fts5SegIter *pSeg){ + UNUSED_PARAM(pSeg); + pIter->base.nData = 0; +} + /* ** xSetOutputs callback used by detail=col when there is a column filter ** and there are 100 or more columns. Also called as a fallback from @@ -179625,7 +189825,7 @@ static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){ if( aiCol==aiColEnd ) goto setoutputs_col_out; } if( *aiCol==iPrev ){ - *aOut++ = (iPrev - iPrevOut) + 2; + *aOut++ = (u8)((iPrev - iPrevOut) + 2); iPrevOut = iPrev; } } @@ -179681,6 +189881,10 @@ static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){ pIter->xSetOutputs = fts5IterSetOutputs_Nocolset; } + else if( pIter->pColset->nCol==0 ){ + pIter->xSetOutputs = fts5IterSetOutputs_ZeroColset; + } + else if( pConfig->eDetail==FTS5_DETAIL_FULL ){ pIter->xSetOutputs = fts5IterSetOutputs_Full; } @@ -184029,7 +194233,6 @@ static int fts5FilterMethod( pCsr->ePlan = FTS5_PLAN_SOURCE; pCsr->pExpr = pTab->pSortCsr->pExpr; rc = fts5CursorFirst(pTab, pCsr, bDesc); - sqlite3Fts5ExprClearEof(pCsr->pExpr); }else if( pMatch ){ const char *zExpr = (const char*)sqlite3_value_text(apVal[0]); if( zExpr==0 ) zExpr = ""; @@ -185458,7 +195661,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2016-04-08 15:09:49 fe7d3b75fe1bde41511b323925af8ae1b910bc4d", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2016-11-28 19:13:37 bbd85d235f7037c6a033a9690534391ffeacecc8", -1, SQLITE_TRANSIENT); } static int fts5Init(sqlite3 *db){ @@ -185546,7 +195749,7 @@ static int fts5Init(sqlite3 *db){ #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_fts_init( +SQLITE_API int sqlite3_fts_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -185559,7 +195762,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_fts_init( #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_fts5_init( +SQLITE_API int sqlite3_fts5_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -185823,7 +196026,11 @@ static int sqlite3Fts5CreateTable( char *zErr = 0; rc = fts5ExecPrintf(pConfig->db, &zErr, "CREATE TABLE %Q.'%q_%q'(%s)%s", - pConfig->zDb, pConfig->zName, zPost, zDefn, bWithout?" WITHOUT ROWID":"" + pConfig->zDb, pConfig->zName, zPost, zDefn, +#ifndef SQLITE_FTS5_NO_WITHOUT_ROWID + bWithout?" WITHOUT ROWID": +#endif + "" ); if( zErr ){ *pzErr = sqlite3_mprintf( @@ -188936,8 +199143,19 @@ static int fts5VocabBestIndexMethod( } } - pInfo->idxNum = idxNum; + /* This virtual table always delivers results in ascending order of + ** the "term" column (column 0). So if the user has requested this + ** specifically - "ORDER BY term" or "ORDER BY term ASC" - set the + ** sqlite3_index_info.orderByConsumed flag to tell the core the results + ** are already in sorted order. */ + if( pInfo->nOrderBy==1 + && pInfo->aOrderBy[0].iColumn==0 + && pInfo->aOrderBy[0].desc==0 + ){ + pInfo->orderByConsumed = 1; + } + pInfo->idxNum = idxNum; return SQLITE_OK; } diff --git a/src/mod/sqlite3/sqlite3.h b/src/mod/sqlite3/sqlite3.h index b7e7d859..8222b793 100644 --- a/src/mod/sqlite3/sqlite3.h +++ b/src/mod/sqlite3/sqlite3.h @@ -30,8 +30,8 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. */ -#ifndef _SQLITE3_H_ -#define _SQLITE3_H_ +#ifndef SQLITE3_H +#define SQLITE3_H #include /* Needed for the definition of va_list */ /* @@ -54,8 +54,17 @@ extern "C" { #ifndef SQLITE_CDECL # define SQLITE_CDECL #endif +#ifndef SQLITE_APICALL +# define SQLITE_APICALL +#endif #ifndef SQLITE_STDCALL -# define SQLITE_STDCALL +# define SQLITE_STDCALL SQLITE_APICALL +#endif +#ifndef SQLITE_CALLBACK +# define SQLITE_CALLBACK +#endif +#ifndef SQLITE_SYSAPI +# define SQLITE_SYSAPI #endif /* @@ -99,7 +108,8 @@ extern "C" { ** be held constant and Z will be incremented or else Y will be incremented ** and Z will be reset to zero. ** -** Since version 3.6.18, SQLite source code has been stored in the +** Since [version 3.6.18] ([dateof:3.6.18]), +** SQLite source code has been stored in the ** Fossil configuration management ** system. ^The SQLITE_SOURCE_ID macro evaluates to ** a string which identifies a particular check-in of SQLite @@ -111,9 +121,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.12.1" -#define SQLITE_VERSION_NUMBER 3012001 -#define SQLITE_SOURCE_ID "2016-04-08 15:09:49 fe7d3b75fe1bde41511b323925af8ae1b910bc4d" +#define SQLITE_VERSION "3.15.2" +#define SQLITE_VERSION_NUMBER 3015002 +#define SQLITE_SOURCE_ID "2016-11-28 19:13:37 bbd85d235f7037c6a033a9690534391ffeacecc8" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -146,9 +156,9 @@ extern "C" { ** See also: [sqlite_version()] and [sqlite_source_id()]. */ SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; -SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void); -SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void); -SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void); +SQLITE_API const char *sqlite3_libversion(void); +SQLITE_API const char *sqlite3_sourceid(void); +SQLITE_API int sqlite3_libversion_number(void); /* ** CAPI3REF: Run-Time Library Compilation Options Diagnostics @@ -173,8 +183,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void); ** [sqlite_compileoption_get()] and the [compile_options pragma]. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName); -SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N); +SQLITE_API int sqlite3_compileoption_used(const char *zOptName); +SQLITE_API const char *sqlite3_compileoption_get(int N); #endif /* @@ -213,7 +223,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N); ** ** See the [threading mode] documentation for additional information. */ -SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void); +SQLITE_API int sqlite3_threadsafe(void); /* ** CAPI3REF: Database Connection Handle @@ -310,8 +320,8 @@ typedef sqlite_uint64 sqlite3_uint64; ** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer ** argument is a harmless no-op. */ -SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3*); -SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3*); +SQLITE_API int sqlite3_close(sqlite3*); +SQLITE_API int sqlite3_close_v2(sqlite3*); /* ** The type for a callback function. @@ -382,7 +392,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. ** */ -SQLITE_API int SQLITE_STDCALL sqlite3_exec( +SQLITE_API int sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ int (*callback)(void*,int,char**,char**), /* Callback function */ @@ -443,7 +453,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec( ** [result codes]. However, experience has shown that many of ** these result codes are too coarse-grained. They do not provide as ** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 and later) include +** address this, newer versions of SQLite (version 3.3.8 [dateof:3.3.8] +** and later) include ** support for additional result codes that provide more detailed information ** about errors. These [extended result codes] are enabled or disabled ** on a per database connection basis using the @@ -506,6 +517,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec( #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) +#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8)) /* ** CAPI3REF: Flags For File Open Operations @@ -966,6 +978,12 @@ struct sqlite3_io_methods { ** on whether or not the file has been renamed, moved, or deleted since it ** was first opened. ** +**
  • [[SQLITE_FCNTL_WIN32_GET_HANDLE]] +** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the +** underlying native file handle associated with a file handle. This file +** control interprets its argument as a pointer to a native file handle and +** writes the resulting value there. +** **
  • [[SQLITE_FCNTL_WIN32_SET_HANDLE]] ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This ** opcode causes the xFileControl method to swap the file handle with the one @@ -1016,6 +1034,7 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_RBU 26 #define SQLITE_FCNTL_VFS_POINTER 27 #define SQLITE_FCNTL_JOURNAL_POINTER 28 +#define SQLITE_FCNTL_WIN32_GET_HANDLE 29 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE @@ -1035,6 +1054,16 @@ struct sqlite3_io_methods { */ typedef struct sqlite3_mutex sqlite3_mutex; +/* +** CAPI3REF: Loadable Extension Thunk +** +** A pointer to the opaque sqlite3_api_routines structure is passed as +** the third parameter to entry points of [loadable extensions]. This +** structure must be typedefed in order to work around compiler warnings +** on some platforms. +*/ +typedef struct sqlite3_api_routines sqlite3_api_routines; + /* ** CAPI3REF: OS Interface Object ** @@ -1370,10 +1399,10 @@ struct sqlite3_vfs { ** must return [SQLITE_OK] on success and some other [error code] upon ** failure. */ -SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void); -SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void); -SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void); -SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); +SQLITE_API int sqlite3_initialize(void); +SQLITE_API int sqlite3_shutdown(void); +SQLITE_API int sqlite3_os_init(void); +SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library @@ -1406,7 +1435,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code]. */ -SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...); +SQLITE_API int sqlite3_config(int, ...); /* ** CAPI3REF: Configure database connections @@ -1425,7 +1454,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...); ** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if ** the call is considered successful. */ -SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3*, int op, ...); +SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); /* ** CAPI3REF: Memory Allocation Routines @@ -1932,12 +1961,40 @@ struct sqlite3_mem_methods { ** following this call. The second parameter may be a NULL pointer, in ** which case the new setting is not reported back. ** +**
    SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
    +**
    ^This option is used to enable or disable the [sqlite3_load_extension()] +** interface independently of the [load_extension()] SQL function. +** The [sqlite3_enable_load_extension()] API enables or disables both the +** C-API [sqlite3_load_extension()] and the SQL function [load_extension()]. +** There should be two additional arguments. +** When the first argument to this interface is 1, then only the C-API is +** enabled and the SQL function remains disabled. If the first argument to +** this interface is 0, then both the C-API and the SQL function are disabled. +** If the first argument is -1, then no changes are made to state of either the +** C-API or the SQL function. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface +** is disabled or enabled following this call. The second parameter may +** be a NULL pointer, in which case the new setting is not reported back. +**
    +** +**
    SQLITE_DBCONFIG_MAINDBNAME
    +**
    ^This option is used to change the name of the "main" database +** schema. ^The sole argument is a pointer to a constant UTF8 string +** which will become the new schema name in place of "main". ^SQLite +** does not make a copy of the new main schema name string, so the application +** must ensure that the argument passed into this DBCONFIG option is unchanged +** until after the database connection closes. +**
    +** ** */ +#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #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* */ /* @@ -1948,7 +2005,7 @@ struct sqlite3_mem_methods { ** [extended result codes] feature of SQLite. ^The extended result ** codes are disabled by default for historical compatibility. */ -SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff); +SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); /* ** CAPI3REF: Last Insert Rowid @@ -2000,7 +2057,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff) ** unpredictable and might not equal either the old or the new ** last insert [rowid]. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*); +SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); /* ** CAPI3REF: Count The Number Of Rows Modified @@ -2053,7 +2110,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*); ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. */ -SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*); +SQLITE_API int sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified @@ -2077,7 +2134,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*); ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. */ -SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*); +SQLITE_API int sqlite3_total_changes(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query @@ -2117,7 +2174,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*); ** If the database connection closes while [sqlite3_interrupt()] ** is running then bad things will likely happen. */ -SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*); +SQLITE_API void sqlite3_interrupt(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete @@ -2152,8 +2209,8 @@ SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*); ** The input to [sqlite3_complete16()] must be a zero-terminated ** UTF-16 string in native byte order. */ -SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *sql); -SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql); +SQLITE_API int sqlite3_complete(const char *sql); +SQLITE_API int sqlite3_complete16(const void *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors @@ -2214,7 +2271,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql); ** A busy handler must not close the database connection ** or [prepared statement] that invoked the busy handler. */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); +SQLITE_API int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*); /* ** CAPI3REF: Set A Busy Timeout @@ -2237,7 +2294,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*, int(*)(void*,int), ** ** See also: [PRAGMA busy_timeout] */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms); +SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); /* ** CAPI3REF: Convenience Routines For Running Queries @@ -2312,7 +2369,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms); ** reflected in subsequent calls to [sqlite3_errcode()] or ** [sqlite3_errmsg()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_table( +SQLITE_API int sqlite3_get_table( sqlite3 *db, /* An open database */ const char *zSql, /* SQL to be evaluated */ char ***pazResult, /* Results of the query */ @@ -2320,7 +2377,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_table( int *pnColumn, /* Number of result columns written here */ char **pzErrmsg /* Error msg written here */ ); -SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); +SQLITE_API void sqlite3_free_table(char **result); /* ** CAPI3REF: Formatted String Printing Functions @@ -2426,10 +2483,10 @@ SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); ** addition that after the string has been read and copied into ** the result, [sqlite3_free()] is called on the input string.)^ */ -SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char*,...); -SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char*, va_list); -SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int,char*,const char*, ...); -SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list); +SQLITE_API char *sqlite3_mprintf(const char*,...); +SQLITE_API char *sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); +SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); /* ** CAPI3REF: Memory Allocation Subsystem @@ -2519,12 +2576,12 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list ** a block of memory after it has been released using ** [sqlite3_free()] or [sqlite3_realloc()]. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int); -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64); -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void*, int); -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void*, sqlite3_uint64); -SQLITE_API void SQLITE_STDCALL sqlite3_free(void*); -SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*); +SQLITE_API void *sqlite3_malloc(int); +SQLITE_API void *sqlite3_malloc64(sqlite3_uint64); +SQLITE_API void *sqlite3_realloc(void*, int); +SQLITE_API void *sqlite3_realloc64(void*, sqlite3_uint64); +SQLITE_API void sqlite3_free(void*); +SQLITE_API sqlite3_uint64 sqlite3_msize(void*); /* ** CAPI3REF: Memory Allocator Statistics @@ -2549,8 +2606,8 @@ SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*); ** by [sqlite3_memory_highwater(1)] is the high-water mark ** prior to the reset. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag); +SQLITE_API sqlite3_int64 sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); /* ** CAPI3REF: Pseudo-Random Number Generator @@ -2573,7 +2630,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag); ** internally and without recourse to the [sqlite3_vfs] xRandomness ** method. */ -SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P); +SQLITE_API void sqlite3_randomness(int N, void *P); /* ** CAPI3REF: Compile-Time Authorization Callbacks @@ -2656,7 +2713,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P); ** as stated in the previous paragraph, sqlite3_step() invokes ** sqlite3_prepare_v2() to reprepare a statement after a schema change. */ -SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( +SQLITE_API int sqlite3_set_authorizer( sqlite3*, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pUserData @@ -2736,6 +2793,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( ** CAPI3REF: Tracing And Profiling Functions ** METHOD: sqlite3 ** +** These routines are deprecated. Use the [sqlite3_trace_v2()] interface +** instead of the routines described here. +** ** These routines register callback functions that can be used for ** tracing and profiling the execution of SQL statements. ** @@ -2761,10 +2821,104 @@ SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( ** sqlite3_profile() function is considered experimental and is ** subject to change in future versions of SQLite. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_profile(sqlite3*, +SQLITE_API SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*, + void(*xTrace)(void*,const char*), void*); +SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, void(*xProfile)(void*,const char*,sqlite3_uint64), void*); +/* +** CAPI3REF: SQL Trace Event Codes +** KEYWORDS: SQLITE_TRACE +** +** These constants identify classes of events that can be monitored +** using the [sqlite3_trace_v2()] tracing logic. The third argument +** to [sqlite3_trace_v2()] is an OR-ed combination of one or more of +** the following constants. ^The first argument to the trace callback +** is one of the following constants. +** +** New tracing constants may be added in future releases. +** +** ^A trace callback has four arguments: xCallback(T,C,P,X). +** ^The T argument is one of the integer type codes above. +** ^The C argument is a copy of the context pointer passed in as the +** fourth argument to [sqlite3_trace_v2()]. +** The P and X arguments are pointers whose meanings depend on T. +** +**
    +** [[SQLITE_TRACE_STMT]]
    SQLITE_TRACE_STMT
    +**
    ^An SQLITE_TRACE_STMT callback is invoked when a prepared statement +** first begins running and possibly at other times during the +** execution of the prepared statement, such as at the start of each +** trigger subprogram. ^The P argument is a pointer to the +** [prepared statement]. ^The X argument is a pointer to a string which +** is the unexpanded SQL text of the prepared statement or an SQL comment +** that indicates the invocation of a trigger. ^The callback can compute +** the same text that would have been returned by the legacy [sqlite3_trace()] +** interface by using the X argument when X begins with "--" and invoking +** [sqlite3_expanded_sql(P)] otherwise. +** +** [[SQLITE_TRACE_PROFILE]]
    SQLITE_TRACE_PROFILE
    +**
    ^An SQLITE_TRACE_PROFILE callback provides approximately the same +** information as is provided by the [sqlite3_profile()] callback. +** ^The P argument is a pointer to the [prepared statement] and the +** X argument points to a 64-bit integer which is the estimated of +** the number of nanosecond that the prepared statement took to run. +** ^The SQLITE_TRACE_PROFILE callback is invoked when the statement finishes. +** +** [[SQLITE_TRACE_ROW]]
    SQLITE_TRACE_ROW
    +**
    ^An SQLITE_TRACE_ROW callback is invoked whenever a prepared +** statement generates a single row of result. +** ^The P argument is a pointer to the [prepared statement] and the +** X argument is unused. +** +** [[SQLITE_TRACE_CLOSE]]
    SQLITE_TRACE_CLOSE
    +**
    ^An SQLITE_TRACE_CLOSE callback is invoked when a database +** connection closes. +** ^The P argument is a pointer to the [database connection] object +** and the X argument is unused. +**
    +*/ +#define SQLITE_TRACE_STMT 0x01 +#define SQLITE_TRACE_PROFILE 0x02 +#define SQLITE_TRACE_ROW 0x04 +#define SQLITE_TRACE_CLOSE 0x08 + +/* +** CAPI3REF: SQL Trace Hook +** METHOD: sqlite3 +** +** ^The sqlite3_trace_v2(D,M,X,P) interface registers a trace callback +** function X against [database connection] D, using property mask M +** and context pointer P. ^If the X callback is +** NULL or if the M mask is zero, then tracing is disabled. The +** M argument should be the bitwise OR-ed combination of +** zero or more [SQLITE_TRACE] constants. +** +** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides +** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2(). +** +** ^The X callback is invoked whenever any of the events identified by +** mask M occur. ^The integer return value from the callback is currently +** ignored, though this may change in future releases. Callback +** implementations should return zero to ensure future compatibility. +** +** ^A trace callback is invoked with four arguments: callback(T,C,P,X). +** ^The T argument is one of the [SQLITE_TRACE] +** constants to indicate why the callback was invoked. +** ^The C argument is a copy of the context pointer. +** The P and X arguments are pointers whose meanings depend on T. +** +** The sqlite3_trace_v2() interface is intended to replace the legacy +** interfaces [sqlite3_trace()] and [sqlite3_profile()], both of which +** are deprecated. +*/ +SQLITE_API int sqlite3_trace_v2( + sqlite3*, + unsigned uMask, + int(*xCallback)(unsigned,void*,void*,void*), + void *pCtx +); + /* ** CAPI3REF: Query Progress Callbacks ** METHOD: sqlite3 @@ -2797,7 +2951,7 @@ SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_profile(sqlite3*, ** database connections for the meaning of "modify" in this paragraph. ** */ -SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); +SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); /* ** CAPI3REF: Opening A New Database Connection @@ -3026,15 +3180,15 @@ SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(vo ** ** See also: [sqlite3_temp_directory] */ -SQLITE_API int SQLITE_STDCALL sqlite3_open( +SQLITE_API int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_open16( +SQLITE_API int sqlite3_open16( const void *filename, /* Database filename (UTF-16) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( +SQLITE_API int sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ @@ -3080,9 +3234,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( ** VFS method, then the behavior of this routine is undefined and probably ** undesirable. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam); -SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const char*, sqlite3_int64); +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); /* @@ -3126,11 +3280,11 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const cha ** was invoked incorrectly by the application. In that case, the ** error code and message may or may not be set. */ -SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db); -SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db); -SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3*); -SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int); +SQLITE_API int sqlite3_errcode(sqlite3 *db); +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *sqlite3_errmsg(sqlite3*); +SQLITE_API const void *sqlite3_errmsg16(sqlite3*); +SQLITE_API const char *sqlite3_errstr(int); /* ** CAPI3REF: Prepared Statement Object @@ -3198,7 +3352,7 @@ typedef struct sqlite3_stmt sqlite3_stmt; ** ** New run-time limit categories may be added in future releases. */ -SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); +SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Run-Time Limit Categories @@ -3350,28 +3504,28 @@ SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); **
  • ** */ -SQLITE_API int SQLITE_STDCALL sqlite3_prepare( +SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2( +SQLITE_API int sqlite3_prepare_v2( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( +SQLITE_API int sqlite3_prepare16( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( +SQLITE_API int sqlite3_prepare16_v2( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ @@ -3383,11 +3537,35 @@ SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( ** CAPI3REF: Retrieving Statement SQL ** METHOD: sqlite3_stmt ** -** ^This interface can be used to retrieve a saved copy of the original -** SQL text used to create a [prepared statement] if that statement was -** compiled using either [sqlite3_prepare_v2()] or [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()]. +** ^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. +** +** ^(For example, if a prepared statement is created using the SQL +** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 +** and parameter :xyz is unbound, then sqlite3_sql() will return +** the original string, "SELECT $abc,:xyz" but sqlite3_expanded_sql() +** will return "SELECT 2345,NULL".)^ +** +** ^The sqlite3_expanded_sql() interface returns NULL if insufficient memory +** is available to hold the result, or if the result would exceed the +** the maximum string length determined by the [SQLITE_LIMIT_LENGTH]. +** +** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of +** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time +** option causes sqlite3_expanded_sql() to always return NULL. +** +** ^The string returned by sqlite3_sql(P) is managed by SQLite and is +** automatically freed when the prepared statement is finalized. +** ^The string returned by sqlite3_expanded_sql(P), on the other hand, +** is obtained from [sqlite3_malloc()] and must be free by the application +** by passing it to [sqlite3_free()]. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt); +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); +SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database @@ -3419,7 +3597,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt); ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset @@ -3440,7 +3618,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt); ** for example, in diagnostic routines to search for prepared ** statements that are holding a transaction open. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt*); +SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); /* ** CAPI3REF: Dynamically Typed Value Object @@ -3604,20 +3782,20 @@ typedef struct sqlite3_context sqlite3_context; ** See also: [sqlite3_bind_parameter_count()], ** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, +SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt*, int, double); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt*, int, int); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, +SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); +SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, void(*)(void*), unsigned char encoding); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); +SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); +SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); /* ** CAPI3REF: Number Of SQL Parameters @@ -3638,7 +3816,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite ** [sqlite3_bind_parameter_name()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*); +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); /* ** CAPI3REF: Name Of A Host Parameter @@ -3666,7 +3844,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*); ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, int); +SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); /* ** CAPI3REF: Index Of A Parameter With A Given Name @@ -3683,7 +3861,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_name()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); /* ** CAPI3REF: Reset All Bindings On A Prepared Statement @@ -3693,7 +3871,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const ** the [sqlite3_bind_blob | bindings] on a [prepared statement]. ** ^Use this routine to reset all host parameters to NULL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*); +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); /* ** CAPI3REF: Number Of Columns In A Result Set @@ -3705,7 +3883,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*); ** ** See also: [sqlite3_data_count()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Column Names In A Result Set @@ -3734,8 +3912,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt); ** then the name of the column is unspecified and may change from ** one release of SQLite to the next. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt*, int N); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N); +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); /* ** CAPI3REF: Source Of Data In A Query Result @@ -3783,12 +3961,12 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N ** for the same [prepared statement] and result column ** at the same time then the results are undefined. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt*,int); -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt*,int); -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); /* ** CAPI3REF: Declared Datatype Of A Query Result @@ -3820,8 +3998,8 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt* ** is associated with individual values, not with the containers ** used to hold those values. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); /* ** CAPI3REF: Evaluate An SQL Statement @@ -3882,7 +4060,8 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,in ** 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, sqlite3_step() began +** 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 ** break because any application that ever receives an SQLITE_MISUSE error @@ -3901,7 +4080,7 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,in ** then the more specific [error codes] are returned directly ** by sqlite3_step(). The use of the "v2" interface is recommended. */ -SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*); +SQLITE_API int sqlite3_step(sqlite3_stmt*); /* ** CAPI3REF: Number of columns in a result set @@ -3922,7 +4101,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*); ** ** See also: [sqlite3_column_count()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Fundamental Datatypes @@ -4112,16 +4291,16 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); ** pointer. Subsequent calls to [sqlite3_errcode()] will return ** [SQLITE_NOMEM].)^ */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt*, int iCol); -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*, int iCol); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int iCol); +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); /* ** CAPI3REF: Destroy A Prepared Statement Object @@ -4149,7 +4328,7 @@ SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int ** statement after it has been finalized can result in undefined and ** undesirable behavior such as segfaults and heap corruption. */ -SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); /* ** CAPI3REF: Reset A Prepared Statement Object @@ -4176,7 +4355,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt); ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ -SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); /* ** CAPI3REF: Create Or Redefine SQL Functions @@ -4276,7 +4455,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt); ** close the database connection nor finalize or reset the prepared ** statement in which the function is running. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_function( +SQLITE_API int sqlite3_create_function( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4286,7 +4465,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( +SQLITE_API int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, @@ -4296,7 +4475,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( +SQLITE_API int sqlite3_create_function_v2( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4342,12 +4521,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( ** these functions, we will not explain what they do. */ #ifndef SQLITE_OMIT_DEPRECATED -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_global_recover(void); -SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_thread_cleanup(void); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), +SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), void*,sqlite3_int64); #endif @@ -4397,18 +4576,18 @@ SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(voi ** These routines must be called from the same thread as ** the SQL function that supplied the [sqlite3_value*] parameters. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value*); -SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value*); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value*); -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*); +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 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_type(sqlite3_value*); +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Finding The Subtype Of SQL Values @@ -4424,7 +4603,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*); ** from the result of one [application-defined SQL function] into the ** input of another. */ -SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value*); +SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); /* ** CAPI3REF: Copy And Free SQL Values @@ -4440,8 +4619,8 @@ SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value*); ** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer ** then sqlite3_value_free(V) is a harmless no-op. */ -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value*); -SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*); +SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value*); +SQLITE_API void sqlite3_value_free(sqlite3_value*); /* ** CAPI3REF: Obtain Aggregate Function Context @@ -4486,7 +4665,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*); ** This routine must be called from the same thread in which ** the aggregate SQL function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int nBytes); +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* ** CAPI3REF: User Data For Functions @@ -4501,7 +4680,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int ** This routine must be called from the same thread in which ** the application-defined function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*); +SQLITE_API void *sqlite3_user_data(sqlite3_context*); /* ** CAPI3REF: Database Connection For Functions @@ -4513,7 +4692,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*); ** and [sqlite3_create_function16()] routines that originally ** registered the application defined function. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); /* ** CAPI3REF: Function Auxiliary Data @@ -4545,12 +4724,13 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); ** SQLite will invoke the destructor function X with parameter P exactly ** once, when the metadata is discarded. ** SQLite is free to discard the metadata at any time, including:
      -**
    • when the corresponding function parameter changes, or -**
    • when [sqlite3_reset()] or [sqlite3_finalize()] is called for the -** SQL statement, or -**
    • when sqlite3_set_auxdata() is invoked again on the same parameter, or -**
    • during the original sqlite3_set_auxdata() call when a memory -** allocation error occurs.
    )^ +**
  • ^(when the corresponding function parameter changes)^, or +**
  • ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the +** SQL statement)^, or +**
  • ^(when sqlite3_set_auxdata() is invoked again on the same +** parameter)^, or +**
  • ^(during the original sqlite3_set_auxdata() call when a memory +** allocation error occurs.)^ ** ** Note the last bullet in particular. The destructor X in ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the @@ -4566,8 +4746,8 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); ** These routines must be called from the same thread in which ** the SQL function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context*, int N); -SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); /* @@ -4703,27 +4883,27 @@ typedef void (*sqlite3_destructor_type)(void*); ** than the one containing the application-defined function that received ** the [sqlite3_context] pointer, the results are undefined. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64(sqlite3_context*,const void*, +SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*, sqlite3_uint64,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context*, double); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context*, const char*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context*, const void*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, +SQLITE_API void sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void sqlite3_result_null(sqlite3_context*); +SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n); -SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); +SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(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_zeroblob(sqlite3_context*, int n); +SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); /* @@ -4738,7 +4918,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context*,unsigned int); +SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); /* ** CAPI3REF: Define New Collating Sequences @@ -4820,14 +5000,14 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context*,unsigned ** ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation( +SQLITE_API int sqlite3_create_collation( sqlite3*, const char *zName, int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( +SQLITE_API int sqlite3_create_collation_v2( sqlite3*, const char *zName, int eTextRep, @@ -4835,7 +5015,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( int(*xCompare)(void*,int,const void*,int,const void*), void(*xDestroy)(void*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( +SQLITE_API int sqlite3_create_collation16( sqlite3*, const void *zName, int eTextRep, @@ -4870,12 +5050,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( ** [sqlite3_create_collation()], [sqlite3_create_collation16()], or ** [sqlite3_create_collation_v2()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( +SQLITE_API int sqlite3_collation_needed( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const char*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( +SQLITE_API int sqlite3_collation_needed16( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) @@ -4889,11 +5069,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int SQLITE_STDCALL sqlite3_key( +SQLITE_API int sqlite3_key( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The key */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_key_v2( +SQLITE_API int sqlite3_key_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The key */ @@ -4907,11 +5087,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_key_v2( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int SQLITE_STDCALL sqlite3_rekey( +SQLITE_API int sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2( +SQLITE_API int sqlite3_rekey_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The new key */ @@ -4921,7 +5101,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2( ** Specify the activation key for a SEE database. Unless ** activated, none of the SEE routines will work. */ -SQLITE_API void SQLITE_STDCALL sqlite3_activate_see( +SQLITE_API void sqlite3_activate_see( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -4931,7 +5111,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_activate_see( ** Specify the activation key for a CEROD database. Unless ** activated, none of the CEROD routines will work. */ -SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod( +SQLITE_API void sqlite3_activate_cerod( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -4953,7 +5133,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod( ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. */ -SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int); +SQLITE_API int sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files @@ -5072,7 +5252,7 @@ SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory; ** connection while this routine is running, then the return value ** is undefined. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*); +SQLITE_API int sqlite3_get_autocommit(sqlite3*); /* ** CAPI3REF: Find The Database Handle Of A Prepared Statement @@ -5085,7 +5265,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*); ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*); +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Filename For A Database Connection @@ -5102,7 +5282,7 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*); ** will be an absolute pathname, even if the filename used ** to open the database originally was a URI or relative pathname. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName); +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only @@ -5112,7 +5292,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const cha ** of connection D is read-only, 0 if it is read/write, or -1 if N is not ** the name of a database on connection D. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName); +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Find the next prepared statement @@ -5128,7 +5308,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbNa ** [sqlite3_next_stmt(D,S)] must refer to an open database ** connection and in particular must not be a NULL pointer. */ -SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); /* ** CAPI3REF: Commit And Rollback Notification Callbacks @@ -5177,8 +5357,8 @@ SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_ ** ** See also the [sqlite3_update_hook()] interface. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); +SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* ** CAPI3REF: Data Change Notification Callbacks @@ -5187,7 +5367,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), ** ^The sqlite3_update_hook() interface registers a callback function ** with the [database connection] identified by the first argument ** to be invoked whenever a row is updated, inserted or deleted in -** a rowid table. +** a [rowid table]. ** ^Any callback set by a previous call to this function ** for the same database connection is overridden. ** @@ -5226,10 +5406,10 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), ** on the same [database connection] D, or NULL for ** the first call on D. ** -** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] -** interfaces. +** See also the [sqlite3_commit_hook()], [sqlite3_rollback_hook()], +** and [sqlite3_preupdate_hook()] interfaces. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( +SQLITE_API void *sqlite3_update_hook( sqlite3*, void(*)(void *,int ,char const *,char const *,sqlite3_int64), void* @@ -5244,7 +5424,8 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( ** and disabled if the argument is false.)^ ** ** ^Cache sharing is enabled and disabled for an entire process. -** This is a change as of SQLite version 3.5.0. In prior versions of SQLite, +** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). +** In prior versions of SQLite, ** sharing was enabled or disabled for each thread separately. ** ** ^(The cache sharing mode set by this interface effects all subsequent @@ -5269,7 +5450,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( ** ** See Also: [SQLite Shared-Cache Mode] */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int); +SQLITE_API int sqlite3_enable_shared_cache(int); /* ** CAPI3REF: Attempt To Free Heap Memory @@ -5285,7 +5466,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int); ** ** See also: [sqlite3_db_release_memory()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int); +SQLITE_API int sqlite3_release_memory(int); /* ** CAPI3REF: Free Memory Used By A Database Connection @@ -5299,7 +5480,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int); ** ** See also: [sqlite3_release_memory()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); +SQLITE_API int sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size @@ -5338,7 +5519,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); ** from the heap. ** )^ ** -** Beginning with SQLite version 3.7.3, the soft heap limit is enforced +** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]), +** the soft heap limit is enforced ** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] ** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], ** the soft heap limit is enforced on every memory allocation. Without @@ -5351,7 +5533,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); ** The circumstances under which SQLite will enforce the soft heap limit may ** changes in future releases of SQLite. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 N); +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface @@ -5362,7 +5544,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 ** only. All new applications should use the ** [sqlite3_soft_heap_limit64()] interface rather than this one. */ -SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); +SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); /* @@ -5377,7 +5559,7 @@ SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); ** column exists. ^The sqlite3_table_column_metadata() interface returns ** SQLITE_ERROR and if the specified column does not exist. ** ^If the column-name parameter to sqlite3_table_column_metadata() is a -** NULL pointer, then this routine simply checks for the existance of the +** 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. ** @@ -5432,7 +5614,7 @@ SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); ** parsed, if that has not already been done, and returns an error if ** any errors are encountered while loading the schema. */ -SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( +SQLITE_API int sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ @@ -5474,12 +5656,21 @@ SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( ** should free this memory by calling [sqlite3_free()]. ** ** ^Extension loading must be enabled using -** [sqlite3_enable_load_extension()] prior to calling this API, +** [sqlite3_enable_load_extension()] or +** [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],1,NULL) +** prior to calling this API, ** otherwise an error will be returned. ** +** Security warning: It is recommended that the +** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this +** interface. The use of the [sqlite3_enable_load_extension()] interface +** should be avoided. This will keep the SQL function [load_extension()] +** disabled and prevent SQL injections from giving attackers +** access to extension loading capabilities. +** ** See also the [load_extension() SQL function]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( +SQLITE_API int sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Derived from zFile if 0 */ @@ -5499,8 +5690,19 @@ SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( ** ^Call the sqlite3_enable_load_extension() routine with onoff==1 ** to turn extension loading on and call it with onoff==0 to turn ** it back off again. +** +** ^This interface enables or disables both the C-API +** [sqlite3_load_extension()] and the SQL function [load_extension()]. +** ^(Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..) +** to enable or disable only the C-API.)^ +** +** Security warning: It is recommended that extension loading +** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method +** rather than this interface, so the [load_extension()] SQL function +** remains disabled. This will prevent SQL injections from giving attackers +** access to extension loading capabilities. */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff); +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ** CAPI3REF: Automatically Load Statically Linked Extensions @@ -5512,7 +5714,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int ono ** ** ^(Even though the function prototype shows that xEntryPoint() takes ** no arguments and returns void, SQLite invokes xEntryPoint() with three -** arguments and expects and integer result as if the signature of the +** arguments and expects an integer result as if the signature of the ** entry point where as follows: ** **
    @@ -5538,7 +5740,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int ono
     ** See also: [sqlite3_reset_auto_extension()]
     ** and [sqlite3_cancel_auto_extension()]
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xEntryPoint)(void));
    +SQLITE_API int sqlite3_auto_extension(void(*xEntryPoint)(void));
     
     /*
     ** CAPI3REF: Cancel Automatic Extension Loading
    @@ -5550,7 +5752,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xEntryPoint)(void));
     ** unregistered and it returns 0 if X was not on the list of initialization
     ** routines.
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
    +SQLITE_API int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void));
     
     /*
     ** CAPI3REF: Reset Automatic Extension Loading
    @@ -5558,7 +5760,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xEntryPoint)(
     ** ^This interface disables all automatic extensions previously
     ** registered using [sqlite3_auto_extension()].
     */
    -SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void);
    +SQLITE_API void sqlite3_reset_auto_extension(void);
     
     /*
     ** The interface to the virtual-table mechanism is currently considered
    @@ -5712,13 +5914,15 @@ struct sqlite3_module {
     ** the xUpdate method are automatically rolled back by SQLite.
     **
     ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
    -** structure for SQLite version 3.8.2. If a virtual table extension is
    +** structure for SQLite [version 3.8.2] ([dateof:3.8.2]). 
    +** If a virtual table extension is
     ** used with an SQLite version earlier than 3.8.2, the results of attempting 
     ** to read or write the estimatedRows field are undefined (but are likely 
     ** to included crashing the application). The estimatedRows field should
     ** therefore only be used if [sqlite3_libversion_number()] returns a
     ** value greater than or equal to 3008002. Similarly, the idxFlags field
    -** was added for version 3.9.0. It may therefore only be used if
    +** was added for [version 3.9.0] ([dateof:3.9.0]). 
    +** It may therefore only be used if
     ** sqlite3_libversion_number() returns a value greater than or equal to
     ** 3009000.
     */
    @@ -5803,13 +6007,13 @@ struct sqlite3_index_info {
     ** interface is equivalent to sqlite3_create_module_v2() with a NULL
     ** destructor.
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_create_module(
    +SQLITE_API int sqlite3_create_module(
       sqlite3 *db,               /* SQLite connection to register module with */
       const char *zName,         /* Name of the module */
       const sqlite3_module *p,   /* Methods for the module */
       void *pClientData          /* Client data for xCreate/xConnect */
     );
    -SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2(
    +SQLITE_API int sqlite3_create_module_v2(
       sqlite3 *db,               /* SQLite connection to register module with */
       const char *zName,         /* Name of the module */
       const sqlite3_module *p,   /* Methods for the module */
    @@ -5872,7 +6076,7 @@ struct sqlite3_vtab_cursor {
     ** to declare the format (the names and datatypes of the columns) of
     ** the virtual tables they implement.
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL);
    +SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
     
     /*
     ** CAPI3REF: Overload A Function For A Virtual Table
    @@ -5891,7 +6095,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL);
     ** purpose is to be a placeholder function that can be overloaded
     ** by a [virtual table].
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
    +SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
     
     /*
     ** The interface to the virtual-table mechanism defined above (back up
    @@ -5990,7 +6194,7 @@ 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()].
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_blob_open(
    +SQLITE_API int sqlite3_blob_open(
       sqlite3*,
       const char *zDb,
       const char *zTable,
    @@ -6023,7 +6227,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open(
     **
     ** ^This function sets the database handle error code and message.
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
    +SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
     
     /*
     ** CAPI3REF: Close A BLOB Handle
    @@ -6046,7 +6250,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64)
     ** is passed a valid open blob handle, the values returned by the 
     ** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning.
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *);
    +SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
     
     /*
     ** CAPI3REF: Return The Size Of An Open BLOB
    @@ -6062,7 +6266,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *);
     ** been closed by [sqlite3_blob_close()].  Passing any other pointer in
     ** to this routine results in undefined and probably undesirable behavior.
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *);
    +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *);
     
     /*
     ** CAPI3REF: Read Data From A BLOB Incrementally
    @@ -6091,7 +6295,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *);
     **
     ** See also: [sqlite3_blob_write()].
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
    +SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
     
     /*
     ** CAPI3REF: Write Data Into A BLOB Incrementally
    @@ -6133,7 +6337,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N,
     **
     ** See also: [sqlite3_blob_read()].
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
    +SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
     
     /*
     ** CAPI3REF: Virtual File System Objects
    @@ -6164,9 +6368,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z,
     ** ^(If the default VFS is unregistered, another VFS is chosen as
     ** the default.  The choice for the new VFS is arbitrary.)^
     */
    -SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfsName);
    -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
    -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*);
    +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
    +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
    +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
     
     /*
     ** CAPI3REF: Mutexes
    @@ -6282,11 +6486,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*);
     **
     ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
     */
    -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int);
    -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex*);
    -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex*);
    -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex*);
    -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex*);
    +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int);
    +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*);
    +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*);
    +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*);
    +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
     
     /*
     ** CAPI3REF: Mutex Methods Object
    @@ -6396,8 +6600,8 @@ struct sqlite3_mutex_methods {
     ** interface should also return 1 when given a NULL pointer.
     */
     #ifndef NDEBUG
    -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex*);
    -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*);
    +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
    +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
     #endif
     
     /*
    @@ -6416,7 +6620,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*);
     #define SQLITE_MUTEX_STATIC_MEM       3  /* sqlite3_malloc() */
     #define SQLITE_MUTEX_STATIC_MEM2      4  /* NOT USED */
     #define SQLITE_MUTEX_STATIC_OPEN      4  /* sqlite3BtreeOpen() */
    -#define SQLITE_MUTEX_STATIC_PRNG      5  /* sqlite3_random() */
    +#define SQLITE_MUTEX_STATIC_PRNG      5  /* sqlite3_randomness() */
     #define SQLITE_MUTEX_STATIC_LRU       6  /* lru page list */
     #define SQLITE_MUTEX_STATIC_LRU2      7  /* NOT USED */
     #define SQLITE_MUTEX_STATIC_PMEM      7  /* sqlite3PageMalloc() */
    @@ -6437,7 +6641,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*);
     ** ^If the [threading mode] is Single-thread or Multi-thread then this
     ** routine returns a NULL pointer.
     */
    -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*);
    +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
     
     /*
     ** CAPI3REF: Low-Level Control Of Database Files
    @@ -6472,7 +6676,7 @@ SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*);
     **
     ** See also: [SQLITE_FCNTL_LOCKSTATE]
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
    +SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
     
     /*
     ** CAPI3REF: Testing Interface
    @@ -6491,7 +6695,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName
     ** Unlike most of the SQLite API, this function is not guaranteed to
     ** operate consistently from one release to the next.
     */
    -SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...);
    +SQLITE_API int sqlite3_test_control(int op, ...);
     
     /*
     ** CAPI3REF: Testing Interface Operation Codes
    @@ -6520,6 +6724,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...);
     #define SQLITE_TESTCTRL_SCRATCHMALLOC           17
     #define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
     #define SQLITE_TESTCTRL_EXPLAIN_STMT            19  /* NOT USED */
    +#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD    19
     #define SQLITE_TESTCTRL_NEVER_CORRUPT           20
     #define SQLITE_TESTCTRL_VDBE_COVERAGE           21
     #define SQLITE_TESTCTRL_BYTEORDER               22
    @@ -6554,8 +6759,8 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...);
     **
     ** See also: [sqlite3_db_status()]
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
    -SQLITE_API int SQLITE_STDCALL sqlite3_status64(
    +SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
    +SQLITE_API int sqlite3_status64(
       int op,
       sqlite3_int64 *pCurrent,
       sqlite3_int64 *pHighwater,
    @@ -6680,7 +6885,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status64(
     **
     ** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
     */
    -SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
    +SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
     
     /*
     ** CAPI3REF: Status Parameters for database connections
    @@ -6726,6 +6931,18 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int
     ** memory used by all pager caches associated with the database connection.)^
     ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
     **
    +** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]] 
    +** ^(
    SQLITE_DBSTATUS_CACHE_USED_SHARED
    +**
    This parameter is similar to DBSTATUS_CACHE_USED, except that if a +** pager cache is shared between two or more connections the bytes of heap +** memory used by that pager cache is divided evenly between the attached +** connections.)^ In other words, if none of the pager caches associated +** with the database connection are shared, this request returns the same +** value as DBSTATUS_CACHE_USED. Or, if one or more or the pager caches are +** shared, the value returned by this call will be smaller than that returned +** by DBSTATUS_CACHE_USED. ^The highwater mark associated with +** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0. +** ** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(
    SQLITE_DBSTATUS_SCHEMA_USED
    **
    This parameter returns the approximate number of bytes of heap ** memory used to store the schema for all databases associated @@ -6783,7 +7000,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_CACHE_WRITE 9 #define SQLITE_DBSTATUS_DEFERRED_FKS 10 -#define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 +#define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */ /* @@ -6810,7 +7028,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int ** ** See also: [sqlite3_status()] and [sqlite3_db_status()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); +SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); /* ** CAPI3REF: Status Parameters for prepared statements @@ -7137,7 +7355,7 @@ typedef struct sqlite3_backup sqlite3_backup; ** must be different or else sqlite3_backup_init(D,N,S,M) will fail with ** an error. ** -** ^A call to sqlite3_backup_init() will fail, returning SQLITE_ERROR, if +** ^A call to sqlite3_backup_init() will fail, returning NULL, if ** there is already a read or read-write transaction open on the ** destination database. ** @@ -7279,16 +7497,16 @@ typedef struct sqlite3_backup sqlite3_backup; ** same time as another thread is invoking sqlite3_backup_step() it is ** possible that they return invalid values. */ -SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( +SQLITE_API sqlite3_backup *sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ const char *zSourceName /* Source database name */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); /* ** CAPI3REF: Unlock Notification @@ -7405,7 +7623,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p); ** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE_LOCKED.)^ */ -SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( +SQLITE_API int sqlite3_unlock_notify( sqlite3 *pBlocked, /* Waiting connection */ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ void *pNotifyArg /* Argument to pass to xNotify */ @@ -7420,8 +7638,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( ** strings in a case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *, const char *); -SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int); +SQLITE_API int sqlite3_stricmp(const char *, const char *); +SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* ** CAPI3REF: String Globbing @@ -7438,7 +7656,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int); ** ** See also: [sqlite3_strlike()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zStr); +SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); /* ** CAPI3REF: String LIKE Matching @@ -7461,7 +7679,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zSt ** ** See also: [sqlite3_strglob()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc); +SQLITE_API int sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc); /* ** CAPI3REF: Error Logging Interface @@ -7484,7 +7702,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zGlob, const char *zSt ** a few hundred characters, it will be truncated to the length of the ** buffer. */ -SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...); +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); /* ** CAPI3REF: Write-Ahead Log Commit Hook @@ -7520,7 +7738,7 @@ SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...) ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** overwrite any prior [sqlite3_wal_hook()] settings. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( +SQLITE_API void *sqlite3_wal_hook( sqlite3*, int(*)(void *,sqlite3*,const char*,int), void* @@ -7555,7 +7773,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( ** is only necessary if the default setting is found to be suboptimal ** for a particular application. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N); +SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); /* ** CAPI3REF: Checkpoint a database @@ -7577,7 +7795,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N); ** start a callback but which do not need the full power (and corresponding ** complication) of [sqlite3_wal_checkpoint_v2()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); +SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Checkpoint a database @@ -7671,7 +7889,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zD ** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface ** from SQL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( +SQLITE_API int sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of attached database (or NULL) */ int eMode, /* SQLITE_CHECKPOINT_* value */ @@ -7707,7 +7925,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( ** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options ** may be added in the future. */ -SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...); +SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); /* ** CAPI3REF: Virtual Table Configuration Options @@ -7760,7 +7978,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...); ** of the SQL statement that triggered the call to the [xUpdate] method of the ** [virtual table]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *); +SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); /* ** CAPI3REF: Conflict resolution modes @@ -7865,7 +8083,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *); ** ** See also: [sqlite3_stmt_scanstatus_reset()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( +SQLITE_API int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ @@ -7881,7 +8099,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ -SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); +SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** CAPI3REF: Flush caches to disk mid-transaction @@ -7913,19 +8131,115 @@ SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); ** ^This function does not set the database handle error code or message ** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3*); +SQLITE_API int sqlite3_db_cacheflush(sqlite3*); + +/* +** CAPI3REF: The pre-update hook. +** +** ^These interfaces are only available if SQLite is compiled using the +** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option. +** +** ^The [sqlite3_preupdate_hook()] interface registers a callback function +** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation +** on a [rowid 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. +** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()] +** with a NULL pointer as the second parameter. +** ^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 second parameter to the preupdate callback is a pointer to +** the [database connection] that registered the preupdate hook. +** ^The third parameter to the preupdate callback is one of the constants +** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to identify the +** kind of update operation that is about to occur. +** ^(The fourth parameter to the preupdate callback is the name of the +** database within the database connection that is being modified. This +** will be "main" for the main database or "temp" for TEMP tables or +** the name given after the AS keyword in the [ATTACH] statement for attached +** 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. +** +** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()], +** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces +** provide additional information about a preupdate event. These routines +** may only be called from within a preupdate callback. Invoking any of +** these routines from outside of a preupdate callback or with a +** [database connection] pointer that is different from the one supplied +** to the preupdate callback results in undefined and probably undesirable +** behavior. +** +** ^The [sqlite3_preupdate_count(D)] interface returns the number of columns +** in the row that is being inserted, updated, or deleted. +** +** ^The [sqlite3_preupdate_old(D,N,P)] interface writes into P a pointer to +** a [protected sqlite3_value] that contains the value of the Nth column of +** the table row before it is updated. The N parameter must be between 0 +** and one less than the number of columns or the behavior will be +** undefined. This must only be used within SQLITE_UPDATE and SQLITE_DELETE +** preupdate callbacks; if it is used by an SQLITE_INSERT callback then the +** behavior is undefined. The [sqlite3_value] that P points to +** will be destroyed when the preupdate callback returns. +** +** ^The [sqlite3_preupdate_new(D,N,P)] interface writes into P a pointer to +** a [protected sqlite3_value] that contains the value of the Nth column of +** the table row after it is updated. The N parameter must be between 0 +** and one less than the number of columns or the behavior will be +** undefined. This must only be used within SQLITE_INSERT and SQLITE_UPDATE +** preupdate callbacks; if it is used by an SQLITE_DELETE callback then the +** behavior is undefined. The [sqlite3_value] that P points to +** will be destroyed when the preupdate callback returns. +** +** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate +** callback was invoked as a result of a direct insert, update, or delete +** operation; or 1 for inserts, updates, or deletes invoked by top-level +** triggers; or 2 for changes resulting from triggers called by top-level +** triggers; and so forth. +** +** See also: [sqlite3_update_hook()] +*/ +SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook( + sqlite3 *db, + void(*xPreUpdate)( + void *pCtx, /* Copy of third arg to preupdate_hook() */ + sqlite3 *db, /* Database handle */ + int op, /* SQLITE_UPDATE, DELETE or INSERT */ + char const *zDb, /* Database name */ + char const *zName, /* Table name */ + sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ + sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ + ), + 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 **); /* ** CAPI3REF: Low-level system error code ** ** ^Attempt to return the underlying operating system error code or error -** number that caused the most reason I/O error or failure to open a file. +** number that caused the most recent I/O error or failure to open a file. ** The return value is OS-dependent. For example, on unix systems, after ** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be ** called to get back the underlying "errno" that caused the problem, such ** as ENOSPC, EAUTH, EISDIR, and so forth. */ -SQLITE_API int SQLITE_STDCALL sqlite3_system_errno(sqlite3*); +SQLITE_API int sqlite3_system_errno(sqlite3*); /* ** CAPI3REF: Database Snapshot @@ -7975,7 +8289,7 @@ typedef struct sqlite3_snapshot sqlite3_snapshot; ** The [sqlite3_snapshot_get()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_get( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( sqlite3 *db, const char *zSchema, sqlite3_snapshot **ppSnapshot @@ -7985,26 +8299,35 @@ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_get( ** CAPI3REF: Start a read transaction on an historical snapshot ** EXPERIMENTAL ** -** ^The [sqlite3_snapshot_open(D,S,P)] interface attempts to move the -** read transaction that is currently open on schema S of -** [database connection] D so that it refers to historical [snapshot] P. +** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a +** read transaction for schema S of +** [database connection] D such that the read transaction +** refers to historical [snapshot] P, rather than the most +** recent change to the database. ** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success ** or an appropriate [error code] if it fails. ** ** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be -** the first operation, apart from other sqlite3_snapshot_open() calls, -** following the [BEGIN] that starts a new read transaction. -** ^A [snapshot] will fail to open if it has been overwritten by a +** the first operation following the [BEGIN] that takes the schema S +** out of [autocommit mode]. +** ^In other words, schema S must not currently be in +** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the +** database connection D must be out of [autocommit mode]. +** ^A [snapshot] will fail to open if it has been overwritten by a ** [checkpoint]. -** ^A [snapshot] will fail to open if the database connection D has not -** previously completed at least one read operation against the database -** file. (Hint: Run "[PRAGMA application_id]" against a newly opened +** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the +** database connection D does not know that the database file for +** schema S is in [WAL mode]. A database connection might not know +** that the database file is in [WAL mode] if there has been no prior +** I/O on that database connection, or if the database entered [WAL mode] +** after the most recent I/O on the database connection.)^ +** (Hint: Run "[PRAGMA application_id]" against a newly opened ** database connection in order to make it ready to use snapshots.) ** ** The [sqlite3_snapshot_open()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_open( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( sqlite3 *db, const char *zSchema, sqlite3_snapshot *pSnapshot @@ -8021,7 +8344,34 @@ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_open( ** The [sqlite3_snapshot_free()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ -SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3_snapshot*); +SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); + +/* +** CAPI3REF: Compare the ages of two snapshot handles. +** EXPERIMENTAL +** +** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages +** of two valid snapshot handles. +** +** If the two snapshot handles are not associated with the same database +** file, the result of the comparison is undefined. +** +** Additionally, the result of the comparison is only valid if both of the +** snapshot handles were obtained by calling sqlite3_snapshot_get() since the +** last time the wal file was deleted. The wal file is deleted when the +** database is changed back to rollback mode or when the number of database +** clients drops to zero. If either snapshot handle was obtained before the +** wal file was last deleted, the value returned by this function +** is undefined. +** +** Otherwise, this API returns a negative value if P1 refers to an older +** snapshot than P2, zero if the two handles refer to the same database +** snapshot, and a positive value if P1 is a newer snapshot than P2. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( + sqlite3_snapshot *p1, + sqlite3_snapshot *p2 +); /* ** Undo the hack that converts floating point types to integer for @@ -8034,8 +8384,9 @@ SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3 #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif -#endif /* _SQLITE3_H_ */ +#endif /* SQLITE3_H */ +/******** Begin file sqlite3rtree.h *********/ /* ** 2010 August 30 ** @@ -8075,7 +8426,7 @@ typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info; ** ** SELECT ... FROM WHERE MATCH $zGeom(... params ...) */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( +SQLITE_API int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), @@ -8101,7 +8452,7 @@ struct sqlite3_rtree_geometry { ** ** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( +SQLITE_API int sqlite3_rtree_query_callback( sqlite3 *db, const char *zQueryFunc, int (*xQueryFunc)(sqlite3_rtree_query_info*), @@ -8153,6 +8504,1291 @@ struct sqlite3_rtree_query_info { #endif /* ifndef _SQLITE3RTREE_H_ */ +/******** End of sqlite3rtree.h *********/ +/******** Begin file sqlite3session.h *********/ + +#if !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) +#define __SQLITESESSION_H_ 1 + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" { +#endif + + +/* +** CAPI3REF: Session Object Handle +*/ +typedef struct sqlite3_session sqlite3_session; + +/* +** CAPI3REF: Changeset Iterator Handle +*/ +typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; + +/* +** CAPI3REF: Create A New Session Object +** +** Create a new session object attached to database handle db. If successful, +** a pointer to the new object is written to *ppSession and SQLITE_OK is +** returned. If an error occurs, *ppSession is set to NULL and an SQLite +** error code (e.g. SQLITE_NOMEM) is returned. +** +** It is possible to create multiple session objects attached to a single +** database handle. +** +** Session objects created using this function should be deleted using the +** [sqlite3session_delete()] function before the database handle that they +** are attached to is itself closed. If the database handle is closed before +** the session object is deleted, then the results of calling any session +** module function, including [sqlite3session_delete()] on the session object +** are undefined. +** +** Because the session module uses the [sqlite3_preupdate_hook()] API, it +** is not possible for an application to register a pre-update hook on a +** database handle that has one or more session objects attached. Nor is +** it possible to create a session object attached to a database handle for +** which a pre-update hook is already defined. The results of attempting +** either of these things are undefined. +** +** The session object will be used to create changesets for tables in +** database zDb, where zDb is either "main", or "temp", or the name of an +** 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( + sqlite3 *db, /* Database handle */ + const char *zDb, /* Name of db (e.g. "main") */ + sqlite3_session **ppSession /* OUT: New session object */ +); + +/* +** CAPI3REF: Delete A Session Object +** +** Delete a session object previously allocated using +** [sqlite3session_create()]. Once a session object has been deleted, the +** results of attempting to use pSession with any other session module +** function are undefined. +** +** Session objects must be deleted before the database handle to which they +** are attached is closed. Refer to the documentation for +** [sqlite3session_create()] for details. +*/ +void sqlite3session_delete(sqlite3_session *pSession); + + +/* +** CAPI3REF: Enable Or Disable A Session Object +** +** Enable or disable the recording of changes by a session object. When +** enabled, a session object records changes made to the database. When +** disabled - it does not. A newly created session object is enabled. +** Refer to the documentation for [sqlite3session_changeset()] for further +** details regarding how enabling and disabling a session object affects +** the eventual changesets. +** +** Passing zero to this function disables the session. Passing a value +** greater than zero enables it. Passing a value less than zero is a +** no-op, and may be used to query the current state of the session. +** +** 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); + +/* +** CAPI3REF: Set Or Clear the Indirect Change Flag +** +** Each change recorded by a session object is marked as either direct or +** indirect. A change is marked as indirect if either: +** +**
      +**
    • The session object "indirect" flag is set when the change is +** made, or +**
    • The change is made by an SQL trigger or foreign key action +** instead of directly as a result of a users SQL statement. +**
    +** +** If a single row is affected by more than one operation within a session, +** then the change is considered indirect if all operations meet the criteria +** for an indirect change above, or direct otherwise. +** +** This function is used to set, clear or query the session object indirect +** flag. If the second argument passed to this function is zero, then the +** indirect flag is cleared. If it is greater than zero, the indirect flag +** is set. Passing a value less than zero does not modify the current value +** of the indirect flag, and may be used to query the current state of the +** indirect flag for the specified session object. +** +** 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); + +/* +** CAPI3REF: Attach A Table To A Session Object +** +** If argument zTab is not NULL, then it is the name of a table to attach +** to the session object passed as the first argument. All subsequent changes +** made to the table while the session object is enabled will be recorded. See +** documentation for [sqlite3session_changeset()] for further details. +** +** Or, if argument zTab is NULL, then changes are recorded for all tables +** in the database. If additional tables are added to the database (by +** executing "CREATE TABLE" statements) after this call is made, changes for +** the new tables are also recorded. +** +** Changes can only be recorded for tables that have a PRIMARY KEY explicitly +** defined as part of their CREATE TABLE statement. It does not matter if the +** PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) or not. The PRIMARY +** KEY may consist of a single column, or may be a composite key. +** +** It is not an error if the named table does not exist in the database. Nor +** is it an error if the named table does not have a PRIMARY KEY. However, +** no changes will be recorded in either of these scenarios. +** +** Changes are not recorded for individual rows that have NULL values stored +** in one or more of their PRIMARY KEY columns. +** +** 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( + sqlite3_session *pSession, /* Session object */ + const char *zTab /* Table name */ +); + +/* +** CAPI3REF: Set a table filter on a Session Object. +** +** The second argument (xFilter) is the "filter callback". For changes to rows +** in tables that are not attached to the Session object, the filter is called +** to determine whether changes to the table's rows should be tracked or not. +** 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( + sqlite3_session *pSession, /* Session object */ + int(*xFilter)( + void *pCtx, /* Copy of third arg to _filter_table() */ + const char *zTab /* Table name */ + ), + void *pCtx /* First argument passed to xFilter */ +); + +/* +** CAPI3REF: Generate A Changeset From A Session Object +** +** Obtain a changeset containing changes to the tables attached to the +** session object passed as the first argument. If successful, +** set *ppChangeset to point to a buffer containing the changeset +** and *pnChangeset to the size of the changeset in bytes before returning +** SQLITE_OK. If an error occurs, set both *ppChangeset and *pnChangeset to +** zero and return an SQLite error code. +** +** A changeset consists of zero or more INSERT, UPDATE and/or DELETE changes, +** each representing a change to a single row of an attached table. An INSERT +** change contains the values of each field of a new database row. A DELETE +** contains the original values of each field of a deleted database row. An +** UPDATE change contains the original values of each field of an updated +** database row along with the updated values for each updated non-primary-key +** column. It is not possible for an UPDATE change to represent a change that +** modifies the values of primary key columns. If such a change is made, it +** is represented in a changeset as a DELETE followed by an INSERT. +** +** Changes are not recorded for rows that have NULL values stored in one or +** more of their PRIMARY KEY columns. If such a row is inserted or deleted, +** no corresponding change is present in the changesets returned by this +** function. If an existing row with one or more NULL values stored in +** PRIMARY KEY columns is updated so that all PRIMARY KEY columns are non-NULL, +** only an INSERT is appears in the changeset. Similarly, if an existing row +** with non-NULL PRIMARY KEY values is updated so that one or more of its +** PRIMARY KEY columns are set to NULL, the resulting changeset contains a +** DELETE change only. +** +** The contents of a changeset may be traversed using an iterator created +** using the [sqlite3changeset_start()] API. A changeset may be applied to +** a database with a compatible schema using the [sqlite3changeset_apply()] +** API. +** +** Within a changeset generated by this function, all changes related to a +** single table are grouped together. In other words, when iterating through +** a changeset or when applying a changeset to a database, all changes related +** to a single table are processed before moving on to the next table. Tables +** are sorted in the same order in which they were attached (or auto-attached) +** to the sqlite3_session object. The order in which the changes related to +** a single table are stored is undefined. +** +** Following a successful call to this function, it is the responsibility of +** the caller to eventually free the buffer that *ppChangeset points to using +** [sqlite3_free()]. +** +**

    Changeset Generation

    +** +** Once a table has been attached to a session object, the session object +** records the primary key values of all new rows inserted into the table. +** It also records the original primary key and other column values of any +** deleted or updated rows. For each unique primary key value, data is only +** recorded once - the first time a row with said primary key is inserted, +** updated or deleted in the lifetime of the session. +** +** There is one exception to the previous paragraph: when a row is inserted, +** updated or deleted, if one or more of its primary key columns contain a +** NULL value, no record of the change is made. +** +** The session object therefore accumulates two types of records - those +** that consist of primary key values only (created when the user inserts +** a new record) and those that consist of the primary key values and the +** original values of other table columns (created when the users deletes +** or updates a record). +** +** When this function is called, the requested changeset is created using +** both the accumulated records and the current contents of the database +** file. Specifically: +** +**
      +**
    • For each record generated by an insert, the database is queried +** for a row with a matching primary key. If one is found, an INSERT +** change is added to the changeset. If no such row is found, no change +** is added to the changeset. +** +**
    • For each record generated by an update or delete, the database is +** queried for a row with a matching primary key. If such a row is +** found and one or more of the non-primary key fields have been +** modified from their original values, an UPDATE change is added to +** the changeset. Or, if no such row is found in the table, a DELETE +** change is added to the changeset. If there is a row with a matching +** primary key in the database, but all fields contain their original +** values, no change is added to the changeset. +**
    +** +** This means, amongst other things, that if a row is inserted and then later +** deleted while a session object is active, neither the insert nor the delete +** will be present in the changeset. Or if a row is deleted and then later a +** row with the same primary key values inserted while a session object is +** active, the resulting changeset will contain an UPDATE change instead of +** a DELETE and an INSERT. +** +** When a session object is disabled (see the [sqlite3session_enable()] API), +** it does not accumulate records when rows are inserted, updated or deleted. +** This may appear to have some counter-intuitive effects if a single row +** is written to more than once during a session. For example, if a row +** is inserted while a session object is enabled, then later deleted while +** the same session object is disabled, no INSERT record will appear in the +** changeset, even though the delete took place while the session was disabled. +** Or, if one field of a row is updated while a session is disabled, and +** 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( + sqlite3_session *pSession, /* Session object */ + int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ + void **ppChangeset /* OUT: Buffer containing changeset */ +); + +/* +** CAPI3REF: Load The Difference Between Tables Into A Session +** +** If it is not already attached to the session object passed as the first +** argument, this function attaches table zTbl in the same manner as the +** [sqlite3session_attach()] function. If zTbl does not exist, or if it +** does not have a primary key, this function is a no-op (but does not return +** an error). +** +** Argument zFromDb must be the name of a database ("main", "temp" etc.) +** attached to the same database handle as the session object that contains +** a table compatible with the table attached to the session by this function. +** A table is considered compatible if it: +** +**
      +**
    • Has the same name, +**
    • Has the same set of columns declared in the same order, and +**
    • Has the same PRIMARY KEY definition. +**
    +** +** If the tables are not compatible, SQLITE_SCHEMA is returned. If the tables +** are compatible but do not have any PRIMARY KEY columns, it is not an error +** but no changes are added to the session object. As with other session +** APIs, tables without PRIMARY KEYs are simply ignored. +** +** This function adds a set of changes to the session object that could be +** used to update the table in database zFrom (call this the "from-table") +** so that its content is the same as the table attached to the session +** object (call this the "to-table"). Specifically: +** +**
      +**
    • For each row (primary key) that exists in the to-table but not in +** the from-table, an INSERT record is added to the session object. +** +**
    • For each row (primary key) that exists in the to-table but not in +** 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. +**
    +** +** To clarify, if this function is called and then a changeset constructed +** using [sqlite3session_changeset()], then after applying that changeset to +** database zFrom the contents of the two compatible tables would be +** identical. +** +** It an error if database zFrom does not exist or does not contain the +** required compatible table. +** +** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite +** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg +** may be set to point to a buffer containing an English language error +** message. It is the responsibility of the caller to free this buffer using +** sqlite3_free(). +*/ +int sqlite3session_diff( + sqlite3_session *pSession, + const char *zFromDb, + const char *zTbl, + char **pzErrMsg +); + + +/* +** CAPI3REF: Generate A Patchset From A Session Object +** +** The differences between a patchset and a changeset are that: +** +**
      +**
    • DELETE records consist of the primary key fields only. The +** original values of other fields are omitted. +**
    • The original values of any modified fields are omitted from +** UPDATE records. +**
    +** +** A patchset blob may be used with up to date versions of all +** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(), +** which returns SQLITE_CORRUPT if it is passed a patchset. Similarly, +** attempting to use a patchset blob with old versions of the +** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error. +** +** Because the non-primary key "old.*" fields are omitted, no +** SQLITE_CHANGESET_DATA conflicts can be detected or reported if a patchset +** is passed to the sqlite3changeset_apply() API. Other conflict types work +** in the same way as for changesets. +** +** Changes within a patchset are ordered in the same way as for changesets +** generated by the sqlite3session_changeset() function (i.e. all changes for +** a single table are grouped together, tables appear in the order in which +** they were attached to the session object). +*/ +int sqlite3session_patchset( + sqlite3_session *pSession, /* Session object */ + int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ + void **ppPatchset /* OUT: Buffer containing changeset */ +); + +/* +** CAPI3REF: Test if a changeset has recorded any changes. +** +** Return non-zero if no changes to attached tables have been recorded by +** the session object passed as the first argument. Otherwise, if one or +** more changes have been recorded, return zero. +** +** Even if this function returns zero, it is possible that calling +** [sqlite3session_changeset()] on the session handle may still return a +** changeset that contains no changes. This can happen when a row in +** an attached table is modified and then later on the original values +** are restored. However, if this function returns non-zero, then it is +** guaranteed that a call to sqlite3session_changeset() will return a +** changeset containing zero changes. +*/ +int sqlite3session_isempty(sqlite3_session *pSession); + +/* +** CAPI3REF: Create An Iterator To Traverse A Changeset +** +** Create an iterator used to iterate through the contents of a changeset. +** If successful, *pp is set to point to the iterator handle and SQLITE_OK +** is returned. Otherwise, if an error occurs, *pp is set to zero and an +** SQLite error code is returned. +** +** The following functions can be used to advance and query a changeset +** iterator created by this function: +** +**
      +**
    • [sqlite3changeset_next()] +**
    • [sqlite3changeset_op()] +**
    • [sqlite3changeset_new()] +**
    • [sqlite3changeset_old()] +**
    +** +** It is the responsibility of the caller to eventually destroy the iterator +** by passing it to [sqlite3changeset_finalize()]. The buffer containing the +** changeset (pChangeset) must remain valid until after the iterator is +** destroyed. +** +** Assuming the changeset blob was created by one of the +** [sqlite3session_changeset()], [sqlite3changeset_concat()] or +** [sqlite3changeset_invert()] functions, all changes within the changeset +** that apply to a single table are grouped together. This means that when +** an application iterates through a changeset using an iterator created by +** this function, all changes that relate to a single table are visited +** consecutively. There is no chance that the iterator will visit a change +** the applies to table X, then one for table Y, and then later on visit +** another change for table X. +*/ +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 */ +); + + +/* +** CAPI3REF: Advance A Changeset Iterator +** +** This function may only be used with iterators created by function +** [sqlite3changeset_start()]. If it is called on an iterator passed to +** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE +** is returned and the call has no effect. +** +** Immediately after an iterator is created by sqlite3changeset_start(), it +** does not point to any change in the changeset. Assuming the changeset +** is not empty, the first call to this function advances the iterator to +** point to the first change in the changeset. Each subsequent call advances +** the iterator to point to the next change in the changeset (if any). If +** no error occurs and the iterator points to a valid change after a call +** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned. +** Otherwise, if all changes in the changeset have already been visited, +** SQLITE_DONE is returned. +** +** If an error occurs, an SQLite error code is returned. Possible error +** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or +** SQLITE_NOMEM. +*/ +int sqlite3changeset_next(sqlite3_changeset_iter *pIter); + +/* +** CAPI3REF: Obtain The Current Operation From A Changeset Iterator +** +** The pIter argument passed to this function may either be an iterator +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +** created by [sqlite3changeset_start()]. In the latter case, the most recent +** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this +** is not the case, this function returns [SQLITE_MISUSE]. +** +** If argument pzTab is not NULL, then *pzTab is set to point to a +** nul-terminated utf-8 encoded string containing the name of the table +** affected by the current change. The buffer remains valid until either +** sqlite3changeset_next() is called on the iterator or until the +** conflict-handler function returns. If pnCol is not NULL, then *pnCol is +** set to the number of columns in the table affected by the change. If +** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change +** is an indirect change, or false (0) otherwise. See the documentation for +** [sqlite3session_indirect()] for a description of direct and indirect +** changes. Finally, if pOp is not NULL, then *pOp is set to one of +** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the +** type of change that the iterator currently points to. +** +** If no error occurs, SQLITE_OK is returned. If an error does occur, an +** SQLite error code is returned. The values of the output variables may not +** be trusted in this case. +*/ +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 */ + int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */ + int *pbIndirect /* OUT: True for an 'indirect' change */ +); + +/* +** CAPI3REF: Obtain The Primary Key Definition Of A Table +** +** For each modified table, a changeset includes the following: +** +**
      +**
    • The number of columns in the table, and +**
    • Which of those columns make up the tables PRIMARY KEY. +**
    +** +** This function is used to find which columns comprise the PRIMARY KEY of +** the table modified by the change that iterator pIter currently points to. +** If successful, *pabPK is set to point to an array of nCol entries, where +** nCol is the number of columns in the table. Elements of *pabPK are set to +** 0x01 if the corresponding column is part of the tables primary key, or +** 0x00 if it is not. +** +** If argument pnCol is not NULL, then *pnCol is set to the number of columns +** in the table. +** +** If this function is called when the iterator does not point to a valid +** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, +** SQLITE_OK is returned and the output variables populated as described +** above. +*/ +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 */ +); + +/* +** CAPI3REF: Obtain old.* Values From A Changeset Iterator +** +** The pIter argument passed to this function may either be an iterator +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +** created by [sqlite3changeset_start()]. In the latter case, the most recent +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. +** Furthermore, it may only be called if the type of change that the iterator +** currently points to is either [SQLITE_DELETE] or [SQLITE_UPDATE]. Otherwise, +** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. +** +** Argument iVal must be greater than or equal to 0, and less than the number +** of columns in the table affected by the current change. Otherwise, +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. +** +** If successful, this function sets *ppValue to point to a protected +** sqlite3_value object containing the iVal'th value from the vector of +** original row values stored as part of the UPDATE or DELETE change and +** returns SQLITE_OK. The name of the function comes from the fact that this +** is similar to the "old.*" columns available to update or delete triggers. +** +** 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( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ +); + +/* +** CAPI3REF: Obtain new.* Values From A Changeset Iterator +** +** The pIter argument passed to this function may either be an iterator +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +** created by [sqlite3changeset_start()]. In the latter case, the most recent +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. +** Furthermore, it may only be called if the type of change that the iterator +** currently points to is either [SQLITE_UPDATE] or [SQLITE_INSERT]. Otherwise, +** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. +** +** Argument iVal must be greater than or equal to 0, and less than the number +** of columns in the table affected by the current change. Otherwise, +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. +** +** If successful, this function sets *ppValue to point to a protected +** sqlite3_value object containing the iVal'th value from the vector of +** new row values stored as part of the UPDATE or INSERT change and +** returns SQLITE_OK. If the change is an UPDATE and does not include +** a new value for the requested column, *ppValue is set to NULL and +** SQLITE_OK returned. The name of the function comes from the fact that +** this is similar to the "new.*" columns available to update or delete +** triggers. +** +** 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( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ +); + +/* +** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator +** +** This function should only be used with iterator objects passed to a +** conflict-handler callback by [sqlite3changeset_apply()] with either +** [SQLITE_CHANGESET_DATA] or [SQLITE_CHANGESET_CONFLICT]. If this function +** is called on any other iterator, [SQLITE_MISUSE] is returned and *ppValue +** is set to NULL. +** +** Argument iVal must be greater than or equal to 0, and less than the number +** of columns in the table affected by the current change. Otherwise, +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. +** +** If successful, this function sets *ppValue to point to a protected +** sqlite3_value object containing the iVal'th value from the +** "conflicting row" associated with the current conflict-handler callback +** and returns SQLITE_OK. +** +** 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( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: Value from conflicting row */ +); + +/* +** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations +** +** This function may only be called with an iterator passed to an +** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case +** it sets the output variable to the total number of known foreign key +** violations in the destination database and returns SQLITE_OK. +** +** In all other cases this function returns SQLITE_MISUSE. +*/ +int sqlite3changeset_fk_conflicts( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int *pnOut /* OUT: Number of FK violations */ +); + + +/* +** CAPI3REF: Finalize A Changeset Iterator +** +** This function is used to finalize an iterator allocated with +** [sqlite3changeset_start()]. +** +** This function should only be called on iterators created using the +** [sqlite3changeset_start()] function. If an application calls this +** function with an iterator passed to a conflict-handler by +** [sqlite3changeset_apply()], [SQLITE_MISUSE] is immediately returned and the +** call has no effect. +** +** If an error was encountered within a call to an sqlite3changeset_xxx() +** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an +** [SQLITE_NOMEM] in [sqlite3changeset_new()]) then an error code corresponding +** to that error is returned by this function. Otherwise, SQLITE_OK is +** returned. This is to allow the following pattern (pseudo-code): +** +** sqlite3changeset_start(); +** while( SQLITE_ROW==sqlite3changeset_next() ){ +** // Do something with change. +** } +** rc = sqlite3changeset_finalize(); +** if( rc!=SQLITE_OK ){ +** // An error has occurred +** } +*/ +int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); + +/* +** CAPI3REF: Invert A Changeset +** +** This function is used to "invert" a changeset object. Applying an inverted +** changeset to a database reverses the effects of applying the uninverted +** changeset. Specifically: +** +**
      +**
    • Each DELETE change is changed to an INSERT, and +**
    • Each INSERT change is changed to a DELETE, and +**
    • For each UPDATE change, the old.* and new.* values are exchanged. +**
    +** +** This function does not change the order in which changes appear within +** the changeset. It merely reverses the sense of each individual change. +** +** If successful, a pointer to a buffer containing the inverted changeset +** is stored in *ppOut, the size of the same buffer is stored in *pnOut, and +** SQLITE_OK is returned. If an error occurs, both *pnOut and *ppOut are +** zeroed and an SQLite error code returned. +** +** It is the responsibility of the caller to eventually call sqlite3_free() +** on the *ppOut pointer to free the buffer allocation following a successful +** call to this function. +** +** WARNING/TODO: This function currently assumes that the input is a valid +** changeset. If it is not, the results are undefined. +*/ +int sqlite3changeset_invert( + int nIn, const void *pIn, /* Input changeset */ + int *pnOut, void **ppOut /* OUT: Inverse of input */ +); + +/* +** CAPI3REF: Concatenate Two Changeset Objects +** +** This function is used to concatenate two changesets, A and B, into a +** single changeset. The result is a changeset equivalent to applying +** changeset A followed by changeset B. +** +** This function combines the two input changesets using an +** sqlite3_changegroup object. Calling it produces similar results as the +** following code fragment: +** +** sqlite3_changegroup *pGrp; +** rc = sqlite3_changegroup_new(&pGrp); +** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA); +** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nB, pB); +** if( rc==SQLITE_OK ){ +** rc = sqlite3changegroup_output(pGrp, pnOut, ppOut); +** }else{ +** *ppOut = 0; +** *pnOut = 0; +** } +** +** Refer to the sqlite3_changegroup documentation below for details. +*/ +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 */ + void *pB, /* Pointer to buffer containing changeset B */ + int *pnOut, /* OUT: Number of bytes in output changeset */ + void **ppOut /* OUT: Buffer containing output changeset */ +); + + +/* +** CAPI3REF: Changegroup Handle +*/ +typedef struct sqlite3_changegroup sqlite3_changegroup; + +/* +** CAPI3REF: Create A New Changegroup Object +** +** An sqlite3_changegroup object is used to combine two or more changesets +** (or patchsets) into a single changeset (or patchset). A single changegroup +** object may combine changesets or patchsets, but not both. The output is +** always in the same format as the input. +** +** If successful, this function returns SQLITE_OK and populates (*pp) with +** a pointer to a new sqlite3_changegroup object before returning. The caller +** should eventually free the returned object using a call to +** sqlite3changegroup_delete(). If an error occurs, an SQLite error code +** (i.e. SQLITE_NOMEM) is returned and *pp is set to NULL. +** +** The usual usage pattern for an sqlite3_changegroup object is as follows: +** +**
      +**
    • It is created using a call to sqlite3changegroup_new(). +** +**
    • Zero or more changesets (or patchsets) are added to the object +** by calling sqlite3changegroup_add(). +** +**
    • The result of combining all input changesets together is obtained +** by the application via a call to sqlite3changegroup_output(). +** +**
    • The object is deleted using a call to sqlite3changegroup_delete(). +**
    +** +** Any number of calls to add() and output() may be made between the calls to +** new() and delete(), and in any order. +** +** As well as the regular sqlite3changegroup_add() and +** sqlite3changegroup_output() functions, also available are the streaming +** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm(). +*/ +int sqlite3changegroup_new(sqlite3_changegroup **pp); + +/* +** CAPI3REF: Add A Changeset To A Changegroup +** +** Add all changes within the changeset (or patchset) in buffer pData (size +** nData bytes) to the changegroup. +** +** If the buffer contains a patchset, then all prior calls to this function +** on the same changegroup object must also have specified patchsets. Or, if +** the buffer contains a changeset, so must have the earlier calls to this +** function. Otherwise, SQLITE_ERROR is returned and no changes are added +** to the changegroup. +** +** Rows within the changeset and changegroup are identified by the values in +** their PRIMARY KEY columns. A change in the changeset is considered to +** apply to the same row as a change already present in the changegroup if +** the two rows have the same primary key. +** +** Changes to rows that do not already appear in the changegroup are +** simply copied into it. Or, if both the new changeset and the changegroup +** contain changes that apply to a single row, the final contents of the +** changegroup depends on the type of each change, as follows: +** +**
  • +** +** +**
    Existing Change New Change Output Change +**
    INSERT INSERT +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    INSERT UPDATE +** The INSERT change remains in the changegroup. The values in the +** INSERT change are modified as if the row was inserted by the +** existing change and then updated according to the new change. +**
    INSERT DELETE +** The existing INSERT is removed from the changegroup. The DELETE is +** not added. +**
    UPDATE INSERT +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    UPDATE UPDATE +** The existing UPDATE remains within the changegroup. It is amended +** so that the accompanying values are as if the row was updated once +** by the existing change and then again by the new change. +**
    UPDATE DELETE +** The existing UPDATE is replaced by the new DELETE within the +** changegroup. +**
    DELETE INSERT +** If one or more of the column values in the row inserted by the +** new change differ from those in the row deleted by the existing +** change, the existing DELETE is replaced by an UPDATE within the +** changegroup. Otherwise, if the inserted row is exactly the same +** as the deleted row, the existing DELETE is simply discarded. +**
    DELETE UPDATE +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    DELETE DELETE +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    +** +** If the new changeset contains changes to a table that is already present +** in the changegroup, then the number of columns and the position of the +** primary key columns for the table must be consistent. If this is not the +** case, this function fails with SQLITE_SCHEMA. If the input changeset +** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is +** returned. Or, if an out-of-memory condition occurs during processing, this +** function returns SQLITE_NOMEM. In all cases, if an error occurs the +** final contents of the changegroup is undefined. +** +** If no error occurs, SQLITE_OK is returned. +*/ +int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); + +/* +** CAPI3REF: Obtain A Composite Changeset From A Changegroup +** +** Obtain a buffer containing a changeset (or patchset) representing the +** current contents of the changegroup. If the inputs to the changegroup +** were themselves changesets, the output is a changeset. Or, if the +** inputs were patchsets, the output is also a patchset. +** +** As with the output of the sqlite3session_changeset() and +** sqlite3session_patchset() functions, all changes related to a single +** table are grouped together in the output of this function. Tables appear +** in the same order as for the very first changeset added to the changegroup. +** If the second or subsequent changesets added to the changegroup contain +** changes for tables that do not appear in the first changeset, they are +** appended onto the end of the output changeset, again in the order in +** which they are first encountered. +** +** If an error occurs, an SQLite error code is returned and the output +** variables (*pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK +** is returned and the output variables are set to the size of and a +** pointer to the output buffer, respectively. In this case it is the +** responsibility of the caller to eventually free the buffer using a +** call to sqlite3_free(). +*/ +int sqlite3changegroup_output( + sqlite3_changegroup*, + int *pnData, /* OUT: Size of output buffer in bytes */ + void **ppData /* OUT: Pointer to output buffer */ +); + +/* +** CAPI3REF: Delete A Changegroup Object +*/ +void sqlite3changegroup_delete(sqlite3_changegroup*); + +/* +** CAPI3REF: Apply A Changeset To A Database +** +** Apply a changeset to a database. This function attempts to update the +** "main" database attached to handle db with the changes found in the +** changeset passed via the second and third arguments. +** +** The fourth argument (xFilter) passed to this function is the "filter +** callback". If it is not NULL, then for each table affected by at least one +** change in the changeset, the filter callback is invoked with +** the table name as the second argument, and a copy of the context pointer +** passed as the sixth argument to this function as the first. If the "filter +** callback" returns zero, then no attempt is made to apply any changes to +** the table. Otherwise, if the return value is non-zero or the xFilter +** argument to this function is NULL, all changes related to the table are +** attempted. +** +** For each table that is not excluded by the filter callback, this function +** tests that the target database contains a compatible table. A table is +** considered compatible if all of the following are true: +** +**
      +**
    • 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 +** changeset, and +**
    • The table has primary key columns in the same position as +** recorded in the changeset. +**
    +** +** If there is no compatible table, it is not an error, but none of the +** changes associated with the table are applied. A warning message is issued +** via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most +** one such warning is issued for each table in the changeset. +** +** For each change for which there is a compatible table, an attempt is made +** to modify the table contents according to the UPDATE, INSERT or DELETE +** change. If a change cannot be applied cleanly, the conflict handler +** function passed as the fifth argument to sqlite3changeset_apply() may be +** invoked. A description of exactly when the conflict handler is invoked for +** each type of change is below. +** +** Unlike the xFilter argument, xConflict may not be passed NULL. The results +** of passing anything other than a valid function pointer as the xConflict +** argument are undefined. +** +** Each time the conflict handler function is invoked, it must return one +** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or +** [SQLITE_CHANGESET_REPLACE]. SQLITE_CHANGESET_REPLACE may only be returned +** if the second argument passed to the conflict handler is either +** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If the conflict-handler +** returns an illegal value, any changes already made are rolled back and +** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different +** actions are taken by sqlite3changeset_apply() depending on the value +** returned by each invocation of the conflict-handler function. Refer to +** the documentation for the three +** [SQLITE_CHANGESET_OMIT|available return values] for details. +** +**
    +**
    DELETE Changes
    +** For each DELETE 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 deleted from 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 the original +** row value stored in the changeset, the conflict-handler function is +** invoked with [SQLITE_CHANGESET_DATA] as the second argument. +** +** If no row with matching primary key values is found in the database, +** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] +** passed as the second argument. +** +** If the DELETE operation is attempted, but SQLite returns SQLITE_CONSTRAINT +** (which can only happen if a foreign key constraint is violated), the +** conflict-handler function is invoked with [SQLITE_CHANGESET_CONSTRAINT] +** passed as the second argument. This includes the case where the DELETE +** operation is attempted because an earlier call to the conflict handler +** function returned [SQLITE_CHANGESET_REPLACE]. +** +**
    INSERT Changes
    +** For each INSERT change, an attempt is made to insert the new row into +** the database. +** +** If the attempt to insert the row fails because the database already +** contains a row with the same primary key values, the conflict handler +** function is invoked with the second argument set to +** [SQLITE_CHANGESET_CONFLICT]. +** +** If the attempt to insert the row fails because of some other constraint +** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is +** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT]. +** This includes the case where the INSERT operation is re-attempted because +** an earlier call to the conflict handler function returned +** [SQLITE_CHANGESET_REPLACE]. +** +**
    UPDATE Changes
    +** 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. +** +** 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 +** 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. +** +** If no row with matching primary key values is found in the database, +** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] +** passed as the second argument. +** +** If the UPDATE operation is attempted, but SQLite returns +** SQLITE_CONSTRAINT, the conflict-handler function is invoked with +** [SQLITE_CHANGESET_CONSTRAINT] passed as the second argument. +** This includes the case where the UPDATE operation is attempted after +** an earlier call to the conflict handler function returned +** [SQLITE_CHANGESET_REPLACE]. +**
    +** +** It is safe to execute SQL statements, including those that write to the +** table that the callback related to, from within the xConflict callback. +** This can be used to further customize the applications conflict +** resolution strategy. +** +** All changes made by this function are enclosed in a savepoint transaction. +** If any other error (aside from a constraint failure when attempting to +** write to the target database) occurs, then the savepoint transaction is +** rolled back, restoring the target database to its original state, and an +** SQLite error code returned. +*/ +int sqlite3changeset_apply( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx /* First argument passed to xConflict */ +); + +/* +** CAPI3REF: Constants Passed To The Conflict Handler +** +** Values that may be passed as the second argument to a conflict-handler. +** +**
    +**
    SQLITE_CHANGESET_DATA
    +** The conflict handler is invoked with CHANGESET_DATA as the second argument +** when processing a DELETE or UPDATE change if a row with the required +** PRIMARY KEY fields is present in the database, but one or more other +** (non primary-key) fields modified by the update do not contain the +** expected "before" values. +** +** The conflicting row, in this case, is the database row with the matching +** primary key. +** +**
    SQLITE_CHANGESET_NOTFOUND
    +** The conflict handler is invoked with CHANGESET_NOTFOUND as the second +** argument when processing a DELETE or UPDATE change if a row with the +** required PRIMARY KEY fields is not present in the database. +** +** There is no conflicting row in this case. The results of invoking the +** sqlite3changeset_conflict() API are undefined. +** +**
    SQLITE_CHANGESET_CONFLICT
    +** CHANGESET_CONFLICT is passed as the second argument to the conflict +** handler while processing an INSERT change if the operation would result +** in duplicate primary key values. +** +** The conflicting row in this case is the database row with the matching +** primary key. +** +**
    SQLITE_CHANGESET_FOREIGN_KEY
    +** If foreign key handling is enabled, and applying a changeset leaves the +** database in a state containing foreign key violations, the conflict +** handler is invoked with CHANGESET_FOREIGN_KEY as the second argument +** exactly once before the changeset is committed. If the conflict handler +** returns CHANGESET_OMIT, the changes, including those that caused the +** foreign key constraint violation, are committed. Or, if it returns +** CHANGESET_ABORT, the changeset is rolled back. +** +** No current or conflicting row information is provided. The only function +** it is possible to call on the supplied sqlite3_changeset_iter handle +** is sqlite3changeset_fk_conflicts(). +** +**
    SQLITE_CHANGESET_CONSTRAINT
    +** If any other constraint violation occurs while applying a change (i.e. +** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is +** invoked with CHANGESET_CONSTRAINT as the second argument. +** +** There is no conflicting row in this case. The results of invoking the +** sqlite3changeset_conflict() API are undefined. +** +**
    +*/ +#define SQLITE_CHANGESET_DATA 1 +#define SQLITE_CHANGESET_NOTFOUND 2 +#define SQLITE_CHANGESET_CONFLICT 3 +#define SQLITE_CHANGESET_CONSTRAINT 4 +#define SQLITE_CHANGESET_FOREIGN_KEY 5 + +/* +** CAPI3REF: Constants Returned By The Conflict Handler +** +** A conflict handler callback must return one of the following three values. +** +**
    +**
    SQLITE_CHANGESET_OMIT
    +** If a conflict handler returns this value no special action is taken. The +** change that caused the conflict is not applied. The session module +** continues to the next change in the changeset. +** +**
    SQLITE_CHANGESET_REPLACE
    +** This value may only be returned if the second argument to the conflict +** handler was SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this +** is not the case, any changes applied so far are rolled back and the +** call to sqlite3changeset_apply() returns SQLITE_MISUSE. +** +** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_DATA conflict +** handler, then the conflicting row is either updated or deleted, depending +** on the type of change. +** +** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_CONFLICT conflict +** handler, then the conflicting row is removed from the database and a +** second attempt to apply the change is made. If this second attempt fails, +** the original row is restored to the database before continuing. +** +**
    SQLITE_CHANGESET_ABORT
    +** If this value is returned, any changes applied so far are rolled back +** and the call to sqlite3changeset_apply() returns SQLITE_ABORT. +**
    +*/ +#define SQLITE_CHANGESET_OMIT 0 +#define SQLITE_CHANGESET_REPLACE 1 +#define SQLITE_CHANGESET_ABORT 2 + +/* +** CAPI3REF: Streaming Versions of API functions. +** +** The six streaming API xxx_strm() functions serve similar purposes to the +** corresponding non-streaming API functions: +** +** +** +**
    Streaming functionNon-streaming equivalent
    sqlite3changeset_apply_str[sqlite3changeset_apply] +**
    sqlite3changeset_concat_str[sqlite3changeset_concat] +**
    sqlite3changeset_invert_str[sqlite3changeset_invert] +**
    sqlite3changeset_start_str[sqlite3changeset_start] +**
    sqlite3session_changeset_str[sqlite3session_changeset] +**
    sqlite3session_patchset_str[sqlite3session_patchset] +**
    +** +** Non-streaming functions that accept changesets (or patchsets) as input +** require that the entire changeset be stored in a single buffer in memory. +** Similarly, those that return a changeset or patchset do so by returning +** a pointer to a single large buffer allocated using sqlite3_malloc(). +** Normally this is convenient. However, if an application running in a +** low-memory environment is required to handle very large changesets, the +** large contiguous memory allocations required can become onerous. +** +** In order to avoid this problem, instead of a single large buffer, input +** is passed to a streaming API functions by way of a callback function that +** the sessions module invokes to incrementally request input data as it is +** required. In all cases, a pair of API function parameters such as +** +**
    +**        int nChangeset,
    +**        void *pChangeset,
    +**  
    +** +** Is replaced by: +** +**
    +**        int (*xInput)(void *pIn, void *pData, int *pnData),
    +**        void *pIn,
    +**  
    +** +** Each time the xInput callback is invoked by the sessions module, the first +** argument passed is a copy of the supplied pIn context pointer. The second +** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no +** error occurs the xInput method should copy up to (*pnData) bytes of data +** into the buffer and set (*pnData) to the actual number of bytes copied +** before returning SQLITE_OK. If the input is completely exhausted, (*pnData) +** should be set to zero to indicate this. Or, if an error occurs, an SQLite +** error code should be returned. In all cases, if an xInput callback returns +** an error, all processing is abandoned and the streaming API function +** returns a copy of the error code to the caller. +** +** In the case of sqlite3changeset_start_strm(), the xInput callback may be +** invoked by the sessions module at any point during the lifetime of the +** iterator. If such an xInput callback returns an error, the iterator enters +** an error state, whereby all subsequent calls to iterator functions +** immediately fail with the same error code as returned by xInput. +** +** Similarly, streaming API functions that return changesets (or patchsets) +** return them in chunks by way of a callback function instead of via a +** pointer to a single large buffer. In this case, a pair of parameters such +** as: +** +**
    +**        int *pnChangeset,
    +**        void **ppChangeset,
    +**  
    +** +** Is replaced by: +** +**
    +**        int (*xOutput)(void *pOut, const void *pData, int nData),
    +**        void *pOut
    +**  
    +** +** The xOutput callback is invoked zero or more times to return data to +** the application. The first parameter passed to each call is a copy of the +** pOut pointer supplied by the application. The second parameter, pData, +** points to a buffer nData bytes in size containing the chunk of output +** data being returned. If the xOutput callback successfully processes the +** supplied data, it should return SQLITE_OK to indicate success. Otherwise, +** it should return some other SQLite error code. In this case processing +** is immediately abandoned and the streaming API function returns a copy +** of the xOutput error code to the application. +** +** The sessions module never invokes an xOutput callback with the third +** 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( + 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 */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx /* First argument passed to xConflict */ +); +int sqlite3changeset_concat_strm( + int (*xInputA)(void *pIn, void *pData, int *pnData), + void *pInA, + int (*xInputB)(void *pIn, void *pData, int *pnData), + void *pInB, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +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( + sqlite3_changeset_iter **pp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn +); +int sqlite3session_changeset_strm( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +int sqlite3session_patchset_strm( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +int sqlite3changegroup_add_strm(sqlite3_changegroup*, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn +); +int sqlite3changegroup_output_strm(sqlite3_changegroup*, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); + + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +} +#endif + +#endif /* !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) */ + +/******** End of sqlite3session.h *********/ +/******** Begin file fts5.h *********/ /* ** 2014 May 31 ** @@ -8297,11 +9933,13 @@ struct Fts5PhraseIter { ** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid ** ** with $p set to a phrase equivalent to the phrase iPhrase of the -** current query is executed. For each row visited, the callback function -** passed as the fourth argument is invoked. The context and API objects -** passed to the callback function may be used to access the properties of -** each matched row. Invoking Api.xUserData() returns a copy of the pointer -** passed as the third argument to pUserData. +** current query is executed. Any column filter that applies to +** phrase iPhrase of the current query is included in $p. For each +** row visited, the callback function passed as the fourth argument +** is invoked. The context and API objects passed to the callback +** function may be used to access the properties of each matched row. +** Invoking Api.xUserData() returns a copy of the pointer passed as +** the third argument to pUserData. ** ** If the callback function returns any value other than SQLITE_OK, the ** query is abandoned and the xQueryPhrase function returns immediately. @@ -8470,7 +10108,7 @@ struct Fts5ExtensionApi { ** behaviour. The structure methods are expected to function as follows: ** ** xCreate: -** This function is used to allocate and inititalize a tokenizer instance. +** This function is used to allocate and initialize a tokenizer instance. ** A tokenizer instance is required to actually tokenize text. ** ** The first argument passed to this function is a copy of the (void*) @@ -8730,4 +10368,4 @@ struct fts5_api { #endif /* _FTS5_H */ - +/******** End of fts5.h *********/ diff --git a/src/mod/version.inc b/src/mod/version.inc index 95a8d3e0..85fa261d 100644 --- a/src/mod/version.inc +++ b/src/mod/version.inc @@ -1,6 +1,6 @@ // version, change on release #ifndef REMOD_VERSION -#define REMOD_VERSION "v1.0.13" +#define REMOD_VERSION "v1.0.14" #endif // codename