From 22eb936d1ca3ccff8575bb1f7dd8f790a5c8953f Mon Sep 17 00:00:00 2001
From: Arin Alexander <arin_a@bk.ru>
Date: Wed, 30 Jan 2019 22:49:20 +0300
Subject: [PATCH] Parameter "nobind" has been added to variable

---
 include/lrdatasourceintf.h         | 47 ++++++++++++++++++++++++
 include/lrglobal.h                 |  5 ++-
 limereport/designer.pri            |  1 +
 limereport/lrdatadesignintf.cpp    | 59 +++---------------------------
 limereport/lrdatasourcemanager.cpp | 35 ++++++++++++------
 limereport/lrglobal.h              |  5 ++-
 6 files changed, 83 insertions(+), 69 deletions(-)
 create mode 100644 include/lrdatasourceintf.h

diff --git a/include/lrdatasourceintf.h b/include/lrdatasourceintf.h
new file mode 100644
index 0000000..c2a6c90
--- /dev/null
+++ b/include/lrdatasourceintf.h
@@ -0,0 +1,47 @@
+#ifndef LRDATASOURCEINTF_H
+#define LRDATASOURCEINTF_H
+#include <QSharedPointer>
+#include <QAbstractItemModel>
+namespace LimeReport {
+
+class IDataSource {
+public:
+    enum DatasourceMode{DESIGN_MODE,RENDER_MODE};
+    typedef QSharedPointer<IDataSource> Ptr;
+    virtual ~IDataSource() {}
+    virtual bool next() = 0;
+    virtual bool hasNext() = 0;
+    virtual bool prior() = 0;
+    virtual void first() = 0;
+    virtual void last() = 0;
+    virtual bool bof() = 0;
+    virtual bool eof() = 0;
+    virtual QVariant data(const QString& columnName) = 0;
+    virtual QVariant dataByKeyField(const QString& columnName, const QString& keyColumnName, QVariant keyData) = 0;
+    virtual int columnCount() = 0;
+    virtual QString columnNameByIndex(int columnIndex) = 0;
+    virtual int columnIndexByName(QString name) = 0;
+    virtual bool isInvalid() const = 0;
+    virtual QString lastError() = 0;
+    virtual QAbstractItemModel* model() = 0;
+};
+
+class IDataSourceHolder {
+public:
+    virtual ~IDataSourceHolder(){}
+    virtual IDataSource* dataSource(IDataSource::DatasourceMode mode = IDataSource::RENDER_MODE) = 0;
+    virtual QString lastError() const = 0;
+    virtual bool isInvalid() const = 0;
+    virtual bool isOwned() const = 0;
+    virtual bool isEditable() const = 0;
+    virtual bool isRemovable() const = 0;
+    virtual void invalidate(IDataSource::DatasourceMode mode, bool dbWillBeClosed = false) = 0;
+    virtual void update() = 0;
+    virtual void clearErrors() = 0;
+};
+
+} // namespace LimeReport
+
+#endif // LRDATASOURCEINTF_H
+
+
diff --git a/include/lrglobal.h b/include/lrglobal.h
index bf23065..a82998f 100644
--- a/include/lrglobal.h
+++ b/include/lrglobal.h
@@ -82,8 +82,8 @@ namespace Const{
     const qreal BAND_NAME_TEXT_OPACITY = 0.6;
     const qreal SELECTION_OPACITY = 0.3;
     const QString FIELD_RX = "\\$D\\s*\\{\\s*([^{}]*)\\s*\\}";
-    const QString VARIABLE_RX = "\\$V\\s*\\{\\s*([^{}]*)\\s*\\}";
-    const QString NAMED_VARIABLE_RX = "\\$V\\s*\\{\\s*(%1)\\s*\\}";
+    const QString VARIABLE_RX = "\\$V\\s*\\{\\s*(?:([^\\{\\},]*)|(?:([^\\{\\}]*)\\s*,\\s*([^\\{\\}]*)))\\s*\\}";
+    const QString NAMED_VARIABLE_RX = "\\$V\\s*\\{\\s*(?:(%1)|(?:(%1)\\s*,\\s*([^\\{\\}]*)))\\s*\\}";
     const QString SCRIPT_RX = "\\$S\\s*\\{(.*)\\}";    
     const QString GROUP_FUNCTION_PARAM_RX = "\\(\\s*((?:(?:\\\")|(?:))(?:(?:\\$(?:(?:D\\{\\s*\\w*..*\\})|(?:V\\{\\s*\\w*\\s*\\})|(?:S\\{.+\\})))|(?:\\w*))(?:(?:\\\")|(?:)))(?:(?:\\s*,\\s*(?:\\\"(\\w*)\\\"))|(?:))(?:(?:\\s*,\\s*(?:(\\w*)))|(?:))\\)";
     const int DATASOURCE_INDEX = 3;
@@ -94,6 +94,7 @@ namespace Const{
     const QString GROUP_FUNCTION_NAME_RX = "%1\\s*\\((.*[^\\)])\\)";
     const int SCENE_MARGIN = 50;
     const QString FUNCTION_MANAGER_NAME = "LimeReport";
+    const QString DATAFUNCTIONS_MANAGER_NAME = "DatasourceFunctions";
     const QString EOW("~!@#$%^&*()+{}|:\"<>?,/;'[]\\-=");
     const int DEFAULT_TAB_INDENTION = 4;
 
diff --git a/limereport/designer.pri b/limereport/designer.pri
index 5fb31ad..f377546 100644
--- a/limereport/designer.pri
+++ b/limereport/designer.pri
@@ -1,3 +1,4 @@
+include(../common.pri)
 DEFINES+=HAVE_REPORT_DESIGNER
 
 contains(CONFIG,dialogdesigner){
diff --git a/limereport/lrdatadesignintf.cpp b/limereport/lrdatadesignintf.cpp
index 5f695e8..23b1e76 100644
--- a/limereport/lrdatadesignintf.cpp
+++ b/limereport/lrdatadesignintf.cpp
@@ -77,10 +77,8 @@ bool QueryHolder::runQuery(IDataSource::DatasourceMode mode)
         return false;
     }
 
-    if (!m_prepared){
-        extractParams();
-        if (!m_prepared) return false;
-    }
+    extractParams();
+    if (!m_prepared) return false;
 
     query.prepare(m_preparedSQL);
     fillParams(&query);
@@ -152,35 +150,13 @@ void QueryHolder::fillParams(QSqlQuery *query)
 
 void QueryHolder::extractParams()
 {
-    m_preparedSQL = replaceVariables(m_queryText);
+    m_preparedSQL =  dataManager()->replaceVariables(m_queryText, m_aliasesToParam);
     m_prepared = true;
 }
 
 QString QueryHolder::replaceVariables(QString query)
 {
-    QRegExp rx(Const::VARIABLE_RX);
-    int curentAliasIndex = 0;
-    if (query.contains(rx)){
-        int pos = -1;
-        while ((pos=rx.indexIn(query))!=-1){
-
-            QString variable=rx.cap(0);
-            variable.remove("$V{");
-            variable.remove("}");
-
-            if (m_aliasesToParam.contains(variable)){
-                curentAliasIndex++;
-                m_aliasesToParam.insert(variable+"_alias"+QString::number(curentAliasIndex),variable);
-                variable += "_alias"+QString::number(curentAliasIndex);
-            } else {
-                m_aliasesToParam.insert(variable,variable);
-            }
-
-            query.replace(pos,rx.cap(0).length(),":"+variable);
-
-        }
-    }
-    return query;
+    return dataManager()->replaceVariables(query, m_aliasesToParam);
 }
 
 QString QueryHolder::queryText()
@@ -450,32 +426,7 @@ QString SubQueryHolder::extractField(QString source)
 
 QString SubQueryHolder::replaceFields(QString query)
 {
-    QRegExp rx(Const::FIELD_RX);
-    int curentAliasIndex=0;
-    if (query.contains(rx)){
-        int pos;
-        while ((pos=rx.indexIn(query))!=-1){
-            QString field=rx.cap(0);
-            field.remove("$D{");
-            field.remove("}");
-
-            if (!m_aliasesToParam.contains(field)){
-                if (field.contains("."))
-                    m_aliasesToParam.insert(field,field);
-                else
-                    m_aliasesToParam.insert(field,m_masterDatasource+"."+field);
-            } else {
-                curentAliasIndex++;
-                if (field.contains("."))
-                    m_aliasesToParam.insert(field+"_alias"+QString::number(curentAliasIndex),field);
-                else
-                    m_aliasesToParam.insert(field+"_alias"+QString::number(curentAliasIndex),m_masterDatasource+"."+field);
-                field+="_alias"+QString::number(curentAliasIndex);
-            }
-            query.replace(pos,rx.cap(0).length(),":"+extractField(field));
-        }
-    }
-    return query;
+    return dataManager()->replaceFields(query, m_aliasesToParam);
 }
 
 SubQueryDesc::SubQueryDesc(QString queryName, QString queryText, QString connection, QString masterDatasourceName)
diff --git a/limereport/lrdatasourcemanager.cpp b/limereport/lrdatasourcemanager.cpp
index ad1cd58..bcb71fb 100644
--- a/limereport/lrdatasourcemanager.cpp
+++ b/limereport/lrdatasourcemanager.cpp
@@ -450,17 +450,32 @@ QString DataSourceManager::replaceVariables(QString query, QMap<QString,QString>
             QString var=rx.cap(0);
             var.remove("$V{");
             var.remove("}");
-
-            if (aliasesToParam.contains(var)){
-                curentAliasIndex++;
-                aliasesToParam.insert(var+"_v_alias"+QString::number(curentAliasIndex),var);
-                var += "_v_alias"+QString::number(curentAliasIndex);
+            if (!rx.cap(1).isEmpty()){
+                if (aliasesToParam.contains(var)){
+                    curentAliasIndex++;
+                    aliasesToParam.insert(var+"_v_alias"+QString::number(curentAliasIndex),var);
+                    var += "_v_alias"+QString::number(curentAliasIndex);
+                } else {
+                    aliasesToParam.insert(var,var);
+                }
+                query.replace(pos,rx.cap(0).length(),":"+var);
             } else {
-                aliasesToParam.insert(var,var);
+                QString varName = rx.cap(2).trimmed();
+                QString varParam = rx.cap(3).trimmed();
+                if (!varName.isEmpty()){
+                    if (!varParam.isEmpty() && varParam.compare("nobind") == 0 ){
+                        query.replace(pos,rx.cap(0).length(), variable(varName).toString());
+                    } else {
+                        query.replace(pos,rx.cap(0).length(),
+                                      QString(tr("Uknown parametr \"%1\" for variable \"%2\" found!")
+                                              .arg(varName)
+                                              .arg(varParam))
+                                      );
+                    }
+                } else {
+                    query.replace(pos,rx.cap(0).length(),QString(tr("Variable \"%1\" not found!").arg(var)));
+                }
             }
-
-            query.replace(pos,rx.cap(0).length(),":"+var);
-
         }
     }
     return query;
@@ -1291,13 +1306,11 @@ void DataSourceManager::invalidateQueriesContainsVariable(const QString& variabl
 
 void DataSourceManager::slotVariableHasBeenAdded(const QString& variableName)
 {
-    //qDebug()<< "variable has been added"<< variableName;
     invalidateQueriesContainsVariable(variableName);
 }
 
 void DataSourceManager::slotVariableHasBeenChanged(const QString& variableName)
 {
-    //qDebug()<< "variable has been changed"<< variableName;
     invalidateQueriesContainsVariable(variableName);
 }
 
diff --git a/limereport/lrglobal.h b/limereport/lrglobal.h
index bf23065..a82998f 100644
--- a/limereport/lrglobal.h
+++ b/limereport/lrglobal.h
@@ -82,8 +82,8 @@ namespace Const{
     const qreal BAND_NAME_TEXT_OPACITY = 0.6;
     const qreal SELECTION_OPACITY = 0.3;
     const QString FIELD_RX = "\\$D\\s*\\{\\s*([^{}]*)\\s*\\}";
-    const QString VARIABLE_RX = "\\$V\\s*\\{\\s*([^{}]*)\\s*\\}";
-    const QString NAMED_VARIABLE_RX = "\\$V\\s*\\{\\s*(%1)\\s*\\}";
+    const QString VARIABLE_RX = "\\$V\\s*\\{\\s*(?:([^\\{\\},]*)|(?:([^\\{\\}]*)\\s*,\\s*([^\\{\\}]*)))\\s*\\}";
+    const QString NAMED_VARIABLE_RX = "\\$V\\s*\\{\\s*(?:(%1)|(?:(%1)\\s*,\\s*([^\\{\\}]*)))\\s*\\}";
     const QString SCRIPT_RX = "\\$S\\s*\\{(.*)\\}";    
     const QString GROUP_FUNCTION_PARAM_RX = "\\(\\s*((?:(?:\\\")|(?:))(?:(?:\\$(?:(?:D\\{\\s*\\w*..*\\})|(?:V\\{\\s*\\w*\\s*\\})|(?:S\\{.+\\})))|(?:\\w*))(?:(?:\\\")|(?:)))(?:(?:\\s*,\\s*(?:\\\"(\\w*)\\\"))|(?:))(?:(?:\\s*,\\s*(?:(\\w*)))|(?:))\\)";
     const int DATASOURCE_INDEX = 3;
@@ -94,6 +94,7 @@ namespace Const{
     const QString GROUP_FUNCTION_NAME_RX = "%1\\s*\\((.*[^\\)])\\)";
     const int SCENE_MARGIN = 50;
     const QString FUNCTION_MANAGER_NAME = "LimeReport";
+    const QString DATAFUNCTIONS_MANAGER_NAME = "DatasourceFunctions";
     const QString EOW("~!@#$%^&*()+{}|:\"<>?,/;'[]\\-=");
     const int DEFAULT_TAB_INDENTION = 4;