/* * * ProLinga-Data * * Copyright (C) 2002-2009 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 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) { xmlXPathContextPtr ctxObj; xmlXPathObjectPtr resObj; GdaConnection *connection; char *extTableName; gchar *extTableNameQuoted; char *objDataSource = NULL, *objTable = NULL, *buildOption = NULL, *ddType; char *idxPrimary, *idxName, *idxUnique, *nameTblIdx, *colName; char *keyName; char *ddAllowNulls, tmpString[255]; int i, j, k, dbstatus = 0, dataHits, idxHits, keyHits, length; glong size, decimals; GdaServerProvider *prov; GdaServerOperation *op; const gchar *dbms_type; GdaMetaContext mcontext = {"_tables", 1, NULL, NULL}; gboolean metaStoreUpdateOK; GError *error = NULL; /* 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 DBMS Provider */ prov = gda_connection_get_provider(connection); if (!prov) return 70023; /* Get external (= table to build) table name */ resObj = xmlXPathEval((const xmlChar *)"/ProLinga/Object/ManageData/ExternalTableName", ctxObj); extTableName = (char *)xmlXPathCastToString(resObj); /* Drop Table */ op = gda_server_provider_create_operation (prov, connection, GDA_SERVER_OPERATION_DROP_TABLE, NULL, &error); if (!op) { if (error) { *externalError = error->message; return 90001; } else return 70022; } else { /* we have to set the table name parameter */ if (!gda_server_operation_set_value_at(op, extTableName, NULL, "/TABLE_DESC_P/TABLE_NAME")) { g_object_unref (op); return 70022; } else { /* Drop table and ignore error output. If there is nothing to drop, that is OK */ gda_connection_perform_operation(connection, op, NULL); } g_object_unref (op); } /* Prepare to create the table */ op = gda_server_provider_create_operation (prov, connection, GDA_SERVER_OPERATION_CREATE_TABLE, NULL, &error); if (!op) { if (error) { *externalError = error->message; return 90001; } else return 70023; } /* Get the data values */ resObj = xmlXPathEval((const xmlChar *)"count(/ProLinga/Object/DataInstances/DataInstance)", ctxObj); dataHits = (int)xmlXPathCastToNumber(resObj); /* Set Table Name */ if (!gda_server_operation_set_value_at (op, extTableName, NULL, "/TABLE_DEF_P/TABLE_NAME")) { g_object_unref (op); return 70023; } /* Get data Values (Columns) */ for (i = 0; i<= (dataHits-1); i++) { /* Set XML Doc idx */ j = i+1; /* Column Name */ sprintf(tmpString, "/ProLinga/Object/DataInstances/DataInstance[@SequenceNo='%d']/@Name", j); resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj); colName = (char *)xmlXPathCastToString(resObj); if (!gda_server_operation_set_value_at (op, colName, NULL, "/FIELDS_A/@COLUMN_NAME/%d", i)) { g_object_unref (op); return 70023; } /* Size */ sprintf(tmpString, "/ProLinga/Object/DataInstances/DataInstance[@SequenceNo='%d']/@Size", j); resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj); size = (glong)xmlXPathCastToNumber(resObj); /* Decimals */ sprintf(tmpString, "/ProLinga/Object/DataInstances/DataInstance[@SequenceNo='%d']/@Decimals", j); resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj); decimals = (glong)xmlXPathCastToNumber(resObj); /* Storage Type */ sprintf(tmpString, "/ProLinga/Object/DataInstances/DataInstance[@SequenceNo='%d']/@StorageType", j); resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj); ddType = (char *)xmlXPathCastToString(resObj); if (strcmp(ddType, "Character") == 0) dbms_type = gda_server_provider_get_default_dbms_type(prov,connection,G_TYPE_STRING); else if (strcmp(ddType, "Integer") == 0) dbms_type = gda_server_provider_get_default_dbms_type(prov,connection,G_TYPE_INT); else if (strcmp(ddType, "Long") == 0) dbms_type = gda_server_provider_get_default_dbms_type(prov,connection,G_TYPE_INT64); else if (strcmp(ddType, "Single") == 0) dbms_type = gda_server_provider_get_default_dbms_type(prov,connection,G_TYPE_FLOAT); else if (strcmp(ddType, "Double") == 0) dbms_type = gda_server_provider_get_default_dbms_type(prov,connection,G_TYPE_DOUBLE); else if (strcmp(ddType, "Numeric") == 0) dbms_type = gda_server_provider_get_default_dbms_type(prov,connection,GDA_TYPE_NUMERIC); else if (strcmp(ddType, "Date") == 0) dbms_type = gda_server_provider_get_default_dbms_type(prov,connection,G_TYPE_DATE); else { g_object_unref (op); return 70018; } if (!gda_server_operation_set_value_at (op, dbms_type, NULL, "/FIELDS_A/@COLUMN_TYPE/%d", i)) { g_object_unref (op); return 70023; } /* Size */ if ((strcmp(ddType, "Numeric") == 0) || (strcmp(ddType, "Character") == 0)) { sprintf(tmpString, "%ld", size); if (!gda_server_operation_set_value_at (op, tmpString, NULL, "/FIELDS_A/@COLUMN_SIZE/%d", i)) { g_object_unref (op); return 70023; } } /* Scale */ if (strcmp(ddType, "Numeric") == 0) { sprintf(tmpString, "%ld", decimals); if (!gda_server_operation_set_value_at (op, tmpString, NULL, "/FIELDS_A/@COLUMN_SCALE/%d", i)) { g_object_unref (op); return 70023; } } /* AllowNulls */ sprintf(tmpString, "/ProLinga/Object/DataInstances/DataInstance[@SequenceNo='%d']/@AllowNulls", j); resObj = xmlXPathEval((const xmlChar *)tmpString, ctxObj); ddAllowNulls = (char *)xmlXPathCastToString(resObj); if (strcmp(ddAllowNulls,"True") == 0) { if (!gda_server_operation_set_value_at (op, "TRUE", NULL, "/FIELDS_A/@COLUMN_NNUL/%d", i)) { g_object_unref (op); return 70023; } } else { if (!gda_server_operation_set_value_at (op, "FALSE", NULL, "/FIELDS_A/@COLUMN_NNUL/%d", i)) { g_object_unref (op); return 70023; } } /* Set Primary and Unique to FALSE */ if (!gda_server_operation_set_value_at (op, "FALSE", NULL, "/FIELDS_A/@COLUMN_UNIQUE/%d", i)) { g_object_unref (op); return 70023; } /* Check if column name part of primary key */ if (isPrimaryKeyField(docObj, colName) == true) { if (!gda_server_operation_set_value_at (op, "TRUE", NULL, "/FIELDS_A/@COLUMN_PKEY/%d", i)) { g_object_unref (op); return 70023; } } else { if (!gda_server_operation_set_value_at (op, "FALSE", NULL, "/FIELDS_A/@COLUMN_PKEY/%d", i)) { g_object_unref (op); return 70023; } } } /* Call create table call */ if (! gda_server_provider_perform_operation(prov, connection, op, &error)) { if (error) { *externalError = error->message; g_object_unref (op); return 90001; } else { g_object_unref (op); return 70023; } } 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) { if (!gda_server_operation_set_value_at (op, nameTblIdx, NULL, "/INDEX_DESC_P/INDEX_NAME")) { delete nameTblIdx; g_object_unref (op); return 70024; } if (!gda_server_operation_set_value_at (op, extTableName, NULL, "/INDEX_DESC_P/INDEX_ON_TABLE")) { delete nameTblIdx; g_object_unref (op); return 70024; } /* Remove index and ignore output as we don't care if the index was really there */ gda_server_provider_perform_operation(prov, connection, op, NULL); /* Clean up */ 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) { if (error) { *externalError = error->message; delete nameTblIdx; g_object_unref (op); return 90001; } else { delete nameTblIdx; g_object_unref (op); return 70025; } } if (!gda_server_operation_set_value_at (op, nameTblIdx, NULL, "/INDEX_DEF_P/INDEX_NAME")) { delete nameTblIdx; g_object_unref (op); return 70025; } /* 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) { if (!gda_server_operation_set_value_at (op, "UNIQUE", NULL, "/INDEX_DEF_P/INDEX_TYPE")) { delete nameTblIdx; g_object_unref (op); return 70025; } } else { if (!gda_server_operation_set_value_at (op, "", NULL, "/INDEX_DEF_P/INDEX_TYPE")) { delete nameTblIdx; g_object_unref (op); return 70025; } } if (!gda_server_operation_set_value_at (op, extTableName, NULL, "/INDEX_DEF_P/INDEX_ON_TABLE")) { delete nameTblIdx; g_object_unref (op); return 70025; } /* 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 (k = 0; k<= (keyHits-1); k++) { /* Set XML Doc idx */ j = k+1; /* 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); if (!gda_server_operation_set_value_at (op, keyName, NULL, "/INDEX_FIELDS_S/%d/INDEX_FIELD", k)) { delete nameTblIdx; g_object_unref (op); return 70025; } } /* Call create index call */ if (! gda_server_provider_perform_operation(prov, connection, op, &error)) { if (error) { *externalError = error->message; delete nameTblIdx; g_object_unref (op); return 90001; } else { delete nameTblIdx; g_object_unref (op); return 70025; } } /* Clean up */ g_object_unref (op); delete nameTblIdx; } /* Update Meta Store */ mcontext.column_names = g_new (gchar *, 1); mcontext.column_names[0] = "table_name"; mcontext.column_values = g_new (GValue *, 1); extTableNameQuoted = gda_sql_identifier_quote(extTableName, connection, NULL, TRUE, FALSE); g_value_set_string ((mcontext.column_values[0] = gda_value_new(G_TYPE_STRING)), extTableNameQuoted); g_free(extTableNameQuoted); metaStoreUpdateOK = gda_connection_update_meta_store(connection, &mcontext, &error); gda_value_free (mcontext.column_values[0]); if (metaStoreUpdateOK == FALSE) { *externalError = error->message; return 90001; } } 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 */ op = gda_connection_create_operation(connection,GDA_SERVER_OPERATION_DROP_TABLE, NULL, &error); if (!op) { if (error) { *externalError = error->message; return 90001; } else return 70024; } else { /* we have to set the table name parameter */ if (!gda_server_operation_set_value_at(op, extTableName, NULL, "/TABLE_DESC_P/TABLE_NAME")) { g_object_unref (op); return 70024; } else { if(!gda_connection_perform_operation(connection, op, NULL)) { g_object_unref (op); return 70024; } /* Update Meta Store */ mcontext.column_names = g_new (gchar *, 1); mcontext.column_names[0] = "table_name"; mcontext.column_values = g_new (GValue *, 1); extTableNameQuoted = gda_sql_identifier_quote(extTableName, connection, NULL, TRUE, FALSE); g_value_set_string ((mcontext.column_values[0] = gda_value_new(G_TYPE_STRING)), extTableNameQuoted); g_free(extTableNameQuoted); metaStoreUpdateOK = gda_connection_update_meta_store(connection, &mcontext, &error); gda_value_free (mcontext.column_values[0]); if (metaStoreUpdateOK == FALSE) { *externalError = error->message; return 90001; } } 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; }