/* * * 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; }