summaryrefslogtreecommitdiff
path: root/dbaccess
diff options
context:
space:
mode:
authorJenei Gábor <jengab@elte.hu>2011-08-31 12:53:26 +0200
committerEike Rathke <erack@erack.de>2011-09-03 01:19:51 +0200
commitbc0a497f08d52450fd74c6372c9f6780f6715e40 (patch)
tree5392f3e31dea56ab5715dc017db1791399a8c40c /dbaccess
parent69b6d6cfd29c2cfee92eef3faba03a78c671aac3 (diff)
Fixes fdo#36594 Syntax error in SQL on "--" comment (and "//" and "/**/")
The SQL parser implementation does not handle comments. Temporarily remove "-- ..." and "// ..." end-of-line comments and "/* ... */" inline comments of a query and append comments after recomposition of the query. NOTE: The original comment positions are not preserved, all comments are appended to the query! Based on the original patch further development was done for inline comments and preserving comments' line order.
Diffstat (limited to 'dbaccess')
-rw-r--r--dbaccess/source/ui/querydesign/querycontroller.cxx148
1 files changed, 148 insertions, 0 deletions
diff --git a/dbaccess/source/ui/querydesign/querycontroller.cxx b/dbaccess/source/ui/querydesign/querycontroller.cxx
index 054c854e846a..e9ce07a99840 100644
--- a/dbaccess/source/ui/querydesign/querycontroller.cxx
+++ b/dbaccess/source/ui/querydesign/querycontroller.cxx
@@ -94,6 +94,8 @@
#include <vcl/msgbox.hxx>
#include <vcl/svapp.hxx>
#include <osl/mutex.hxx>
+#include <rtl/strbuf.hxx>
+#include <vector>
extern "C" void SAL_CALL createRegistryInfo_OQueryControl()
{
@@ -1589,6 +1591,149 @@ bool OQueryController::doSaveAsDoc(sal_Bool _bSaveAs)
return bSuccess;
}
+//-----------------------------------------------------------------------------
+
+namespace {
+struct CommentStrip
+{
+ ::rtl::OUString maComment;
+ bool mbLastOnLine;
+ CommentStrip( const ::rtl::OUString& rComment, bool bLastOnLine )
+ : maComment( rComment), mbLastOnLine( bLastOnLine) {}
+};
+}
+
+/** Obtain all comments in a query.
+
+ See also delComment() implementation for OSQLParser::parseTree().
+ */
+static ::std::vector< CommentStrip > getComment( const ::rtl::OUString& rQuery )
+{
+ ::std::vector< CommentStrip > aRet;
+ // First a quick search if there is any "--" or "//" or "/*", if not then
+ // the whole copying loop is pointless.
+ if (rQuery.indexOfAsciiL( "--", 2, 0) < 0 && rQuery.indexOfAsciiL( "//", 2, 0) < 0 &&
+ rQuery.indexOfAsciiL( "/*", 2, 0) < 0)
+ return aRet;
+
+ const sal_Unicode* pCopy = rQuery.getStr();
+ const sal_Int32 nQueryLen = rQuery.getLength();
+ bool bIsText1 = false; // "text"
+ bool bIsText2 = false; // 'text'
+ bool bComment2 = false; // /* comment */
+ bool bComment = false; // -- or // comment
+ ::rtl::OUStringBuffer aBuf;
+ for (sal_Int32 i=0; i < nQueryLen; ++i)
+ {
+ if (bComment2)
+ {
+ aBuf.append( &pCopy[i], 1);
+ if ((i+1) < nQueryLen)
+ {
+ if (pCopy[i]=='*' && pCopy[i+1]=='/')
+ {
+ bComment2 = false;
+ aBuf.append( &pCopy[++i], 1);
+ aRet.push_back( CommentStrip( aBuf.makeStringAndClear(), false));
+ }
+ }
+ else
+ {
+ // comment can't close anymore, actually an error, but..
+ aRet.push_back( CommentStrip( aBuf.makeStringAndClear(), false));
+ }
+ continue;
+ }
+ if (pCopy[i] == '\n' || i == nQueryLen-1)
+ {
+ if (bComment)
+ {
+ if (i == nQueryLen-1 && pCopy[i] != '\n')
+ aBuf.append( &pCopy[i], 1);
+ aRet.push_back( CommentStrip( aBuf.makeStringAndClear(), true));
+ bComment = false;
+ }
+ else if (!aRet.empty())
+ aRet.back().mbLastOnLine = true;
+ }
+ else if (!bComment)
+ {
+ if (pCopy[i] == '\"' && !bIsText2)
+ bIsText1 = !bIsText1;
+ else if (pCopy[i] == '\'' && !bIsText1)
+ bIsText2 = !bIsText2;
+ if (!bIsText1 && !bIsText2 && (i+1) < nQueryLen)
+ {
+ if ((pCopy[i]=='-' && pCopy[i+1]=='-') || (pCopy[i]=='/' && pCopy[i+1]=='/'))
+ bComment = true;
+ else if ((pCopy[i]=='/' && pCopy[i+1]=='*'))
+ bComment2 = true;
+ }
+ }
+ if (bComment || bComment2)
+ aBuf.append( &pCopy[i], 1);
+ }
+ return aRet;
+}
+//------------------------------------------------------------------------------
+
+/** Concat/insert comments that were previously obtained with getComment().
+
+ NOTE: The current parser implementation does not preserve newlines, so all
+ comments are always appended to the entire query, also inline comments
+ that would need positioning anyway that can't be obtained after
+ recomposition. This is ugly but at least allows commented queries while
+ preserving the comments _somehow_.
+ */
+static ::rtl::OUString concatComment( const ::rtl::OUString& rQuery, const ::std::vector< CommentStrip >& rComments )
+{
+ // No comments => return query.
+ if (rComments.empty())
+ return rQuery;
+
+ const sal_Unicode* pBeg = rQuery.getStr();
+ const sal_Int32 nLen = rQuery.getLength();
+ const size_t nComments = rComments.size();
+ // Obtaining the needed size once should be faster than reallocating.
+ // Also add a blank or linefeed for each comment.
+ sal_Int32 nBufSize = nLen + nComments;
+ for (::std::vector< CommentStrip >::const_iterator it( rComments.begin()); it != rComments.end(); ++it)
+ nBufSize += (*it).maComment.getLength();
+ ::rtl::OUStringBuffer aBuf( nBufSize );
+ sal_Int32 nIndBeg = 0;
+ sal_Int32 nIndLF = rQuery.indexOf('\n');
+ size_t i = 0;
+ while (nIndLF >= 0 && i < nComments)
+ {
+ aBuf.append( pBeg + nIndBeg, nIndLF - nIndBeg);
+ do
+ {
+ aBuf.append( rComments[i].maComment);
+ } while (!rComments[i++].mbLastOnLine && i < nComments);
+ aBuf.append( pBeg + nIndLF, 1); // the LF
+ nIndBeg = nIndLF + 1;
+ nIndLF = (nIndBeg < nLen ? rQuery.indexOf( '\n', nIndBeg) : -1);
+ }
+ // Append remainder of query.
+ if (nIndBeg < nLen)
+ aBuf.append( pBeg + nIndBeg, nLen - nIndBeg);
+ // Append all remaining comments, preserve lines.
+ bool bNewLine = false;
+ for ( ; i < nComments; ++i)
+ {
+ if (!bNewLine)
+ aBuf.append( sal_Unicode(' '));
+ aBuf.append( rComments[i].maComment);
+ if (rComments[i].mbLastOnLine)
+ {
+ aBuf.append( sal_Unicode('\n'));
+ bNewLine = true;
+ }
+ else
+ bNewLine = false;
+ }
+ return aBuf.makeStringAndClear();
+}
// -----------------------------------------------------------------------------
::rtl::OUString OQueryController::translateStatement( bool _bFireStatementChange )
{
@@ -1601,6 +1746,8 @@ bool OQueryController::doSaveAsDoc(sal_Bool _bSaveAs)
{
::rtl::OUString aErrorMsg;
+ ::std::vector< CommentStrip > aComments = getComment( m_sStatement);
+
::connectivity::OSQLParseNode* pNode = m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign );
if(pNode)
{
@@ -1610,6 +1757,7 @@ bool OQueryController::doSaveAsDoc(sal_Bool _bSaveAs)
m_xComposer->setQuery(sTranslatedStmt);
sTranslatedStmt = m_xComposer->getComposedQuery();
+ sTranslatedStmt = concatComment( sTranslatedStmt, aComments);
}
catch(const SQLException& e)
{