mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 02:50:46 -06:00
177 lines
12 KiB
C++
177 lines
12 KiB
C++
#include "SqlUiLexer.h"
|
|
#include "Qsci/qsciapis.h"
|
|
|
|
SqlUiLexer::SqlUiLexer(QObject* parent) :
|
|
QsciLexerSQL(parent)
|
|
{
|
|
// Setup auto completion
|
|
autocompleteApi = new QsciAPIs(this);
|
|
setupAutoCompletion();
|
|
autocompleteApi->prepare();
|
|
|
|
// Setup folding
|
|
setFoldComments(true);
|
|
setFoldCompact(false);
|
|
}
|
|
|
|
void SqlUiLexer::setupAutoCompletion()
|
|
{
|
|
// Set keywords
|
|
QStringList keywordPatterns;
|
|
keywordPatterns
|
|
// Keywords
|
|
<< "ABORT" << "ACTION" << "ADD" << "AFTER" << "ALL"
|
|
<< "ALTER" << "ANALYZE" << "AND" << "AS" << "ASC"
|
|
<< "ATTACH" << "AUTOINCREMENT" << "BEFORE" << "BEGIN" << "BETWEEN"
|
|
<< "BY" << "CASCADE" << "CASE" << "CAST" << "CHECK"
|
|
<< "COLLATE" << "COLUMN" << "COMMIT" << "CONFLICT" << "CONSTRAINT"
|
|
<< "CREATE" << "CROSS" << "CURRENT_DATE" << "CURRENT_TIME" << "CURRENT_TIMESTAMP"
|
|
<< "DATABASE" << "DEFAULT" << "DEFERRABLE" << "DEFERRED" << "DELETE"
|
|
<< "DESC" << "DETACH" << "DISTINCT" << "DROP" << "EACH"
|
|
<< "ELSE" << "END" << "ESCAPE" << "EXCEPT" << "EXCLUSIVE"
|
|
<< "EXISTS" << "EXPLAIN" << "FAIL" << "FOR" << "FOREIGN"
|
|
<< "FROM" << "FULL" << "GLOB" << "GROUP" << "HAVING"
|
|
<< "IF" << "IGNORE" << "IMMEDIATE" << "IN" << "INDEX"
|
|
<< "INDEXED" << "INITIALLY" << "INNER" << "INSERT" << "INSTEAD"
|
|
<< "INTERSECT" << "INTO" << "IS" << "ISNULL" << "JOIN"
|
|
<< "KEY" << "LEFT" << "LIKE" << "LIMIT" << "MATCH"
|
|
<< "NATURAL" << "NO" << "NOT" << "NOTNULL" << "NULL"
|
|
<< "OF" << "OFFSET" << "ON" << "OR" << "ORDER"
|
|
<< "OUTER" << "PLAN" << "PRAGMA" << "PRIMARY" << "QUERY"
|
|
<< "RAISE" << "RECURSIVE" << "REFERENCES" << "REGEXP" << "REINDEX" << "RELEASE"
|
|
<< "RENAME" << "REPLACE" << "RESTRICT" << "RIGHT" << "ROLLBACK"
|
|
<< "ROW" << "SAVEPOINT" << "SELECT" << "SET" << "TABLE"
|
|
<< "TEMP" << "TEMPORARY" << "THEN" << "TO" << "TRANSACTION"
|
|
<< "TRIGGER" << "UNION" << "UNIQUE" << "UPDATE" << "USING"
|
|
<< "VACUUM" << "VALUES" << "VIEW" << "VIRTUAL" << "WHEN"
|
|
<< "WHERE" << "WITH" << "WITHOUT"
|
|
// Data types
|
|
<< "INT" << "INTEGER" << "REAL" << "TEXT" << "BLOB" << "NUMERIC" << "CHAR";
|
|
foreach(const QString& keyword, keywordPatterns)
|
|
{
|
|
autocompleteApi->add(keyword + "?" + QString::number(ApiCompleterIconIdKeyword));
|
|
autocompleteApi->add(keyword.toLower() + "?" + QString::number(ApiCompleterIconIdKeyword));
|
|
}
|
|
|
|
// Functions
|
|
QStringList functionPatterns;
|
|
functionPatterns
|
|
// Core functions
|
|
<< "abs" + tr("(X) The abs(X) function returns the absolute value of the numeric argument X.")
|
|
<< "changes" + tr("() The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement.")
|
|
<< "char" + tr("(X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. ")
|
|
<< "coalesce" + tr("(X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL")
|
|
<< "glob" + tr("(X,Y) The glob(X,Y) function is equivalent to the expression \"Y GLOB X\".")
|
|
<< "ifnull" + tr("(X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL.")
|
|
<< "instr" + tr("(X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X.")
|
|
<< "hex" + tr("(X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob.")
|
|
<< "last_insert_rowid" + tr("() The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function.")
|
|
<< "length" + tr("(X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character.")
|
|
<< "like" + tr("(X,Y) The like() function is used to implement the \"Y LIKE X\" expression.")
|
|
<< "like" + tr("(X,Y,Z) The like() function is used to implement the \"Y LIKE X ESCAPE Z\" expression.")
|
|
<< "load_extension" + tr("(X) The load_extension(X) function loads SQLite extensions out of the shared library file named X.")
|
|
<< "load_extension" + tr("(X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y.")
|
|
<< "lower" + tr("(X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case.")
|
|
<< "ltrim" + tr("(X) ltrim(X) removes spaces from the left side of X.")
|
|
<< "ltrim" + tr("(X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X.")
|
|
<< "max" + tr("(X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL.")
|
|
<< "min" + tr("(X,Y,...) The multi-argument min() function returns the argument with the minimum value.")
|
|
<< "nullif" + tr("(X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same.")
|
|
<< "printf" + tr("(FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library.")
|
|
<< "quote" + tr("(X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement.")
|
|
<< "random" + tr("() The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807.")
|
|
<< "randomblob" + tr("(N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes.")
|
|
<< "replace" + tr("(X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X.")
|
|
<< "round" + tr("(X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point.")
|
|
<< "round" + tr("(X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point.")
|
|
<< "rtrim" + tr("(X) rtrim(X) removes spaces from the right side of X.")
|
|
<< "rtrim" + tr("(X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X.")
|
|
<< "soundex" + tr("(X) The soundex(X) function returns a string that is the soundex encoding of the string X.")
|
|
<< "substr" + tr("(X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th.")
|
|
<< "substr" + tr("(X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long.")
|
|
<< "total_changes" + tr("() The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened.")
|
|
<< "trim" + tr("(X) trim(X) removes spaces from both ends of X.")
|
|
<< "trim" + tr("(X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X.")
|
|
<< "typeof" + tr("(X) The typeof(X) function returns a string that indicates the datatype of the expression X.")
|
|
<< "unicode" + tr("(X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X.")
|
|
<< "upper" + tr("(X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent.")
|
|
<< "zeroblob" + tr("(N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00.")
|
|
// Date and time functions
|
|
<< "date" + tr("(timestring,modifier,modifier,...)")
|
|
<< "time" + tr("(timestring,modifier,modifier,...)")
|
|
<< "datetime" + tr("(timestring,modifier,modifier,...)")
|
|
<< "julianday" + tr("(timestring,modifier,modifier,...)")
|
|
<< "strftime" + tr("(format,timestring,modifier,modifier,...)")
|
|
// Aggregate functions
|
|
<< "avg" + tr("(X) The avg() function returns the average value of all non-NULL X within a group.")
|
|
<< "count" + tr("(X) The count(X) function returns a count of the number of times that X is not NULL in a group.")
|
|
<< "group_concat" + tr("(X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X.")
|
|
<< "group_concat" + tr("(X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X.")
|
|
<< "max" + tr("(X) The max() aggregate function returns the maximum value of all values in the group.")
|
|
<< "min" + tr("(X) The min() aggregate function returns the minimum non-NULL value of all values in the group.")
|
|
<< "sum" + tr("(X) The sum() and total() aggregate functions return sum of all non-NULL values in the group.")
|
|
<< "total" + tr("(X) The sum() and total() aggregate functions return sum of all non-NULL values in the group.");
|
|
|
|
listFunctions.clear();
|
|
foreach(const QString& keyword, functionPatterns)
|
|
{
|
|
QString fn = keyword.left(keyword.indexOf('('));
|
|
QString descr = keyword.mid(keyword.indexOf('('));
|
|
|
|
autocompleteApi->add(fn + "?" + QString::number(ApiCompleterIconIdFunction) + descr);
|
|
autocompleteApi->add(fn.toUpper() + "?" + QString::number(ApiCompleterIconIdFunction) + descr);
|
|
|
|
// Store all function names in order to highlight them in a different colour
|
|
listFunctions.append(fn);
|
|
}
|
|
}
|
|
|
|
void SqlUiLexer::setTableNames(const TablesAndColumnsMap& tables)
|
|
{
|
|
// Update list for auto completion
|
|
autocompleteApi->clear();
|
|
listTables.clear();
|
|
setupAutoCompletion();
|
|
for(TablesAndColumnsMap::ConstIterator it=tables.constBegin();it!=tables.constEnd();++it)
|
|
{
|
|
foreach(const QString& field, it.value())
|
|
autocompleteApi->add(it.key() + "?" + QString::number(SqlUiLexer::ApiCompleterIconIdTable) + "." +
|
|
field + "?" + QString::number(SqlUiLexer::ApiCompleterIconIdColumn));
|
|
|
|
// Store the table name list in order to highlight them in a different colour
|
|
listTables.append(it.key());
|
|
}
|
|
autocompleteApi->prepare();
|
|
}
|
|
|
|
const char* SqlUiLexer::keywords(int set) const
|
|
{
|
|
// Function and table names are generated automatically but need to be returned to the calling functions.
|
|
// In order to not have them deleted after this function ends they are stored as static variables. Because
|
|
// the functions list doesn't change after the first call it's initialised here whereas the tables list, which
|
|
// can change, is updated for each call
|
|
static std::string functions = listFunctions.join(" ").toUtf8().constData();
|
|
static std::string tables;
|
|
|
|
if(set == 6) // This corresponds to the QsciLexerSQL::KeywordSet6 style in SqlTextEdit
|
|
{
|
|
tables = listTables.join(" ").toLower().toUtf8().constData();
|
|
return tables.c_str();
|
|
} else if(set == 7) { // This corresponds to the QsciLexerSQL::KeywordSet7 style in SqlTextEdit
|
|
return functions.c_str();
|
|
} else {
|
|
// For all other keyword sets simply call the parent implementation
|
|
return QsciLexerSQL::keywords(set);
|
|
}
|
|
}
|
|
|
|
QStringList SqlUiLexer::autoCompletionWordSeparators() const
|
|
{
|
|
// The only word separator for auto completion in SQL is "." as in "tablename.columnname".
|
|
// Because this isn't implemented in the default QScintilla SQL lexer for some reason we add it here.
|
|
|
|
QStringList wl;
|
|
wl << ".";
|
|
return wl;
|
|
}
|