LCOV - code coverage report
Current view: top level - sql/backends/monet5/vaults/shp - shp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3 281 1.1 %
Date: 2024-04-25 21:43:30 Functions: 1 11 9.1 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : /*
      14             :  * Authors: K. Kyzirakos, D. Savva
      15             :  * This module contains primitives for accessing geospatial data
      16             :  * stored in ESRI Shapefile documents.
      17             :  */
      18             : 
      19             : #include "monetdb_config.h"
      20             : #include <string.h>
      21             : #include "sql_mvc.h"
      22             : #include "sql.h"
      23             : #ifndef __clang_major__         /* stupid include file gdal/cpl_port.h */
      24             : #define __clang_major__ 0
      25             : #endif
      26             : #include "shp.h"
      27             : #include <cpl_conv.h>             /* for CPLFree */
      28             : #include "sql_execute.h"
      29             : #include "mal_exception.h"
      30             : 
      31             : #include "libgeom.h"
      32             : 
      33           0 : GDALWConnection * GDALWConnect(char * source) {
      34           0 :         GDALWConnection * conn = NULL;
      35           0 :         OGRFeatureDefnH featureDefn;
      36           0 :         int fieldCount, i;
      37           0 :         OGRRegisterAll();
      38           0 :         conn = malloc(sizeof(GDALWConnection));
      39           0 :         if (conn == NULL) {
      40           0 :                 TRC_ERROR(SHP, "Could not allocate memory\n");
      41           0 :                 return NULL;
      42             :         }
      43           0 :         conn->handler = OGROpen(source, 0 , &(conn->driver));
      44           0 :         if (conn->handler == NULL) {
      45           0 :                 free(conn);
      46           0 :                 return NULL;
      47             :         }
      48             : 
      49           0 :         conn->layer = OGR_DS_GetLayer(conn->handler, 0);
      50           0 :         if (conn->layer == NULL) {
      51           0 :                 OGRReleaseDataSource(conn->handler);
      52           0 :                 free(conn);
      53           0 :                 return NULL;
      54             :         }
      55             : 
      56           0 :         conn->layername = (const char *) OGR_L_GetName(conn->layer);
      57             : 
      58           0 :         featureDefn = OGR_L_GetLayerDefn(conn->layer);
      59           0 :         fieldCount = OGR_FD_GetFieldCount(featureDefn);
      60           0 :         conn->numFieldDefinitions = fieldCount;
      61           0 :         conn->fieldDefinitions = malloc(fieldCount * sizeof(OGRFieldDefnH));
      62           0 :         if (conn->fieldDefinitions == NULL) {
      63           0 :                 OGRReleaseDataSource(conn->handler);
      64           0 :                 free(conn);
      65           0 :                 TRC_ERROR(SHP, "Could not allocate memory\n");
      66           0 :                 return NULL;
      67             :         }
      68           0 :         for (i=0 ; i<fieldCount ; i++) {
      69           0 :                 conn->fieldDefinitions[i] = OGR_FD_GetFieldDefn(featureDefn, i);
      70             :         }
      71             : 
      72             :         return conn;
      73             : }
      74             : 
      75           0 : void GDALWClose(GDALWConnection * conn) {
      76           0 :         free(conn->fieldDefinitions);
      77           0 :         OGRReleaseDataSource(conn->handler);
      78           0 :         free(conn);
      79           0 : }
      80             : 
      81           0 : GDALWSimpleFieldDef * GDALWGetSimpleFieldDefinitions(GDALWConnection conn) {
      82           0 :         int i;
      83           0 :         GDALWSimpleFieldDef * columns;
      84           0 :         OGRFieldDefnH fieldDefn;
      85             :         /*if (conn.layer == NULL || conn.handler == NULL || conn.driver == NULL) {
      86             :                 printf("Could not extract columns, initialize a connection first.\n");
      87             :                 exit(-1);
      88             :         }*/
      89           0 :         columns = malloc(conn.numFieldDefinitions * sizeof(GDALWSimpleFieldDef));
      90           0 :         if (columns == NULL) {
      91           0 :                 TRC_ERROR(SHP, "Could not allocate memory\n");
      92           0 :                 return NULL;
      93             :         }
      94           0 :         for (i=0 ; i<conn.numFieldDefinitions ; i++) {
      95           0 :                 fieldDefn = conn.fieldDefinitions[i];
      96           0 :                 columns[i].fieldName = OGR_Fld_GetNameRef(fieldDefn);
      97           0 :                 columns[i].fieldType = OGR_GetFieldTypeName(OGR_Fld_GetType(fieldDefn));
      98             :         }
      99             : 
     100             :         return columns;
     101             : }
     102             : 
     103           0 : void GDALWPrintRecords(GDALWConnection conn) {
     104           0 :         char * wkt;
     105           0 :         int i;
     106           0 :         OGRFeatureH feature;
     107           0 :         OGRGeometryH geometry;
     108           0 :         OGRFeatureDefnH featureDefn;
     109           0 :         featureDefn = OGR_L_GetLayerDefn(conn.layer);
     110           0 :         OGR_L_ResetReading(conn.layer);
     111           0 :         while( (feature = OGR_L_GetNextFeature(conn.layer)) != NULL ) {
     112           0 :                 for(i = 0; i < OGR_FD_GetFieldCount(featureDefn); i++ ) {
     113           0 :                         OGRFieldDefnH hFieldDefn = OGR_FD_GetFieldDefn( featureDefn, i );
     114           0 :                     if( OGR_Fld_GetType(hFieldDefn) == OFTInteger )
     115           0 :                         printf( "%d,", OGR_F_GetFieldAsInteger( feature, i ) );
     116           0 :                     else if( OGR_Fld_GetType(hFieldDefn) == OFTReal )
     117           0 :                         printf( "%.3f,", OGR_F_GetFieldAsDouble( feature, i) );
     118             :                     else
     119           0 :                         printf( "%s,", OGR_F_GetFieldAsString( feature, i) );
     120             : 
     121             :                 }
     122           0 :                 geometry = OGR_F_GetGeometryRef(feature);
     123           0 :                 OGR_G_ExportToWkt(geometry, &wkt);
     124           0 :                 printf("%s", wkt);
     125           0 :                 printf("\n");
     126           0 :                 CPLFree(wkt);
     127           0 :                 OGR_F_Destroy(feature);
     128             :         }
     129           0 : }
     130             : 
     131           0 : GDALWSpatialInfo GDALWGetSpatialInfo(GDALWConnection conn) {
     132           0 :         GDALWSpatialInfo spatialInfo;
     133           0 :         OGRSpatialReferenceH spatialRef = OGR_L_GetSpatialRef(conn.layer);
     134           0 :         char * proj4, * srsText, * srid;
     135             : 
     136           0 :         OSRExportToProj4(spatialRef, &proj4);
     137           0 :         OSRExportToWkt(spatialRef, &srsText);
     138           0 :         srid = (char *) OSRGetAttrValue(spatialRef, "AUTHORITY", 1);
     139           0 :         if (srid == NULL) {
     140             :                 spatialInfo.epsg = 4326;
     141             :         }
     142             :         else {
     143           0 :                 spatialInfo.epsg = atoi(OSRGetAttrValue(spatialRef, "AUTHORITY", 1));
     144             :         }
     145           0 :         spatialInfo.authName = OSRGetAttrValue(spatialRef, "AUTHORITY", 0);
     146           0 :         if (spatialInfo.authName == NULL) {
     147           0 :                 spatialInfo.authName = "EPSG";
     148             :         }
     149           0 :         spatialInfo.proj4Text = proj4;
     150           0 :         spatialInfo.srsText = srsText;
     151             : 
     152           0 :         return spatialInfo;
     153             : }
     154             : 
     155             : //Using SQL query
     156           0 : str createSHPtable(Client cntxt, str schemaname, str tablename, GDALWConnection shp_conn, GDALWSimpleFieldDef *field_definitions) {
     157           0 :         unsigned int size = BUFSIZ;
     158           0 :         char *buf = NULL, *temp_buf = GDKmalloc(BUFSIZ * sizeof(char));
     159           0 :         char *nameToLowerCase = NULL;
     160           0 :         str msg = MAL_SUCCEED;
     161             : 
     162           0 :         if (field_definitions == NULL)
     163             :         {
     164             :                 /* Can't find shapefile field definitions */
     165           0 :                 return createException(MAL, "shp.load", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     166             :         }
     167             : 
     168             :         /* Create the table that will store the data of the shape file (Allows integers, floats and strings) */
     169           0 :         temp_buf[0] = '\0';
     170           0 :         for (int i = 0; i < shp_conn.numFieldDefinitions; i++)
     171             :         {
     172             :                 /*If the next column definition doesn't fit in the buffer, resize the buffers to double
     173             :                 Compare current buffer size with current lenght + field name lenght + 11 (lenght of string column definition)*/
     174           0 :                 if (size <= (11 + strlen(field_definitions[i].fieldName) + strlen(temp_buf)))
     175             :                 {
     176           0 :                         size = 2 * size;
     177           0 :                         temp_buf = GDKrealloc(temp_buf, size);
     178             :                 }
     179           0 :                 nameToLowerCase = toLower(field_definitions[i].fieldName);
     180           0 :                 if (strcmp(field_definitions[i].fieldType, "Integer") == 0)
     181             :                 {
     182           0 :                         sprintf(temp_buf + strlen(temp_buf), "\"%s\" INT, ", nameToLowerCase);
     183             :                 }
     184           0 :                 else if (strcmp(field_definitions[i].fieldType, "Real") == 0)
     185             :                 {
     186           0 :                         sprintf(temp_buf + strlen(temp_buf), "\"%s\" FLOAT, ", nameToLowerCase);
     187             :                 }
     188             :                 else
     189           0 :                         sprintf(temp_buf + strlen(temp_buf), "\"%s\" STRING, ", nameToLowerCase);
     190           0 :                 GDKfree(nameToLowerCase);
     191             :         }
     192             : 
     193             :         //Each shapefile table has one geom column
     194           0 :         sprintf(temp_buf + strlen(temp_buf), "geom GEOMETRY ");
     195             : 
     196             :         //Concat the schema name with the table name
     197           0 :         size_t schemaTableSize = strlen(schemaname) + strlen(tablename) + 3;
     198           0 :         char *schemaTable = GDKmalloc(schemaTableSize);
     199           0 :         snprintf(schemaTable, schemaTableSize - 1, "%s.%s", schemaname, tablename);
     200             : 
     201             :         //Build the CREATE TABLE command
     202           0 :         buf = GDKmalloc((size + schemaTableSize) * sizeof(char));
     203           0 :         snprintf(buf, size + schemaTableSize, CRTTBL, schemaTable, temp_buf);
     204             :         //And execute it
     205           0 :         msg = SQLstatementIntern(cntxt, buf, "shp.load", TRUE, FALSE, NULL);
     206             : 
     207           0 :         GDKfree(buf);
     208           0 :         GDKfree(temp_buf);
     209           0 :         GDKfree(schemaTable);
     210           0 :         return msg;
     211             : }
     212             : 
     213           0 : str loadSHPtable(mvc *m, sql_schema *sch, str schemaname, str tablename, GDALWConnection shp_conn, GDALWSimpleFieldDef *field_definitions, GDALWSpatialInfo spatial_info) {
     214           0 :         sql_table *data_table = NULL;
     215           0 :         sql_column **cols;
     216           0 :         BAT **colsBAT;
     217           0 :         int colsNum = 2; //we will have at least the gid column and a geometry column
     218           0 :         int rowsNum = 0; //the number of rows in the shape file that will be imported
     219           0 :         int gidNum = 0;
     220           0 :         str msg = MAL_SUCCEED;
     221           0 :         char *nameToLowerCase = NULL;
     222           0 :         int i;
     223             : 
     224           0 :         BUN offset;
     225           0 :         BAT *pos = NULL;
     226           0 :         sqlstore *store;
     227             : 
     228             :         /* SHP-level descriptor */
     229           0 :         OGRFieldDefnH hFieldDefn;
     230           0 :         OGRFeatureH feature;
     231           0 :         OGRFeatureDefnH featureDefn;
     232             : 
     233             :         /* Count the number of lines in the shape file */
     234           0 :         if ((rowsNum = OGR_L_GetFeatureCount(shp_conn.layer, false)) == -1) {
     235           0 :                 OGR_L_ResetReading(shp_conn.layer);
     236           0 :                 rowsNum = 0;
     237           0 :                 while ((feature = OGR_L_GetNextFeature(shp_conn.layer)) != NULL) {
     238           0 :                         rowsNum++;
     239           0 :                         OGR_F_Destroy(feature);
     240             :                 }
     241             :         }
     242             : 
     243             :         /* bind the columns of the data table that was just created
     244             :         * and create a BAT for each of the columns */
     245           0 :         if (!(data_table = mvc_bind_table(m, sch, tablename))) {
     246             :                 /* Previously create output table is missing */
     247           0 :                 msg = createException(MAL, "shp.load", SQLSTATE(42SO2) "Table '%s.%s' missing", schemaname, tablename);
     248           0 :                 return msg;
     249             :         }
     250           0 :         colsNum += shp_conn.numFieldDefinitions;
     251           0 :         if (!(cols = (sql_column **)GDKmalloc(sizeof(sql_column *) * colsNum))) {
     252           0 :                 msg = createException(MAL, "shp.load", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     253           0 :                 return msg;
     254             :         }
     255           0 :         if (!(colsBAT = (BAT **)GDKzalloc(sizeof(BAT *) * colsNum))) {
     256           0 :                 msg = createException(MAL, "shp.load", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     257           0 :                 GDKfree(cols);
     258           0 :                 return msg;
     259             :         }
     260             : 
     261             :         /* Bind shapefile attributes to columns */
     262           0 :         for (i = 0; i < colsNum - 2; i++) {
     263           0 :                 cols[i] = NULL;
     264             :                 /* bind the column */
     265           0 :                 nameToLowerCase = toLower(field_definitions[i].fieldName);
     266           0 :                 cols[i] = mvc_bind_column(m, data_table, nameToLowerCase);
     267           0 :                 GDKfree(nameToLowerCase);
     268           0 :                 if (cols[i] == NULL) {
     269           0 :                         msg = createException(MAL, "shp.load", SQLSTATE(42SO2) "Column '%s.%s(%s)' missing", schemaname, tablename, toLower(field_definitions[i].fieldName));
     270           0 :                         goto unfree;
     271             :                 }
     272             :                 /*create the BAT */
     273           0 :                 if (strcmp(field_definitions[i].fieldType, "Integer") == 0) {
     274           0 :                         if (!(colsBAT[i] = COLnew(0, TYPE_int, rowsNum, PERSISTENT))) {
     275           0 :                                 msg = createException(MAL, "shp.load", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     276           0 :                                 goto unfree;
     277             :                         }
     278             :                 }
     279           0 :                 else if (strcmp(field_definitions[i].fieldType, "Real") == 0) {
     280           0 :                         if (!(colsBAT[i] = COLnew(0, TYPE_dbl, rowsNum, PERSISTENT))) {
     281           0 :                                 msg = createException(MAL, "shp.load", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     282           0 :                                 goto unfree;
     283             :                         }
     284             :                 }
     285             :                 else {
     286           0 :                         if (!(colsBAT[i] = COLnew(0, TYPE_str, rowsNum, PERSISTENT))) {
     287           0 :                                 msg = createException(MAL, "shp.load", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     288           0 :                                 goto unfree;
     289             :                         }
     290             :                 }
     291             :         }
     292             :         /* Bind GID and GEOM columns */
     293           0 :         if (!(cols[colsNum - 2] = mvc_bind_column(m, data_table, "gid"))) {
     294           0 :                 msg = createException(MAL, "shp.load", SQLSTATE(42SO2) "Column '%s.%s(gid)' missing", schemaname, tablename);
     295           0 :                 goto unfree;
     296             :         }
     297           0 :         if (!(colsBAT[colsNum - 2] = COLnew(0, TYPE_int, rowsNum, PERSISTENT))) {
     298           0 :                 msg = createException(MAL, "shp.load", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     299           0 :                 goto unfree;
     300             :         }
     301           0 :         if (!(cols[colsNum - 1] = mvc_bind_column(m, data_table, "geom"))) {
     302           0 :                 msg = createException(MAL, "shp.load", SQLSTATE(42SO2) "Column '%s.%s(geom)' missing", schemaname, tablename);
     303           0 :                 goto unfree;
     304             :         }
     305           0 :         if (!(colsBAT[colsNum - 1] = COLnew(0, ATOMindex("wkb"), rowsNum, PERSISTENT))) {
     306           0 :                 msg = createException(MAL, "shp.load", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     307           0 :                 goto unfree;
     308             :         }
     309             : 
     310             :         /* Import the data */
     311           0 :         featureDefn = OGR_L_GetLayerDefn(shp_conn.layer);
     312           0 :         OGR_L_ResetReading(shp_conn.layer);
     313             :         /* Import shapefile attributes */
     314           0 :         while ((feature = OGR_L_GetNextFeature(shp_conn.layer)) != NULL) {
     315           0 :                 wkb *geomWKB;
     316           0 :                 int len;
     317           0 :                 int gidTemp = ++gidNum;
     318           0 :                 gdk_return rc;
     319             : 
     320           0 :                 OGRGeometryH geometry = OGR_F_GetGeometryRef(feature);
     321             : 
     322           0 :                 for (i = 0; i < colsNum - 2; i++) {
     323           0 :                         hFieldDefn = OGR_FD_GetFieldDefn(featureDefn, i);
     324           0 :                         if (OGR_Fld_GetType(hFieldDefn) == OFTInteger) {
     325           0 :                                 int val = OGR_F_GetFieldAsInteger(feature, i);
     326           0 :                                 rc = BUNappend(colsBAT[i], &val, false);
     327             :                         }
     328           0 :                         else if (OGR_Fld_GetType(hFieldDefn) == OFTReal) {
     329           0 :                                 double val = OGR_F_GetFieldAsDouble(feature, i);
     330           0 :                                 rc = BUNappend(colsBAT[i], &val, false);
     331             :                         }
     332             :                         else {
     333           0 :                                 rc = BUNappend(colsBAT[i], OGR_F_GetFieldAsString(feature, i), false);
     334             :                         }
     335           0 :                         if (rc != GDK_SUCCEED) {
     336             :                                 /* Append to column failed */
     337           0 :                                 msg = createException(MAL, "shp.load", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     338           0 :                                 goto unfree;
     339             :                         }
     340             :                 }
     341             : 
     342             :                 /* Import GID and GEOM columns */
     343           0 :                 if (BUNappend(colsBAT[colsNum - 2], &gidTemp, false) != GDK_SUCCEED) {
     344           0 :                         msg = createException(MAL, "shp.load", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     345           0 :                         goto unfree;
     346             :                 }
     347             : 
     348           0 :                 len = OGR_G_WkbSize(geometry);
     349           0 :                 if (!(geomWKB = GDKmalloc(sizeof(wkb) + len))) {
     350           0 :                         msg = createException(MAL, "shp.load", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     351           0 :                         OGR_F_Destroy(feature);
     352           0 :                         goto unfree;
     353             :                 }
     354           0 :                 geomWKB->len = len;
     355             :                 /* Set SRID */
     356           0 :                 geomWKB->srid = spatial_info.epsg;
     357           0 :                 OGR_G_ExportToWkb(geometry, wkbNDR, (unsigned char *)geomWKB->data);
     358           0 :                 rc = BUNappend(colsBAT[colsNum - 1], geomWKB, false);
     359             : 
     360           0 :                 GDKfree(geomWKB);
     361           0 :                 OGR_F_Destroy(feature);
     362           0 :                 if (rc != GDK_SUCCEED)
     363           0 :                         goto unfree;
     364             :         }
     365             :         /* finalise the BATs */
     366           0 :         store = m->session->tr->store;
     367           0 :         if (store->storage_api.claim_tab(m->session->tr, data_table, BATcount(colsBAT[0]), &offset, &pos) != LOG_OK) {
     368           0 :                 msg = createException(MAL, "shp.load", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     369           0 :                 goto unfree;
     370             :         }
     371             : 
     372           0 :         for (i = 0; i < colsNum; i++) {
     373           0 :                 if (store->storage_api.append_col(m->session->tr, cols[i], offset, pos, colsBAT[i], BATcount(colsBAT[i]), true, colsBAT[i]->ttype) != LOG_OK) {
     374           0 :                         bat_destroy(pos);
     375           0 :                         msg = createException(MAL, "shp.load", SQLSTATE(38000) "Geos append column failed");
     376           0 :                         goto unfree;
     377             :                 }
     378             :         }
     379           0 :         GDKfree(colsBAT);
     380           0 :         GDKfree(cols);
     381           0 :         bat_destroy(pos);
     382           0 :         return msg;
     383           0 : unfree:
     384           0 :         for (i = 0; i < colsNum; i++)
     385           0 :                 if (colsBAT[i])
     386           0 :                         BBPunfix(colsBAT[i]->batCacheid);
     387           0 :         free(field_definitions);
     388           0 :         GDKfree(cols);
     389           0 :         GDKfree(colsBAT);
     390           0 :         return msg;
     391             : }
     392             : 
     393           0 : static str SHPloadInternal (Client cntxt, MalBlkPtr mb, str filename, str schemaname, str tablename) {
     394           0 :         str msg = MAL_SUCCEED;
     395           0 :         mvc *m = NULL;
     396           0 :         sql_schema *sch = NULL;
     397             : 
     398           0 :         if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != MAL_SUCCEED)
     399             :                 return msg;
     400           0 :         if ((msg = checkSQLContext(cntxt)) != MAL_SUCCEED)
     401             :                 return msg;
     402             : 
     403             :         /* SHP-level descriptor */
     404           0 :         GDALWConnection shp_conn;
     405           0 :         GDALWConnection *shp_conn_ptr = NULL;
     406           0 :         GDALWSimpleFieldDef *field_definitions;
     407           0 :         GDALWSpatialInfo spatial_info;
     408             : 
     409           0 :         if (!(sch = mvc_bind_schema(m, schemaname)))
     410             :                 /* Can't find schema */
     411           0 :                 return createException(MAL, "shp.load", SQLSTATE(38000) "Schema %s missing\n", schemaname);
     412             : 
     413           0 :         if ((tablename != NULL) && (tablename[0] == '\0'))
     414             :                 /* Output table name is NULL */
     415           0 :                 return createException(MAL, "shp.load", SQLSTATE(38000) "Missing output table name %s\n", tablename);
     416             : 
     417           0 :         if ((shp_conn_ptr = GDALWConnect((char *)filename)) == NULL)
     418             :                 /* Can't find shapefile */
     419           0 :                 return createException(MAL, "shp.load", SQLSTATE(38000) "Missing shape file %s\n", filename);
     420             : 
     421             :         /* Get info about fields and spatial attributes of shapefile*/
     422           0 :         shp_conn = *shp_conn_ptr;
     423           0 :         spatial_info = GDALWGetSpatialInfo(shp_conn);
     424           0 :         field_definitions = GDALWGetSimpleFieldDefinitions(shp_conn);
     425             : 
     426             :         /* Convert schema and table name to lower case*/
     427           0 :         schemaname = toLower(schemaname);
     428           0 :         tablename = toLower(tablename);
     429             : 
     430             :         /* Create table for outputting shapefile data */
     431           0 :         if ((msg = createSHPtable(cntxt, schemaname, tablename, shp_conn, field_definitions)) != MAL_SUCCEED) {
     432             :                 /* Create table failed */
     433           0 :                 GDKfree(schemaname);
     434           0 :                 GDKfree(tablename);
     435           0 :                 free(field_definitions);
     436           0 :                 GDALWClose(shp_conn_ptr);
     437           0 :                 return msg;
     438             :         }
     439             : 
     440             :         //TODO If createSHPtable works and loadSHPtable doesn't, we have to clean the created table
     441             :         /* Load shapefile data into table */
     442           0 :         msg = loadSHPtable(m, sch, schemaname, tablename, shp_conn, field_definitions, spatial_info);
     443             : 
     444             :         /* Frees */
     445           0 :         GDKfree(schemaname);
     446           0 :         GDKfree(tablename);
     447           0 :         free(field_definitions);
     448           0 :         GDALWClose(shp_conn_ptr);
     449             : 
     450           0 :         return msg;
     451             : }
     452             : 
     453             : /* TODO: Use Shapefile table to avoid loading the same file more than once, or allow the user to load as many times as he wants? */
     454             : /* Attach and load single shp file given its file name and output table name */
     455           0 : str SHPloadSchema(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     456             : {
     457             :         /* Shapefile name (argument 1) */
     458           0 :         str filename = *(str *)getArgReference(stk, pci, 1);
     459             :         /* Output schema name (argument 2) */
     460           0 :         str schemaname = *(str *)getArgReference(stk, pci, 2);
     461             :         /* Output table name (argument 3) */
     462           0 :         str tablename = *(str *)getArgReference(stk, pci, 3);
     463           0 :         return SHPloadInternal(cntxt,mb,filename,schemaname,tablename);
     464             : }
     465             : 
     466           0 : str SHPload(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
     467             :         /* Shapefile name (argument 1) */
     468           0 :         str filename = *(str *)getArgReference(stk, pci, 1);
     469             :         /* Output table name (argument 3) */
     470           0 :         str tablename = *(str *)getArgReference(stk, pci, 2);
     471           0 :         return SHPloadInternal(cntxt,mb,filename,"sys",tablename);
     472             : }
     473             : 
     474             : #include "mel.h"
     475             : static mel_func shp_init_funcs[] = {
     476             :         pattern("shp", "load", SHPloadSchema, false, "Import an ESRI Shapefile into a new table, on a certain schema", args(1, 4, arg("", void), arg("filename", str), arg("schemaname", str), arg("tablename", str))),
     477             :         pattern("shp", "load", SHPload, false, "Import an ESRI Shapefile into a new table, on the sys schema", args(1, 3, arg("", void), arg("filename", str), arg("tablename", str))),
     478             :         {.imp = NULL}};
     479             : #include "mal_import.h"
     480             : #ifdef _MSC_VER
     481             : #undef read
     482             : #pragma section(".CRT$XCU", read)
     483             : #endif
     484         329 : LIB_STARTUP_FUNC(init_shp_mal)
     485             : {
     486         329 :         mal_module("shp", NULL, shp_init_funcs);
     487         329 : }

Generated by: LCOV version 1.14