123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include <algorithm>
- #include <array>
- #include <cctype>
- #include <cstdint>
- #include <iomanip>
- #include <map>
- #include <sstream>
- #include <string>
- #include <vector>
- #include "third_party/sqlite/fuzz/icu_codes.pb.h"
- #include "third_party/sqlite/fuzz/sql_queries.pb.h"
- #include "third_party/sqlite/fuzz/sql_query_grammar.pb.h"
- #include "third_party/sqlite/fuzz/sql_query_proto_to_string.h"
- using namespace sql_query_grammar;
- #define CONV_FN(TYPE, VAR_NAME) std::string TYPE##ToString(const TYPE& VAR_NAME)
- #define RETURN_IF_DISABLED_QUERY(TYPE) \
- if (disabled_queries_.count(#TYPE) != 0) \
- return "";
- namespace sql_fuzzer {
- namespace {
- constexpr uint32_t kMaxColumnNumber = 20;
- #if !defined(FUZZ_FTS3)
- constexpr uint32_t kMaxTableNumber = 8;
- #endif
- constexpr uint32_t kMaxSchemaNumber = 4;
- constexpr uint32_t kMaxWindowNumber = 5;
- constexpr uint32_t kMaxColumnConstraintNumber = 10;
- constexpr uint32_t kMaxTableConstraintNumber = 10;
- constexpr uint32_t kMaxIndexNumber = 10;
- // should be less than kMaxTableNumber
- constexpr uint32_t kMaxFTS3TableNumber = 2;
- constexpr uint32_t kMaxStrLength =
- 200; // So these are readable and somewhat performant, keep a maximum
- // string length......
- #if !defined(FUZZ_OMIT_SAVEPOINT)
- constexpr uint32_t kMaxSavePointNumber = 10;
- #endif
- constexpr uint32_t kMaxViewNumber = 5;
- constexpr uint32_t kMaxTriggerNumber = 10;
- std::set<std::string> disabled_queries_;
- } // namespace
- CONV_FN(Expr, expr);
- CONV_FN(Select, select);
- CONV_FN(TableOrSubquery, tos);
- CONV_FN(FTS3Table, ft);
- CONV_FN(FTS3NearQuery, fnq);
- CONV_FN(FTS3AuxiliaryFn, faf);
- CONV_FN(FTS3MatchFormat, fmf);
- CONV_FN(DateAndTimeFn, sfn);
- CONV_FN(ExprSchemaTableFn, estf);
- // ~~~~Numbered values to string~~~
- // WARNING does not include space at the end
- CONV_FN(Column, col) {
- if (col.has_rowid() && col.rowid())
- return "rowid";
- #if defined(FUZZ_FTS3)
- if (col.has_fts3_docid() && col.fts3_docid())
- return "docid";
- if (col.has_fts3_table())
- return FTS3TableToString(col.fts3_table());
- #endif
- std::string ret("Col");
- ret += std::to_string(col.column() % kMaxColumnNumber);
- return ret;
- }
- // WARNING does not include space at the end
- CONV_FN(Table, table) {
- std::string ret("Table");
- #if defined(FUZZ_FTS3)
- // only fuzzing FTS3 tables, clamp to the max FTS3 table num.
- ret += std::to_string(table.table() & kMaxFTS3TableNumber);
- if (table.fts3_content_table())
- ret += "_content";
- #else
- ret += std::to_string(table.table() % kMaxTableNumber);
- #endif
- return ret;
- }
- // WARNING does not include space at the end
- CONV_FN(Schema, schema) {
- if (schema.main()) {
- return "main";
- }
- if (schema.temp()) {
- return "temp";
- }
- std::string ret("Schema");
- ret += std::to_string(schema.schema() % kMaxSchemaNumber);
- return ret;
- }
- // WARNING does not include space at the end
- CONV_FN(WindowName, win) {
- std::string ret("Window");
- ret += std::to_string(win.window_name() % kMaxWindowNumber);
- return ret;
- }
- // WARNING does not include space at the end
- CONV_FN(ColumnConstraintName, cc) {
- std::string ret("ColConstraint");
- ret += std::to_string(cc.constraint_name() % kMaxColumnConstraintNumber);
- return ret;
- }
- // WARNING does not include space at the end
- CONV_FN(TableConstraintName, tc) {
- std::string ret("TableConstraint");
- ret += std::to_string(tc.constraint_name() % kMaxTableConstraintNumber);
- return ret;
- }
- // WARNING does not include space at the end
- CONV_FN(Index, index) {
- std::string ret("Index");
- ret += std::to_string(index.index() % kMaxIndexNumber);
- return ret;
- }
- #if !defined(FUZZ_OMIT_SAVEPOINT)
- CONV_FN(SavePoint, sp) {
- std::string ret("SavePoint");
- ret += std::to_string(sp.savepoint_num() % kMaxSavePointNumber);
- return ret;
- }
- #endif
- CONV_FN(View, v) {
- std::string ret("View");
- ret += std::to_string(v.view() % kMaxViewNumber);
- return ret;
- }
- CONV_FN(Trigger, t) {
- std::string ret("Trigger");
- ret += std::to_string(t.trigger() % kMaxTriggerNumber);
- return ret;
- }
- // ~~~~Utility functions~~~~
- std::string AscDescToString(AscDesc a) {
- switch (a) {
- case ASCDESC_NONE:
- return " ";
- case ASCDESC_ASC:
- return "ASC ";
- case ASCDESC_DESC:
- return "DESC ";
- default:
- return " ";
- }
- }
- std::string StrToLower(std::string s) {
- std::transform(
- s.begin(), s.end(), s.begin(),
- [](unsigned char c) -> unsigned char { return std::tolower(c); });
- return s;
- }
- std::string StripTrailingUnderscores(std::string s) {
- s.erase(std::find_if(s.rbegin(), s.rend(),
- [](unsigned char ch) { return ch != '_'; })
- .base(),
- s.end());
- return s;
- }
- // Converts underscores to spaces in a string.
- // This is because many enums like SET_NULL will be displayed at SET NULL in
- // the query, and I want to use protobuf's enum to string function to save time.
- std::string EnumStrReplaceUnderscores(std::string s) {
- std::transform(s.begin(), s.end(), s.begin(),
- [](unsigned char c) -> unsigned char {
- if (c == '_')
- return ' ';
- return c;
- });
- return s;
- }
- // Takes garbage data and produces a string, with quotes escaped.
- // Caps the number of bytes received from the protobuf at kMaxStrLength.
- // The final string could be as much as kMaxStrLength*2 as we added an extra
- // single quote for every single quote in the input string.
- std::string ConvertToSqlString(const std::string& s) {
- std::string ret;
- ret.reserve(kMaxStrLength * 2);
- for (size_t i = 0; i < s.length() && i < kMaxStrLength; i++) {
- ret += s[i];
- if (s[i] == '\'')
- ret += '\'';
- }
- return ret;
- }
- // WARNING does not include space
- std::string BytesToHex(const std::string& str) {
- std::ostringstream ss;
- ss << std::hex << std::setfill('0');
- for (size_t i = 0; i < str.size() && i < kMaxStrLength; i++) {
- ss << std::setw(2) << static_cast<int>(str[i]);
- }
- return ss.str();
- }
- // WARNING no space at end
- CONV_FN(ExprSchemaTable, st) {
- std::string ret;
- if (st.has_schema_name()) {
- ret += SchemaToString(st.schema_name());
- ret += ".";
- }
- ret += TableToString(st.table_name());
- return ret;
- }
- CONV_FN(ExprSchemaTableColumn, stc) {
- std::string ret;
- if (stc.has_schema()) {
- ret += SchemaToString(stc.schema());
- ret += ".";
- }
- if (stc.has_table()) {
- ret += TableToString(stc.table());
- ret += ".";
- }
- ret += ColumnToString(stc.col());
- return ret;
- }
- // WARNING does not include parentheses, nor a space at the end
- CONV_FN(ColumnList, cl) {
- std::string ret = ColumnToString(cl.col());
- for (int i = 0; i < cl.extra_cols_size(); i++) {
- ret += ", ";
- ret += ColumnToString(cl.extra_cols(i));
- }
- return ret;
- }
- CONV_FN(ExprList, me) {
- std::string ret = ExprToString(me.expr());
- for (int i = 0; i < me.extra_exprs_size(); i++) {
- ret += ", ";
- ret += ExprToString(me.extra_exprs(i));
- }
- return ret;
- }
- // WARNING does not include space
- CONV_FN(CollateType, collate_type) {
- std::string ct = CollateType_Name(collate_type);
- ct.erase(0, std::string("COLLATE_").length());
- return ct;
- }
- // WARNING does not include space
- CONV_FN(IndexedColumn, ic) {
- std::string ret;
- if (ic.has_expr()) {
- ret += ExprToString(ic.expr());
- } else {
- ret += ColumnToString(ic.col());
- }
- ret += " ";
- if (ic.has_collate_type()) {
- ret += "COLLATE ";
- ret += CollateTypeToString(ic.collate_type());
- ret += " ";
- }
- ret += AscDescToString(ic.asc_desc());
- return ret;
- }
- CONV_FN(IndexedColumnList, ic_list) {
- std::string ret;
- ret += IndexedColumnToString(ic_list.indexed_col());
- for (int i = 0; i < ic_list.extra_indexed_cols_size(); i++) {
- ret += ", ";
- ret += IndexedColumnToString(ic_list.extra_indexed_cols(i));
- }
- return ret;
- }
- CONV_FN(SchemaTableAsAlias, staa) {
- std::string ret;
- ret += ExprSchemaTableToString(staa.schema_table());
- ret += " ";
- if (staa.has_as_table_alias()) {
- ret += "AS ";
- ret += TableToString(staa.as_table_alias());
- ret += " ";
- }
- return ret;
- }
- // ~~~~Expression stuff~~~~
- // WARNING does not include space
- CONV_FN(NumericLiteral, nl) {
- static constexpr char hex_digits[] = "0123456789ABCDEF";
- static constexpr char digits[] = "0123456789";
- std::string ret;
- if (nl.hex_digits_size() > 0) {
- ret += "0x";
- for (int i = 0; i < nl.hex_digits_size(); i++) {
- ret += hex_digits[nl.hex_digits(i) % sizeof(hex_digits)];
- }
- return ret;
- }
- for (int i = 0; i < nl.digits_size(); i++) {
- ret += digits[nl.digits(i) % sizeof(digits)];
- }
- if (nl.decimal_point()) {
- ret += ".";
- if (nl.dec_digits_size() == 0) {
- ret += "0";
- } else {
- for (int i = 0; i < nl.dec_digits_size(); i++) {
- ret += digits[nl.dec_digits(i) % sizeof(digits)];
- }
- }
- }
- if (nl.exp_digits_size() > 0) {
- ret += "E";
- if (nl.negative_exp())
- ret += "-";
- if (nl.exp_digits_size() == 0) {
- ret += "0";
- } else {
- for (int i = 0; i < nl.exp_digits_size(); i++) {
- ret += digits[nl.exp_digits(i) % sizeof(digits)];
- }
- }
- }
- return ret;
- }
- // WARNING does not include space
- CONV_FN(LiteralValue, lit_val) {
- std::string ret;
- using LitValType = LiteralValue::LitValOneofCase;
- switch (lit_val.lit_val_oneof_case()) {
- case LitValType::kNumLit:
- return std::to_string(lit_val.num_lit());
- case LitValType::kStringLit:
- ret += '\'';
- ret += ConvertToSqlString(lit_val.string_lit());
- ret += '\'';
- return ret;
- case LitValType::kBlobLit:
- ret += "x\'";
- ret += BytesToHex(lit_val.blob_lit());
- ret += '\'';
- return ret;
- case LitValType::kSpecialVal:
- // special case for NULL, TRUE, FALSE
- if (lit_val.special_val() == LiteralValue::VAL_NULL)
- return "NULL";
- if (lit_val.special_val() == LiteralValue::VAL_TRUE)
- return "TRUE";
- if (lit_val.special_val() == LiteralValue::VAL_FALSE)
- return "FALSE";
- // do not remove underscores
- return LiteralValue_SpecialVal_Name(lit_val.special_val());
- case LitValType::kNumericLit:
- return NumericLiteralToString(lit_val.numeric_lit());
- default:
- return "1";
- }
- }
- CONV_FN(UnaryExpr, uexpr) {
- std::string ret;
- switch (uexpr.unary_op()) {
- case UNOP_MINUS:
- ret += "-";
- break;
- case UNOP_PLUS:
- ret += "+";
- break;
- case UNOP_TILDE:
- ret += "~";
- break;
- case UNOP_NOT:
- ret += "NOT ";
- break;
- default:
- break;
- }
- ret += ExprToString(uexpr.expr());
- return ret;
- }
- CONV_FN(BinaryOperator, bop) {
- switch (bop) {
- case BINOP_CONCAT:
- return " || ";
- break;
- case BINOP_STAR:
- return " * ";
- break;
- case BINOP_SLASH:
- return " / ";
- break;
- case BINOP_PERCENT:
- return " % ";
- break;
- case BINOP_PLUS:
- return " + ";
- break;
- case BINOP_MINUS:
- return " - ";
- break;
- case BINOP_LELE:
- return " << ";
- break;
- case BINOP_GRGR:
- return " >> ";
- break;
- case BINOP_AMPERSAND:
- return " & ";
- break;
- case BINOP_PIPE:
- return " | ";
- break;
- case BINOP_LE:
- return " < ";
- break;
- case BINOP_LEQ:
- return " <= ";
- break;
- case BINOP_GR:
- return " > ";
- break;
- case BINOP_GREQ:
- return " >= ";
- break;
- case BINOP_EQ:
- return " = ";
- break;
- case BINOP_EQEQ:
- return " == ";
- break;
- case BINOP_NOTEQ:
- return " != ";
- break;
- case BINOP_LEGR:
- return " <> ";
- break;
- case BINOP_IS:
- return " IS ";
- break;
- case BINOP_ISNOT:
- return " IS NOT ";
- break;
- case BINOP_IN:
- return " IN "; // CORPUS specialize?
- break;
- case BINOP_LIKE:
- return " LIKE "; // CORPUS specialize?
- break;
- case BINOP_GLOB:
- return " GLOB "; // CORPUS
- break;
- case BINOP_MATCH:
- return " MATCH "; // CORPUS
- break;
- case BINOP_REGEXP:
- return " REGEXP "; // CORPUS
- break;
- case BINOP_AND:
- return " AND ";
- break;
- case BINOP_OR:
- return " OR ";
- break;
- default:
- return " AND ";
- break;
- }
- }
- // TODO(mpdenton) generate better REGEXP queries in non-fts3 case. (in
- // ColumnComparison as well)
- // TODO(mpdenton) generate better MATCH queries in non-fts3 case.
- CONV_FN(BinaryExpr, bexpr) {
- std::string ret;
- ret += ExprToString(bexpr.lhs());
- ret += BinaryOperatorToString(bexpr.op());
- #if defined(FUZZ_FTS3)
- if (bexpr.op() == BINOP_MATCH && bexpr.has_fmt()) {
- ret += FTS3MatchFormatToString(bexpr.fmt());
- return ret;
- }
- #endif
- ret += ExprToString(bexpr.rhs());
- return ret;
- }
- CONV_FN(AggregateFn, af) {
- std::string ret;
- ret += StrToLower(AggregateFn_FnName_Name(af.fn_name()));
- ret += "(";
- if (af.fn_name() == AggregateFn::COUNT && af.count_star())
- return ret + "*) ";
- if (af.distinct())
- ret += "DISTINCT ";
- if (af.has_col1()) {
- ret += ColumnToString(af.col1());
- if (af.fn_name() == AggregateFn::GROUP_CONCAT && af.has_col2()) {
- ret += ", ";
- ret += ColumnToString(af.col2());
- }
- } else {
- ret += ExprToString(af.expr1());
- if (af.fn_name() == AggregateFn::GROUP_CONCAT && af.has_expr2()) {
- ret += ", ";
- ret += ExprToString(af.expr2());
- }
- }
- ret += ") ";
- return ret;
- }
- CONV_FN(ZeroArgFn, zaf) {
- std::string func = ZeroArgFn_Name(zaf);
- // Remove ZFN_ prefix
- func.erase(0, std::string("ZFN_").length());
- return StrToLower(func) + "() ";
- }
- CONV_FN(OneArgFn, oaf) {
- std::string ret;
- ret += StripTrailingUnderscores(
- StrToLower(OneArgFn_OneArgFnEnum_Name(oaf.fn_enum())));
- ret += "(";
- ret += ExprToString(oaf.arg1());
- ret += ") ";
- return ret;
- }
- CONV_FN(TwoArgFn, taf) {
- std::string ret;
- ret += StrToLower(TwoArgFn_TwoArgFnEnum_Name(taf.fn_enum()));
- ret += "(";
- ret += ExprToString(taf.arg1());
- ret += ", ";
- ret += ExprToString(taf.arg2());
- ret += ") ";
- return ret;
- }
- CONV_FN(ThreeArgFn, taf) {
- std::string ret;
- ret += StrToLower(ThreeArgFn_ThreeArgFnEnum_Name(taf.fn_enum()));
- ret += "(";
- ret += ExprToString(taf.arg1());
- ret += ", ";
- ret += ExprToString(taf.arg2());
- ret += ", ";
- ret += ExprToString(taf.arg3());
- ret += ") ";
- return ret;
- }
- CONV_FN(VarNumFn, vfn) {
- std::string ret;
- ret += StrToLower(VarNumFn_VarNumFnEnum_Name(vfn.fn_enum()));
- ret += "(";
- ret += ExprToString(vfn.arg1());
- ret += ", ";
- ret += ExprToString(vfn.arg2());
- for (int i = 0; i < vfn.other_args_size(); i++) {
- ret += ", ";
- ret += ExprToString(vfn.other_args(i));
- }
- ret += ") ";
- return ret;
- }
- CONV_FN(CharFn, cfn) {
- std::string ret("char(");
- ret += std::to_string(cfn.char_());
- for (int i = 0; i < cfn.extra_chars_size(); i++) {
- ret += ", ";
- ret += std::to_string(cfn.extra_chars(i));
- }
- ret += ") ";
- return ret;
- }
- CONV_FN(SimpleFn, sfn) {
- // oneof
- if (sfn.has_zero_arg_fn()) {
- return ZeroArgFnToString(sfn.zero_arg_fn());
- } else if (sfn.has_one_arg_fn()) {
- return OneArgFnToString(sfn.one_arg_fn());
- } else if (sfn.has_two_arg_fn()) {
- return TwoArgFnToString(sfn.two_arg_fn());
- } else if (sfn.has_three_arg_fn()) {
- return ThreeArgFnToString(sfn.three_arg_fn());
- } else if (sfn.has_varnum_fn()) {
- return VarNumFnToString(sfn.varnum_fn());
- } else if (sfn.has_char_fn()) {
- return CharFnToString(sfn.char_fn());
- } else {
- return "changes() ";
- }
- }
- CONV_FN(PrintfFormatSpecifier, pfs) {
- std::string ret("%");
- for (int i = 0; i < pfs.flags_size(); i++) {
- switch (pfs.flags(i)) {
- case PrintfFormatSpecifier::MINUS:
- ret += "-";
- break;
- case PrintfFormatSpecifier::PLUS:
- ret += "+";
- break;
- case PrintfFormatSpecifier::SPACE:
- ret += " ";
- break;
- case PrintfFormatSpecifier::ZERO:
- ret += "0";
- break;
- case PrintfFormatSpecifier::HASH:
- ret += "#";
- break;
- case PrintfFormatSpecifier::COMMA:
- ret += ",";
- break;
- case PrintfFormatSpecifier::BANG:
- ret += "!";
- break;
- }
- }
- if (pfs.has_width()) {
- ret += std::to_string(pfs.width());
- } else if (pfs.width_star()) {
- ret += "*";
- }
- if (pfs.has_precision()) {
- ret += ".";
- ret += std::to_string(pfs.precision());
- }
- if (pfs.has_length()) {
- if (pfs.length() % 3 == 1) {
- ret += "l";
- } else if (pfs.length() % 3 == 2) {
- ret += "ll";
- }
- }
- if (pfs.percent()) {
- ret += "%";
- } else {
- std::string specifier = PrintfFormatSpecifier_SubType_Name(pfs.sub_type());
- if (pfs.lowercase())
- specifier = StrToLower(specifier);
- ret += specifier;
- }
- return ret;
- }
- CONV_FN(Printf, p) {
- std::string ret("printf(\'");
- for (int i = 0; i < p.specifiers_size(); i++) {
- ret += PrintfFormatSpecifierToString(p.specifiers(i));
- if (i < p.strings_size()) {
- ret += ConvertToSqlString(p.strings(i));
- }
- }
- ret += "\'";
- for (int i = 0; i < p.exprs_size(); i++) {
- ret += ", ";
- ret += ExprToString(p.exprs(i));
- }
- ret += ") ";
- return ret;
- }
- CONV_FN(Fn, fn) {
- // oneof
- if (fn.has_simple_fn()) {
- return SimpleFnToString(fn.simple_fn());
- } else if (fn.has_fts_aux_fn()) {
- #if defined(FUZZ_FTS3)
- return FTS3AuxiliaryFnToString(fn.fts_aux_fn()) + " ";
- #else
- return "changes() ";
- #endif
- } else if (fn.has_dat_fn()) {
- return DateAndTimeFnToString(fn.dat_fn());
- } else if (fn.has_aggregate_fn()) {
- return AggregateFnToString(fn.aggregate_fn());
- } else if (fn.has_printf()) {
- return PrintfToString(fn.printf());
- } else {
- return "changes() ";
- }
- }
- CONV_FN(ParenthesesExpr, pexpr) {
- std::string ret("(");
- ret += ExprToString(pexpr.expr());
- for (int i = 0; i < pexpr.other_exprs_size(); i++) {
- ret += ", ";
- ret += ExprToString(pexpr.other_exprs(i));
- }
- ret += ") ";
- return ret;
- }
- CONV_FN(CastExpr, cexpr) {
- std::string ret("CAST(");
- ret += ExprToString(cexpr.expr());
- ret += " AS ";
- ret += EnumStrReplaceUnderscores(
- CastTypeName_CastTypeNameEnum_Name(cexpr.type_name().type_enum()));
- ret += ") ";
- return ret;
- }
- CONV_FN(CollateExpr, cexpr) {
- std::string ret;
- ret += ExprToString(cexpr.expr());
- ret += " COLLATE ";
- ret += CollateTypeToString(cexpr.collate_type());
- return ret;
- }
- CONV_FN(Expr1, e) {
- std::string ret;
- ret += ExprToString(e.expr1());
- ret += " ";
- if (e.not_())
- ret += "NOT ";
- ret += EnumStrReplaceUnderscores(Expr1_PossibleKeywords_Name(e.keyword()));
- ret += " ";
- ret += ExprToString(e.expr2());
- ret += " "; //
- if (e.has_escape_expr()) {
- ret += "ESCAPE ";
- ret += ExprToString(e.escape_expr());
- ret += " "; //
- }
- return ret;
- }
- CONV_FN(ExprNullTests, e) {
- std::string ret = ExprToString(e.expr());
- ret += " ";
- ret += EnumStrReplaceUnderscores(
- ExprNullTests_PossibleKeywords_Name(e.keyword()));
- ret += " ";
- return ret;
- }
- CONV_FN(ExprIs, e) {
- std::string ret = ExprToString(e.expr1());
- ret += " IS ";
- if (e.not_())
- ret += "NOT ";
- ret += ExprToString(e.expr2());
- ret += " "; //
- return ret;
- }
- CONV_FN(ExprBetween, e) {
- std::string ret;
- ret += ExprToString(e.expr1());
- ret += " ";
- if (e.not_())
- ret += "NOT ";
- ret += "BETWEEN ";
- ret += ExprToString(e.expr2());
- ret += " AND ";
- ret += ExprToString(e.expr3());
- return ret;
- }
- CONV_FN(ExprInParen, e) {
- std::string ret("(");
- // oneof
- if (e.has_select()) {
- ret += SelectToString(e.select());
- } else if (e.has_exprs()) {
- ret += ExprListToString(e.exprs());
- }
- ret += ") ";
- return ret;
- }
- CONV_FN(ExprIn, e) {
- std::string ret = ExprToString(e.expr());
- ret += " ";
- if (e.not_())
- ret += "NOT ";
- if (e.has_expr_in_paren()) {
- ret += ExprInParenToString(e.expr_in_paren());
- } else if (e.has_schema_table()) {
- ret += ExprSchemaTableToString(e.schema_table());
- } else if (e.has_schema_table_fn()) {
- ret += ExprSchemaTableFnToString(e.schema_table_fn());
- } else {
- ret += "()";
- }
- return ret + " ";
- }
- CONV_FN(ExprExists, e) {
- std::string ret;
- if (e.not_())
- ret += "NOT EXISTS ";
- else if (e.exists())
- ret += "EXISTS ";
- ret += "(";
- ret += SelectToString(e.select());
- ret += ") ";
- return ret;
- }
- // WARNING no space at end
- CONV_FN(ExprWhenThen, e) {
- std::string ret("WHEN ");
- ret += ExprToString(e.when_expr());
- ret += " THEN ";
- ret += ExprToString(e.then_expr());
- return ret;
- }
- CONV_FN(ExprCase, e) {
- std::string ret("CASE ");
- if (e.has_expr()) {
- ret += ExprToString(e.expr());
- ret += " ";
- }
- ret += ExprWhenThenToString(e.when_then());
- ret += " ";
- for (int i = 0; i < e.extra_when_thens_size(); i++) {
- ret += ExprWhenThenToString(e.extra_when_thens(i));
- ret += " ";
- }
- if (e.has_else_expr()) {
- ret += "ELSE ";
- ret += ExprToString(e.else_expr());
- ret += " ";
- }
- ret += "END ";
- return ret;
- }
- CONV_FN(ExprRaiseFn, e) {
- std::string ret("RAISE(");
- if (e.ignore()) {
- ret += "IGNORE";
- } else {
- ret +=
- EnumStrReplaceUnderscores(ExprRaiseFn_RaiseFnEnum_Name(e.raise_fn()));
- ret += " ";
- ret += ", \'";
- ret += ConvertToSqlString(e.error_msg());
- ret += "\'";
- }
- ret += ") ";
- return ret;
- }
- CONV_FN(ComplicatedExpr, expr) {
- using ExprType = ComplicatedExpr::ComplicatedExprOneofCase;
- switch (expr.complicated_expr_oneof_case()) {
- case ExprType::kExprStc:
- return ExprSchemaTableColumnToString(expr.expr_stc());
- case ExprType::kUnaryExpr:
- return UnaryExprToString(expr.unary_expr());
- case ExprType::kBinaryExpr:
- return BinaryExprToString(expr.binary_expr());
- case ExprType::kFnExpr:
- return FnToString(expr.fn_expr());
- case ExprType::kParExpr:
- return ParenthesesExprToString(expr.par_expr());
- case ExprType::kCastExpr:
- return CastExprToString(expr.cast_expr());
- case ExprType::kCollateExpr:
- return CollateExprToString(expr.collate_expr());
- case ExprType::kExpr1:
- return Expr1ToString(expr.expr1());
- case ExprType::kExprNullTests:
- return ExprNullTestsToString(expr.expr_null_tests());
- case ExprType::kExprIs:
- return ExprIsToString(expr.expr_is());
- case ExprType::kExprBetween:
- return ExprBetweenToString(expr.expr_between());
- case ExprType::kExprIn:
- return ExprInToString(expr.expr_in());
- case ExprType::kExprExists:
- return ExprExistsToString(expr.expr_exists());
- case ExprType::kExprCase:
- return ExprCaseToString(expr.expr_case());
- case ExprType::kExprRaise:
- return ExprRaiseFnToString(expr.expr_raise());
- default:
- return "1";
- }
- }
- // TODO(mpdenton) wrap in parentheses???
- CONV_FN(Expr, expr) {
- if (expr.has_lit_val()) {
- return LiteralValueToString(expr.lit_val());
- } else if (expr.has_comp_expr()) {
- return ComplicatedExprToString(expr.comp_expr());
- } else { // default
- return "1";
- }
- }
- // ~~~~Other~~~~
- std::string ForeignKeyClauseNotMatchToString(
- const ForeignKeyClauseNotMatch& nm) {
- std::string ret("ON ");
- ret += EnumStrReplaceUnderscores(
- ForeignKeyClauseNotMatch_DeleteOrUpdate_Name(nm.del_or_update()));
- ret += " ";
- ret += EnumStrReplaceUnderscores(
- ForeignKeyClauseNotMatch_Action_Name(nm.action()));
- ret += " ";
- return ret;
- }
- CONV_FN(ForeignKeyClauseCore, fkc) {
- if (fkc.has_fkey_not_match())
- return ForeignKeyClauseNotMatchToString(fkc.fkey_not_match());
- return "MATCH PARTIAL"; // Sqlite does not actually parse MATCH clauses. This
- // is assumed to be MATCH SIMPLE.
- }
- CONV_FN(DeferStrategy, ds) {
- std::string ret;
- if (ds.not_()) {
- ret += "NOT ";
- }
- ret += "DEFERRABLE ";
- ret +=
- EnumStrReplaceUnderscores(DeferStrategy_DeferStratEnum_Name(ds.strat()));
- return ret;
- }
- CONV_FN(ForeignKeyClause, fkey_clause) {
- std::string ret("REFERENCES ");
- ret += TableToString(fkey_clause.foreign_table());
- if (fkey_clause.has_col_list()) {
- ret += "(";
- ret += ColumnListToString(fkey_clause.col_list());
- ret += ")";
- }
- ret += " ";
- for (int i = 0; i < fkey_clause.fkey_cores_size(); i++) {
- ret += ForeignKeyClauseCoreToString(fkey_clause.fkey_cores(i));
- ret += " ";
- }
- if (fkey_clause.has_defer_strat()) {
- ret += DeferStrategyToString(fkey_clause.defer_strat());
- ret += " ";
- }
- return ret;
- }
- CONV_FN(ConflictClause, conf) {
- if (!conf.has_on_conflict())
- return " ";
- std::string ret("ON CONFLICT ");
- ret += EnumStrReplaceUnderscores(
- ConflictClause_OnConflict_Name(conf.on_conflict()));
- ret += " ";
- return ret;
- }
- CONV_FN(ColConstraintOpt1, opt1) {
- std::string ret("PRIMARY KEY ");
- ret += AscDescToString(opt1.asc_desc());
- // space at the end already
- ret += ConflictClauseToString(opt1.conflict());
- if (opt1.autoincrement())
- ret += "AUTOINCREMENT ";
- return ret;
- }
- CONV_FN(ColConstraintOpt2, opt2) {
- std::string ret("DEFAULT ");
- if (opt2.has_expr()) {
- ret += "(";
- ret += ExprToString(opt2.expr());
- ret += ")";
- } else {
- ret += LiteralValueToString(opt2.lit_val());
- }
- ret += " ";
- return ret;
- }
- CONV_FN(ColumnConstraint, col_constr) {
- std::string ret;
- if (col_constr.has_constraint_name()) {
- ret += "CONSTRAINT ";
- ret += ColumnConstraintNameToString(col_constr.constraint_name());
- ret += " ";
- }
- using ColConstrType = ColumnConstraint::ColConstraintOneofCase;
- switch (col_constr.col_constraint_oneof_case()) {
- case ColConstrType::kOpt1:
- ret += ColConstraintOpt1ToString(col_constr.opt1());
- break;
- case ColConstrType::kNotNullConfClause:
- ret += "NOT NULL ";
- ret += ConflictClauseToString(col_constr.not_null_conf_clause());
- break;
- case ColConstrType::kUniqueConfClause:
- ret += "UNIQUE ";
- ret += ConflictClauseToString(col_constr.unique_conf_clause());
- break;
- case ColConstrType::kCheckExpr:
- ret += "CHECK(";
- ret += ExprToString(col_constr.check_expr());
- ret += ") ";
- break;
- case ColConstrType::kOpt2:
- ret += ColConstraintOpt2ToString(col_constr.opt2());
- break;
- case ColConstrType::kCollate:
- ret += "COLLATE ";
- ret += CollateTypeToString(col_constr.collate());
- ret += " ";
- break;
- case ColConstrType::kFkeyClause:
- ret += ForeignKeyClauseToString(col_constr.fkey_clause());
- break;
- default:
- ret += ColConstraintOpt2ToString(col_constr.opt2_fallback());
- }
- return ret;
- }
- CONV_FN(TypeName, type_name) {
- std::string ret;
- ret += EnumStrReplaceUnderscores(
- CastTypeName_CastTypeNameEnum_Name(type_name.ctn().type_enum()));
- if (type_name.has_sn()) {
- ret += "(";
- ret += std::to_string(type_name.sn());
- ret += ")";
- }
- ret += " ";
- return ret;
- }
- CONV_FN(ColumnDef, col_def) {
- std::string ret;
- ret += ColumnToString(col_def.col());
- ret += " ";
- if (col_def.has_type_name()) {
- ret += TypeNameToString(col_def.type_name());
- ret += " ";
- }
- for (int i = 0; i < col_def.col_constraints_size(); i++) {
- ret += ColumnConstraintToString(col_def.col_constraints(i));
- ret += " ";
- }
- return ret;
- }
- CONV_FN(TableConstraintOpt1, opt1) {
- std::string ret;
- ret += EnumStrReplaceUnderscores(
- TableConstraintOpt1_ConstraintType_Name(opt1.constraint_type()));
- ret += "(";
- ret += IndexedColumnListToString(opt1.indexed_col_list());
- ret += ") ";
- ret += ConflictClauseToString(opt1.conf_clause());
- return ret;
- }
- CONV_FN(TableConstraintOpt2, opt2) {
- std::string ret("FOREIGN KEY (");
- ret += ColumnListToString(opt2.cols());
- ret += ") ";
- ret += ForeignKeyClauseToString(opt2.fkey_clause());
- return ret;
- }
- CONV_FN(TableConstraint, t_constr) {
- std::string ret;
- if (t_constr.has_name()) {
- ret += "CONSTRAINT ";
- ret += TableConstraintNameToString(t_constr.name());
- ret += " ";
- }
- if (t_constr.has_opt1()) {
- ret += TableConstraintOpt1ToString(t_constr.opt1());
- } else if (t_constr.has_check_expr()) {
- ret += "CHECK(";
- ret += ExprToString(t_constr.check_expr()); // TODO(mpdenton)
- ret += ") ";
- } else if (t_constr.has_opt2()) {
- ret += TableConstraintOpt2ToString(t_constr.opt2());
- } else {
- // default to no constraint
- ret += "CHECK(1)";
- }
- ret += " ";
- return ret;
- }
- CONV_FN(CreateTableOpt1, opt1) {
- std::string ret("(");
- ret += ColumnDefToString(opt1.col_def());
- for (int i = 0; i < opt1.extra_col_defs_size(); i++) {
- ret += ", ";
- ret += ColumnDefToString(opt1.extra_col_defs(i));
- }
- for (int i = 0; i < opt1.table_constraints_size(); i++) {
- ret += ", ";
- ret += TableConstraintToString(opt1.table_constraints(i));
- }
- ret += ") ";
- if (opt1.without_rowid())
- ret += "WITHOUT ROWID ";
- return ret;
- }
- CONV_FN(CreateTable, create_table) {
- RETURN_IF_DISABLED_QUERY(CreateTable);
- #if defined(FUZZ_FTS3)
- return ""; // Don't create normal tables in FTS3 fuzzing mode.
- #endif
- std::string ret("CREATE ");
- if (create_table.has_temp_modifier()) {
- ret += EnumStrReplaceUnderscores(
- TempModifier_Name(create_table.temp_modifier()))
- .erase(0, std::string("TM_").length());
- ret += " ";
- }
- ret += "TABLE ";
- if (create_table.if_not_exists())
- ret += "IF NOT EXISTS ";
- ret += ExprSchemaTableToString(create_table.schema_table());
- ret += " ";
- // TODO(mpdenton) need spaces at the end here???
- using TableCreationType = CreateTable::CreateTableOneofCase;
- switch (create_table.create_table_oneof_case()) {
- case TableCreationType::kOp1:
- ret += CreateTableOpt1ToString(create_table.op1());
- break;
- case TableCreationType::kAsSelectStmt:
- ret += SelectToString(create_table.as_select_stmt());
- break;
- default:
- ret += CreateTableOpt1ToString(create_table.op());
- break;
- }
- return ret; // TODO(mpdenton)
- }
- // ~~~~For INSERT and SELECT~~~~
- CONV_FN(CommonTableExpr, cte) {
- std::string ret;
- ret += TableToString(cte.table());
- if (cte.columns_size() > 0) {
- ret += "(";
- ret += ColumnToString(cte.columns(0));
- for (int i = 1; i < cte.columns_size(); i++) {
- ret += ", ";
- ret += ColumnToString(cte.columns(i));
- }
- ret += ")";
- }
- ret += " AS (";
- ret += SelectToString(cte.select());
- ret += ") ";
- return ret;
- }
- CONV_FN(WithStatement, ws) {
- std::string ret("WITH ");
- if (ws.recursive())
- ret += "RECURSIVE ";
- ret += CommonTableExprToString(ws.table_expr());
- ret += " ";
- for (int i = 0; i < ws.extra_table_exprs_size(); i++) {
- ret += CommonTableExprToString(ws.extra_table_exprs(i));
- ret += " ";
- }
- ret += " ";
- return ret;
- }
- // ~~~~INSERT~~~~
- // WARNING no space at end
- CONV_FN(ColumnComparison, cc) {
- std::string ret;
- ret += ExprSchemaTableColumnToString(cc.col());
- ret += BinaryOperatorToString(cc.op());
- #if defined(FUZZ_FTS3)
- if (cc.op() == BINOP_MATCH && cc.has_fmt()) {
- ret += FTS3MatchFormatToString(cc.fmt());
- return ret;
- }
- #endif
- ret += ExprToString(cc.expr());
- return ret;
- }
- // WARNING no space at end
- CONV_FN(ExprComparisonHighProbability, echp) {
- if (echp.has_cc()) {
- return ColumnComparisonToString(echp.cc());
- } else if (echp.has_expr()) {
- return ExprToString(echp.expr());
- } else {
- return "Col0 = 1"; // default
- }
- }
- CONV_FN(WhereStatement, ws) {
- return "WHERE " + ExprComparisonHighProbabilityToString(ws.expr()) + " ";
- }
- #ifndef SQLITE_OMIT_UPSERT
- CONV_FN(UpsertClausePart1, uc1) {
- std::string ret;
- ret += "(";
- ret += IndexedColumnListToString(uc1.icol_list());
- ret += ") ";
- if (uc1.has_where_stmt()) {
- ret += WhereStatementToString(uc1.where_stmt());
- ret += " ";
- }
- return ret;
- }
- #endif
- // WARNING no space at end
- CONV_FN(ColEqualsExpr, cee) {
- std::string ret;
- if (cee.has_col()) {
- ret += ColumnToString(cee.col());
- } else if (cee.has_col_list()) {
- ret += ColumnListToString(cee.col_list());
- } else {
- ret += "Col0"; // default
- }
- ret += " = ";
- ret += ExprToString(cee.expr());
- return ret;
- }
- CONV_FN(UpsertClausePart2, uc2) {
- std::string ret("SET ");
- ret += ColEqualsExprToString(uc2.cee());
- for (int i = 0; i < uc2.extra_cees_size(); i++) {
- ret += ", ";
- ret += ColEqualsExprToString(uc2.extra_cees(i));
- }
- if (uc2.has_where_stmt()) {
- ret += " ";
- ret += WhereStatementToString(uc2.where_stmt());
- }
- ret += " ";
- return ret;
- }
- CONV_FN(UpsertClause, uc) {
- #ifndef SQLITE_OMIT_UPSERT
- std::string ret("ON CONFLICT ");
- if (uc.has_uclause_p1()) {
- ret += UpsertClausePart1ToString(uc.uclause_p1());
- }
- ret += "DO ";
- if (uc.has_uclause_p2()) {
- ret += "UPDATE ";
- ret += UpsertClausePart2ToString(uc.uclause_p2());
- } else {
- ret += "NOTHING ";
- }
- return ret;
- #else
- return ""; // fine to return empty string here
- #endif
- }
- CONV_FN(ValuesStatement, values) {
- std::string ret("VALUES (");
- ret += ExprListToString(values.expr_list());
- ret += ")";
- for (int i = 0; i < values.extra_expr_lists_size(); i++) {
- ret += ", (";
- ret += ExprListToString(values.extra_expr_lists(i));
- ret += ")";
- }
- ret += " ";
- return ret;
- }
- CONV_FN(Insert, insert) {
- RETURN_IF_DISABLED_QUERY(Insert);
- std::string ret;
- if (insert.has_with()) {
- ret += WithStatementToString(insert.with());
- ret += " ";
- }
- ret +=
- EnumStrReplaceUnderscores(Insert_InsertType_Name(insert.insert_type()));
- ret += " INTO ";
- ret += SchemaTableAsAliasToString(insert.staa());
- if (insert.has_col_list()) {
- ret += "(";
- ret += ColumnListToString(insert.col_list());
- ret += ") ";
- }
- // oneof
- if (insert.has_values()) {
- ret += ValuesStatementToString(insert.values());
- ret += " ";
- } else if (insert.has_select()) {
- ret += SelectToString(insert.select());
- ret += " ";
- } else {
- ret += "DEFAULT VALUES ";
- }
- if (insert.has_upsert_clause()) {
- ret += UpsertClauseToString(insert.upsert_clause());
- ret += " ";
- }
- return ret;
- }
- // ~~~~DELETE~~~~
- CONV_FN(QualifiedTableName, qtn) {
- std::string ret;
- ret += SchemaTableAsAliasToString(qtn.staa());
- ret += " ";
- if (qtn.indexed()) {
- if (qtn.not_indexed()) {
- ret += "NOT INDEXED ";
- } else {
- ret += "INDEXED BY ";
- ret += IndexToString(qtn.indexed_by());
- ret += " ";
- }
- }
- return ret;
- }
- CONV_FN(Delete, delete_) {
- RETURN_IF_DISABLED_QUERY(Delete);
- std::string ret;
- if (delete_.has_with()) {
- ret += WithStatementToString(delete_.with());
- ret += " ";
- }
- ret += "DELETE FROM ";
- ret += QualifiedTableNameToString(delete_.qtn());
- if (delete_.has_where()) {
- ret += WhereStatementToString(delete_.where());
- }
- ret += " ";
- return ret;
- }
- // ~~~~UPDATE~~~~
- // WARNING no space at end
- CONV_FN(Update, update) {
- RETURN_IF_DISABLED_QUERY(Update);
- std::string ret;
- if (update.has_with()) {
- ret += WithStatementToString(update.with());
- ret += " ";
- }
- ret += "UPDATE ";
- if (update.has_update_type()) {
- ret +=
- EnumStrReplaceUnderscores(Update_UpdateType_Name(update.update_type()));
- ret += " ";
- }
- ret += QualifiedTableNameToString(update.qtn());
- ret += " ";
- ret += UpsertClausePart2ToString(update.ucp2());
- return ret;
- }
- // TODO(mpdenton) restrictions on UPDATEs in CREATE TRIGGER????
- // ~~~~SELECT~~~~
- CONV_FN(ExprColAlias, eca) {
- std::string ret;
- ret += ExprToString(eca.expr());
- ret += " ";
- if (eca.has_col_alias()) {
- if (eca.as()) {
- ret += "AS ";
- }
- ret += ColumnToString(eca.col_alias());
- ret += " ";
- }
- return ret;
- }
- // WARNING no space at end
- CONV_FN(ResultColumn, rc) {
- std::string ret;
- // oneof
- if (rc.has_col()) {
- return ColumnToString(rc.col());
- } else if (rc.has_eca()) {
- return ExprColAliasToString(rc.eca());
- } else if (rc.has_table_star()) {
- return TableToString(rc.table_star()) + ".*";
- } else if (rc.has_fts3_fn()) {
- #if defined(FUZZ_FTS3)
- return FTS3AuxiliaryFnToString(rc.fts3_fn());
- #else
- return "*";
- #endif
- } else {
- return "*";
- }
- }
- CONV_FN(AsTableAlias, ata) {
- std::string ret;
- if (ata.as()) {
- ret += "AS ";
- }
- ret += TableToString(ata.table_alias());
- ret += " ";
- return ret;
- }
- // WARNING no space at end
- CONV_FN(JoinOperator, jo) {
- if (jo.comma())
- return ",";
- std::string ret;
- if (jo.natural())
- ret += "NATURAL ";
- if (jo.join_type() != JoinOperator::NONE) {
- ret +=
- EnumStrReplaceUnderscores(JoinOperator_JoinType_Name(jo.join_type()));
- ret += " ";
- }
- ret += "JOIN ";
- return ret;
- }
- CONV_FN(JoinConstraint, jc) {
- // oneof
- if (jc.has_on_expr()) {
- return "ON " + ExprToString(jc.on_expr()) + " ";
- } else if (jc.has_using_expr()) {
- std::string ret("(");
- ret += ColumnListToString(jc.using_expr().col_list());
- ret += ") ";
- return ret;
- }
- return " ";
- }
- CONV_FN(JoinClauseCore, jcc) {
- std::string ret;
- ret += JoinOperatorToString(jcc.join_op());
- ret += " ";
- ret += TableOrSubqueryToString(jcc.tos());
- ret += " ";
- ret += JoinConstraintToString(jcc.join_constraint());
- ret += " ";
- return ret;
- }
- CONV_FN(JoinClause, jc) {
- std::string ret;
- ret += TableOrSubqueryToString(jc.tos());
- ret += " ";
- for (int i = 0; i < jc.clauses_size(); i++) {
- ret += JoinClauseCoreToString(jc.clauses(i));
- }
- ret += " ";
- return ret;
- }
- // TODO(mpdenton) ExprIn needs it schematablefn!!!!!
- CONV_FN(ExprSchemaTableFn, estf) {
- std::string ret;
- const TableFn& tfn = estf.table_fn();
- // oneof for pragma fns
- if (tfn.has_foreign_key_list()) {
- ret += "pragma_foreign_key_list(\'";
- ret += TableToString(tfn.foreign_key_list());
- ret += "\') ";
- } else if (tfn.has_index_info()) {
- ret += "pragma_index_info(\'";
- ret += IndexToString(tfn.index_info());
- ret += "\') ";
- } else if (tfn.has_index_list()) {
- ret += "pragma_index_list(\'";
- ret += TableToString(tfn.index_list());
- ret += "\') ";
- } else if (tfn.has_index_xinfo()) {
- ret += "pragma_index_xinfo(\'";
- ret += IndexToString(tfn.index_xinfo());
- ret += "\') ";
- } else if (tfn.has_integrity_check()) {
- ret += "pragma_integrity_check(\'";
- ret += std::to_string(tfn.integrity_check());
- ret += "\') ";
- } else if (tfn.has_optimize()) {
- ret += "pragma_optimize(\'";
- ret += std::to_string(tfn.optimize());
- ret += "\') ";
- } else if (tfn.has_quick_check()) {
- ret += "pragma_quick_check(\'";
- ret += std::to_string(tfn.quick_check());
- ret += "\') ";
- } else if (tfn.has_table_info()) {
- ret += "pragma_table_info(\'";
- ret += TableToString(tfn.table_info());
- ret += "\') ";
- } else if (tfn.has_table_xinfo()) {
- ret += "pragma_table_xinfo(\'";
- ret += TableToString(tfn.table_xinfo());
- ret += "\') ";
- } else {
- ret += StrToLower(PragmaFnZeroArgOneResult_Name(tfn.no_arg_one_result()))
- .erase(0, std::string("PFN_ZO_").length());
- ret += "() ";
- }
- return ret;
- }
- CONV_FN(TableOrSubqueryOption2, toso2) {
- std::string ret;
- ret += ExprSchemaTableFnToString(toso2.schema_table_fn());
- ret += " ";
- if (toso2.has_as_table_alias()) {
- ret += AsTableAliasToString(toso2.as_table_alias());
- }
- return ret;
- }
- CONV_FN(TableOrSubqueryOption3, tos3) {
- std::string ret;
- if (tos3.tos_list_size() > 0) {
- ret += TableOrSubqueryToString(tos3.tos_list(0));
- for (int i = 1; i < tos3.tos_list_size(); i++) {
- ret += ", ";
- ret += TableOrSubqueryToString(tos3.tos_list(i));
- }
- } else {
- ret += JoinClauseToString(tos3.join_clause());
- }
- return ret;
- }
- CONV_FN(TableOrSubqueryOption4, tos4) {
- std::string ret("(");
- ret += SelectToString(tos4.select());
- ret += ") ";
- if (tos4.has_as_table_alias()) {
- ret += AsTableAliasToString(tos4.as_table_alias());
- ret += " ";
- }
- return ret;
- }
- CONV_FN(TableOrSubquery, tos) {
- // oneof
- if (tos.has_qtn()) {
- return QualifiedTableNameToString(tos.qtn()) + " ";
- } else if (tos.has_toso2()) {
- return TableOrSubqueryOption2ToString(tos.toso2()) + " ";
- } else if (tos.has_toso3()) {
- return "(" + TableOrSubqueryOption3ToString(tos.toso3()) + ") ";
- } else if (tos.has_toso4()) {
- return TableOrSubqueryOption4ToString(tos.toso4()) + " ";
- } else {
- return ExprSchemaTableToString(tos.schema_table_expr()) + " ";
- }
- }
- CONV_FN(FromStatement, fs) {
- return "FROM " + TableOrSubqueryOption3ToString(fs.tos3());
- }
- CONV_FN(GroupByStatement, gbs) {
- std::string ret("GROUP BY ");
- ret += ExprListToString(gbs.exprs());
- ret += " ";
- if (gbs.has_having_expr()) {
- ret += "HAVING ";
- ret += ExprToString(gbs.having_expr());
- ret += " ";
- }
- return ret;
- }
- CONV_FN(WindowStatement, ws) {
- #if !defined(SQLITE_OMIT_WINDOWFUNC)
- return "";
- #else
- return "";
- #endif
- }
- CONV_FN(SelectStatementCore, ssc) {
- std::string ret;
- ret += EnumStrReplaceUnderscores(
- SelectStatementCore_SelectOrDistinct_Name(ssc.s_or_d()));
- ret += " ";
- if (ssc.result_columns_size() == 0) {
- ret += "* ";
- } else {
- ret += ResultColumnToString(ssc.result_columns(0));
- for (int i = 1; i < ssc.result_columns_size(); i++) {
- ret += ", ";
- ret += ResultColumnToString(ssc.result_columns(i));
- }
- ret += " ";
- }
- if (ssc.has_from()) {
- ret += FromStatementToString(ssc.from());
- ret += " ";
- }
- if (ssc.has_where()) {
- ret += WhereStatementToString(ssc.where());
- ret += " ";
- }
- if (ssc.has_groupby()) {
- ret += GroupByStatementToString(ssc.groupby());
- ret += " ";
- }
- if (ssc.has_window()) {
- ret += WindowStatementToString(ssc.window());
- ret += " ";
- }
- return ret;
- }
- CONV_FN(SelectSubStatement, sss) {
- // oneof
- if (sss.has_select_core()) {
- return SelectStatementCoreToString(sss.select_core());
- } else if (sss.has_values()) {
- return ValuesStatementToString(sss.values());
- } else {
- return ValuesStatementToString(sss.values_fallback());
- }
- }
- CONV_FN(ExprOrderingTerm, eot) {
- std::string ret = ExprToString(eot.expr());
- ret += " ";
- if (eot.has_collate_type()) {
- ret += "COLLATE ";
- ret += CollateTypeToString(eot.collate_type());
- ret += " ";
- }
- ret += AscDescToString(eot.asc_desc());
- return ret;
- }
- CONV_FN(OrderByStatement, obs) {
- std::string ret("ORDER BY ");
- ret += ExprOrderingTermToString(obs.ord_term());
- for (int i = 0; i < obs.extra_ord_terms_size(); i++) {
- ret += ", ";
- ret += ExprOrderingTermToString(obs.extra_ord_terms(i));
- }
- ret += " ";
- return ret;
- }
- CONV_FN(LimitStatement, ls) {
- std::string ret("LIMIT ");
- ret += ExprToString(ls.limit_expr());
- ret += " ";
- if (ls.has_second_expr()) {
- if (ls.offset()) {
- ret += "OFFSET ";
- } else {
- ret += ", ";
- }
- ret += ExprToString(ls.second_expr());
- ret += " ";
- }
- return ret;
- }
- CONV_FN(ExtraSelectSubStatement, esss) {
- std::string ret, enum1;
- enum1 = CompoundOperator_Name(esss.compound_op());
- // erase prefix
- enum1.erase(0, std::string("CO_").length());
- ret += EnumStrReplaceUnderscores(enum1);
- ret += " ";
- ret += SelectSubStatementToString(esss.select_substatement());
- return ret;
- }
- CONV_FN(Select, select) {
- RETURN_IF_DISABLED_QUERY(Select);
- std::string ret;
- if (select.has_with()) {
- ret += WithStatementToString(select.with());
- ret += " ";
- }
- ret += SelectStatementCoreToString(select.select_core());
- for (int i = 0; i < select.extra_select_substatements_size(); i++) {
- ret +=
- ExtraSelectSubStatementToString(select.extra_select_substatements(i));
- ret += " ";
- }
- if (select.has_orderby()) {
- ret += OrderByStatementToString(select.orderby());
- ret += " ";
- }
- if (select.has_limit()) {
- ret += LimitStatementToString(select.limit());
- }
- return ret;
- }
- // ~~~~FTS3~~~~
- // CORPUS currently relying on normal SELECTs to generate good compound
- // queries for FTS, like AND, OR, and NOT. Generate a corpus entry with a lot of
- // creative FTS queries.
- CONV_FN(FTS3Table, ft) {
- // std::string ret("FTS3Table");
- std::string ret(
- "Table"); // for now, use the same naming scheme as normal tables.
- ret += std::to_string(ft.table() % kMaxFTS3TableNumber);
- return ret;
- }
- CONV_FN(FTS3MatchToken, fmt) {
- std::string ret;
- if (fmt.has_col()) {
- ret += ColumnToString(fmt.col());
- ret += ":";
- }
- if (fmt.negate()) {
- ret += "-";
- }
- if (fmt.token().length() == 0)
- ret += "a";
- else
- ret += ConvertToSqlString(
- fmt.token()); // TODO(mpdenton) good enough? Need something better????
- if (fmt.prefix())
- ret += "*";
- return ret;
- }
- CONV_FN(FTS3PhraseQuery, fpq) {
- std::string ret("\"");
- ret += FTS3MatchTokenToString(fpq.mt());
- for (int i = 0; i < fpq.extra_mts_size(); i++) {
- ret += " ";
- ret += FTS3MatchTokenToString(fpq.extra_mts(i));
- }
- ret += "\"";
- return ret;
- }
- CONV_FN(FTS3MatchFormatCore, fmfc) {
- // oneof
- if (fmfc.has_pq()) {
- return FTS3PhraseQueryToString(fmfc.pq());
- } else if (fmfc.has_nq()) {
- return FTS3NearQueryToString(fmfc.nq());
- } else {
- return FTS3MatchTokenToString(fmfc.mt_fallback());
- }
- }
- CONV_FN(FTS3NearQuery, fnq) {
- std::string ret = FTS3MatchFormatCoreToString(fnq.format_core1());
- ret += " NEAR";
- if (fnq.has_num_tokens_near()) {
- ret += "/";
- ret += std::to_string(fnq.num_tokens_near());
- }
- ret += " ";
- ret += FTS3MatchFormatCoreToString(fnq.format_core2());
- return ret;
- }
- CONV_FN(FTS3CompoundAndCore, fcac) {
- std::string ret(" ");
- ret += FTS3CompoundAndCore_CompoundOp_Name(fcac.op());
- ret += " ";
- ret += FTS3MatchFormatCoreToString(fcac.core());
- return ret;
- }
- CONV_FN(FTS3MatchCompoundFormat, fmcf) {
- std::string ret = FTS3MatchFormatCoreToString(fmcf.core());
- for (int i = 0; i < fmcf.compound_and_cores_size(); i++) {
- ret += FTS3CompoundAndCoreToString(fmcf.compound_and_cores(i));
- }
- return ret;
- }
- CONV_FN(FTS3MatchFormat, fmf) {
- std::string ret("\'");
- if (fmf.ft_size() > 0) {
- ret += FTS3MatchCompoundFormatToString(fmf.ft(0));
- }
- for (int i = 1; i < fmf.ft_size(); i++) {
- ret += " ";
- ret += FTS3MatchCompoundFormatToString(fmf.ft(i));
- }
- ret += "\'";
- return ret;
- }
- CONV_FN(FTS3SpecialCommand, fsc) {
- RETURN_IF_DISABLED_QUERY(FTS3SpecialCommand);
- std::string ret("INSERT INTO ");
- ret += FTS3TableToString(fsc.table());
- ret += "(";
- ret += FTS3TableToString(fsc.table());
- ret += ") VALUES(\'";
- switch (fsc.command()) {
- case FTS3SpecialCommand::OPTIMIZE:
- ret += "optimize";
- break;
- case FTS3SpecialCommand::REBUILD:
- ret += "rebuild";
- break;
- case FTS3SpecialCommand::INTEGRITY_CHECK:
- ret += "integrity-check";
- break;
- case FTS3SpecialCommand::MERGE:
- ret += "merge=";
- ret += std::to_string(fsc.val1());
- ret += ",";
- ret += std::to_string(fsc.val2());
- break;
- case FTS3SpecialCommand::AUTOMERGE:
- ret += "automerge=";
- ret += std::to_string(fsc.val1() % 16);
- break;
- }
- ret += "\')";
- return ret;
- }
- // WARNING no space at end
- CONV_FN(FTS3SelectMatch, fsm) {
- RETURN_IF_DISABLED_QUERY(FTS3SelectMatch);
- std::string ret("SELECT * FROM ");
- ret += FTS3TableToString(fsm.table());
- ret += " WHERE ";
- ret += ColumnToString(fsm.col());
- ret += " MATCH ";
- ret += FTS3MatchFormatToString(fsm.match_pattern());
- return ret;
- }
- CONV_FN(FTS3SpecificQuery, fsq) {
- RETURN_IF_DISABLED_QUERY(FTS3SpecificQuery);
- #if defined(FUZZ_FTS3)
- // oneof
- if (fsq.has_command()) {
- return FTS3SpecialCommandToString(fsq.command());
- } else if (fsq.has_select()) {
- return FTS3SelectMatchToString(fsq.select());
- } else {
- return "";
- }
- #else
- return "";
- #endif
- }
- CONV_FN(ICULocale, il) {
- std::string ret;
- std::string lc = IsoLangCode_Name(il.iso_lang_code());
- lc.erase(0, std::string("ISO_LANG_CODE_").length());
- ret += lc;
- ret += "_";
- // extract country code from integer
- ret += (char)((il.country_code() & 0xFF) % 26) + 'A';
- ret += (char)(((il.country_code() & 0xFF00) >> 8) % 26) + 'A';
- return ret;
- }
- CONV_FN(CreateFTS3Table, cft) {
- RETURN_IF_DISABLED_QUERY(CreateFTS3Table);
- std::string ret("CREATE VIRTUAL TABLE ");
- if (cft.if_not_exists())
- ret += "IF NOT EXISTS ";
- if (cft.has_schema()) {
- ret += SchemaToString(cft.schema());
- ret += ".";
- }
- ret += FTS3TableToString(cft.table());
- ret += " USING fts3(";
- // TODO(mpdenton) not using schema here, should I???
- if (cft.has_col_list()) {
- ret += ColumnListToString(cft.col_list());
- if (cft.has_tokenizer_type())
- ret += ", ";
- }
- if (cft.has_tokenizer_type()) {
- ret += "tokenize=";
- std::string tt = TokenizerType_Name(cft.tokenizer_type());
- tt.erase(0, std::string("TT_").length());
- tt = StrToLower(tt);
- #if defined(SQLITE_DISABLE_FTS3_UNICODE)
- if (tt == "unicode61")
- tt = "porter";
- #endif
- ret += tt;
- // now generate locales for ICU
- if (cft.tokenizer_type() == TokenizerType::TT_ICU) {
- ret += " ";
- ret += ICULocaleToString(cft.locale());
- } else if (cft.tokenizer_type() == TokenizerType::TT_UNICODE61) {
- // Chrome does not actually enable this option. FIXME in the future.
- }
- }
- ret += ")";
- return ret;
- }
- // WARNING no space at end
- CONV_FN(FTS3OffsetsFn, fof) {
- return "offsets(" + FTS3TableToString(fof.table()) + ")";
- }
- // WARNING no space at end
- CONV_FN(FTS3SnippetsFn, fsf) {
- std::string ret("snippets(");
- ret += FTS3TableToString(fsf.table());
- // Now (possibly) emit the five optional arguments.
- int num_args = (int)fsf.num_optional_args();
- if (num_args >= 1) {
- ret += ", \'";
- ret += ConvertToSqlString(fsf.start_match());
- ret += "\'";
- }
- if (num_args >= 2) {
- ret += ", \'";
- ret += ConvertToSqlString(fsf.end_match());
- ret += "\'";
- }
- if (num_args >= 3) {
- ret += ", \'";
- ret += ConvertToSqlString(fsf.ellipses());
- ret += "\'";
- }
- if (num_args >= 4) {
- ret += ", ";
- if (fsf.has_col_number()) {
- ret += std::to_string(fsf.col_number() % kMaxColumnNumber);
- } else {
- ret += "-1";
- }
- }
- if (num_args >= 5) {
- ret += ", ";
- ret +=
- std::to_string((fsf.num_tokens() % 129) - 64); // clamp into [-64, 64]
- }
- ret += ")";
- return ret;
- }
- // WARNING no space at end
- CONV_FN(FTS3MatchInfoFn, fmi) {
- constexpr static char matchinfo_chars[] = {
- 'p', 'c', 's', 'x', 'y', 'b',
- // 'n', 'a', 'l', // These characters only available for FTS4.
- };
- std::string ret("matchinfo(");
- ret += FTS3TableToString(fmi.table());
- if (fmi.chars_size() > 0) {
- ret += ", \'";
- for (int i = 0; i < fmi.chars_size(); i++) {
- ret += matchinfo_chars[fmi.chars(i) % sizeof(matchinfo_chars)];
- }
- ret += "\'";
- }
- ret += ")";
- return ret;
- }
- // WARNING no space at end
- CONV_FN(FTS3AuxiliaryFn, faf) {
- if (faf.has_snippets()) {
- return FTS3SnippetsFnToString(faf.snippets());
- } else if (faf.has_matchinfo()) {
- return FTS3MatchInfoFnToString(faf.matchinfo());
- } else {
- return FTS3OffsetsFnToString(faf.offsets_fallback());
- }
- }
- CONV_FN(FTS3HiddenTable, fht) {
- std::string tab = FTS3HiddenTable_HiddenTableVal_Name(fht.htv());
- tab = StrToLower(tab);
- return FTS3TableToString(fht.table()) + "_" + tab;
- }
- CONV_FN(FTS3HiddenTableColumn, fhtc) {
- std::string tab = FTS3HiddenTableColumn_Name(fhtc);
- tab = tab.erase(0, std::string("FTS3_HT_").length());
- tab = StrToLower(tab);
- return tab;
- }
- CONV_FN(FTS3HiddenTableInsert, fi) {
- RETURN_IF_DISABLED_QUERY(FTS3HiddenTableInsert);
- std::string ret("INSERT INTO ");
- ret += FTS3HiddenTableToString(fi.fht());
- if (fi.col_vals_size() == 0) {
- ret += " DEFAULT VALUES";
- return ret;
- }
- ret += "(";
- ret += FTS3HiddenTableColumnToString(fi.col_vals(0).col());
- for (int i = 1; i < fi.col_vals_size(); i++) {
- ret += ", ";
- ret += FTS3HiddenTableColumnToString(fi.col_vals(i).col());
- }
- ret += ") VALUES(";
- ret += ExprToString(fi.col_vals(0).expr());
- for (int i = 0; i < fi.col_vals_size(); i++) {
- ret += ", ";
- ret += ExprToString(fi.col_vals(i).expr());
- }
- ret += ")";
- return ret;
- }
- CONV_FN(FTS3HiddenTableUpdate, fu) {
- RETURN_IF_DISABLED_QUERY(FTS3HiddenTableUpdate);
- std::string ret("UPDATE ");
- ret += FTS3HiddenTableToString(fu.fht());
- ret += " ";
- if (fu.col_vals_size() == 0) {
- ret += "start_block = 0";
- return ret;
- }
- ret += "SET ";
- ret += FTS3HiddenTableColumnToString(fu.col_vals(0).col());
- ret += " = ";
- ret += ExprToString(fu.col_vals(0).expr());
- for (int i = 1; i < fu.col_vals_size(); i++) {
- ret += ", ";
- ret += FTS3HiddenTableColumnToString(fu.col_vals(i).col());
- ret += " = ";
- ret += ExprToString(fu.col_vals(i).expr());
- }
- if (fu.has_col_where()) {
- ret += " WHERE ";
- ret += FTS3HiddenTableColumnToString(fu.col_where());
- ret += BinaryOperatorToString(fu.bin_op());
- ret += ExprToString(fu.comp_expr());
- }
- return ret;
- }
- CONV_FN(FTS3HiddenTableDelete, fd) {
- RETURN_IF_DISABLED_QUERY(FTS3HiddenTableDelete);
- std::string ret("DELETE FROM ");
- ret += FTS3HiddenTableToString(fd.fht());
- if (fd.has_col_where()) {
- ret += " WHERE ";
- ret += FTS3HiddenTableColumnToString(fd.col_where());
- ret += BinaryOperatorToString(fd.bin_op());
- ret += ExprToString(fd.comp_expr());
- }
- return ret;
- }
- // ~~~~TRANSACTIONS/SAVEPOINTS
- CONV_FN(BeginTransaction, bt) {
- RETURN_IF_DISABLED_QUERY(BeginTransaction);
- std::string ret("BEGIN ");
- if (bt.has_type()) {
- ret += BeginTransaction_TransactionType_Name(bt.type());
- ret += " ";
- }
- ret += "TRANSACTION";
- return ret;
- }
- CONV_FN(CommitTransaction, ct) {
- RETURN_IF_DISABLED_QUERY(CommitTransaction);
- return EnumStrReplaceUnderscores(
- CommitTransaction_CommitText_Name(ct.text()));
- }
- CONV_FN(RollbackStatement, rt) {
- RETURN_IF_DISABLED_QUERY(RollbackStatement);
- #if !defined(FUZZ_OMIT_SAVEPOINT)
- if (rt.has_save_point()) {
- return "ROLLBACK TO SAVEPOINT " + SavePointToString(rt.save_point());
- }
- #endif
- return "ROLLBACK TRANSACTION";
- }
- #if !defined(FUZZ_OMIT_SAVEPOINT)
- CONV_FN(CreateSavePoint, csp) {
- RETURN_IF_DISABLED_QUERY(CreateSavePoint);
- return "SAVEPOINT " + SavePointToString(csp.save_point());
- }
- CONV_FN(ReleaseSavePoint, rsp) {
- RETURN_IF_DISABLED_QUERY(ReleaseSavePoint);
- return "RELEASE SAVEPOINT " + SavePointToString(rsp.save_point());
- }
- #endif
- CONV_FN(Analyze, a) {
- RETURN_IF_DISABLED_QUERY(Analyze);
- std::string ret("ANALYZE");
- if (a.has_schema_name()) {
- ret += " ";
- ret += SchemaToString(a.schema_name());
- if (a.has_table_name()) {
- ret += ".";
- ret += TableToString(a.table_name());
- } else if (a.has_index_name()) {
- ret += ".";
- ret += IndexToString(a.index_name());
- }
- } else if (a.has_table_name()) {
- ret += " ";
- ret += TableToString(a.table_name());
- } else if (a.has_index_name()) {
- ret += " ";
- ret += IndexToString(a.index_name());
- }
- return ret;
- }
- // ~~~~VACUUM~~~~
- CONV_FN(Vacuum, v) {
- RETURN_IF_DISABLED_QUERY(Vacuum);
- std::string ret("VACUUM");
- if (v.has_schema()) {
- ret += " ";
- ret += SchemaToString(v.schema());
- }
- return ret;
- }
- // ~~~~PRAGMA~~~~
- CONV_FN(Pragma, p) {
- RETURN_IF_DISABLED_QUERY(Pragma);
- #if defined(FUZZ_OMIT_PRAGMA)
- return "";
- #else
- constexpr static const char* locking_modes[] = {"NORMAL", "EXCLUSIVE"};
- constexpr static const char* journal_modes[] = {
- "DELETE", "TRUNCATE", "PERSIST", "MEMORY", "WAL", "OFF"};
- Table table;
- std::string ret("PRAGMA ");
- if (p.has_schema()) {
- ret += SchemaToString(p.schema());
- ret += ".";
- }
- ret += StripTrailingUnderscores(
- StrToLower(Pragma_PragmaCommand_Name(p.command())));
- switch (p.command()) {
- case Pragma::AUTO_VACUUM:
- ret += " = ";
- ret += std::to_string((uint32_t)p.arg1() % 3);
- break;
- case Pragma::WRITEABLE_SCHEMA:
- ret += " = ";
- ret += std::to_string((uint32_t)p.arg1() % 2);
- break;
- case Pragma::LOCKING_MODE:
- ret += " = ";
- ret += locking_modes[(uint32_t)p.arg1() % 2];
- break;
- case Pragma::TEMP_STORE:
- ret += " = ";
- ret += std::to_string((uint32_t)p.arg1() % 3);
- break;
- case Pragma::PAGE_SIZE_:
- ret += " = ";
- ret += std::to_string(p.arg1());
- break;
- case Pragma::TABLE_INFO:
- ret += "(\'";
- table.set_table((uint32_t)p.arg1());
- ret += TableToString(table);
- ret += "\')";
- break;
- case Pragma::JOURNAL_MODE:
- ret += " = ";
- ret += journal_modes[(uint32_t)p.arg1() % 6];
- break;
- case Pragma::MMAP_SIZE:
- ret += " = ";
- ret += std::to_string(p.arg1());
- break;
- }
- return ret;
- #endif
- }
- // ~~~~CREATE INDEX~~~~
- CONV_FN(CreateIndex, ci) {
- RETURN_IF_DISABLED_QUERY(CreateIndex);
- std::string ret("CREATE ");
- if (ci.unique())
- ret += "UNIQUE ";
- ret += "INDEX ";
- if (ci.if_not_exists())
- ret += "IF NOT EXISTS ";
- if (ci.has_schema()) {
- ret += SchemaToString(ci.schema());
- ret += ".";
- }
- ret += IndexToString(ci.index());
- ret += " ON ";
- ret += TableToString(ci.table());
- ret += "(";
- ret += IndexedColumnListToString(ci.icol_list());
- ret += ")";
- if (ci.has_where()) {
- ret += " ";
- ret += WhereStatementToString(ci.where());
- }
- return ret;
- }
- // ~~~~CREATE VIEW~~~~
- CONV_FN(CreateView, cv) {
- RETURN_IF_DISABLED_QUERY(CreateView);
- std::string ret("CREATE ");
- if (cv.has_temp_modifier()) {
- ret += EnumStrReplaceUnderscores(TempModifier_Name(cv.temp_modifier()))
- .erase(0, std::string("TM_").length());
- ret += " ";
- }
- ret += "VIEW ";
- if (cv.if_not_exists())
- ret += "IF NOT EXISTS ";
- if (cv.has_schema()) {
- ret += SchemaToString(cv.schema());
- ret += ".";
- }
- ret += ViewToString(cv.view());
- ret += " ";
- if (cv.has_col_list()) {
- ret += "(";
- ret += ColumnListToString(cv.col_list());
- ret += ") ";
- }
- ret += SelectToString(cv.select());
- return ret;
- }
- // ~~~~CREATE TRIGGER~~~~
- CONV_FN(TypicalQuery, tq) {
- // oneof
- if (tq.has_update())
- return UpdateToString(tq.update());
- else if (tq.has_insert())
- return InsertToString(tq.insert());
- else if (tq.has_select())
- return SelectToString(tq.select());
- else
- return DeleteToString(tq.delete_fallback());
- }
- // WARNING no space at end
- CONV_FN(CreateTrigger, ct) {
- RETURN_IF_DISABLED_QUERY(CreateTrigger);
- std::string ret("CREATE ");
- if (ct.has_temp_modifier()) {
- ret += EnumStrReplaceUnderscores(TempModifier_Name(ct.temp_modifier()))
- .erase(0, std::string("TM_").length());
- ret += " ";
- }
- ret += "TRIGGER ";
- if (ct.if_not_exists())
- ret += "IF NOT EXISTS ";
- if (ct.has_schema()) {
- ret += SchemaToString(ct.schema());
- ret += " ";
- }
- ret += TriggerToString(ct.trigger());
- ret += " ";
- if (ct.has_trigger_type()) {
- ret += EnumStrReplaceUnderscores(
- CreateTrigger_TriggerType_Name(ct.trigger_type()));
- ret += " ";
- }
- ret += CreateTrigger_TriggerInstr_Name(ct.trigger_instr());
- ret += " ";
- if (ct.trigger_instr() == CreateTrigger::UPDATE) {
- ret += "OF ";
- ret += ColumnListToString(ct.col_list());
- ret += " ";
- }
- ret += "ON ";
- ret += TableToString(ct.table());
- ret += " ";
- if (ct.for_each_row())
- ret += "FOR EACH ROW ";
- if (ct.has_when()) {
- ret += "WHEN ";
- ret += ExprComparisonHighProbabilityToString(ct.when());
- ret += " ";
- }
- ret += "BEGIN ";
- ret += TypicalQueryToString(ct.tq());
- ret += "; ";
- for (int i = 0; i < ct.extra_tqs_size(); i++) {
- ret += TypicalQueryToString(ct.extra_tqs(i));
- ret += "; ";
- }
- ret += "END";
- return ret;
- }
- // ~~~~REINDEX~~~~
- CONV_FN(ReIndex, ri) {
- RETURN_IF_DISABLED_QUERY(ReIndex);
- // Chrome doesn't use REINDEX
- #if !defined(SQLITE_OMIT_REINDEX)
- if (ri.empty())
- return "REINDEX";
- std::string ret("REINDEX ");
- if (ri.has_collate_type()) {
- ret += CollateTypeToString(ri.collate_type());
- return ret;
- }
- if (ri.has_schema()) {
- ret += SchemaToString(ri.schema());
- ret += ".";
- }
- if (ri.has_table())
- ret += TableToString(ri.table());
- else
- ret += IndexToString(ri.index());
- return ret;
- #else
- return "";
- #endif
- }
- CONV_FN(Drop, d) {
- RETURN_IF_DISABLED_QUERY(Drop);
- std::string ret("DROP ");
- std::string if_exists("");
- std::string schema("");
- if (d.if_exists())
- if_exists = "IF EXISTS ";
- if (d.has_schema()) {
- schema = SchemaToString(d.schema());
- schema += " ";
- }
- // oneof
- if (d.has_index()) {
- ret += "INDEX ";
- ret += if_exists;
- ret += schema;
- ret += IndexToString(d.index());
- } else if (d.has_table()) {
- ret += "TABLE ";
- ret += if_exists;
- ret += schema;
- ret += TableToString(d.table());
- } else if (d.has_trigger()) {
- ret += "TRIGGER ";
- ret += if_exists;
- ret += schema;
- ret += TriggerToString(d.trigger());
- } else {
- ret += "VIEW ";
- ret += if_exists;
- ret += schema;
- ret += ViewToString(d.view_fallback());
- }
- return ret;
- }
- // ~~~~ALTER TABLE~~~~
- CONV_FN(AlterTable, at) {
- RETURN_IF_DISABLED_QUERY(AlterTable);
- std::string ret("ALTER TABLE ");
- ret += ExprSchemaTableToString(at.schema_table());
- ret += " ";
- if (at.has_col()) {
- ret += "RENAME ";
- if (at.column())
- ret += "COLUMN ";
- ret += ColumnToString(at.col());
- ret += " TO ";
- ret += ColumnToString(at.col_to());
- } else if (at.has_col_def()) {
- ret += "ADD ";
- if (at.column())
- ret += "COLUMN ";
- ret += ColumnDefToString(at.col_def());
- } else {
- ret += "RENAME TO ";
- ret += TableToString(at.table_fallback());
- }
- return ret;
- }
- // ~~~~ATTACH DATABASE~~~~
- CONV_FN(AttachDatabase, ad) {
- RETURN_IF_DISABLED_QUERY(AttachDatabase);
- std::string ret("ATTACH DATABASE \'");
- if (ad.in_memory()) {
- if (ad.file_uri()) {
- ret += "file:";
- std::string add;
- if (ad.has_db_name()) {
- ret += SchemaToString(ad.db_name());
- ret += "?mode=memory";
- add = "&";
- } else {
- ret += ":memory:";
- add = "?";
- }
- if (ad.shared_cache()) {
- ret += add;
- ret += "cache=shared";
- }
- }
- }
- ret += "\' AS ";
- ret += SchemaToString(ad.schema());
- return ret;
- }
- // ~~~~DETACH DATABASE~~~~
- CONV_FN(DetachDatabase, dd) {
- RETURN_IF_DISABLED_QUERY(DetachDatabase);
- std::string ret("DETACH DATABASE ");
- ret += SchemaToString(dd.schema());
- return ret;
- }
- // ~~~~Time and date fns~~~~
- CONV_FN(HoursStuff, hs) {
- std::string ret;
- if (hs.has_hh()) {
- ret += std::to_string(hs.hh() % 100);
- if (hs.has_mm()) {
- ret += ":";
- ret += std::to_string(hs.mm() % 100);
- if (hs.has_ss()) {
- ret += ":";
- ret += std::to_string(hs.ss() % 100);
- if (hs.has_sss()) {
- ret += ".";
- ret += std::to_string(hs.sss() % 1000);
- }
- }
- }
- }
- return ret;
- }
- CONV_FN(TimeString, ts) {
- std::string ret;
- if (ts.has_yyyy()) {
- // FIXME in the future add zeroes for integers < 1000.
- ret += std::to_string(ts.yyyy() % 10000);
- ret += "-";
- ret += std::to_string(ts.mm() % 100);
- ret += "-";
- ret += std::to_string(ts.dd() % 100);
- if (ts.extra_t())
- ret += "T";
- if (ts.has_hs())
- ret += HoursStuffToString(ts.hs());
- } else if (ts.has_hs()) {
- ret += HoursStuffToString(ts.hs());
- } else if (ts.has_dddddddddd()) {
- ret += std::to_string(ts.dddddddddd() % 10000000000);
- } else if (ts.now()) {
- ret += "now";
- } else {
- ret += ConvertToSqlString(ts.random_bytes());
- }
- if (ts.has_tz_plus()) {
- if (ts.z()) {
- ret += "Z";
- } else {
- if (ts.plus())
- ret += "+";
- else
- ret += "-";
- ret += std::to_string(ts.tz_hh() % 100);
- ret += std::to_string(ts.tz_mm() % 100);
- }
- }
- return ret;
- }
- CONV_FN(TimeModifier, tm) {
- std::string ret;
- if (tm.has_nm()) {
- ret += std::to_string(tm.num());
- ret += " ";
- if (tm.has_dot_num()) {
- ret += ".";
- ret += std::to_string(tm.dot_num());
- }
- ret += StrToLower(TimeModifier_NumberedModifiers_Name(tm.nm()));
- } else {
- ret += StrToLower(
- EnumStrReplaceUnderscores(TimeModifier_OtherModifiers_Name(tm.om())));
- }
- if (tm.om() == TimeModifier::WEEKDAY) {
- ret += " ";
- ret += std::to_string(tm.num());
- }
- return ret;
- }
- CONV_FN(SimpleDateAndTimeFn, sfn) {
- std::string ret;
- ret += StrToLower(SimpleDateAndTimeFn_FnName_Name(sfn.fn_name()));
- ret += "(\'";
- ret += TimeStringToString(sfn.time_string());
- ret += "\'";
- for (int i = 0; i < sfn.modifiers_size(); i++) {
- ret += ", \'";
- ret += TimeModifierToString(sfn.modifiers(i));
- ret += "\'";
- }
- ret += ") ";
- return ret;
- }
- CONV_FN(StrftimeFormat, sf) {
- std::string ret;
- if (sf.has_subs()) {
- std::string subs = StrftimeFormat_Substitution_Name(sf.subs());
- if (sf.lowercase())
- subs = StrToLower(subs);
- ret += "%" + subs;
- } else {
- ret += "%%";
- }
- ret += ConvertToSqlString(sf.bytes());
- return ret;
- }
- CONV_FN(StrftimeFn, sfn) {
- std::string ret("strftime(\'");
- for (int i = 0; i < sfn.fmts_size(); i++) {
- ret += StrftimeFormatToString(sfn.fmts(i));
- }
- ret += "\', \'";
- ret += TimeStringToString(sfn.time_string());
- ret += "\'";
- for (int i = 0; i < sfn.modifiers_size(); i++) {
- ret += ", \'";
- ret += TimeModifierToString(sfn.modifiers(i));
- ret += "\'";
- }
- ret += ") ";
- return ret;
- }
- CONV_FN(DateAndTimeFn, dat) {
- if (dat.has_simple())
- return SimpleDateAndTimeFnToString(dat.simple());
- else
- return StrftimeFnToString(dat.strftime());
- }
- // ~~~~QUERY~~~~
- CONV_FN(SQLQuery, query) {
- using QueryType = SQLQuery::QueryOneofCase;
- switch (query.query_oneof_case()) {
- case QueryType::kSelect:
- return SelectToString(query.select());
- case QueryType::kCreateTable:
- return CreateTableToString(query.create_table());
- case QueryType::kInsert:
- return InsertToString(query.insert());
- case QueryType::kDelete:
- return DeleteToString(query.delete_());
- case QueryType::kFts3Table:
- return CreateFTS3TableToString(query.fts3_table());
- case QueryType::kFtsQuery:
- return FTS3SpecificQueryToString(query.fts_query());
- case QueryType::kBeginTxn:
- return BeginTransactionToString(query.begin_txn());
- case QueryType::kCommitTxn:
- return CommitTransactionToString(query.commit_txn());
- case QueryType::kRollbackStmt:
- return RollbackStatementToString(query.rollback_stmt());
- #if !defined(FUZZ_OMIT_SAVEPOINT)
- case QueryType::kCreateSavePoint:
- return CreateSavePointToString(query.create_save_point());
- case QueryType::kReleaseSavePoint:
- return ReleaseSavePointToString(query.release_save_point());
- #endif
- case QueryType::kAnalyze:
- return AnalyzeToString(query.analyze());
- case QueryType::kVacuum:
- return VacuumToString(query.vacuum());
- case QueryType::kPragma:
- return PragmaToString(query.pragma());
- case QueryType::kUpdate:
- return UpdateToString(query.update());
- case QueryType::kCreateIndex:
- return CreateIndexToString(query.create_index());
- case QueryType::kCreateView:
- return CreateViewToString(query.create_view());
- case QueryType::kCreateTrigger:
- return CreateTriggerToString(query.create_trigger());
- case QueryType::kReindex:
- return ReIndexToString(query.reindex());
- case QueryType::kDrop:
- return DropToString(query.drop());
- case QueryType::kAlterTable:
- return AlterTableToString(query.alter_table());
- case QueryType::kAttachDb:
- return AttachDatabaseToString(query.attach_db());
- case QueryType::kDetachDb:
- return DetachDatabaseToString(query.detach_db());
- #if defined(FUZZ_FTS3)
- case QueryType::kFts3Insert:
- return FTS3HiddenTableInsertToString(query.fts3_insert());
- case QueryType::kFts3Update:
- return FTS3HiddenTableUpdateToString(query.fts3_update());
- case QueryType::kFts3Delete:
- return FTS3HiddenTableDeleteToString(query.fts3_delete());
- #endif
- default:
- return "";
- }
- }
- std::vector<std::string> SQLQueriesToVec(const SQLQueries& sql_queries) {
- std::vector<std::string> queries;
- queries.reserve(sql_queries.extra_queries_size() + 1);
- queries.push_back(CreateTableToString(sql_queries.create_table()) + ";");
- for (int i = 0; i < sql_queries.extra_queries_size(); i++) {
- std::string query = SQLQueryToString(sql_queries.extra_queries(i));
- if (query == "")
- continue;
- query += ";";
- queries.push_back(query);
- }
- return queries;
- }
- CONV_FN(SQLQueries, sql_queries) {
- std::string queries;
- for (std::string& query : SQLQueriesToVec(sql_queries)) {
- queries += query;
- queries += "\n";
- }
- return queries;
- }
- void SetDisabledQueries(std::set<std::string> disabled_queries) {
- disabled_queries_ = disabled_queries;
- }
- } // namespace sql_fuzzer
|