/*
*
* ProLinga-Run
*
* Copyright (C) 2002-2009 Xobas Software.
* All rights reserved.
*
* This file is part of ProLinga-Run.
*
* ProLinga-Run is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProLinga-Run is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProLinga-Run. If not, see .
*
* More information is available at the following addresses:
*
* Website : http://www.prolinga.org
*
* Email : prolinga-list@prolinga.org
*
*
*/
#include "RunCommon.h"
#include
#include
#include
#include "DataCommand.hpp"
#include "DataRef.hpp"
#include "BuiltIn.hpp"
extern CaDataSessionPtr caDataSesPtr;
extern BiDataModelStatusPtr biDataModelStatusPtr;
extern DataModelPtr dmPtr;
extern TablePtr tablePtr;
extern BiSqlReturnPtr biSqlReturnPtr;
/* Command : DATAMODEL */
/* Syntax : DATAMODEL APPEND data_model_name */
/* DATAMODEL REMOVE data_model_name */
/* DATAMODEL UPDATE data_model_name */
/* DATAMODEL SELECT data_model_name TABLE table_name [CONDITION condition [condition...]]*/
void CmdDatamodel(const char **argList, int argHits, bool isMainThread)
{
xmlDocPtr docData, docRes;
xmlNodePtr curData;
xmlXPathContextPtr ctxRes;
xmlXPathObjectPtr resRes;
char dataModel[255], dataTable[32], dataTableExt[64], dataConditionTmp[1024], dataCondition[10240], tmpRef[255];
char *dataSource, *rcStatus;
char dataSourceName[64];
int i, rows, cols, retStatus = 0;
/* Init */
biDataModelStatusPtr->setDataModelStatus(0);
/* Get Data Model Name */
getDataRef(argList[2], isMainThread, dataModel, false);
/* APPEND or UPDATE */
if ( (strcmp(argList[1], "APPEND") == 0) || (strcmp(argList[1], "UPDATE") == 0) )
{
/* Check if Data Model Name has been previously loaded */
if (dmPtr->existsDataModel(dmPtr, dataModel) == false )
{
biDataModelStatusPtr->setDataModelStatus(10101);
return;
}
/* Get Data Source Name */
dataSource = dmPtr->getDataSource(dmPtr, dataModel);
/* Create DC Datamodel document */
docData = xmlNewDoc((const xmlChar *)"1.0");
docData->children = xmlNewDocNode(docData, NULL, (const xmlChar *)"ProLinga", NULL);
curData = xmlDocGetRootElement(docData);
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"Data", (const xmlChar *)"");
xmlNewProp(curData, (const xmlChar *)"Version", (const xmlChar *)"1.0");
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"Command", (const xmlChar *)"");
if (strcmp(argList[1], "APPEND") == 0)
xmlNewProp(curData, (const xmlChar *)"Name", (const xmlChar *)"DataModelAppendRow");
else if (strcmp(argList[1], "UPDATE") == 0)
xmlNewProp(curData, (const xmlChar *)"Name", (const xmlChar *)"DataModelUpdateRow");
xmlNewProp(curData, (const xmlChar *)"Mode", (const xmlChar *)"Request");
xmlNewProp(curData, (const xmlChar *)"SessionId", (const xmlChar *)caDataSesPtr->getDataSessionId(caDataSesPtr, dataSource));
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"Object", (const xmlChar *)"");
xmlNewProp(curData, (const xmlChar *)"DataSource", (const xmlChar *)caDataSesPtr->getExternalDataSource(caDataSesPtr, dataSource));
xmlNewProp(curData, (const xmlChar *)"DataModel", (const xmlChar *)dataModel);
if (strcmp(argList[1], "APPEND") == 0)
{
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"DataModelAppendRow", (const xmlChar *)"");
}
else if (strcmp(argList[1], "UPDATE") == 0)
{
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"DataModelUpdateRow", (const xmlChar *)"");
sprintf(tmpRef,"%d",dmPtr->getCurrentRow(dmPtr, dataModel));
xmlNewProp(curData, (const xmlChar *)"RowId", (const xmlChar *)tmpRef);
}
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"DataInstances", (const xmlChar *)"");
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"DataInstance", (const xmlChar *)"");
xmlNewProp(curData, (const xmlChar *)"SequenceNo", (const xmlChar *)"1");
cols = dmPtr->getColumns(dmPtr, dataModel);
/* Get properties columns */
for (i=1;i<=cols;i++)
{
xmlNewTextChild(curData, NULL, (const xmlChar *)dmPtr->getColName(dmPtr, dataModel, i), \
(const xmlChar *)dmPtr->getDataValueColNo(dmPtr, dataModel, i));
}
/* DEBUG */
/*
xmlBufferPtr bufData;
bufData = xmlBufferCreate();
curData = xmlDocGetRootElement(docData);
xmlNodeDump(bufData, docData, curData, 0, 1);
printf("%s\n", (char *)xmlBufferContent(bufData));
xmlBufferFree(bufData);
*/
/* Execute DC */
docRes = DC_Exec(docData);
/* DEBUG */
/*
xmlBufferPtr bufRes;
bufRes = xmlBufferCreate();
xmlNodePtr curRes = xmlDocGetRootElement(docRes);
xmlNodeDump(bufRes, docRes, curRes, 0, 1);
printf("%s\n", (char *)xmlBufferContent(bufRes));
xmlBufferFree(bufRes);
*/
/* Create XPath environment */
ctxRes = xmlXPathNewContext(docRes);
/* Check Status */
resRes = xmlXPathEval((const xmlChar *)"/ProLinga/Data/Command/@Status", ctxRes);
rcStatus = (char *)xmlXPathCastToString(resRes);
if ( strcmp(rcStatus, "Ok") != 0)
{
biDataModelStatusPtr->setDataModelStatus(10101);
}
/* Clean up */
if (docRes != NULL)
xmlFreeDoc(docRes);
xmlFreeDoc(docData);
}
/* REMOVE */
else if (strcmp(argList[1], "REMOVE") == 0)
{
/* Check if Data Model Name has been previously loaded */
if (dmPtr->existsDataModel(dmPtr, dataModel) == false )
{
biDataModelStatusPtr->setDataModelStatus(10101);
return;
}
/* Get Data Source Name */
dataSource = dmPtr->getDataSource(dmPtr, dataModel);
/* Create DC datamodel document */
docData = xmlNewDoc((const xmlChar *)"1.0");
docData->children = xmlNewDocNode(docData, NULL, (const xmlChar *)"ProLinga", NULL);
curData = xmlDocGetRootElement(docData);
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"Data", (const xmlChar *)"");
xmlNewProp(curData, (const xmlChar *)"Version", (const xmlChar *)"1.0");
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"Command", (const xmlChar *)"");
xmlNewProp(curData, (const xmlChar *)"Name", (const xmlChar *)"DataModelRemoveRow");
xmlNewProp(curData, (const xmlChar *)"Mode", (const xmlChar *)"Request");
xmlNewProp(curData, (const xmlChar *)"SessionId", (const xmlChar *)caDataSesPtr->getDataSessionId(caDataSesPtr, dataSource));
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"Object", (const xmlChar *)"");
xmlNewProp(curData, (const xmlChar *)"DataSource", (const xmlChar *)caDataSesPtr->getExternalDataSource(caDataSesPtr, dataSource));
xmlNewProp(curData, (const xmlChar *)"DataModel", (const xmlChar *)dataModel);
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"DataModelRemoveRow", (const xmlChar *)"");
sprintf(tmpRef,"%d",dmPtr->getCurrentRow(dmPtr, dataModel));
xmlNewProp(curData, (const xmlChar *)"RowId", (const xmlChar *)tmpRef);
/* Execute DC */
docRes = DC_Exec(docData);
/* Create XPath environment */
ctxRes = xmlXPathNewContext(docRes);
/* Check Status */
resRes = xmlXPathEval((const xmlChar *)"/ProLinga/Data/Command/@Status", ctxRes);
rcStatus = (char *)xmlXPathCastToString(resRes);
if ( strcmp(rcStatus, "Ok") != 0)
{
biDataModelStatusPtr->setDataModelStatus(10101);
}
/* Clean up */
if (docRes != NULL)
xmlFreeDoc(docRes);
}
/* SELECT */
else if (strcmp(argList[1], "SELECT") == 0)
{
/* Get Table Name */
getDataRef(argList[4], isMainThread, dataTable, false);
/* Get Data Source */
if (tablePtr->getDataSourceName(&tablePtr, dataTable) == NULL)
dataSourceName[0] = '\0';
else
strcpy(dataSourceName, tablePtr->getDataSourceName(&tablePtr, dataTable));
/* Get External Table Name */
if (tablePtr->getExternalName(&tablePtr, dataTable) == NULL)
dataTableExt[0] = '\0';
else
strcpy(dataTableExt, tablePtr->getExternalName(&tablePtr, dataTable));
/* Create DC datamodel document */
docData = xmlNewDoc((const xmlChar *)"1.0");
docData->children = xmlNewDocNode(docData, NULL, (const xmlChar *)"ProLinga", NULL);
curData = xmlDocGetRootElement(docData);
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"Data", (const xmlChar *)"");
xmlNewProp(curData, (const xmlChar *)"Version", (const xmlChar *)"1.0");
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"Command", (const xmlChar *)"");
xmlNewProp(curData, (const xmlChar *)"Name", (const xmlChar *)"ExecuteQueryTableDataModel");
xmlNewProp(curData, (const xmlChar *)"Mode", (const xmlChar *)"Request");
xmlNewProp(curData, (const xmlChar *)"SessionId", (const xmlChar *)caDataSesPtr->getDataSessionId(caDataSesPtr, dataSourceName));
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"Object", (const xmlChar *)"");
xmlNewProp(curData, (const xmlChar *)"DataSource", (const xmlChar *)caDataSesPtr->getExternalDataSource(caDataSesPtr, dataSourceName));
xmlNewProp(curData, (const xmlChar *)"DataModel", (const xmlChar *)dataModel);
curData = xmlNewTextChild(curData, NULL, (const xmlChar *)"Query", (const xmlChar *)"");
xmlNewTextChild(curData, NULL, (const xmlChar *)"Table", (const xmlChar *)dataTableExt);
/* Concatenate 1 big string for condition */
dataCondition[0] = '\0';
for (i = 6; i <= argHits; i++)
{
/* Get Condition */
getDataRef(argList[i], isMainThread, dataConditionTmp, false);
if (i == 6)
strcpy(dataCondition, dataConditionTmp);
else
strcat(dataCondition, dataConditionTmp);
}
/* Set condition */
xmlNewTextChild(curData, NULL, (const xmlChar *)"Condition", (const xmlChar *)dataCondition);
/* DEBUG */
// xmlBufferPtr bufData;
// bufData = xmlBufferCreate();
// curData = xmlDocGetRootElement(docData);
// xmlNodeDump(bufData, docData, curData, 0, 1);
// printf("%s\n", (char *)xmlBufferContent(bufData));
// xmlBufferFree(bufData);
/* Execute DC */
docRes = DC_Exec(docData);
// xmlBufferPtr bufRes;
// bufRes = xmlBufferCreate();
// xmlNodePtr curRes = xmlDocGetRootElement(docRes);
// xmlNodeDump(bufRes, docRes, curRes, 0, 1);
// printf("%s\n", (char *)xmlBufferContent(bufRes));
// xmlBufferFree(bufRes);
/* Create XPath environment */
ctxRes = xmlXPathNewContext(docRes);
/* Check Status */
resRes = xmlXPathEval((const xmlChar *)"/ProLinga/Data/Command/@Status", ctxRes);
rcStatus = (char *)xmlXPathCastToString(resRes);
if ( strcmp(rcStatus, "Ok") != 0)
{
biDataModelStatusPtr->setDataModelStatus(10101);
}
/* Delete Data Model if present */
dmPtr->deleteOne(&dmPtr, dataModel);
/* Set Data Source of Data Model */
dmPtr->putDataSource(&dmPtr, dataModel, dataSourceName);
/* Get and set number of columns in data model */
resRes = xmlXPathEval((const xmlChar *)"/ProLinga/Data/Command/Object/Query/ColumnsDataModel", ctxRes);
cols = (int)xmlXPathCastToNumber(resRes);
dmPtr->putColumns(&dmPtr, dataModel, cols);
/* Get and set number of rows in data model */
resRes = xmlXPathEval((const xmlChar *)"/ProLinga/Data/Command/Object/Query/RowsDataModel", ctxRes);
rows = (int)xmlXPathCastToNumber(resRes);
biSqlReturnPtr->setSqlReturn(rows);
dmPtr->putRows(&dmPtr, dataModel, rows);
/* Load active datamodel row with either 0 (dummy) or the first */
if (rows > 0)
retStatus = dataDataModelGetRow(dataModel, 1);
else
retStatus = dataDataModelGetRow(dataModel, 0);
/* Clean up */
if (docRes != NULL)
xmlFreeDoc(docRes);
}
}