| // Copyright 2018 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| syntax = "proto2"; | |
| import "icu_codes.proto"; | |
| package sql_query_grammar; | |
| /* Generates SQL queries in protobuf format, using enums for the tables and | |
| integers for column names. The column name integers will be wrapped. | |
| Relies heavily on the sqlite grammar from here: | |
| https://www.sqlite.org/lang.html | |
| Yes, it is all in one big blobby proto file, as everything is extremely | |
| mutually recursive and there is no such thing as circular imports or forward | |
| declarations in protobuf. | |
| */ | |
| message SQLQuery { | |
| // No comments generated, nor EXPLAIN queries | |
| oneof query_oneof { | |
| Select select = 1; | |
| CreateTable create_table = 2; | |
| Insert insert = 3; | |
| Delete delete = 4; | |
| CreateFTS3Table fts3_table = 5; | |
| FTS3SpecificQuery fts_query = 6; | |
| BeginTransaction begin_txn = 7; | |
| CommitTransaction commit_txn = 8; | |
| RollbackStatement rollback_stmt = 9; | |
| CreateSavePoint create_save_point = 10; | |
| ReleaseSavePoint release_save_point = 11; | |
| Analyze analyze = 12; | |
| Vacuum vacuum = 13; | |
| Pragma pragma = 14; | |
| Update update = 15; | |
| CreateIndex create_index = 16; | |
| CreateView create_view = 17; | |
| CreateTrigger create_trigger = 18; | |
| ReIndex reindex = 19; | |
| Drop drop = 20; | |
| AlterTable alter_table = 21; | |
| AttachDatabase attach_db = 22; | |
| DetachDatabase detach_db = 23; | |
| FTS3HiddenTableInsert fts3_insert = 24; | |
| FTS3HiddenTableUpdate fts3_update = 25; | |
| FTS3HiddenTableDelete fts3_delete = 26; | |
| } | |
| } | |
| // ~~~~FTS3~~~ | |
| message FTS3SpecificQuery { | |
| oneof query_oneof { | |
| FTS3SpecialCommand command = 1; | |
| // The following exists to increase the probability of hitting MATCH | |
| // queries. | |
| FTS3SelectMatch select = 2; | |
| } | |
| } | |
| message FTS3SelectMatch { | |
| // SELECT * FROM |table| WHERE |col| MATCH |match_pattern| | |
| required FTS3Table table = 1; | |
| required Column col = 2; | |
| required FTS3MatchFormat match_pattern = 3; | |
| } | |
| message FTS3SpecialCommand { | |
| // INSERT INTO xyz(xyz) VALUES('optimize'); | |
| // is a special command that optimizes FTS table xyz. | |
| required FTS3Table table = 1; | |
| enum Command { | |
| OPTIMIZE = 0; | |
| REBUILD = 1; | |
| INTEGRITY_CHECK = 2; | |
| MERGE = 3; | |
| AUTOMERGE = 4; | |
| } | |
| required Command command = 2; | |
| required uint32 val1 = 3; | |
| required uint32 val2 = 4; | |
| } | |
| message ICULocale { | |
| required IsoLangCode iso_lang_code = 1; | |
| // least significant 2 bytes will each be clamped to within 'A' and | |
| // 'Z' and then concatenated together to form a country code. | |
| required uint32 country_code = 2; | |
| // TODO(mpdenton) generate anything else here? Will sqlite care? | |
| } | |
| enum TokenizerType { | |
| TT_SIMPLE = 0; | |
| TT_PORTER = 1; | |
| TT_ICU = 2; | |
| TT_UNICODE61 = 3; // FIXME in the future: remove_diacritics, separators, | |
| // token_chars.... (not supported in Chrome) | |
| } | |
| // FIXME in the future: maybe also fuzz the tokenizer type/icu locales with | |
| // random strings??? | |
| message CreateFTS3Table { | |
| required bool if_not_exists = 1; | |
| optional Schema schema = 6; | |
| required FTS3Table table = 2; | |
| optional ColumnList col_list = 3; | |
| optional TokenizerType tokenizer_type = 4; | |
| required ICULocale locale = 5; // used if tokenizer_type == TT_ICU. | |
| } | |
| message FTS3Table { | |
| required uint32 table = 1; | |
| } | |
| // TODO(mpdenton) query by row id? | |
| message FTS3MatchFormat { | |
| repeated FTS3MatchCompoundFormat ft = 1; | |
| } | |
| message FTS3MatchCompoundFormat { | |
| required FTS3MatchFormatCore core = 1; | |
| repeated FTS3CompoundAndCore compound_and_cores = 2; | |
| } | |
| message FTS3CompoundAndCore { | |
| enum CompoundOp { | |
| OR = 0; | |
| // Chrome does not enable the enhanced query syntax. FIXME in the future. | |
| // AND = 1; | |
| // NOT = 2; | |
| } | |
| required CompoundOp op = 1; | |
| required FTS3MatchFormatCore core = 2; | |
| } | |
| message FTS3MatchFormatCore { | |
| oneof ft_oneof { | |
| FTS3PhraseQuery pq = 1; | |
| FTS3NearQuery nq = 2; | |
| } | |
| required FTS3MatchToken mt_fallback = 3; | |
| } | |
| message FTS3NearQuery { | |
| // May generate into another NEAR query, this is fine. | |
| required FTS3MatchFormatCore format_core1 = 1; | |
| optional uint32 num_tokens_near = 2; | |
| required FTS3MatchFormatCore format_core2 = 3; | |
| } | |
| message FTS3PhraseQuery { | |
| required FTS3MatchToken mt = 1; | |
| repeated FTS3MatchToken extra_mts = 2; | |
| } | |
| message FTS3MatchToken { | |
| optional Column col = 1; // search in this column specifically | |
| required bool negate = 4; | |
| required string token = 2; // token (or prefix) to search for | |
| required bool prefix = 3; // append star to end | |
| } | |
| // FIXME in the future: https://www.sqlite.org/fts3.html Section 8.2: Query | |
| // tokenizers themselves. Unsupported by Chrome. | |
| message FTS3OffsetsFn { | |
| required FTS3Table table = 1; | |
| } | |
| message FTS3SnippetsFn { | |
| required FTS3Table table = 1; | |
| enum NumArgs { | |
| A0 = 0; | |
| A1 = 1; | |
| A2 = 2; | |
| A3 = 3; | |
| A4 = 4; | |
| A5 = 5; | |
| } | |
| required NumArgs num_optional_args = 2; | |
| required string start_match = 3; | |
| required string end_match = 4; | |
| required string ellipses = 5; | |
| optional uint32 col_number = 6; // capped by KMaxColumnNumber | |
| required uint32 num_tokens = 7; // in [-64, 64]. | |
| } | |
| message FTS3MatchInfoFn { | |
| required FTS3Table table = 1; | |
| // The following will be wrapped to any of the characters p,c,n,a,,l,s,x,y,b. | |
| repeated uint32 chars = 2; | |
| } | |
| // FTS3 Auxiliary function format | |
| message FTS3AuxiliaryFn { | |
| required FTS3OffsetsFn offsets_fallback = 1; | |
| oneof fts_aux_fn_oneof { | |
| FTS3SnippetsFn snippets = 2; | |
| FTS3MatchInfoFn matchinfo = 3; | |
| } | |
| } | |
| // Types of hidden tables in FTS3 | |
| message FTS3HiddenTable { | |
| enum HiddenTableVal { | |
| // CONTENT = 0; // Taken care of in |Table| | |
| SEGDIR = 1; | |
| SEGMENTS = 2; | |
| // stat and docsize are FTS4 | |
| } | |
| required HiddenTableVal htv = 1; | |
| required FTS3Table table = 2; | |
| } | |
| // The different columns that go into the FTS3 hidden tables above | |
| enum FTS3HiddenTableColumn { | |
| FTS3_HT_BLOCKID = 0; | |
| FTS3_HT_BLOCK = 1; | |
| FTS3_HT_LEVEL = 2; | |
| FTS3_HT_IDX = 3; | |
| FTS3_HT_START_BLOCK = 4; | |
| FTS3_HT_LEAVES_END_BLOCK = 5; | |
| FTS3_HT_END_BLOCK = 6; | |
| FTS3_HT_ROOT = 7; | |
| } | |
| // Some extra stuff to modify the FTS3 Hidden tables, only used for FTS3 | |
| // Fuzzing. | |
| // Used to insert single values in. | |
| message FTS3HiddenTableInsert { | |
| required FTS3HiddenTable fht = 1; | |
| repeated FTS3HiddenTableColumnValue col_vals = 2; | |
| } | |
| message FTS3HiddenTableUpdate { | |
| required FTS3HiddenTable fht = 1; | |
| repeated FTS3HiddenTableColumnValue col_vals = 2; | |
| // mini WHERE clause with some BinOp | |
| optional FTS3HiddenTableColumn col_where = 3; | |
| required BinaryOperator bin_op = 4; | |
| required Expr comp_expr = 5; | |
| } | |
| message FTS3HiddenTableDelete { | |
| required FTS3HiddenTable fht = 1; | |
| optional FTS3HiddenTableColumn col_where = 2; | |
| required BinaryOperator bin_op = 3; | |
| required Expr comp_expr = 4; | |
| } | |
| message FTS3HiddenTableColumnValue { | |
| required FTS3HiddenTableColumn col = 1; | |
| required Expr expr = 2; | |
| } | |
| // ~~~~TRANSACTIONs~~~~ | |
| // TODO(mpdenton) these could be meta-statements that enclose a bunch of other | |
| // statements. Is that worthwhile or should I just let the fuzzer generate them | |
| // haphazardly? | |
| message BeginTransaction { | |
| enum TransactionType { | |
| DEFERRED = 0; | |
| IMMEDIATE = 1; | |
| EXCLUSIVE = 2; | |
| } | |
| optional TransactionType type = 1; | |
| } | |
| message CommitTransaction { | |
| enum CommitText { | |
| COMMIT = 0; | |
| END = 1; | |
| COMMIT_TRANSACTION = 2; | |
| END_TRANSACTION = 3; | |
| } | |
| required CommitText text = 1; | |
| } | |
| message SavePoint { | |
| required uint32 savepoint_num = 1; | |
| } | |
| message RollbackStatement { | |
| optional SavePoint save_point = 1; | |
| } | |
| message CreateSavePoint { | |
| required SavePoint save_point = 1; | |
| } | |
| message ReleaseSavePoint { | |
| required SavePoint save_point = 1; | |
| } | |
| // ~~~~ANALYZE~~~~ | |
| message Analyze { | |
| optional Schema schema_name = 1; | |
| optional Table table_name = 2; | |
| optional Index index_name = 3; | |
| } | |
| // ~~~~VACUUM~~~~ | |
| message Vacuum { | |
| optional Schema schema = 1; | |
| } | |
| // ~~~~PRAGMA~~~~ | |
| message Pragma { | |
| // FIXME in the future: full list here: https://www.sqlite.org/pragma.html | |
| // These are the ones I've seen in Chrome | |
| enum PragmaCommand { | |
| // QUICK_CHECK = 0; | |
| // INTEGRITY_CHECK = 1; | |
| AUTO_VACUUM = 2; | |
| WRITEABLE_SCHEMA = 3; | |
| LOCKING_MODE = 4; | |
| TEMP_STORE = 5; | |
| PAGE_SIZE_ = 6; | |
| TABLE_INFO = 7; | |
| JOURNAL_MODE = 8; | |
| MMAP_SIZE = 9; | |
| } | |
| required PragmaCommand command = 1; | |
| optional Schema schema = 2; | |
| required int32 arg1 = 3; | |
| } | |
| // ~~~~CREATE_TABLE~~~~ | |
| enum TempModifier { | |
| TM_TEMP = 3; | |
| TM_TEMPORARY = 4; | |
| } | |
| message CreateTable { | |
| optional TempModifier temp_modifier = 1; | |
| required bool if_not_exists = 2; | |
| required ExprSchemaTable schema_table = 3; | |
| oneof create_table_oneof { | |
| CreateTableOpt1 op1 = 4; | |
| Select as_select_stmt = 5; // AS select-stmt | |
| } | |
| required CreateTableOpt1 op = 6; // used only if the above oneof is empty | |
| } | |
| message CreateTableOpt1 { | |
| required ColumnDef col_def = 1; | |
| repeated ColumnDef extra_col_defs = 2; | |
| repeated TableConstraint table_constraints = 3; | |
| required bool without_rowid = 4; | |
| } | |
| message ColumnDef { | |
| required Column col = 1; | |
| optional TypeName type_name = 2; | |
| repeated ColumnConstraint col_constraints = 3; | |
| } | |
| message TypeName { | |
| // Things like VARCHAR(100) are simply not enforced by SQLite (this example | |
| // would end up with a column affinity of TEXT). So I don't make much effort | |
| // to generate them. | |
| required CastTypeName ctn = 1; | |
| optional uint32 sn = 2; | |
| } | |
| message ColumnConstraint { | |
| optional ColumnConstraintName constraint_name = 1; | |
| oneof col_constraint_oneof { | |
| ColConstraintOpt1 opt1 = 2; | |
| ConflictClause not_null_conf_clause = 3; | |
| ConflictClause unique_conf_clause = 4; | |
| Expr check_expr = 5; // CORPUS specialize?? | |
| ColConstraintOpt2 opt2 = 6; | |
| CollateType collate = 7; | |
| ForeignKeyClause fkey_clause = 8; | |
| } | |
| required ColConstraintOpt2 opt2_fallback = 9; | |
| } | |
| message ColConstraintOpt1 { | |
| required AscDesc asc_desc = 1; | |
| required ConflictClause conflict = 2; | |
| required bool autoincrement = 3; | |
| } | |
| message ColConstraintOpt2 { | |
| required LiteralValue lit_val = 1; | |
| optional Expr expr = 2; // CORPUS specialize? | |
| } | |
| message ConflictClause { | |
| enum OnConflict { | |
| ROLLBACK = 0; | |
| ABORT = 1; | |
| FAIL = 2; | |
| IGNORE = 3; | |
| REPLACE = 4; | |
| } | |
| optional OnConflict on_conflict = 1; | |
| } | |
| message TableConstraint { | |
| optional TableConstraintName name = 1; | |
| oneof table_constraint_oneof { | |
| TableConstraintOpt1 opt1 = 2; | |
| Expr check_expr = 3; // CORPUS specialize? | |
| TableConstraintOpt2 opt2 = 4; | |
| } | |
| } | |
| message TableConstraintOpt1 { | |
| enum ConstraintType { | |
| PRIMARY_KEY = 0; | |
| UNIQUE = 1; | |
| } | |
| required ConstraintType constraint_type = 1; | |
| required IndexedColumnList indexed_col_list = 2; | |
| required ConflictClause conf_clause = 3; | |
| } | |
| message TableConstraintOpt2 { | |
| required ColumnList cols = 1; | |
| required ForeignKeyClause fkey_clause = 2; | |
| } | |
| message IndexedColumn { | |
| optional Expr expr = 1; // CORPUS specialize? | |
| required Column col = 2; // only used if expr non-existent | |
| optional CollateType collate_type = 3; | |
| required AscDesc asc_desc = 4; | |
| } | |
| message IndexedColumnList { | |
| required IndexedColumn indexed_col = 1; | |
| repeated IndexedColumn extra_indexed_cols = 2; | |
| } | |
| message ForeignKeyClause { | |
| required Table foreign_table = 1; | |
| optional ColumnList col_list = 2; | |
| repeated ForeignKeyClauseCore fkey_cores = 3; | |
| optional DeferStrategy defer_strat = 4; | |
| } | |
| message ForeignKeyClauseCore { | |
| optional ForeignKeyClauseNotMatch fkey_not_match = 1; | |
| // Sqlite doesn't obey MATCH expressions, MATCH SIMPLE is always assumed | |
| } | |
| message ForeignKeyClauseNotMatch { | |
| enum DeleteOrUpdate { | |
| DELETE = 0; | |
| UPDATE = 1; | |
| } | |
| required DeleteOrUpdate del_or_update = 1; | |
| enum Action { | |
| SET_NULL = 0; | |
| SET_DEFAULT = 1; | |
| CASCADE = 2; | |
| RESTRICT = 3; | |
| NO_ACTION = 4; | |
| } | |
| required Action action = 2; | |
| } | |
| message DeferStrategy { | |
| required bool not = 1; | |
| enum DeferStratEnum { | |
| INITIALLY_DEFERRED = 0; | |
| INITIALLY_IMMEDIATE = 1; | |
| NONE = 2; | |
| } | |
| required DeferStratEnum strat = 2; | |
| } | |
| // ~~~~DELETE~~~~ | |
| // FIXME in the future: SQL_ENABLE_UPDATE_DELETE_LIMIT | |
| message Delete { | |
| optional WithStatement with = 1; | |
| required QualifiedTableName qtn = 2; | |
| optional WhereStatement where = 3; | |
| } | |
| message QualifiedTableName { | |
| required SchemaTableAsAlias staa = 1; | |
| required bool indexed = 2; | |
| required bool not_indexed = 3; | |
| required Index indexed_by = 4; | |
| } | |
| // ~~~~INSERT~~~~ | |
| message UpsertClausePart1 { | |
| required IndexedColumnList icol_list = 1; | |
| optional WhereStatement where_stmt = 2; | |
| } | |
| message ColEqualsExpr { | |
| oneof uclause_p2_oneof { | |
| Column col = 1; | |
| ColumnList col_list = 2; | |
| } | |
| required Expr expr = 3; | |
| } | |
| message UpsertClausePart2 { | |
| required ColEqualsExpr cee = 1; | |
| repeated ColEqualsExpr extra_cees = 2; | |
| optional WhereStatement where_stmt = 3; | |
| } | |
| message UpsertClause { | |
| optional UpsertClausePart1 uclause_p1 = 1; | |
| optional UpsertClausePart2 uclause_p2 = 2; | |
| } | |
| message SchemaTableAsAlias { | |
| required ExprSchemaTable schema_table = 1; | |
| optional Table as_table_alias = 2; | |
| } | |
| message Insert { | |
| optional WithStatement with = 1; | |
| enum InsertType { | |
| INSERT = 0; | |
| REPLACE = 1; | |
| INSERT_OR_REPLACE = 2; | |
| INSERT_OR_ROLLBACK = 3; | |
| INSERT_OR_ABORT = 4; | |
| INSERT_OR_FAIL = 5; | |
| INSERT_OR_IGNORE = 6; | |
| } | |
| required InsertType insert_type = 2; | |
| required SchemaTableAsAlias staa = 3; | |
| optional ColumnList col_list = 5; | |
| oneof insert_oneof { | |
| ValuesStatement values = 6; | |
| Select select = 7; | |
| } // if empty, DEFAULT VALUES | |
| optional UpsertClause upsert_clause = 8; | |
| } | |
| // ~~~~UPDATE~~~~ | |
| message Update { | |
| optional WithStatement with = 1; | |
| enum UpdateType { | |
| OR_ROLLBACK = 0; | |
| OR_ABORT = 1; | |
| OR_REPLACE = 2; | |
| OR_FAIL = 3; | |
| OR_IGNORE = 4; | |
| } | |
| optional UpdateType update_type = 2; | |
| required QualifiedTableName qtn = 3; | |
| required UpsertClausePart2 ucp2 = 4; | |
| } | |
| // ~~~~CREATE INDEX~~~~ | |
| message CreateIndex { | |
| required bool unique = 1; | |
| required bool if_not_exists = 2; | |
| optional Schema schema = 3; | |
| required Index index = 4; | |
| required Table table = 5; | |
| required IndexedColumnList icol_list = 6; | |
| optional WhereStatement where = 7; | |
| } | |
| // ~~~~CREATE VIEW~~~~ | |
| message View { | |
| required uint32 view = 1; | |
| } | |
| message CreateView { | |
| optional TempModifier temp_modifier = 1; | |
| required bool if_not_exists = 2; | |
| optional Schema schema = 3; | |
| required View view = 4; | |
| optional ColumnList col_list = 5; | |
| required Select select = 6; | |
| } | |
| // ~~~~CREATE TRIGGER~~~~ | |
| message Trigger { | |
| required uint32 trigger = 1; | |
| } | |
| message CreateTrigger { | |
| optional TempModifier temp_modifier = 1; | |
| required bool if_not_exists = 2; | |
| optional Schema schema = 3; | |
| required Trigger trigger = 4; | |
| enum TriggerType { | |
| BEFORE = 0; | |
| AFTER = 1; | |
| INSTEAD_OF = 2; | |
| } | |
| optional TriggerType trigger_type = 5; | |
| enum TriggerInstr { | |
| DELETE = 0; | |
| UPDATE = 1; | |
| INSERT = 2; | |
| } | |
| optional TriggerInstr trigger_instr = 6; | |
| required ColumnList col_list = 7; // CORPUS create corpus item with an Update | |
| // using the same ColumnList as this | |
| required Table table = 8; | |
| required bool for_each_row = 9; | |
| optional ExprComparisonHighProbability when = 10; // for the WHEN statement | |
| // There are significant restrictions on update, insert, select, and delete | |
| // expressions used in triggers. However, we might as well generate normal | |
| // queries and see if these restrictions are adequately enforced. | |
| // Also, from https://www.sqlite.org/lang_createtrigger.html: "If a BEFORE | |
| // UPDATE or BEFORE DELETE trigger modifies or deletes a row that was to have | |
| // been updated or deleted, then the result of the subsequent update or delete | |
| // operation is undefined. Furthermore, if a BEFORE trigger modifies or | |
| // deletes a row, then it is undefined whether or not AFTER triggers that | |
| // would have otherwise run on those rows will in fact run." | |
| // It is unclear what is meant by "undefined". Are we talking memory | |
| // corruption? I suppose the fuzzer will find it and we'll see. | |
| required TypicalQuery tq = 11; | |
| repeated TypicalQuery extra_tqs = 12; | |
| } | |
| message TypicalQuery { | |
| oneof tq_oneof { | |
| Update update = 1; | |
| Insert insert = 2; | |
| Select select = 3; | |
| } | |
| required Delete delete_fallback = 4; | |
| } | |
| // ~~~~REINDEX~~~~ | |
| message ReIndex { | |
| required bool empty = 5; | |
| optional CollateType collate_type = 4; // used if schema does not exist | |
| optional Schema schema = 1; | |
| optional Table table = 2; | |
| required Index index = 3; // used if table does not exist. | |
| } | |
| // ~~~~DROP *~~~~ | |
| message Drop { | |
| required bool if_exists = 5; | |
| optional Schema schema = 6; | |
| oneof drop_oneof { | |
| Index index = 1; | |
| Table table = 2; | |
| Trigger trigger = 3; | |
| } | |
| required View view_fallback = 4; | |
| } | |
| // ~~~~ALTER TABLE~~~~ | |
| message AlterTable { | |
| required ExprSchemaTable schema_table = 1; | |
| required bool column = 2; | |
| optional Column col = 4; | |
| required Column col_to = 5; | |
| optional ColumnDef col_def = 6; | |
| required Table table_fallback = 3; | |
| } | |
| // ~~~~ATTACH DATABASE~~~~ | |
| // SEE: https://www.sqlite.org/inmemorydb.html | |
| // Lots of different options. | |
| // TODO(mpdenton) may want to experiment with on-filesystem main dbs as well... | |
| message AttachDatabase { | |
| required bool in_memory = 1; | |
| required bool file_uri = 2; | |
| optional Schema db_name = 3; | |
| required bool shared_cache = 4; | |
| required Schema schema = 5; | |
| } | |
| // ~~~~DETACH DATABASE~~~~ | |
| message DetachDatabase { | |
| required Schema schema = 1; | |
| } | |
| // ~~~~SELECT~~~~ | |
| /* | |
| Select is obviously the most complicated syntax in the language, and the | |
| fuzzer will likely generate plenty of invalid SELECT statements. As long as | |
| it does not generate too many, we should still be perfectly fine. | |
| From sqlite docs: | |
| Note that there are paths through the syntax diagrams that are not allowed in | |
| practice. Some examples: | |
| A VALUES clause can be the first element in a compound SELECT that uses a WITH | |
| clause, but a simple SELECT that consists of just a VALUES clause cannot be | |
| preceded by a WITH clause. The WITH clause must occur on the first SELECT of a | |
| compound SELECT. It cannot follow a compound-operator. | |
| See https://www.sqlite.org/lang_select.html. | |
| */ | |
| message Select { | |
| optional WithStatement with = 1; | |
| // SQL grammar specifies SelectSubStatement here but that just leads | |
| // to a bunch of unparseable VALUES ... ; statements. So require | |
| // SelectCore here. | |
| required SelectStatementCore select_core = 2; | |
| repeated ExtraSelectSubStatement extra_select_substatements = 3; | |
| optional OrderByStatement orderby = 4; | |
| optional LimitStatement limit = 5; | |
| } | |
| message OrderByStatement { | |
| required ExprOrderingTerm ord_term = 1; | |
| repeated ExprOrderingTerm extra_ord_terms = 2; | |
| } | |
| message LimitStatement { | |
| // CORPUS specialize these exprs??? | |
| required Expr limit_expr = 1; | |
| required bool offset = 2; // this is only used if second_expr exists | |
| optional Expr second_expr = 3; | |
| } | |
| message ExtraSelectSubStatement { | |
| required CompoundOperator compound_op = 1; | |
| required SelectSubStatement select_substatement = 2; | |
| } | |
| enum CompoundOperator { | |
| CO_UNION = 0; | |
| CO_UNION_ALL = 1; | |
| CO_INTERSECT = 2; | |
| CO_EXCEPT = 3; | |
| } | |
| message SelectSubStatement { | |
| oneof select_subexpr_oneof { | |
| SelectStatementCore select_core = 1; | |
| ValuesStatement values = 2; | |
| } | |
| required ValuesStatement values_fallback = 3; | |
| } | |
| message ValuesStatement { | |
| required ExprList expr_list = 1; | |
| repeated ExprList extra_expr_lists = 2; // CORPUS specialize? | |
| } | |
| message ExprColAlias { | |
| required Expr expr = 1; | |
| optional Column col_alias = 2; | |
| required bool as = 3; | |
| } | |
| message ResultColumn { | |
| oneof result_col_oneof { | |
| Column col = 1; | |
| ExprColAlias eca = 2; | |
| Table table_star = 3; | |
| FTS3AuxiliaryFn fts3_fn = 4; // Only emitted when FUZZ_FTS3 enabled | |
| } // if nothing, use star * | |
| } | |
| message SelectStatementCore { | |
| enum SelectOrDistinct { | |
| SELECT_DISTINCT = 0; | |
| SELECT = 1; | |
| SELECT_ALL = 2; | |
| } | |
| required SelectOrDistinct s_or_d = 1; | |
| repeated ResultColumn result_columns = 2; | |
| optional FromStatement from = 3; | |
| optional WhereStatement where = 4; | |
| optional GroupByStatement groupby = 5; | |
| optional WindowStatement window = 6; | |
| } | |
| message WithStatement { | |
| required bool recursive = 1; | |
| required CommonTableExpr table_expr = 2; | |
| repeated CommonTableExpr extra_table_exprs = 3; | |
| } | |
| message FromStatement { | |
| required TableOrSubqueryOption3 tos3 = 1; | |
| } | |
| message WindowStatement { | |
| required WindowStatementNaming win = 1; | |
| repeated WindowStatementNaming extra_wins = 2; | |
| } | |
| message WindowStatementNaming { | |
| required WindowName name = 1; | |
| required WindowDefn defn = 2; | |
| } | |
| message GroupByStatement { | |
| // CORPUS specialize all these exprs???? | |
| required ExprList exprs = 1; | |
| optional Expr having_expr = 3; | |
| } | |
| message WhereStatement { | |
| required ExprComparisonHighProbability expr = 1; | |
| } | |
| message CommonTableExpr { | |
| required Table table = 1; | |
| repeated Column columns = 2; | |
| required Select select = 3; | |
| } | |
| // ~~~~Join stuff~~~~~ | |
| message JoinClause { | |
| required TableOrSubquery tos = 1; | |
| repeated JoinClauseCore clauses = 2; | |
| } | |
| message JoinClauseCore { | |
| required JoinOperator join_op = 1; | |
| required TableOrSubquery tos = 2; | |
| required JoinConstraint join_constraint = 3; | |
| } | |
| message JoinOperator { | |
| required bool comma = 1; | |
| // the following fields only used if comma is false | |
| required bool natural = 2; | |
| enum JoinType { | |
| LEFT = 0; | |
| LEFT_OUTER = 1; | |
| INNER = 2; | |
| CROSS = 3; | |
| NONE = 4; | |
| } | |
| required JoinType join_type = 3; | |
| } | |
| message JoinConstraint { | |
| oneof join_constraint_oneof { | |
| Expr on_expr = 1; | |
| UsingExpr using_expr = 2; | |
| } // fine if empty | |
| } | |
| message UsingExpr { | |
| required ColumnList col_list = 1; | |
| } | |
| // ~~~~~Table names etc.~~~~~ | |
| // First checks if main is set. Then checks if temp is set. Then checks if | |
| // other schema number is set. | |
| message Schema { | |
| required uint32 schema = 1; | |
| required bool main = 2; | |
| required bool temp = 3; | |
| } | |
| message Table { | |
| required uint32 table = 1; | |
| optional bool fts3_content_table = 2; // only used for FTS3 fuzzing | |
| } | |
| message Column { | |
| required uint32 column = 1; | |
| optional bool rowid = 2; // can also have "rowid" column | |
| // FTS has a hidden column with the same name as the table. | |
| optional FTS3Table fts3_table = 3; | |
| // FTS3 tables have "docid" as an alias for "rowid". | |
| optional bool fts3_docid = 4; | |
| } | |
| message WindowName { | |
| required uint32 window_name = 1; | |
| } | |
| message ColumnConstraintName { | |
| required uint32 constraint_name = 1; | |
| } | |
| message TableConstraintName { | |
| required uint32 constraint_name = 1; | |
| } | |
| message Index { | |
| required uint32 index = 1; | |
| } | |
| // Example: | |
| // column1, column2, column3 | |
| message ColumnList { | |
| required Column col = 1; | |
| repeated Column extra_cols = 2; | |
| } | |
| // ~~~~table-or-subquery~~~~ | |
| message TableOrSubquery { | |
| oneof tos_oneof { | |
| QualifiedTableName qtn = 1; | |
| TableOrSubqueryOption2 toso2 = 2; | |
| TableOrSubqueryOption3 toso3 = 3; | |
| TableOrSubqueryOption4 toso4 = 4; | |
| } | |
| required ExprSchemaTable schema_table_expr = 5; // used if the oneof is empty | |
| } | |
| message TableOrSubqueryOption2 { | |
| required ExprSchemaTableFn schema_table_fn = 1; | |
| optional AsTableAlias as_table_alias = 2; | |
| } | |
| message TableOrSubqueryOption3 { | |
| repeated TableOrSubquery tos_list = 1; // if empty, use the join clause | |
| required JoinClause join_clause = 2; | |
| } | |
| message TableOrSubqueryOption4 { | |
| required Select select = 1; | |
| optional AsTableAlias as_table_alias = 2; | |
| } | |
| message AsTableAlias { | |
| required bool as = 2; | |
| required Table table_alias = 3; | |
| } | |
| // ~~~~Expressions~~~~ | |
| message Expr { | |
| oneof expr_oneof { | |
| LiteralValue lit_val = 1; | |
| ComplicatedExpr comp_expr = 2; | |
| } | |
| } | |
| message NumericLiteral { | |
| repeated uint32 hex_digits = 1; | |
| repeated uint32 digits = 2; | |
| required bool decimal_point = 3; | |
| repeated uint32 dec_digits = 4; | |
| repeated uint32 exp_digits = 5; | |
| required bool negative_exp = 6; | |
| } | |
| message LiteralValue { | |
| enum SpecialVal { | |
| VAL_NULL = 0; // using just "NULL" vauses it not to compile. | |
| VAL_TRUE = 1; | |
| VAL_FALSE = 2; | |
| CURRENT_TIME = 3; | |
| CURRENT_DATE = 4; | |
| CURRENT_TIMESTAMP = 5; | |
| } | |
| oneof lit_val_oneof { | |
| int64 num_lit = 1; | |
| string string_lit = 2; | |
| bytes blob_lit = 3; | |
| SpecialVal special_val = 4; | |
| NumericLiteral numeric_lit = 5; | |
| } // If no value, just use int64(1) | |
| } | |
| enum UnaryOperator { | |
| UNOP_MINUS = 1; | |
| UNOP_PLUS = 2; | |
| UNOP_TILDE = 3; | |
| UNOP_NOT = 4; | |
| } | |
| message UnaryExpr { | |
| required UnaryOperator unary_op = 1; | |
| required Expr expr = 2; | |
| } | |
| enum BinaryOperator { | |
| BINOP_CONCAT = 1; // double pipe | |
| BINOP_STAR = 2; | |
| BINOP_SLASH = 3; | |
| BINOP_PERCENT = 4; | |
| BINOP_PLUS = 5; | |
| BINOP_MINUS = 6; | |
| BINOP_LELE = 7; // << | |
| BINOP_GRGR = 8; // >> | |
| BINOP_AMPERSAND = 9; | |
| BINOP_PIPE = 10; | |
| BINOP_LE = 11; | |
| BINOP_LEQ = 12; | |
| BINOP_GR = 13; | |
| BINOP_GREQ = 14; | |
| BINOP_EQ = 15; | |
| BINOP_EQEQ = 16; | |
| BINOP_NOTEQ = 17; | |
| BINOP_LEGR = 18; // <> (not equal) | |
| BINOP_IS = 19; | |
| BINOP_ISNOT = 20; | |
| BINOP_IN = 21; | |
| BINOP_LIKE = 22; | |
| BINOP_GLOB = 23; | |
| BINOP_MATCH = 24; | |
| BINOP_REGEXP = 25; | |
| BINOP_AND = 26; | |
| BINOP_OR = 27; | |
| } | |
| message BinaryExpr { | |
| required Expr lhs = 1; | |
| required BinaryOperator op = 2; | |
| required Expr rhs = 3; | |
| // In FUZZ_FTS3 mode, if |fmt| exists we will use it instead of rhs to | |
| // help generate better MATCH queries. | |
| optional FTS3MatchFormat fmt = 4; | |
| } | |
| // Used to inflate the probability that we get a comparison of a column with an | |
| // expr. This is useful, as an example, for WHERE expressions. | |
| message ExprComparisonHighProbability { | |
| oneof expr_comp_oneof { | |
| ColumnComparison cc = 1; | |
| Expr expr = 2; | |
| } | |
| } | |
| // Special version of expr that only generates predicates with a column on the | |
| // left. | |
| message ColumnComparison { | |
| required ExprSchemaTableColumn col = 1; | |
| required BinaryOperator op = 2; | |
| required Expr expr = 3; | |
| // In FUZZ_FTS3 mode, if |fmt| exists we will use it instead of rhs to | |
| // help generate better MATCH queries. | |
| optional FTS3MatchFormat fmt = 4; | |
| } | |
| message ExprSchemaTableColumn { | |
| optional Schema schema = 1; | |
| optional Table table = 2; | |
| required Column col = 3; | |
| } | |
| // Separate this out to inflate the probability of having a literal value | |
| message ComplicatedExpr { | |
| // Don't want bind-parameter, unless fuzzing sql_bind | |
| oneof complicated_expr_oneof { | |
| ExprSchemaTableColumn expr_stc = 2; | |
| UnaryExpr unary_expr = 3; | |
| BinaryExpr binary_expr = 4; | |
| Fn fn_expr = 5; | |
| ParenthesesExpr par_expr = 6; | |
| CastExpr cast_expr = 7; | |
| CollateExpr collate_expr = 8; | |
| Expr1 expr1 = 9; | |
| ExprNullTests expr_null_tests = 10; | |
| ExprIs expr_is = 11; | |
| ExprBetween expr_between = 12; | |
| ExprIn expr_in = 17; | |
| ExprExists expr_exists = 13; | |
| ExprCase expr_case = 14; | |
| ExprRaiseFn expr_raise = 15; | |
| } | |
| required LiteralValue lit_val = 16; // used if oneof is empty. | |
| } | |
| message ExprRaiseFn { | |
| required bool ignore = 3; | |
| enum RaiseFnEnum { | |
| ROLLBACK = 0; | |
| ABORT = 1; | |
| FAIL = 2; | |
| } | |
| required RaiseFnEnum raise_fn = 1; | |
| required string error_msg = 2; | |
| } | |
| message ExprCase { | |
| optional Expr expr = 1; | |
| required ExprWhenThen when_then = 2; | |
| repeated ExprWhenThen extra_when_thens = 3; | |
| optional Expr else_expr = 4; | |
| } | |
| message ExprWhenThen { | |
| required Expr when_expr = 1; | |
| required Expr then_expr = 2; | |
| } | |
| message ExprExists { | |
| required bool not = 1; | |
| required bool exists = 2; | |
| required Select select = 3; | |
| } | |
| message ExprIn { | |
| required Expr expr = 5; | |
| required bool not = 1; | |
| oneof exprin_oneof { | |
| ExprInParen expr_in_paren = 2; | |
| ExprSchemaTable schema_table = 3; | |
| ExprSchemaTableFn schema_table_fn = 4; | |
| } | |
| } | |
| message ExprSchemaTable { | |
| optional Schema schema_name = 1; | |
| required Table table_name = 2; | |
| } | |
| message ExprSchemaTableFn { | |
| required TableFn table_fn = 2; | |
| // FIXME in the future add more. For now, no exprs. | |
| } | |
| message ExprInParen { | |
| oneof exprin_paren_oneof { | |
| Select select = 1; | |
| ExprList exprs = 2; | |
| } // if zero, can just emit closed parentheses | |
| } | |
| message ExprList { | |
| required Expr expr = 1; | |
| repeated Expr extra_exprs = 2; | |
| } | |
| message Expr1 { | |
| required Expr expr1 = 5; | |
| required bool not = 1; | |
| enum PossibleKeywords { | |
| LIKE = 0; | |
| GLOB = 1; | |
| REGEXP = 2; | |
| MATCH = 3; | |
| } | |
| required PossibleKeywords keyword = 2; | |
| required Expr expr2 = 3; | |
| optional Expr escape_expr = 4; // CORPUS specialize? | |
| } | |
| message ExprNullTests { | |
| required Expr expr = 1; | |
| enum PossibleKeywords { | |
| ISNULL = 0; | |
| NOTNULL = 1; | |
| NOT_NULL = 2; | |
| } | |
| required PossibleKeywords keyword = 2; | |
| } | |
| message ExprIs { | |
| required bool not = 1; | |
| required Expr expr1 = 2; | |
| required Expr expr2 = 3; | |
| } | |
| message ExprBetween { | |
| required bool not = 1; | |
| required Expr expr1 = 2; | |
| required Expr expr2 = 3; | |
| required Expr expr3 = 4; | |
| } | |
| enum CollateType { | |
| COLLATE_BINARY = 1; | |
| COLLATE_NOCASE = 2; | |
| COLLATE_RTRIM = 3; | |
| } | |
| message CollateExpr { | |
| required Expr expr = 1; | |
| required CollateType collate_type = 2; | |
| } | |
| message CastTypeName { | |
| enum CastTypeNameEnum { | |
| BLOB = 0; | |
| TEXT = 1; | |
| REAL = 2; | |
| INTEGER = 3; | |
| NUMERIC = 4; | |
| } | |
| required CastTypeNameEnum type_enum = 1; | |
| } | |
| message CastExpr { | |
| required Expr expr = 1; | |
| required CastTypeName type_name = 2; | |
| } | |
| message ParenthesesExpr { | |
| required Expr expr = 1; | |
| repeated Expr other_exprs = 2; | |
| } | |
| message Fn { | |
| oneof fn_oneof { | |
| SimpleFn simple_fn = 1; | |
| FTS3AuxiliaryFn fts_aux_fn = 2; | |
| DateAndTimeFn dat_fn = 3; | |
| AggregateFn aggregate_fn = 4; | |
| Printf printf = 5; | |
| } | |
| // FIXME in the future: JSON functions. Not used in Chrome. | |
| } | |
| // Aggregate FNs | |
| message AggregateFn { | |
| optional bool count_star = 7; | |
| enum FnName { | |
| AVG = 0; | |
| COUNT = 1; | |
| GROUP_CONCAT = 2; | |
| MAX = 3; | |
| MIN = 4; | |
| SUM = 5; | |
| TOTAL = 6; | |
| } | |
| required FnName fn_name = 6; | |
| required bool distinct = 5; | |
| optional Column col1 = 1; | |
| optional Column col2 = 2; | |
| required Expr expr1 = 3; | |
| optional Expr expr2 = 4; | |
| } | |
| // Date and Time Functions | |
| message DateAndTimeFn { | |
| optional SimpleDateAndTimeFn simple = 1; | |
| required StrftimeFn strftime = 2; | |
| } | |
| message StrftimeFn { | |
| repeated StrftimeFormat fmts = 1; | |
| required TimeString time_string = 2; | |
| repeated TimeModifier modifiers = 3; | |
| } | |
| message StrftimeFormat { | |
| enum Substitution { | |
| D = 0; | |
| F = 1; | |
| H = 2; | |
| J = 3; | |
| M = 4; | |
| S = 5; | |
| W = 6; | |
| Y = 7; | |
| } | |
| required bool lowercase = 1; | |
| optional Substitution subs = 2; | |
| required string bytes = 3; | |
| } | |
| message SimpleDateAndTimeFn { | |
| enum FnName { | |
| DATE = 0; | |
| TIME = 1; | |
| DATETIME = 2; | |
| JULIANDAY = 3; | |
| } | |
| required FnName fn_name = 1; | |
| required TimeString time_string = 2; | |
| repeated TimeModifier modifiers = 3; | |
| } | |
| message HoursStuff { | |
| optional uint32 hh = 1; | |
| optional uint32 mm = 2; | |
| optional uint32 ss = 3; | |
| optional uint32 sss = 4; | |
| } | |
| message TimeString { | |
| optional uint32 yyyy = 1; | |
| optional uint32 mm = 2; | |
| optional uint32 dd = 3; | |
| optional HoursStuff hs = 4; | |
| required bool extra_t = 6; | |
| optional uint32 dddddddddd = 7; | |
| required bool now = 8; | |
| optional string random_bytes = 9; | |
| required bool z = 13; | |
| required bool plus = 14; | |
| optional bool tz_plus = 10; | |
| optional uint32 tz_hh = 11; | |
| optional uint32 tz_mm = 12; | |
| } | |
| message TimeModifier { | |
| enum NumberedModifiers { | |
| DAYS = 0; | |
| HOURS = 1; | |
| MINUTES = 2; | |
| SECONDS = 3; | |
| MONTHS = 4; | |
| YEARS = 5; | |
| } | |
| required uint32 num = 4; | |
| optional uint32 dot_num = 5; | |
| optional NumberedModifiers nm = 1; | |
| enum OtherModifiers { | |
| START_OF_MONTH = 0; | |
| START_OF_YEAR = 1; | |
| START_OF_DAY = 2; | |
| WEEKDAY = 3; | |
| UNIXEPOCH = 4; | |
| LOCALTIME = 5; | |
| UTC = 6; | |
| } | |
| required OtherModifiers om = 2; | |
| required uint32 weekday = 3; | |
| } | |
| // Simple Functions finish | |
| message SimpleFn { | |
| oneof simple_fn_oneof { | |
| ZeroArgFn zero_arg_fn = 1; | |
| OneArgFn one_arg_fn = 2; | |
| TwoArgFn two_arg_fn = 3; | |
| ThreeArgFn three_arg_fn = 4; | |
| VarNumFn varnum_fn = 5; | |
| CharFn char_fn = 6; | |
| } | |
| } | |
| // Zero arguments fn | |
| enum ZeroArgFn { | |
| ZFN_CHANGES = 0; | |
| ZFN_LAST_INSERT_ROWID = 1; | |
| ZFN_RANDOM = 2; | |
| ZFN_SQLITE_SOURCE_ID = 3; | |
| ZFN_SQLITE_VERSION = 4; | |
| ZFN_TOTAL_CHANGES = 5; | |
| } | |
| message OneArgFn { | |
| enum OneArgFnEnum { | |
| ABS = 1; | |
| HEX = 2; | |
| LENGTH = 3; | |
| LIKELY = 4; | |
| LOWER = 5; | |
| LTRIM = 6; | |
| LOAD_EXTENSION = 7; | |
| QUOTE = 8; | |
| ROUND = 9; | |
| RTRIM = 10; | |
| RANDOMBLOB = 11; | |
| SOUNDEX = 12; | |
| SQLITE_COMPILE_OPTION_GET = 13; | |
| SQLITE_COMPILE_OPTION_USED = 14; | |
| SQLITE_OFFSET = 15; | |
| TRIM = 16; | |
| TYPEOF = 17; | |
| UNICODE_ = 18; | |
| UNLIKELY = 19; | |
| UPPER = 20; | |
| ZEROBLOB = 21; | |
| } | |
| required OneArgFnEnum fn_enum = 1; | |
| required Expr arg1 = 2; | |
| } | |
| message TwoArgFn { | |
| enum TwoArgFnEnum { | |
| GLOB = 1; | |
| IFNULL = 2; | |
| INSTR = 3; | |
| LIKE = 4; | |
| LIKELIHOOD = 5; | |
| LOAD_EXTENSION = 6; | |
| LTRIM = 7; | |
| NULLIF = 8; | |
| ROUND = 9; | |
| RTRIM = 10; | |
| SUBSTR = 11; | |
| TRIM = 12; | |
| } | |
| required TwoArgFnEnum fn_enum = 1; | |
| required Expr arg1 = 2; | |
| required Expr arg2 = 3; | |
| } | |
| message ThreeArgFn { | |
| enum ThreeArgFnEnum { | |
| LIKE = 0; | |
| REPLACE = 1; | |
| SUBSTR = 2; | |
| } | |
| required ThreeArgFnEnum fn_enum = 1; | |
| required Expr arg1 = 2; | |
| required Expr arg2 = 3; | |
| required Expr arg3 = 4; | |
| } | |
| // Fns with two args required + an arbitrary number of other args. | |
| message VarNumFn { | |
| enum VarNumFnEnum { | |
| COALESCE = 1; | |
| MAX = 2; | |
| MIN = 3; | |
| } | |
| required VarNumFnEnum fn_enum = 1; | |
| required Expr arg1 = 2; | |
| required Expr arg2 = 3; | |
| repeated Expr other_args = 4; | |
| } | |
| message CharFn { | |
| required uint64 char = 1; | |
| repeated uint64 extra_chars = 2; | |
| } | |
| message Printf { | |
| repeated string strings = 1; | |
| repeated PrintfFormatSpecifier specifiers = 2; | |
| repeated Expr exprs = 3; | |
| } | |
| message PrintfFormatSpecifier { | |
| enum Flags { | |
| MINUS = 0; | |
| PLUS = 1; | |
| SPACE = 2; | |
| ZERO = 3; | |
| HASH = 4; | |
| COMMA = 5; | |
| BANG = 6; | |
| } | |
| repeated Flags flags = 1; | |
| optional uint32 precision = 2; | |
| optional uint32 width = 3; | |
| optional bool width_star = 4; | |
| // The length modifiers make no difference for the sqlite function. | |
| optional uint32 length = 5; | |
| enum SubType { | |
| I = 0; | |
| D = 1; | |
| U = 2; | |
| F = 3; | |
| E = 4; | |
| G = 5; | |
| X = 6; | |
| O = 7; | |
| S = 8; | |
| Z = 9; | |
| C = 10; | |
| P = 11; | |
| N = 12; | |
| Q = 13; | |
| W = 14; | |
| } | |
| optional bool percent = 8; | |
| required SubType sub_type = 6; | |
| required bool lowercase = 7; | |
| } | |
| // Window fns! | |
| // FIXME in the future: this may only be in the result set and the ORDER_BY | |
| // clause of a SELECT statement. | |
| message WindowFnInvocation { | |
| oneof window_fn_oneof { | |
| ZeroArgWinFn zero_arg_fn = 1; | |
| OneArgWinFn one_arg_fn = 2; | |
| NthValueFn nth_value_fn = 4; | |
| MiscWinFn misc_fn = 3; | |
| } | |
| // Used if the above oneof produces zero values. | |
| required ZeroArgWinFn fallback_zero_arg_fn = 5; | |
| // FIXME in the future: may just replace with a WHERE expr. | |
| optional ExprFilter expr_filter = 6; | |
| optional WindowDefn win_defn = 7; | |
| required WindowName win_name = 8; // used only if win_defn above is unused. | |
| } | |
| message WindowDefn { | |
| // FIXME in the future: change to specialized expr | |
| optional ExprList partition_exprs = 1; | |
| optional MultipleOrderingTerm ordering_terms = 2; | |
| optional ExprFrameSpec frame_spec = 3; | |
| } | |
| message ExprFrameSpec { | |
| enum RangeRows { | |
| RANGE = 0; | |
| ROWS = 1; | |
| } | |
| required RangeRows range_rows = 1; | |
| required FrameSpecSubExpr left_expr = 2; | |
| // if this exists, then this is a BETWEEN statement. | |
| optional FrameSpecSubExprRight right_expr = 3; | |
| } | |
| message FrameSpecSubExpr { | |
| enum Which { | |
| UNBOUNDED_PRECEDING = 0; | |
| EXPR_PRECEDING = 1; | |
| CURRENT_ROW = 2; | |
| EXPR_FOLLOWING = 3; | |
| } | |
| required Which which = 1; | |
| // only used if which is EXPR_PRECEDING or EXPR_FOLLOWING | |
| optional Expr expr = 2; // CORPUS specialize? integer? | |
| } | |
| message FrameSpecSubExprRight { | |
| enum Which { | |
| UNBOUNDED_FOLLOWING = 0; | |
| EXPR_PRECEDING = 1; | |
| CURRENT_ROW = 2; | |
| EXPR_FOLLOWING = 3; | |
| } | |
| required Which which = 1; | |
| // only used if which is EXPR_PRECEDING or EXPR_FOLLOWING | |
| optional Expr expr = 2; // CORPUS specialize? integer? | |
| } | |
| message MultipleOrderingTerm { | |
| repeated ExprOrderingTerm terms = 1; | |
| } | |
| message ExprOrderingTerm { | |
| required Expr expr = 1; // CORPUS specialize??? | |
| optional CollateType collate_type = 2; | |
| required AscDesc asc_desc = 3; | |
| } | |
| enum AscDesc { | |
| ASCDESC_NONE = 0; | |
| ASCDESC_ASC = 1; | |
| ASCDESC_DESC = 2; | |
| } | |
| message ExprFilter { | |
| required Expr expr = 1; | |
| } | |
| message ZeroArgWinFn { | |
| enum ZeroArgWinFnEnum { | |
| ROW_NUMBER = 0; | |
| RANK = 1; | |
| DENSE_RANK = 2; | |
| PERCENT_RANK = 3; | |
| CUME_DIST = 4; | |
| } | |
| required ZeroArgWinFnEnum win_fn = 1; | |
| } | |
| message OneArgWinFn { | |
| enum OneArgWinFnEnum { | |
| NTILE = 0; | |
| FIRST_VALUE = 1; | |
| LAST_VALUE = 2; | |
| } | |
| required OneArgWinFnEnum win_fn = 1; | |
| required Expr expr = 2; | |
| } | |
| message NthValueFn { | |
| required Expr expr = 1; | |
| required uint32 row_num = 2; | |
| } | |
| message MiscWinFn { | |
| enum MiscWinFnEnum { | |
| LAG = 0; | |
| LEAD = 1; | |
| } | |
| required MiscWinFnEnum fn = 1; | |
| required Expr expr = 2; | |
| optional uint32 offset = 3; | |
| optional Expr default = 4; // unused if offset non-existent | |
| } | |
| // FIXME in the future: all aggregate functions may be used as window aggregate | |
| // functions! | |
| // Table-valued FNs, including pragma table-valued fns. | |
| enum PragmaFnZeroArgOneResult { | |
| PFN_ZO_APPLICATION_ID = 0; | |
| PFN_ZO_AUTO_VACUUM = 1; | |
| PFN_ZO_AUTOMATIC_INDEX = 2; | |
| PFN_ZO_BUSY_TIMEOUT = 3; | |
| PFN_ZO_CACHE_SIZE = 4; | |
| PFN_ZO_CACHE_SPILL = 5; | |
| PFN_ZO_CELL_SIZE_CHECK = 6; | |
| PFN_ZO_CHECKPOINT_FULL_FSYNC = 7; | |
| PFN_ZO_COLLATION_LIST = 8; | |
| PFN_ZO_COMPILE_OPTIONS = 9; | |
| PFN_ZO_COUNT_CHANGES = 10; | |
| PFN_ZO_DATA_VERSION = 11; | |
| PFN_ZO_DATABASE_LIST = 12; | |
| PFN_ZO_DEFAULT_CACHE_SIZE = 13; | |
| PFN_ZO_DEFER_FOREIGN_KEYS = 14; | |
| PFN_ZO_EMPTY_RESULT_CALLBACKS = 15; | |
| PFN_ZO_ENCODING = 16; | |
| PFN_ZO_FOREIGN_KEY_CHECK = 17; | |
| PFN_ZO_FOREIGN_KEYS = 18; | |
| PFN_ZO_FREELIST_COUNT = 19; | |
| PFN_ZO_FULL_COLUMN_NAMES = 20; | |
| PFN_ZO_FULLFSYNC = 21; | |
| PFN_ZO_FUNCTION_LIST = 22; | |
| PFN_ZO_IGNORE_CHECK_CONSTRAINTS = 23; | |
| PFN_ZO_INTEGRITY_CHECK = 24; | |
| PFN_ZO_JOURNAL_SIZE_LIMIT = 25; | |
| PFN_ZO_LEGACY_ALTER_TABLE = 26; | |
| PFN_ZO_LEGACY_FILE_FORMAT = 27; | |
| PFN_ZO_LOCK_STATUS = 28; | |
| PFN_ZO_LOCKING_MODE = 29; | |
| PFN_ZO_MAX_PAGE_COUNT = 30; | |
| PFN_ZO_MODULE_LIST = 31; | |
| PFN_ZO_PAGE_COUNT = 32; | |
| PFN_ZO_PAGE_SIZE = 33; | |
| PFN_ZO_PRAGMA_LIST = 34; | |
| PFN_ZO_QUERY_ONLY = 35; | |
| PFN_ZO_QUICK_CHECK = 36; | |
| PFN_ZO_READ_UNCOMMITTED = 37; | |
| PFN_ZO_RECURSIVE_TRIGGERS = 38; | |
| PFN_ZO_REVERSE_UNORDERED_SELECTS = 39; | |
| PFN_ZO_SCHEMA_VERSION = 40; | |
| PFN_ZO_SECURE_DELETE = 41; | |
| PFN_ZO_SHORT_COLUMN_NAMES = 42; | |
| PFN_ZO_SOFT_HEAP_LIMIT = 43; | |
| PFN_ZO_SQL_TRACE = 44; | |
| PFN_ZO_STATS = 45; | |
| PFN_ZO_SYNCHRONOUS = 46; | |
| PFN_ZO_TEMP_STORE = 47; | |
| PFN_ZO_THREADS = 48; | |
| PFN_ZO_USER_VERSION = 49; | |
| // omit vdbe_* debug pragmas | |
| PFN_ZO_WRITEABLE_SCHEMA = 50; | |
| } | |
| message TableFn { | |
| required PragmaFnZeroArgOneResult no_arg_one_result = 10; | |
| oneof pragma_fn_oneof { | |
| Table foreign_key_list = 1; | |
| Index index_info = 2; | |
| Table index_list = 3; | |
| Index index_xinfo = 4; | |
| uint32 integrity_check = 5; | |
| uint32 optimize = 6; | |
| uint32 quick_check = 7; | |
| Table table_info = 8; | |
| Table table_xinfo = 9; | |
| } | |
| } |