/*
*
* ProLinga-Data
*
* Copyright (C) 2002-2008 Xobas Software.
* All rights reserved.
*
* This file is part of ProLinga-Data.
*
* ProLinga-Data 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-Data 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-Data. If not, see .
*
* More information is available at the following addresses:
*
* Website : http://www.prolinga.org
*
* Email : prolinga-list@prolinga.org
*
*
*/
#include "DatCommon.h"
#include
#include
#include
#include
#include "DatMain.hpp"
#include "DCManageData.hpp"
#include "ExecuteSql.hpp"
#include "DCSession.hpp"
#include "DatConfig.hpp"
extern DCSessionPtr sesPtr;
bool TableExists(GdaConnection *connection, char *objTable)
{
GdaDataModel *dm = NULL;
GdaParameterList *pml;
GdaParameter *pm;
bool retValue;
GSList *list = NULL;
GError *error;
/* Create parameter list */
pml = gda_parameter_list_new(list);
/* Create parameter */
pm = gda_parameter_new_string("name", objTable);
/* Add parameter to list */
gda_parameter_list_add_param(pml, pm);
/* Check if table exists */
dm = gda_connection_get_schema(connection, GDA_CONNECTION_SCHEMA_FIELDS, pml, &error);
if (error != NULL)
retValue = false;
else
{
retValue = true;
g_object_unref(dm);
}
/* Cleanup */
g_object_unref(pml);
//gda_parameter_list_free(pml);
/* Return */
return retValue;
}
void FreeColumn(gpointer data, gpointer user_data)
{
GdaColumn *dmca = (GdaColumn *)data;
g_object_unref(dmca);
}
void FreeColumnIndex(gpointer data, gpointer user_data)
{
GdaColumnIndex *dmcia = (GdaColumnIndex *)data;
g_object_unref(dmcia);
}
bool isPrimaryKeyField (const xmlDocPtr docObj, const char *colName)
{
xmlXPathContextPtr ctxObj;
xmlXPathObjectPtr resObj;
int i, j, idxHits, keyHits;
char *idxPrimary, *keyName, tmpString[255];
/* Create XPath Environment */
ctxObj = xmlXPathNewContext(docObj);
/* Get the index values */
resObj = xmlXPathEval((const xmlChar *)"count(/ProLinga/Object/IndexInstances/IndexInstance)", ctxObj);
idxHits = (int)xmlXPathCastToNumber(resObj);
/* Get index Values */
for (i = 1; i<= idxHits; i++)
{
/* Skip non-primary key as this one is created during create table */
sprintf(tmpString, "/ProLinga/Object/IndexInstances/IndexInstance[@SequenceNo='%d']/@Primary", i);
resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
idxPrimary = (char *)xmlXPathCastToString(resObj);
if (strcmp(idxPrimary, "True") != 0)
continue;
/* Get the key values */
sprintf(tmpString, "count(/ProLinga/Object/IndexInstances/IndexInstance[@SequenceNo='%d']/KeyInstances/KeyInstance)", i);
resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
keyHits = (int)xmlXPathCastToNumber(resObj);
/* Get index Values */
for (j = 1; j<= keyHits; j++)
{
/* Name */
sprintf(tmpString, "/ProLinga/Object/IndexInstances/IndexInstance[@SequenceNo='%d']/KeyInstances/KeyInstance[@SequenceNo='%d']/@Name", i,j);
resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
keyName = (char *)xmlXPathCastToString(resObj);
/* Check if name matches */
if (strcmp(colName, keyName) == 0)
return true;
}
}
/* Return */
return false;
}
int DCManageData(const xmlDocPtr docObj, const char *sessionId, char **externalError, xmlDocPtr *docReturn)
{
xmlDocPtr docOp;
xmlNodePtr curOp, curOp2, curOp3;
xmlXPathContextPtr ctxObj;
xmlXPathObjectPtr resObj;
GdaConnection *connection;
char *extTableName;
char *objDataSource = NULL, *objTable = NULL, *buildOption = NULL, *ddType;
char *idxPrimary, *idxName, *idxUnique, *nameTblIdx, *colName;
char *keyName;
char *ddAllowNulls, tmpString[255];
int i, j, dbstatus = 0, dataHits, idxHits, keyHits, length;
glong size, decimals;
GdaServerProvider *prov;
GdaServerOperation *op;
/* Create XPath Environment */
ctxObj = xmlXPathNewContext(docObj);
/* Get DataSource name */
resObj = xmlXPathEval((const xmlChar *)"/ProLinga/Object/@DataSource", ctxObj);
objDataSource = (char *)xmlXPathCastToString(resObj);
/* Get Table name */
resObj = xmlXPathEval((const xmlChar *)"/ProLinga/Object/@Table", ctxObj);
objTable = (char *)xmlXPathCastToString(resObj);
/* Get Build Option */
resObj = xmlXPathEval((const xmlChar *)"/ProLinga/Object/ManageData/@Option", ctxObj);
buildOption = (char *)xmlXPathCastToString(resObj);
/* Get Connection Object to Data Source */
connection = sesPtr->getGdaConnection(sesPtr, sessionId, objDataSource);
if (connection == NULL)
return 70002;
/* Check Option */
if (strcmp(buildOption, "Create") == 0)
{
/* Get external (= table to build) table name */
resObj = xmlXPathEval((const xmlChar *)"/ProLinga/Object/ManageData/ExternalTableName", ctxObj);
extTableName = (char *)xmlXPathCastToString(resObj);
/* Drop table (if exists) */
prov = gda_connection_get_provider_obj(connection);
op = gda_server_provider_create_operation (prov, connection, GDA_SERVER_OPERATION_DROP_TABLE, NULL, NULL);
if (op)
{
/* We have to set the table parameters */
docOp = xmlNewDoc((const xmlChar *)XML_VERSION);
docOp->children = xmlNewDocNode(docOp, NULL, (const xmlChar *)"serv_op_data", NULL);
curOp = xmlDocGetRootElement(docOp);
curOp = xmlNewTextChild (curOp, NULL, (const xmlChar *)"op_data", (const xmlChar *)extTableName);
xmlNewProp (curOp, (const xmlChar *)"path", (const xmlChar *)"/TABLE_DESC_P/TABLE_NAME");
if (!gda_server_operation_load_data_from_xml (op, xmlDocGetRootElement (docOp), NULL))
{
/* error */
}
else
{
if(!gda_server_provider_perform_operation (prov, connection, op, NULL))
{
/* error */
}
}
xmlFreeDoc (docOp);
g_object_unref (op);
}
/* Prepare to create the table */
op = gda_server_provider_create_operation (prov, connection, GDA_SERVER_OPERATION_CREATE_TABLE, NULL, NULL);
if (!op)
return 70023;
/* Get the data values */
resObj = xmlXPathEval((const xmlChar *)"count(/ProLinga/Object/DataInstances/DataInstance)", ctxObj);
dataHits = (int)xmlXPathCastToNumber(resObj);
/* Collect New Table Values */
docOp = xmlNewDoc((const xmlChar *)XML_VERSION);
docOp->children = xmlNewDocNode(docOp, NULL, (const xmlChar *)"serv_op_data", NULL);
curOp = xmlDocGetRootElement(docOp);
curOp2 = xmlNewTextChild (curOp, NULL, (const xmlChar *)"op_data", (const xmlChar *)extTableName);
xmlNewProp (curOp2, (const xmlChar *)"path", (const xmlChar *)"/TABLE_DEF_P/TABLE_NAME");
curOp = xmlNewTextChild (curOp, NULL, (const xmlChar *)"op_data", (const xmlChar *)"");
xmlNewProp (curOp, (const xmlChar *)"path", (const xmlChar *)"/FIELDS_A");
curOp = xmlNewTextChild (curOp, NULL, (const xmlChar *)"gda_array_data", (const xmlChar *)"");
/* Get data Values (Columns) */
for (i = 1; i<= dataHits; i++)
{
/* New column entry */
curOp2 = xmlNewTextChild (curOp, NULL, (const xmlChar *)"gda_array_row", (const xmlChar *)"");
/* Column Name */
sprintf(tmpString, "/ProLinga/Object/DataInstances/DataInstance[@SequenceNo='%d']/@Name", i);
resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
colName = (char *)xmlXPathCastToString(resObj);
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)colName);
xmlNewProp (curOp3, (const xmlChar *)"colid", (const xmlChar *)"COLUMN_NAME");
/* Size */
sprintf(tmpString, "/ProLinga/Object/DataInstances/DataInstance[@SequenceNo='%d']/@Size", i);
resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
size = (glong)xmlXPathCastToNumber(resObj);
/* Decimals */
sprintf(tmpString, "/ProLinga/Object/DataInstances/DataInstance[@SequenceNo='%d']/@Decimals", i);
resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
decimals = (glong)xmlXPathCastToNumber(resObj);
/* Storage Type */
sprintf(tmpString, "/ProLinga/Object/DataInstances/DataInstance[@SequenceNo='%d']/@StorageType", i);
resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
ddType = (char *)xmlXPathCastToString(resObj);
if (strcmp(ddType, "Character") == 0)
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)gda_server_provider_get_default_dbms_type(prov,connection,G_TYPE_STRING));
else if (strcmp(ddType, "Integer") == 0)
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)gda_server_provider_get_default_dbms_type(prov,connection,G_TYPE_INT));
else if (strcmp(ddType, "Long") == 0)
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)gda_server_provider_get_default_dbms_type(prov,connection,G_TYPE_INT64));
else if (strcmp(ddType, "Single") == 0)
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)gda_server_provider_get_default_dbms_type(prov,connection,G_TYPE_FLOAT));
else if (strcmp(ddType, "Double") == 0)
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)gda_server_provider_get_default_dbms_type(prov,connection,G_TYPE_DOUBLE));
else if (strcmp(ddType, "Numeric") == 0)
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)gda_server_provider_get_default_dbms_type(prov,connection,GDA_TYPE_NUMERIC));
else if (strcmp(ddType, "Date") == 0)
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)gda_server_provider_get_default_dbms_type(prov,connection,G_TYPE_DATE));
else
return 70018;
xmlNewProp (curOp3, (const xmlChar *)"colid", (const xmlChar *)"COLUMN_TYPE");
/* Size */
if ((strcmp(ddType, "Numeric") == 0) || (strcmp(ddType, "Character") == 0))
{
sprintf(tmpString, "%ld", size);
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)tmpString);
xmlNewProp (curOp3, (const xmlChar *)"colid", (const xmlChar *)"COLUMN_SIZE");
}
/* Scale */
if (strcmp(ddType, "Numeric") == 0)
{
sprintf(tmpString, "%ld", decimals);
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)tmpString);
xmlNewProp (curOp3, (const xmlChar *)"colid", (const xmlChar *)"COLUMN_SCALE");
}
/* AllowNulls */
sprintf(tmpString, "/ProLinga/Object/DataInstances/DataInstance[@SequenceNo='%d']/@AllowNulls", i);
resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
ddAllowNulls = (char *)xmlXPathCastToString(resObj);
if (strcmp(ddAllowNulls,"True") == 0)
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)"FALSE");
else
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)"TRUE");
xmlNewProp (curOp3, (const xmlChar *)"colid", (const xmlChar *)"COLUMN_NNUL");
/* Set Primary and Unique to FALSE */
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)"FALSE");
xmlNewProp (curOp3, (const xmlChar *)"colid", (const xmlChar *)"COLUMN_UNIQUE");
/* Check if column name part of primary key */
if (isPrimaryKeyField(docObj, colName) == true)
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)"TRUE");
else
curOp3 = xmlNewTextChild (curOp2, NULL, (const xmlChar *)"gda_array_value", (const xmlChar *)"FALSE");
xmlNewProp (curOp3, (const xmlChar *)"colid", (const xmlChar *)"COLUMN_PKEY");
}
/* Call create table call */
if (!gda_server_operation_load_data_from_xml (op, xmlDocGetRootElement (docOp), NULL))
return 70023;
if(!gda_server_provider_perform_operation (prov, connection, op, NULL))
return 70023;
xmlFreeDoc (docOp);
g_object_unref (op);
/* Create Indexes */
/* Get the index values */
resObj = xmlXPathEval((const xmlChar *)"count(/ProLinga/Object/IndexInstances/IndexInstance)", ctxObj);
idxHits = (int)xmlXPathCastToNumber(resObj);
/* Get index Values */
for (i = 1; i<= idxHits; i++)
{
/* Skip primary key as this one is created during create table */
sprintf(tmpString, "/ProLinga/Object/IndexInstances/IndexInstance[@SequenceNo='%d']/@Primary", i);
resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
idxPrimary = (char *)xmlXPathCastToString(resObj);
if (strcmp(idxPrimary, "True") == 0)
continue;
/* Name */
sprintf(tmpString, "/ProLinga/Object/IndexInstances/IndexInstance[@SequenceNo='%d']/@Name", i);
resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
idxName = (char *)xmlXPathCastToString(resObj);
length = strlen(extTableName) + strlen(idxName) + 1;
nameTblIdx = new char[(length+1)];
strcpy(nameTblIdx, extTableName);
strcat(nameTblIdx, "_");
strcat(nameTblIdx, idxName);
/* Drop Index */
op = gda_server_provider_create_operation (prov, connection, GDA_SERVER_OPERATION_DROP_INDEX, NULL, NULL);
if (op)
{
/* we have to set the index parameters */
docOp = xmlNewDoc((const xmlChar *)XML_VERSION);
docOp->children = xmlNewDocNode(docOp, NULL, (const xmlChar *)"serv_op_data", NULL);
curOp = xmlDocGetRootElement(docOp);
curOp2 = xmlNewTextChild (curOp, NULL, (const xmlChar *)"op_data", (const xmlChar *)nameTblIdx);
xmlNewProp (curOp2, (const xmlChar *)"path", (const xmlChar *)"/INDEX_DESC_P/INDEX_NAME");
curOp2 = xmlNewTextChild (curOp, NULL, (const xmlChar *)"op_data", (const xmlChar *)"extTableName");
xmlNewProp (curOp2, (const xmlChar *)"path", (const xmlChar *)"/INDEX_DEF_P/INDEX_ON_TABLE");
if (!gda_server_operation_load_data_from_xml (op, xmlDocGetRootElement (docOp), NULL))
{
/* error */
}
else
{
if(!gda_server_provider_perform_operation (prov, connection, op, NULL))
{
/* error */
}
}
xmlFreeDoc (docOp);
g_object_unref (op);
}
/* Prepare to create the index */
op = gda_server_provider_create_operation (prov, connection, GDA_SERVER_OPERATION_CREATE_INDEX, NULL, NULL);
if (!op)
return 70025;
/* we have to set the index parameters */
docOp = xmlNewDoc((const xmlChar *)XML_VERSION);
docOp->children = xmlNewDocNode(docOp, NULL, (const xmlChar *)"serv_op_data", NULL);
curOp = xmlDocGetRootElement(docOp);
curOp2 = xmlNewTextChild (curOp, NULL, (const xmlChar *)"op_data", (const xmlChar *)nameTblIdx);
xmlNewProp (curOp2, (const xmlChar *)"path", (const xmlChar *)"/INDEX_DEF_P/INDEX_NAME");
/* Unique */
sprintf(tmpString, "/ProLinga/Object/IndexInstances/IndexInstance[@SequenceNo='%d']/@Unique", i);
resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
idxUnique = (char *)xmlXPathCastToString(resObj);
if (strcmp(idxUnique, "True") == 0)
{
curOp2 = xmlNewTextChild (curOp, NULL, (const xmlChar *)"op_data", (const xmlChar *)"UNIQUE");
xmlNewProp (curOp2, (const xmlChar *)"path", (const xmlChar *)"/INDEX_DEF_P/INDEX_TYPE");
}
curOp2 = xmlNewTextChild (curOp, NULL, (const xmlChar *)"op_data", (const xmlChar *)extTableName);
xmlNewProp (curOp2, (const xmlChar *)"path", (const xmlChar *)"/INDEX_DEF_P/INDEX_ON_TABLE");
/* Get the key values */
sprintf(tmpString, "count(/ProLinga/Object/IndexInstances/IndexInstance[@SequenceNo='%d']/KeyInstances/KeyInstance)", i);
resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
keyHits = (int)xmlXPathCastToNumber(resObj);
/* Get index Values */
for (j = 1; j<= keyHits; j++)
{
/* Name */
sprintf(tmpString, "/ProLinga/Object/IndexInstances/IndexInstance[@SequenceNo='%d']/KeyInstances/KeyInstance[@SequenceNo='%d']/@Name", i,j);
resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
keyName = (char *)xmlXPathCastToString(resObj);
curOp2 = xmlNewTextChild (curOp, NULL, (const xmlChar *)"op_data", (const xmlChar *)keyName);
sprintf(tmpString, "/INDEX_FIELDS_S/%d/INDEX_FIELD",j-1);
xmlNewProp (curOp2, (const xmlChar *)"path", (const xmlChar *)tmpString);
// /* Sort */
// sprintf(tmpString, "/ProLinga/Object/IndexInstances/IndexInstance[@SequenceNo='%d']/KeyInstances/KeyInstance[@SequenceNo='%d']/@Sort", i,j);
// resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj);
// keySort = (char *)xmlXPathCastToString(resObj);
// if (strcmp(keySort, "Descending") == 0)
// gda_column_index_set_sorting(dmcia, GDA_SORTING_DESCENDING);
// else
// gda_column_index_set_sorting(dmcia, GDA_SORTING_ASCENDING);
}
// xmlBufferPtr bufTmp;
// bufTmp = xmlBufferCreate();
// curOp = xmlDocGetRootElement(docOp);
// xmlNodeDump(bufTmp, docOp, curOp, 0, 1);
// printf("%s\n", (char *)xmlBufferContent(bufTmp));
// xmlBufferFree(bufTmp);
/* Call create index call */
if (!gda_server_operation_load_data_from_xml (op, xmlDocGetRootElement (docOp), NULL))
return 70025;
if(!gda_server_provider_perform_operation (prov, connection, op, NULL))
return 70025;
/* Clean up */
xmlFreeDoc (docOp);
g_object_unref (op);
delete nameTblIdx;
}
}
else if (strcmp(buildOption, "Drop") == 0)
{
/* Get external (= table to build) table name */
resObj = xmlXPathEval((const xmlChar *)"/ProLinga/Object/ManageData/ExternalTableName", ctxObj);
extTableName = (char *)xmlXPathCastToString(resObj);
/* Drop Table */
prov = gda_connection_get_provider_obj(connection);
op = gda_server_provider_create_operation (prov, connection, GDA_SERVER_OPERATION_DROP_TABLE, NULL, NULL);
if (!op)
return 70022;
else
{
/* we have to set the table parameters */
docOp = xmlNewDoc((const xmlChar *)XML_VERSION);
docOp->children = xmlNewDocNode(docOp, NULL, (const xmlChar *)"serv_op_data", NULL);
curOp = xmlDocGetRootElement(docOp);
curOp = xmlNewTextChild (curOp, NULL, (const xmlChar *)"op_data", (const xmlChar *)extTableName);
xmlNewProp (curOp, (const xmlChar *)"path", (const xmlChar *)"/TABLE_DESC_P/TABLE_NAME");
if (!gda_server_operation_load_data_from_xml (op, xmlDocGetRootElement (docOp), NULL))
{
xmlFreeDoc (docOp);
g_object_unref (op);
return 70022;
}
else
{
if(!gda_server_provider_perform_operation (prov, connection, op, NULL))
{
xmlFreeDoc (docOp);
g_object_unref (op);
return 70022;
}
}
xmlFreeDoc (docOp);
g_object_unref (op);
}
}
else
return 70013;
/* Create return document */
*docReturn = xmlNewDoc((const xmlChar *)XML_VERSION);
(*docReturn)->children = xmlNewDocNode(*docReturn, NULL, (const xmlChar *)ROOT_ELEM, NULL);
/* Return */
return dbstatus;
}