From 6b78b13871123b66bdfbeaa7eead1144d4ee4c59 Mon Sep 17 00:00:00 2001 From: mgrojo Date: Sat, 7 Jul 2018 20:36:25 +0200 Subject: [PATCH] Improvements for "Copy as SQL" feature (PR #1422) - Set the line terminator according to operating system (text and SQL versions). - Quote identifiers using the user preference and string literals as 'SQL standard'. - Support BLOB literals for any kind of binary data and avoid converting any kind of image to PNG in the process of setting the BLOB literal in SQL. --- src/ExtendedTableWidget.cpp | 43 +++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/ExtendedTableWidget.cpp b/src/ExtendedTableWidget.cpp index ff728250..c2ae1c93 100644 --- a/src/ExtendedTableWidget.cpp +++ b/src/ExtendedTableWidget.cpp @@ -320,9 +320,13 @@ void ExtendedTableWidget::copy(const bool withHeaders, const bool inSQL ) const QString fieldSepHtml = ""; const QString rowSepHtml = ""; const QString fieldSepText = "\t"; +#ifdef Q_OS_WIN const QString rowSepText = "\r\n"; +#else + const QString rowSepText = "\n"; +#endif - QString sqlInsertStatement = QString("INSERT INTO %1 ( '").arg(sqlb::escapeIdentifier(m->currentTableName().toString())); + QString sqlInsertStatement = QString("INSERT INTO %1 (").arg(m->currentTableName().toString()); // Table headers if (withHeaders || inSQL) { htmlResult.append(""); @@ -332,16 +336,16 @@ void ExtendedTableWidget::copy(const bool withHeaders, const bool inSQL ) if (i != firstColumn) { result.append(fieldSepText); htmlResult.append(""); - sqlInsertStatement.append("', '"); + sqlInsertStatement.append(", "); } result.append(escapeCopiedData(headerText)); htmlResult.append(headerText); - sqlInsertStatement.append(escapeCopiedData(headerText)); + sqlInsertStatement.append(sqlb::escapeIdentifier(headerText)); } result.append(rowSepText); htmlResult.append(""); - sqlInsertStatement.append("') VALUES (\""); + sqlInsertStatement.append(") VALUES ("); } // Table data rows @@ -353,19 +357,19 @@ void ExtendedTableWidget::copy(const bool withHeaders, const bool inSQL ) } else if (index.row() != currentRow) { result.append(rowSepText); htmlResult.append(rowSepHtml); - sqlResult.append("\");\r\n"+sqlInsertStatement); + sqlResult.append(");" + rowSepText + sqlInsertStatement); } else { result.append(fieldSepText); htmlResult.append(fieldSepHtml); - sqlResult.append("\", \""); + sqlResult.append(", "); } currentRow = index.row(); QImage img; QVariant data = index.data(Qt::EditRole); - // Table cell data: image? Store it as an embedded image in HTML and as base 64 in text version - if (img.loadFromData(data.toByteArray())) + // Table cell data: image? Store it as an embedded image in HTML + if (!inSQL && img.loadFromData(data.toByteArray())) { QByteArray ba; QBuffer buffer(&ba); @@ -377,24 +381,27 @@ void ExtendedTableWidget::copy(const bool withHeaders, const bool inSQL ) htmlResult.append("\"Image\""); } else { QByteArray text; - if (!m->isBinary(index)) + if (!m->isBinary(index)) { text = data.toByteArray(); - // Table cell data: text - if (text.contains('\n') || text.contains('\t')) - htmlResult.append("
" + QString(text).toHtmlEscaped() + "
"); - else - htmlResult.append(QString(text).toHtmlEscaped()); + // Table cell data: text + if (text.contains('\n') || text.contains('\t')) + htmlResult.append("
" + QString(text).toHtmlEscaped() + "
"); + else + htmlResult.append(QString(text).toHtmlEscaped()); + + result.append(escapeCopiedData(text)); + sqlResult.append("'" + text.replace("'", "''") + "'"); + } else + // Table cell data: binary. Save as BLOB literal in SQL + sqlResult.append( "X'" + data.toByteArray().toHex() + "'" ); - result.append(escapeCopiedData(text)); - sqlResult.append(text.replace("\"", "\"\"")); } } - sqlResult.append("\");"); + sqlResult.append(");"); QMimeData *mimeData = new QMimeData; if ( inSQL )