mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 11:00:44 -06:00
Improve escpaing support
When generating SQL statements properly escape all identifiers, even those containing backticks which apparently are allowed inside identifiers in SQLite. See issue #387.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "ColumnDisplayFormatDialog.h"
|
||||
#include "ui_ColumnDisplayFormatDialog.h"
|
||||
#include "sqlitetypes.h"
|
||||
|
||||
ColumnDisplayFormatDialog::ColumnDisplayFormatDialog(const QString& colname, QString current_format, QWidget* parent)
|
||||
: QDialog(parent),
|
||||
@@ -56,21 +57,21 @@ void ColumnDisplayFormatDialog::updateSqlCode()
|
||||
QString format = ui->comboDisplayFormat->itemData(ui->comboDisplayFormat->currentIndex()).toString();
|
||||
#endif
|
||||
if(format == "default")
|
||||
ui->editDisplayFormat->setText("`" + column_name + "`");
|
||||
ui->editDisplayFormat->setText(sqlb::escapeIdentifier(column_name));
|
||||
else if(format == "lower")
|
||||
ui->editDisplayFormat->setText("lower(`" + column_name + "`)");
|
||||
ui->editDisplayFormat->setText("lower(" + sqlb::escapeIdentifier(column_name) + ")");
|
||||
else if(format == "upper")
|
||||
ui->editDisplayFormat->setText("upper(`" + column_name + "`)");
|
||||
ui->editDisplayFormat->setText("upper(" + sqlb::escapeIdentifier(column_name) + ")");
|
||||
else if(format == "epoch")
|
||||
ui->editDisplayFormat->setText("datetime(`" + column_name + "`, 'unixepoch')");
|
||||
ui->editDisplayFormat->setText("datetime(" + sqlb::escapeIdentifier(column_name) + ", 'unixepoch')");
|
||||
else if(format == "julian")
|
||||
ui->editDisplayFormat->setText("datetime(`" + column_name + "`)");
|
||||
ui->editDisplayFormat->setText("datetime(" + sqlb::escapeIdentifier(column_name) + ")");
|
||||
else if(format == "round")
|
||||
ui->editDisplayFormat->setText("round(`" + column_name + "`)");
|
||||
ui->editDisplayFormat->setText("round(" + sqlb::escapeIdentifier(column_name) + ")");
|
||||
else if(format == "hex")
|
||||
ui->editDisplayFormat->setText("printf('%x', `" + column_name + "`)");
|
||||
ui->editDisplayFormat->setText("printf('%x', " + sqlb::escapeIdentifier(column_name) + ")");
|
||||
else if(format == "octal")
|
||||
ui->editDisplayFormat->setText("printf('%o', `" + column_name + "`)");
|
||||
ui->editDisplayFormat->setText("printf('%o', " + sqlb::escapeIdentifier(column_name) + ")");
|
||||
else if(format == "exponent")
|
||||
ui->editDisplayFormat->setText("printf('%e', `" + column_name + "`)");
|
||||
ui->editDisplayFormat->setText("printf('%e', " + sqlb::escapeIdentifier(column_name) + ")");
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ void CreateIndexDialog::tableChanged(const QString& new_table)
|
||||
void CreateIndexDialog::checkInput()
|
||||
{
|
||||
bool valid = true;
|
||||
if(ui->editIndexName->text().isEmpty() || ui->editIndexName->text().contains("`"))
|
||||
if(ui->editIndexName->text().isEmpty())
|
||||
valid = false;
|
||||
|
||||
int num_columns = 0;
|
||||
@@ -74,17 +74,17 @@ void CreateIndexDialog::checkInput()
|
||||
|
||||
void CreateIndexDialog::accept()
|
||||
{
|
||||
QString sql = QString("CREATE %1 INDEX `%2` ON `%3` (")
|
||||
QString sql = QString("CREATE %1 INDEX %2 ON %3 (")
|
||||
.arg(ui->checkIndexUnique->isChecked() ? "UNIQUE" : "")
|
||||
.arg(ui->editIndexName->text())
|
||||
.arg(ui->comboTableName->currentText());
|
||||
.arg(sqlb::escapeIdentifier(ui->editIndexName->text()))
|
||||
.arg(sqlb::escapeIdentifier(ui->comboTableName->currentText()));
|
||||
|
||||
for(int i=0; i < ui->tableIndexColumns->rowCount(); ++i)
|
||||
{
|
||||
if(ui->tableIndexColumns->item(i, 1)->data(Qt::CheckStateRole) == Qt::Checked)
|
||||
{
|
||||
sql.append(QString("`%1` %2,")
|
||||
.arg(ui->tableIndexColumns->item(i, 0)->text())
|
||||
sql.append(QString("%1 %2,")
|
||||
.arg(sqlb::escapeIdentifier(ui->tableIndexColumns->item(i, 0)->text()))
|
||||
.arg(qobject_cast<QComboBox*>(ui->tableIndexColumns->cellWidget(i, 2))->currentText()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ QMimeData* DbStructureModel::mimeData(const QModelIndexList& indices) const
|
||||
tableModel.setTable(data(index.sibling(index.row(), 0), Qt::DisplayRole).toString());
|
||||
for(int i=0; i < tableModel.rowCount(); ++i)
|
||||
{
|
||||
QString insertStatement = "INSERT INTO `" + data(index.sibling(index.row(), 0), Qt::DisplayRole).toString() + "` VALUES(";
|
||||
QString insertStatement = "INSERT INTO " + sqlb::escapeIdentifier(data(index.sibling(index.row(), 0), Qt::DisplayRole).toString()) + " VALUES(";
|
||||
for(int j=1; j < tableModel.columnCount(); ++j)
|
||||
insertStatement += QString("'%1',").arg(tableModel.data(tableModel.index(i, j)).toString());
|
||||
insertStatement.chop(1);
|
||||
|
||||
@@ -16,7 +16,7 @@ EditTableDialog::EditTableDialog(DBBrowserDB* db, const QString& tableName, bool
|
||||
curTable(tableName),
|
||||
m_table(tableName),
|
||||
m_bNewTable(createTable),
|
||||
m_sRestorePointName(QString("edittable_%1_save_%2").arg(curTable).arg(QDateTime::currentMSecsSinceEpoch()))
|
||||
m_sRestorePointName(sqlb::escapeIdentifier(QString("edittable_%1_save_%2").arg(curTable).arg(QDateTime::currentMSecsSinceEpoch())))
|
||||
{
|
||||
// Create UI
|
||||
ui->setupUi(this);
|
||||
@@ -173,7 +173,7 @@ void EditTableDialog::checkInput()
|
||||
{
|
||||
QString normTableName = ui->editTableName->text().trimmed();
|
||||
bool valid = true;
|
||||
if(normTableName.isEmpty() || normTableName.contains("`"))
|
||||
if(normTableName.isEmpty())
|
||||
valid = false;
|
||||
if(ui->treeWidget->topLevelItemCount() == 0)
|
||||
valid = false;
|
||||
@@ -272,7 +272,10 @@ void EditTableDialog::itemChanged(QTreeWidgetItem *item, int column)
|
||||
// we need to check for this case and cancel here. Maybe we can think of some way to modify the INSERT INTO ... SELECT statement
|
||||
// to at least replace all troublesome NULL values by the default value
|
||||
SqliteTableModel m(this, pdb);
|
||||
m.setQuery(QString("SELECT COUNT(`%1`) FROM `%2` WHERE `%3` IS NULL;").arg(pdb->getObjectByName(curTable).table.rowidColumn()).arg(curTable).arg(field->name()));
|
||||
m.setQuery(QString("SELECT COUNT(%1) FROM %2 WHERE %3 IS NULL;")
|
||||
.arg(sqlb::escapeIdentifier(pdb->getObjectByName(curTable).table.rowidColumn()))
|
||||
.arg(sqlb::escapeIdentifier(curTable))
|
||||
.arg(sqlb::escapeIdentifier(field->name())));
|
||||
if(m.data(m.index(0, 0)).toInt() > 0)
|
||||
{
|
||||
// There is a NULL value, so print an error message, uncheck the combobox, and return here
|
||||
@@ -296,7 +299,10 @@ void EditTableDialog::itemChanged(QTreeWidgetItem *item, int column)
|
||||
if(!m_bNewTable)
|
||||
{
|
||||
SqliteTableModel m(this, pdb);
|
||||
m.setQuery(QString("SELECT COUNT(*) FROM `%1` WHERE `%2` <> CAST(`%3` AS INTEGER);").arg(curTable).arg(field->name()).arg(field->name()));
|
||||
m.setQuery(QString("SELECT COUNT(*) FROM %1 WHERE %2 <> CAST(%3 AS INTEGER);")
|
||||
.arg(sqlb::escapeIdentifier(curTable))
|
||||
.arg(sqlb::escapeIdentifier(field->name()))
|
||||
.arg(sqlb::escapeIdentifier(field->name())));
|
||||
if(m.data(m.index(0, 0)).toInt() > 0)
|
||||
{
|
||||
// There is a non-integer value, so print an error message, uncheck the combobox, and return here
|
||||
@@ -337,14 +343,14 @@ void EditTableDialog::itemChanged(QTreeWidgetItem *item, int column)
|
||||
{
|
||||
// Because our renameColumn() function fails when setting a column to unique when it already contains the same values
|
||||
SqliteTableModel m(this, pdb);
|
||||
m.setQuery(QString("SELECT COUNT(`%2`) FROM `%1`;").arg(curTable).arg(field->name()));
|
||||
m.setQuery(QString("SELECT COUNT(%2) FROM %1;").arg(sqlb::escapeIdentifier(curTable)).arg(sqlb::escapeIdentifier(field->name())));
|
||||
int rowcount = m.data(m.index(0, 0)).toInt();
|
||||
m.setQuery(QString("SELECT COUNT(distinct `%2`) FROM `%1`;").arg(curTable).arg(field->name()));
|
||||
m.setQuery(QString("SELECT COUNT(DISTINCT %2) FROM %1;").arg(sqlb::escapeIdentifier(curTable)).arg(sqlb::escapeIdentifier(field->name())));
|
||||
int uniquecount = m.data(m.index(0, 0)).toInt();
|
||||
if(rowcount != uniquecount)
|
||||
{
|
||||
// There is a NULL value, so print an error message, uncheck the combobox, and return here
|
||||
QMessageBox::information(this, qApp->applicationName(), tr("Column `%1` has no unique data.\n").arg(field->name())
|
||||
QMessageBox::information(this, qApp->applicationName(), tr("Column '%1'' has no unique data.\n").arg(field->name())
|
||||
+ tr("This makes it impossible to set this flag. Please change the table data first."));
|
||||
item->setCheckState(column, Qt::Unchecked);
|
||||
return;
|
||||
|
||||
@@ -210,7 +210,7 @@ void ExportCsvDialog::accept()
|
||||
{
|
||||
// if we are called from execute sql tab, query is already set
|
||||
// and we only export 1 select
|
||||
QString sQuery = QString("SELECT * from `%1`;").arg(selectedItems.at(i)->text());
|
||||
QString sQuery = QString("SELECT * FROM %1;").arg(sqlb::escapeIdentifier(selectedItems.at(i)->text()));
|
||||
|
||||
exportQuery(sQuery, filenames.at(i));
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ void ImportCsvDialog::accept()
|
||||
it != csv.csv().end();
|
||||
++it)
|
||||
{
|
||||
QString sql = QString("INSERT INTO `%1` VALUES(").arg(ui->editName->text());
|
||||
QString sql = QString("INSERT INTO %1 VALUES(").arg(sqlb::escapeIdentifier(ui->editName->text()));
|
||||
|
||||
QStringList insertlist;
|
||||
for(QStringList::const_iterator jt = it->begin(); jt != it->end(); ++jt)
|
||||
@@ -321,7 +321,7 @@ void ImportCsvDialog::updatePreview()
|
||||
void ImportCsvDialog::checkInput()
|
||||
{
|
||||
bool valid = true;
|
||||
if(ui->editName->text().isEmpty() || ui->editName->text().contains("`"))
|
||||
if(ui->editName->text().isEmpty())
|
||||
valid = false;
|
||||
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid);
|
||||
|
||||
@@ -348,7 +348,7 @@ void MainWindow::populateTable(const QString& tablename)
|
||||
v.push_back(format);
|
||||
only_defaults = false;
|
||||
} else {
|
||||
v.push_back("`" + db.getObjectByName(tablename).table.fields().at(i)->name() + "`");
|
||||
v.push_back(sqlb::escapeIdentifier(db.getObjectByName(tablename).table.fields().at(i)->name()));
|
||||
}
|
||||
}
|
||||
if(only_defaults)
|
||||
@@ -652,7 +652,7 @@ void MainWindow::deleteObject()
|
||||
QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape) == QMessageBox::Yes)
|
||||
{
|
||||
// Delete the table
|
||||
QString statement = QString("DROP %1 `%2`;").arg(type.toUpper()).arg(table);
|
||||
QString statement = QString("DROP %1 %2;").arg(type.toUpper()).arg(sqlb::escapeIdentifier(table));
|
||||
if(!db.executeSQL( statement))
|
||||
{
|
||||
QString error = tr("Error: could not delete the %1. Message from database engine:\n%2").arg(type).arg(db.lastErrorMessage);
|
||||
|
||||
@@ -100,7 +100,7 @@ void SqlExecutionArea::saveAsView()
|
||||
return;
|
||||
|
||||
// Create the view
|
||||
if(db->executeSQL(QString("CREATE VIEW `%1` AS %2;").arg(name).arg(model->query())))
|
||||
if(db->executeSQL(QString("CREATE VIEW %1 AS %2;").arg(sqlb::escapeIdentifier(name)).arg(model->query())))
|
||||
QMessageBox::information(this, qApp->applicationName(), tr("View successfully created."));
|
||||
else
|
||||
QMessageBox::warning(this, qApp->applicationName(), tr("Error creating view: %1").arg(db->lastErrorMessage));
|
||||
|
||||
@@ -55,7 +55,7 @@ void VacuumDialog::accept()
|
||||
// No, so execute a vacuum command for each selected object individually
|
||||
QList<QTreeWidgetItem*> selection = ui->treeSelectedObjects->selectedItems();
|
||||
foreach(QTreeWidgetItem* item, selection)
|
||||
db->executeSQL(QString("VACUUM `%1`;").arg(item->text(0)), false);
|
||||
db->executeSQL(QString("VACUUM %1;").arg(sqlb::escapeIdentifier(item->text(0))), false);
|
||||
}
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
@@ -164,14 +164,14 @@ bool DBBrowserDB::attach(const QString& filename, QString attach_as)
|
||||
// Attach database
|
||||
QString key;
|
||||
if(cipher) key = cipher->password();
|
||||
if(!executeSQL(QString("ATTACH '%1' AS `%2` KEY '%3'").arg(filename).arg(attach_as).arg(key), false))
|
||||
if(!executeSQL(QString("ATTACH '%1' AS %2 KEY '%3'").arg(filename).arg(sqlb::escapeIdentifier(attach_as)).arg(key), false))
|
||||
{
|
||||
QMessageBox::warning(0, qApp->applicationName(), lastErrorMessage);
|
||||
return false;
|
||||
}
|
||||
if(cipher && cipher->pageSize() != 1024)
|
||||
{
|
||||
if(!executeSQL(QString("PRAGMA `%1`.cipher_page_size = %2").arg(attach_as).arg(cipher->pageSize()), false))
|
||||
if(!executeSQL(QString("PRAGMA %1.cipher_page_size = %2").arg(sqlb::escapeIdentifier(attach_as)).arg(cipher->pageSize()), false))
|
||||
{
|
||||
QMessageBox::warning(0, qApp->applicationName(), lastErrorMessage);
|
||||
return false;
|
||||
@@ -179,7 +179,7 @@ bool DBBrowserDB::attach(const QString& filename, QString attach_as)
|
||||
}
|
||||
#else
|
||||
// Attach database
|
||||
if(!executeSQL(QString("ATTACH '%1' AS `%2`").arg(filename).arg(attach_as), false))
|
||||
if(!executeSQL(QString("ATTACH '%1' AS %2").arg(filename).arg(sqlb::escapeIdentifier(attach_as)), false))
|
||||
{
|
||||
QMessageBox::warning(0, qApp->applicationName(), lastErrorMessage);
|
||||
return false;
|
||||
@@ -453,7 +453,7 @@ bool DBBrowserDB::dump(const QString& filename,
|
||||
// get columns
|
||||
QStringList cols(it->table.fieldNames());
|
||||
|
||||
QString sQuery = QString("SELECT * FROM `%1`;").arg(it->getTableName());
|
||||
QString sQuery = QString("SELECT * FROM %1;").arg(sqlb::escapeIdentifier(it->getTableName()));
|
||||
QByteArray utf8Query = sQuery.toUtf8();
|
||||
sqlite3_stmt *stmt;
|
||||
QString lineSep(QString(")%1\n").arg(insertNewSyntx?',':';'));
|
||||
@@ -470,7 +470,7 @@ bool DBBrowserDB::dump(const QString& filename,
|
||||
|
||||
if (!insertNewSyntx || !counter)
|
||||
{
|
||||
stream << "INSERT INTO `" << it->getTableName() << '`';
|
||||
stream << "INSERT INTO " << sqlb::escapeIdentifier(it->getTableName());
|
||||
if (insertColNames)
|
||||
stream << " (" << cols.join(",") << ")";
|
||||
stream << " VALUES (";
|
||||
@@ -650,7 +650,11 @@ bool DBBrowserDB::executeMultiSQL(const QString& statement, bool dirty, bool log
|
||||
|
||||
bool DBBrowserDB::getRow(const QString& sTableName, const QString& rowid, QList<QByteArray>& rowdata)
|
||||
{
|
||||
QString sQuery = QString("SELECT * FROM `%1` WHERE `%2`='%3';").arg(sTableName).arg(getObjectByName(sTableName).table.rowidColumn()).arg(rowid);
|
||||
QString sQuery = QString("SELECT * FROM %1 WHERE %2='%3';")
|
||||
.arg(sqlb::escapeIdentifier(sTableName))
|
||||
.arg(sqlb::escapeIdentifier(getObjectByName(sTableName).table.rowidColumn()))
|
||||
.arg(rowid);
|
||||
|
||||
QByteArray utf8Query = sQuery.toUtf8();
|
||||
sqlite3_stmt *stmt;
|
||||
bool ret = false;
|
||||
@@ -684,7 +688,7 @@ bool DBBrowserDB::getRow(const QString& sTableName, const QString& rowid, QList<
|
||||
|
||||
QString DBBrowserDB::max(const sqlb::Table& t, sqlb::FieldPtr field) const
|
||||
{
|
||||
QString sQuery = QString("SELECT MAX(CAST(`%2` AS INTEGER)) FROM `%1`;").arg(t.name()).arg(field->name());
|
||||
QString sQuery = QString("SELECT MAX(CAST(%2 AS INTEGER)) FROM %1;").arg(sqlb::escapeIdentifier(t.name())).arg(sqlb::escapeIdentifier(field->name()));
|
||||
QByteArray utf8Query = sQuery.toUtf8();
|
||||
sqlite3_stmt *stmt;
|
||||
QString ret = "0";
|
||||
@@ -708,7 +712,7 @@ QString DBBrowserDB::max(const sqlb::Table& t, sqlb::FieldPtr field) const
|
||||
|
||||
QString DBBrowserDB::emptyInsertStmt(const sqlb::Table& t, const QString& pk_value) const
|
||||
{
|
||||
QString stmt = QString("INSERT INTO `%1`").arg(t.name());
|
||||
QString stmt = QString("INSERT INTO %1").arg(sqlb::escapeIdentifier(t.name()));
|
||||
|
||||
QStringList vals;
|
||||
QStringList fields;
|
||||
@@ -749,12 +753,14 @@ QString DBBrowserDB::emptyInsertStmt(const sqlb::Table& t, const QString& pk_val
|
||||
}
|
||||
|
||||
if(fields.empty())
|
||||
stmt.append(" DEFAULT VALUES;");
|
||||
else
|
||||
{
|
||||
stmt.append("(`");
|
||||
stmt.append(fields.join("`,`"));
|
||||
stmt.append("`) VALUES (");
|
||||
stmt.append(" DEFAULT VALUES;");
|
||||
} else {
|
||||
stmt.append("(");
|
||||
foreach(const QString& f, fields)
|
||||
stmt.append(sqlb::escapeIdentifier(f) + ",");
|
||||
stmt.chop(1);
|
||||
stmt.append(") VALUES (");
|
||||
stmt.append(vals.join(","));
|
||||
stmt.append(");");
|
||||
}
|
||||
@@ -797,7 +803,10 @@ bool DBBrowserDB::deleteRecord(const QString& table, const QString& rowid)
|
||||
if (!isOpen()) return false;
|
||||
bool ok = false;
|
||||
|
||||
QString statement = QString("DELETE FROM `%1` WHERE `%2`='%3';").arg(table).arg(getObjectByName(table).table.rowidColumn()).arg(rowid);
|
||||
QString statement = QString("DELETE FROM %1 WHERE %2='%3';")
|
||||
.arg(sqlb::escapeIdentifier(table))
|
||||
.arg(sqlb::escapeIdentifier(getObjectByName(table).table.rowidColumn()))
|
||||
.arg(rowid);
|
||||
if(executeSQL(statement))
|
||||
ok = true;
|
||||
else
|
||||
@@ -810,7 +819,11 @@ bool DBBrowserDB::updateRecord(const QString& table, const QString& column, cons
|
||||
{
|
||||
if (!isOpen()) return false;
|
||||
|
||||
QString sql = QString("UPDATE `%1` SET `%2`=? WHERE `%3`='%4';").arg(table).arg(column).arg(getObjectByName(table).table.rowidColumn()).arg(rowid);
|
||||
QString sql = QString("UPDATE %1 SET %2=? WHERE %3='%4';")
|
||||
.arg(sqlb::escapeIdentifier(table))
|
||||
.arg(sqlb::escapeIdentifier(column))
|
||||
.arg(sqlb::escapeIdentifier(getObjectByName(table).table.rowidColumn()))
|
||||
.arg(rowid);
|
||||
|
||||
logSQL(sql, kLogMsg_App);
|
||||
setRestorePoint();
|
||||
@@ -865,7 +878,7 @@ bool DBBrowserDB::createTable(const QString& name, const sqlb::FieldVector& stru
|
||||
|
||||
bool DBBrowserDB::addColumn(const QString& tablename, const sqlb::FieldPtr& field)
|
||||
{
|
||||
QString sql = QString("ALTER TABLE `%1` ADD COLUMN %2").arg(tablename).arg(field->toString());
|
||||
QString sql = QString("ALTER TABLE %1 ADD COLUMN %2").arg(sqlb::escapeIdentifier(tablename)).arg(field->toString());
|
||||
|
||||
// Execute it and update the schema
|
||||
bool result = executeSQL(sql);
|
||||
@@ -880,9 +893,9 @@ bool DBBrowserDB::renameColumn(const QString& tablename, const QString& name, sq
|
||||
// function can be changed to executing something like this:
|
||||
//QString sql;
|
||||
//if(to.isNull())
|
||||
// sql = QString("ALTER TABLE `%1` DROP COLUMN `%2`;").arg(table).arg(column);
|
||||
// sql = QString("ALTER TABLE %1 DROP COLUMN %2;").arg(sqlb::escapeIdentifier(table)).arg(sqlb::escapeIdentifier(column));
|
||||
//else
|
||||
// sql = QString("ALTER TABLE `%1` MODIFY `%2` %3").arg(tablename).arg(to).arg(type); // This is wrong...
|
||||
// sql = QString("ALTER TABLE %1 MODIFY %2 %3").arg(sqlb::escapeIdentifier(tablename)).arg(sqlb::escapeIdentifier(to)).arg(type); // This is wrong...
|
||||
//return executeSQL(sql);
|
||||
|
||||
// Collect information on the current DB layout
|
||||
@@ -925,7 +938,7 @@ bool DBBrowserDB::renameColumn(const QString& tablename, const QString& name, sq
|
||||
newSchema.removeField(name);
|
||||
|
||||
for(int i=0;i<newSchema.fields().count();++i)
|
||||
select_cols.append(QString("`%1`,").arg(newSchema.fields().at(i)->name()));
|
||||
select_cols.append(sqlb::escapeIdentifier(newSchema.fields().at(i)->name()) + ',');
|
||||
select_cols.chop(1); // remove last comma
|
||||
} else {
|
||||
// We want to modify it
|
||||
@@ -938,7 +951,7 @@ bool DBBrowserDB::renameColumn(const QString& tablename, const QString& name, sq
|
||||
|
||||
// Get names of fields to select from old table now - after the field has been moved and before it might be renamed
|
||||
for(int i=0;i<newSchema.fields().count();++i)
|
||||
select_cols.append(QString("`%1`,").arg(newSchema.fields().at(i)->name()));
|
||||
select_cols.append(sqlb::escapeIdentifier(newSchema.fields().at(i)->name()) + ',');
|
||||
select_cols.chop(1); // remove last comma
|
||||
|
||||
// Modify field
|
||||
@@ -956,7 +969,7 @@ bool DBBrowserDB::renameColumn(const QString& tablename, const QString& name, sq
|
||||
}
|
||||
|
||||
// Copy the data from the old table to the new one
|
||||
if(!executeSQL(QString("INSERT INTO sqlitebrowser_rename_column_new_table SELECT %1 FROM `%2`;").arg(select_cols).arg(tablename)))
|
||||
if(!executeSQL(QString("INSERT INTO sqlitebrowser_rename_column_new_table SELECT %1 FROM %2;").arg(select_cols).arg(sqlb::escapeIdentifier(tablename))))
|
||||
{
|
||||
QString error(tr("renameColumn: copying data to new table failed. DB says:\n%1").arg(lastErrorMessage));
|
||||
qWarning() << error;
|
||||
@@ -979,7 +992,7 @@ bool DBBrowserDB::renameColumn(const QString& tablename, const QString& name, sq
|
||||
setPragma("foreign_keys", "0");
|
||||
|
||||
// Delete the old table
|
||||
if(!executeSQL(QString("DROP TABLE `%1`;").arg(tablename)))
|
||||
if(!executeSQL(QString("DROP TABLE %1;").arg(sqlb::escapeIdentifier(tablename))))
|
||||
{
|
||||
QString error(tr("renameColumn: deleting old table failed. DB says: %1").arg(lastErrorMessage));
|
||||
qWarning() << error;
|
||||
@@ -1022,7 +1035,7 @@ bool DBBrowserDB::renameColumn(const QString& tablename, const QString& name, sq
|
||||
|
||||
bool DBBrowserDB::renameTable(const QString& from_table, const QString& to_table)
|
||||
{
|
||||
QString sql = QString("ALTER TABLE `%1` RENAME TO `%2`").arg(from_table, to_table);
|
||||
QString sql = QString("ALTER TABLE %1 RENAME TO %2").arg(sqlb::escapeIdentifier(from_table)).arg(sqlb::escapeIdentifier(to_table));
|
||||
if(!executeSQL(sql))
|
||||
{
|
||||
QString error = tr("Error renaming table '%1' to '%2'."
|
||||
@@ -1129,7 +1142,7 @@ void DBBrowserDB::updateSchema( )
|
||||
{
|
||||
(*it).table = sqlb::Table::parseSQL((*it).getsql()).first;
|
||||
} else if((*it).gettype() == "view") {
|
||||
statement = QString("PRAGMA TABLE_INFO(`%1`);").arg((*it).getname());
|
||||
statement = QString("PRAGMA TABLE_INFO(%1);").arg(sqlb::escapeIdentifier((*it).getname()));
|
||||
logSQL(statement, kLogMsg_App);
|
||||
err=sqlite3_prepare_v2(_db,statement.toUtf8(),statement.length(),
|
||||
&vm, &tail);
|
||||
|
||||
@@ -69,7 +69,7 @@ void SqliteTableModel::setTable(const QString& table, const QVector<QString>& di
|
||||
|
||||
if(!allOk)
|
||||
{
|
||||
QString sColumnQuery = QString::fromUtf8("SELECT * FROM `%1`;").arg(table);
|
||||
QString sColumnQuery = QString::fromUtf8("SELECT * FROM %1;").arg(sqlb::escapeIdentifier(table));
|
||||
m_headers.push_back("rowid");
|
||||
m_headers.append(getColumns(sColumnQuery, m_vDataTypes));
|
||||
}
|
||||
@@ -484,7 +484,7 @@ void SqliteTableModel::buildQuery()
|
||||
column = QString("col%1").arg(i.key());
|
||||
else
|
||||
column = m_headers.at(i.key());
|
||||
where.append(QString(" AND `%1` %2").arg(column).arg(i.value()));
|
||||
where.append(QString(" AND %1 %2").arg(sqlb::escapeIdentifier(column)).arg(i.value()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -498,7 +498,13 @@ void SqliteTableModel::buildQuery()
|
||||
selector.chop(1);
|
||||
}
|
||||
|
||||
QString sql = QString("SELECT `%1`,%2 FROM `%3` %4 ORDER BY `%5` %6").arg(m_headers.at(0)).arg(selector).arg(m_sTable).arg(where).arg(m_headers.at(m_iSortColumn)).arg(m_sSortOrder);
|
||||
QString sql = QString("SELECT %1,%2 FROM %3 %4 ORDER BY %5 %6")
|
||||
.arg(sqlb::escapeIdentifier(m_headers.at(0)))
|
||||
.arg(selector)
|
||||
.arg(sqlb::escapeIdentifier(m_sTable))
|
||||
.arg(where)
|
||||
.arg(sqlb::escapeIdentifier(m_headers.at(m_iSortColumn)))
|
||||
.arg(m_sSortOrder);
|
||||
setQuery(sql, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,11 @@ namespace sqlb {
|
||||
|
||||
QStringList Field::Datatypes = QStringList() << "INTEGER" << "TEXT" << "BLOB" << "REAL" << "NUMERIC";
|
||||
|
||||
QString escapeIdentifier(QString id)
|
||||
{
|
||||
return '`' + id.replace('`', "``") + '`';
|
||||
}
|
||||
|
||||
bool ForeignKeyClause::isSet() const
|
||||
{
|
||||
return m_override.size() || m_table.size();
|
||||
@@ -22,13 +27,13 @@ QString ForeignKeyClause::toString() const
|
||||
if(m_override.size())
|
||||
return m_override;
|
||||
|
||||
QString result = "`" + m_table + "`";
|
||||
QString result = escapeIdentifier(m_table);
|
||||
|
||||
if(m_columns.size())
|
||||
{
|
||||
result += "(";
|
||||
foreach(const QString& column, m_columns)
|
||||
result += "`" + column + "`,";
|
||||
result += escapeIdentifier(column) + ',';
|
||||
result.chop(1); // Remove last comma
|
||||
result += ")";
|
||||
}
|
||||
@@ -46,7 +51,7 @@ void ForeignKeyClause::setFromString(const QString& fk)
|
||||
|
||||
QString Field::toString(const QString& indent, const QString& sep) const
|
||||
{
|
||||
QString str = indent + '`' + m_name + '`' + sep + m_type;
|
||||
QString str = indent + escapeIdentifier(m_name) + sep + m_type;
|
||||
if(m_notnull)
|
||||
str += " NOT NULL";
|
||||
if(!m_defaultvalue.isEmpty())
|
||||
@@ -204,7 +209,7 @@ QPair<Table, bool> Table::parseSQL(const QString &sSQL)
|
||||
|
||||
QString Table::sql() const
|
||||
{
|
||||
QString sql = QString("CREATE TABLE `%1` (\n").arg(m_name);
|
||||
QString sql = QString("CREATE TABLE %1 (\n").arg(escapeIdentifier(m_name));
|
||||
|
||||
sql += fieldList().join(",\n");
|
||||
|
||||
@@ -230,7 +235,7 @@ QString Table::sql() const
|
||||
foreach(FieldPtr f, m_fields)
|
||||
{
|
||||
if(f->foreignKey().isSet())
|
||||
sql += QString(",\n\tFOREIGN KEY(`%1`) REFERENCES %2").arg(f->name()).arg(f->foreignKey().toString());
|
||||
sql += QString(",\n\tFOREIGN KEY(%1) REFERENCES %2").arg(escapeIdentifier(f->name())).arg(f->foreignKey().toString());
|
||||
}
|
||||
|
||||
sql += "\n)";
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
namespace sqlb {
|
||||
|
||||
QString escapeIdentifier(QString id);
|
||||
|
||||
class ForeignKeyClause
|
||||
{
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user