1 /******************************************************************************
2 * $Id: ogrcartodbtablelayer.cpp 29004 2015-04-25 08:38:29Z rouault $
3 *
4 * Project: CartoDB Translator
5 * Purpose: Implements OGRCARTODBTableLayer class.
6 * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 *
8 ******************************************************************************
9 * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 ****************************************************************************/
29
30 #include "ogr_cartodb.h"
31 #include "ogr_p.h"
32 #include "ogr_pgdump.h"
33
34 CPL_CVSID("$Id: ogrcartodbtablelayer.cpp 29004 2015-04-25 08:38:29Z rouault $");
35
36 /************************************************************************/
37 /* OGRCARTODBEscapeIdentifier( ) */
38 /************************************************************************/
39
OGRCARTODBEscapeIdentifier(const char * pszStr)40 CPLString OGRCARTODBEscapeIdentifier(const char* pszStr)
41 {
42 CPLString osStr;
43
44 osStr += "\"";
45
46 char ch;
47 for(int i=0; (ch = pszStr[i]) != '\0'; i++)
48 {
49 if (ch == '"')
50 osStr.append(1, ch);
51 osStr.append(1, ch);
52 }
53
54 osStr += "\"";
55
56 return osStr;
57 }
58
59 /************************************************************************/
60 /* OGRCARTODBEscapeLiteral( ) */
61 /************************************************************************/
62
OGRCARTODBEscapeLiteral(const char * pszStr)63 CPLString OGRCARTODBEscapeLiteral(const char* pszStr)
64 {
65 CPLString osStr;
66
67 char ch;
68 for(int i=0; (ch = pszStr[i]) != '\0'; i++)
69 {
70 if (ch == '\'')
71 osStr.append(1, ch);
72 osStr.append(1, ch);
73 }
74
75 return osStr;
76 }
77
78 /************************************************************************/
79 /* OGRCARTODBTableLayer() */
80 /************************************************************************/
81
OGRCARTODBTableLayer(OGRCARTODBDataSource * poDS,const char * pszName)82 OGRCARTODBTableLayer::OGRCARTODBTableLayer(OGRCARTODBDataSource* poDS,
83 const char* pszName) :
84 OGRCARTODBLayer(poDS)
85
86 {
87 osName = pszName;
88 SetDescription( osName );
89 bLaunderColumnNames = TRUE;
90 bInDeferedInsert = poDS->DoBatchInsert();
91 nNextFID = -1;
92 bDeferedCreation = FALSE;
93 bCartoDBify = FALSE;
94 nMaxChunkSize = atoi(CPLGetConfigOption("CARTODB_MAX_CHUNK_SIZE", "15")) * 1024 * 1024;
95 }
96
97 /************************************************************************/
98 /* ~OGRCARTODBTableLayer() */
99 /************************************************************************/
100
~OGRCARTODBTableLayer()101 OGRCARTODBTableLayer::~OGRCARTODBTableLayer()
102
103 {
104 if( bDeferedCreation ) RunDeferedCreationIfNecessary();
105 FlushDeferedInsert();
106 }
107
108 /************************************************************************/
109 /* GetLayerDefnInternal() */
110 /************************************************************************/
111
GetLayerDefnInternal(CPL_UNUSED json_object * poObjIn)112 OGRFeatureDefn * OGRCARTODBTableLayer::GetLayerDefnInternal(CPL_UNUSED json_object* poObjIn)
113 {
114 if( poFeatureDefn != NULL )
115 return poFeatureDefn;
116
117 CPLString osCommand;
118 if( poDS->IsAuthenticatedConnection() )
119 {
120 // Get everything !
121 osCommand.Printf(
122 "SELECT a.attname, t.typname, a.attlen, "
123 "format_type(a.atttypid,a.atttypmod), "
124 "a.attnum, "
125 "a.attnotnull, "
126 "i.indisprimary, "
127 "pg_get_expr(def.adbin, c.oid) AS defaultexpr, "
128 "postgis_typmod_dims(a.atttypmod) dim, "
129 "postgis_typmod_srid(a.atttypmod) srid, "
130 "postgis_typmod_type(a.atttypmod)::text geomtyp, "
131 "srtext "
132 "FROM pg_class c "
133 "JOIN pg_attribute a ON a.attnum > 0 AND "
134 "a.attrelid = c.oid AND c.relname = '%s' "
135 "JOIN pg_type t ON a.atttypid = t.oid "
136 "JOIN pg_namespace n ON c.relnamespace=n.oid AND n.nspname= '%s' "
137 "LEFT JOIN pg_index i ON c.oid = i.indrelid AND "
138 "i.indisprimary = 't' AND a.attnum = ANY(i.indkey) "
139 "LEFT JOIN pg_attrdef def ON def.adrelid = c.oid AND "
140 "def.adnum = a.attnum "
141 "LEFT JOIN spatial_ref_sys srs ON srs.srid = postgis_typmod_srid(a.atttypmod) "
142 "ORDER BY a.attnum",
143 OGRCARTODBEscapeLiteral(osName).c_str(),
144 OGRCARTODBEscapeLiteral(poDS->GetCurrentSchema()).c_str());
145 }
146 else if( poDS->HasOGRMetadataFunction() != FALSE )
147 {
148 osCommand.Printf( "SELECT * FROM ogr_table_metadata('%s', '%s')",
149 OGRCARTODBEscapeLiteral(poDS->GetCurrentSchema()).c_str(),
150 OGRCARTODBEscapeLiteral(osName).c_str() );
151 }
152
153 if( osCommand.size() )
154 {
155 if( !poDS->IsAuthenticatedConnection() && poDS->HasOGRMetadataFunction() < 0 )
156 CPLPushErrorHandler(CPLQuietErrorHandler);
157 OGRLayer* poLyr = poDS->ExecuteSQLInternal(osCommand);
158 if( !poDS->IsAuthenticatedConnection() && poDS->HasOGRMetadataFunction() < 0 )
159 {
160 CPLPopErrorHandler();
161 if( poLyr == NULL )
162 {
163 CPLDebug("CARTODB", "ogr_table_metadata(text, text) not available");
164 CPLErrorReset();
165 }
166 else if( poLyr->GetLayerDefn()->GetFieldCount() != 12 )
167 {
168 CPLDebug("CARTODB", "ogr_table_metadata(text, text) has unexpected column count");
169 poDS->ReleaseResultSet(poLyr);
170 poLyr = NULL;
171 }
172 poDS->SetOGRMetadataFunction(poLyr != NULL);
173 }
174 if( poLyr )
175 {
176 poFeatureDefn = new OGRFeatureDefn(osName);
177 poFeatureDefn->Reference();
178 poFeatureDefn->SetGeomType(wkbNone);
179
180 OGRFeature* poFeat;
181 while( (poFeat = poLyr->GetNextFeature()) != NULL )
182 {
183 const char* pszAttname = poFeat->GetFieldAsString("attname");
184 const char* pszType = poFeat->GetFieldAsString("typname");
185 int nWidth = poFeat->GetFieldAsInteger("attlen");
186 const char* pszFormatType = poFeat->GetFieldAsString("format_type");
187 int bNotNull = poFeat->GetFieldAsInteger("attnotnull");
188 int bIsPrimary = poFeat->GetFieldAsInteger("indisprimary");
189 const char* pszDefault = (poFeat->IsFieldSet(poLyr->GetLayerDefn()->GetFieldIndex("defaultexpr"))) ?
190 poFeat->GetFieldAsString("defaultexpr") : NULL;
191
192 if( bIsPrimary &&
193 (EQUAL(pszType, "int2") ||
194 EQUAL(pszType, "int4") ||
195 EQUAL(pszType, "int8") ||
196 EQUAL(pszType, "serial") ||
197 EQUAL(pszType, "bigserial")) )
198 {
199 osFIDColName = pszAttname;
200 }
201 else if( strcmp(pszAttname, "created_at") == 0 ||
202 strcmp(pszAttname, "updated_at") == 0 ||
203 strcmp(pszAttname, "the_geom_webmercator") == 0)
204 {
205 /* ignored */
206 }
207 else
208 {
209 if( EQUAL(pszType,"geometry") )
210 {
211 int nDim = poFeat->GetFieldAsInteger("dim");
212 int nSRID = poFeat->GetFieldAsInteger("srid");
213 const char* pszGeomType = poFeat->GetFieldAsString("geomtyp");
214 const char* pszSRText = (poFeat->IsFieldSet(
215 poLyr->GetLayerDefn()->GetFieldIndex("srtext"))) ?
216 poFeat->GetFieldAsString("srtext") : NULL;
217 OGRwkbGeometryType eType = OGRFromOGCGeomType(pszGeomType);
218 if( nDim == 3 )
219 eType = wkbSetZ(eType);
220 OGRCartoDBGeomFieldDefn *poFieldDefn =
221 new OGRCartoDBGeomFieldDefn(pszAttname, eType);
222 if( bNotNull )
223 poFieldDefn->SetNullable(FALSE);
224 OGRSpatialReference* poSRS = NULL;
225 if( pszSRText != NULL )
226 {
227 poSRS = new OGRSpatialReference();
228 char* pszTmp = (char* )pszSRText;
229 if( poSRS->importFromWkt(&pszTmp) != OGRERR_NONE )
230 {
231 delete poSRS;
232 poSRS = NULL;
233 }
234 if( poSRS != NULL )
235 {
236 poFieldDefn->SetSpatialRef(poSRS);
237 poSRS->Release();
238 }
239 }
240 poFieldDefn->nSRID = nSRID;
241 poFeatureDefn->AddGeomFieldDefn(poFieldDefn, FALSE);
242 }
243 else
244 {
245 OGRFieldDefn oField(pszAttname, OFTString);
246 if( bNotNull )
247 oField.SetNullable(FALSE);
248 OGRPGCommonLayerSetType(oField, pszType, pszFormatType, nWidth);
249 if( pszDefault )
250 OGRPGCommonLayerNormalizeDefault(&oField, pszDefault);
251
252 poFeatureDefn->AddFieldDefn( &oField );
253 }
254 }
255 delete poFeat;
256 }
257
258 poDS->ReleaseResultSet(poLyr);
259 }
260 }
261
262 if( poFeatureDefn == NULL )
263 {
264 osBaseSQL.Printf("SELECT * FROM %s", OGRCARTODBEscapeIdentifier(osName).c_str());
265 EstablishLayerDefn(osName, NULL);
266 osBaseSQL = "";
267 }
268
269 if( osFIDColName.size() > 0 )
270 {
271 osBaseSQL = "SELECT ";
272 osBaseSQL += OGRCARTODBEscapeIdentifier(osFIDColName);
273 }
274 for(int i=0; i<poFeatureDefn->GetGeomFieldCount(); i++)
275 {
276 if( osBaseSQL.size() == 0 )
277 osBaseSQL = "SELECT ";
278 else
279 osBaseSQL += ", ";
280 osBaseSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
281 }
282 for(int i=0; i<poFeatureDefn->GetFieldCount(); i++)
283 {
284 if( osBaseSQL.size() == 0 )
285 osBaseSQL = "SELECT ";
286 else
287 osBaseSQL += ", ";
288 osBaseSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
289 }
290 if( osBaseSQL.size() == 0 )
291 osBaseSQL = "SELECT *";
292 osBaseSQL += " FROM ";
293 osBaseSQL += OGRCARTODBEscapeIdentifier(osName);
294
295 osSELECTWithoutWHERE = osBaseSQL;
296
297 return poFeatureDefn;
298 }
299
300 /************************************************************************/
301 /* FetchNewFeatures() */
302 /************************************************************************/
303
FetchNewFeatures(GIntBig iNext)304 json_object* OGRCARTODBTableLayer::FetchNewFeatures(GIntBig iNext)
305 {
306 if( osFIDColName.size() > 0 )
307 {
308 CPLString osSQL;
309 osSQL.Printf("%s WHERE %s%s >= " CPL_FRMT_GIB " ORDER BY %s ASC LIMIT %d",
310 osSELECTWithoutWHERE.c_str(),
311 ( osWHERE.size() ) ? CPLSPrintf("%s AND ", osWHERE.c_str()) : "",
312 OGRCARTODBEscapeIdentifier(osFIDColName).c_str(),
313 iNext,
314 OGRCARTODBEscapeIdentifier(osFIDColName).c_str(),
315 GetFeaturesToFetch());
316 return poDS->RunSQL(osSQL);
317 }
318 else
319 return OGRCARTODBLayer::FetchNewFeatures(iNext);
320 }
321
322 /************************************************************************/
323 /* GetNextRawFeature() */
324 /************************************************************************/
325
GetNextRawFeature()326 OGRFeature *OGRCARTODBTableLayer::GetNextRawFeature()
327 {
328 if( bDeferedCreation && RunDeferedCreationIfNecessary() != OGRERR_NONE )
329 return NULL;
330 FlushDeferedInsert();
331 return OGRCARTODBLayer::GetNextRawFeature();
332 }
333
334 /************************************************************************/
335 /* SetAttributeFilter() */
336 /************************************************************************/
337
SetAttributeFilter(const char * pszQuery)338 OGRErr OGRCARTODBTableLayer::SetAttributeFilter( const char *pszQuery )
339
340 {
341 GetLayerDefn();
342
343 if( pszQuery == NULL )
344 osQuery = "";
345 else
346 {
347 osQuery = "(";
348 osQuery += pszQuery;
349 osQuery += ")";
350 }
351
352 BuildWhere();
353
354 ResetReading();
355
356 return OGRERR_NONE;
357 }
358
359 /************************************************************************/
360 /* SetSpatialFilter() */
361 /************************************************************************/
362
SetSpatialFilter(int iGeomField,OGRGeometry * poGeomIn)363 void OGRCARTODBTableLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
364
365 {
366 if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
367 GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
368 {
369 if( iGeomField != 0 )
370 {
371 CPLError(CE_Failure, CPLE_AppDefined,
372 "Invalid geometry field index : %d", iGeomField);
373 }
374 return;
375 }
376 m_iGeomFieldFilter = iGeomField;
377
378 if( InstallFilter( poGeomIn ) )
379 {
380 BuildWhere();
381
382 ResetReading();
383 }
384 }
385
386 /************************************************************************/
387 /* FlushDeferedInsert() */
388 /************************************************************************/
389
FlushDeferedInsert()390 void OGRCARTODBTableLayer::FlushDeferedInsert()
391
392 {
393 if( bInDeferedInsert && osDeferedInsertSQL.size() > 0 )
394 {
395 osDeferedInsertSQL = "BEGIN;" + osDeferedInsertSQL + "COMMIT;";
396 json_object* poObj = poDS->RunSQL(osDeferedInsertSQL);
397 if( poObj != NULL )
398 {
399 json_object_put(poObj);
400 }
401 }
402
403 bInDeferedInsert = FALSE;
404 osDeferedInsertSQL = "";
405 nNextFID = -1;
406 }
407
408 /************************************************************************/
409 /* CreateField() */
410 /************************************************************************/
411
CreateField(OGRFieldDefn * poFieldIn,CPL_UNUSED int bApproxOK)412 OGRErr OGRCARTODBTableLayer::CreateField( OGRFieldDefn *poFieldIn,
413 CPL_UNUSED int bApproxOK )
414 {
415 GetLayerDefn();
416
417 if (!poDS->IsReadWrite())
418 {
419 CPLError(CE_Failure, CPLE_AppDefined,
420 "Operation not available in read-only mode");
421 return OGRERR_FAILURE;
422 }
423
424 OGRFieldDefn oField(poFieldIn);
425 if( bLaunderColumnNames )
426 {
427 char* pszName = OGRPGCommonLaunderName(oField.GetNameRef());
428 oField.SetName(pszName);
429 CPLFree(pszName);
430 }
431
432 /* -------------------------------------------------------------------- */
433 /* Create the new field. */
434 /* -------------------------------------------------------------------- */
435
436 if( !bDeferedCreation )
437 {
438 CPLString osSQL;
439 osSQL.Printf( "ALTER TABLE %s ADD COLUMN %s %s",
440 OGRCARTODBEscapeIdentifier(osName).c_str(),
441 OGRCARTODBEscapeIdentifier(oField.GetNameRef()).c_str(),
442 OGRPGCommonLayerGetType(oField, FALSE, TRUE).c_str() );
443 if( !oField.IsNullable() )
444 osSQL += " NOT NULL";
445 if( oField.GetDefault() != NULL && !oField.IsDefaultDriverSpecific() )
446 {
447 osSQL += " DEFAULT ";
448 osSQL += OGRPGCommonLayerGetPGDefault(&oField);
449 }
450
451 json_object* poObj = poDS->RunSQL(osSQL);
452 if( poObj == NULL )
453 return OGRERR_FAILURE;
454 json_object_put(poObj);
455 }
456
457 poFeatureDefn->AddFieldDefn( &oField );
458
459 return OGRERR_NONE;
460 }
461
462 /************************************************************************/
463 /* ICreateFeature() */
464 /************************************************************************/
465
ICreateFeature(OGRFeature * poFeature)466 OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
467
468 {
469 int i;
470
471 if( bDeferedCreation )
472 {
473 if( RunDeferedCreationIfNecessary() != OGRERR_NONE )
474 return OGRERR_FAILURE;
475 }
476
477 GetLayerDefn();
478 int bHasUserFieldMatchingFID = FALSE;
479 if( osFIDColName.size() )
480 bHasUserFieldMatchingFID = poFeatureDefn->GetFieldIndex(osFIDColName) >= 0;
481
482 if (!poDS->IsReadWrite())
483 {
484 CPLError(CE_Failure, CPLE_AppDefined,
485 "Operation not available in read-only mode");
486 return OGRERR_FAILURE;
487 }
488
489 CPLString osSQL;
490
491 int bHasJustGotNextFID = FALSE;
492 if( !bHasUserFieldMatchingFID && bInDeferedInsert && nNextFID < 0 && osFIDColName.size() )
493 {
494 osSQL.Printf("SELECT nextval('%s') AS nextid",
495 OGRCARTODBEscapeLiteral(CPLSPrintf("%s_%s_seq", osName.c_str(), osFIDColName.c_str())).c_str());
496
497 json_object* poObj = poDS->RunSQL(osSQL);
498 json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
499 if( poRowObj != NULL )
500 {
501 json_object* poID = json_object_object_get(poRowObj, "nextid");
502 if( poID != NULL && json_object_get_type(poID) == json_type_int )
503 {
504 nNextFID = json_object_get_int64(poID);
505 bHasJustGotNextFID = TRUE;
506 }
507 }
508
509 if( poObj != NULL )
510 json_object_put(poObj);
511 }
512
513 osSQL.Printf("INSERT INTO %s ", OGRCARTODBEscapeIdentifier(osName).c_str());
514 int bMustComma = FALSE;
515 for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
516 {
517 if( !poFeature->IsFieldSet(i) )
518 continue;
519
520 if( bMustComma )
521 osSQL += ", ";
522 else
523 {
524 osSQL += "(";
525 bMustComma = TRUE;
526 }
527
528 osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
529 }
530
531 for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
532 {
533 if( poFeature->GetGeomFieldRef(i) == NULL )
534 continue;
535
536 if( bMustComma )
537 osSQL += ", ";
538 else
539 {
540 osSQL += "(";
541 bMustComma = TRUE;
542 }
543
544 osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
545 }
546
547 if( !bHasUserFieldMatchingFID &&
548 osFIDColName.size() && (poFeature->GetFID() != OGRNullFID || nNextFID >= 0) )
549 {
550 if( bMustComma )
551 osSQL += ", ";
552 else
553 {
554 osSQL += "(";
555 bMustComma = TRUE;
556 }
557
558 osSQL += OGRCARTODBEscapeIdentifier(osFIDColName);
559 }
560
561 if( !bMustComma )
562 osSQL += " DEFAULT VALUES";
563 else
564 {
565 osSQL += ") VALUES (";
566
567 bMustComma = FALSE;
568 for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
569 {
570 if( !poFeature->IsFieldSet(i) )
571 continue;
572
573 if( bMustComma )
574 osSQL += ", ";
575 else
576 bMustComma = TRUE;
577
578 OGRFieldType eType = poFeatureDefn->GetFieldDefn(i)->GetType();
579 if( eType == OFTString || eType == OFTDateTime || eType == OFTDate || eType == OFTTime )
580 {
581 osSQL += "'";
582 osSQL += OGRCARTODBEscapeLiteral(poFeature->GetFieldAsString(i));
583 osSQL += "'";
584 }
585 else if( (eType == OFTInteger || eType == OFTInteger64) &&
586 poFeatureDefn->GetFieldDefn(i)->GetSubType() == OFSTBoolean )
587 {
588 osSQL += poFeature->GetFieldAsInteger(i) ? "'t'" : "'f'";
589 }
590 else
591 osSQL += poFeature->GetFieldAsString(i);
592 }
593
594 for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
595 {
596 OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
597 if( poGeom == NULL )
598 continue;
599
600 if( bMustComma )
601 osSQL += ", ";
602 else
603 bMustComma = TRUE;
604
605 OGRCartoDBGeomFieldDefn* poGeomFieldDefn =
606 (OGRCartoDBGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(i);
607 int nSRID = poGeomFieldDefn->nSRID;
608 if( nSRID == 0 )
609 nSRID = 4326;
610 char* pszEWKB;
611 if( wkbFlatten(poGeom->getGeometryType()) == wkbPolygon &&
612 wkbFlatten(GetGeomType()) == wkbMultiPolygon )
613 {
614 OGRMultiPolygon* poNewGeom = new OGRMultiPolygon();
615 poNewGeom->addGeometry(poGeom);
616 pszEWKB = OGRGeometryToHexEWKB(poNewGeom, nSRID, FALSE);
617 delete poNewGeom;
618 }
619 else
620 pszEWKB = OGRGeometryToHexEWKB(poGeom, nSRID, FALSE);
621 osSQL += "'";
622 osSQL += pszEWKB;
623 osSQL += "'";
624 CPLFree(pszEWKB);
625 }
626
627 if( !bHasUserFieldMatchingFID )
628 {
629 if( osFIDColName.size() && nNextFID >= 0 )
630 {
631 if( bMustComma )
632 osSQL += ", ";
633 else
634 bMustComma = TRUE;
635
636 if( bHasJustGotNextFID )
637 {
638 osSQL += CPLSPrintf(CPL_FRMT_GIB, nNextFID);
639 }
640 else
641 {
642 osSQL += CPLSPrintf("nextval('%s')",
643 OGRCARTODBEscapeLiteral(CPLSPrintf("%s_%s_seq", osName.c_str(), osFIDColName.c_str())).c_str());
644 }
645 poFeature->SetFID(nNextFID);
646 nNextFID ++;
647 }
648 else if( osFIDColName.size() && poFeature->GetFID() != OGRNullFID )
649 {
650 if( bMustComma )
651 osSQL += ", ";
652 else
653 bMustComma = TRUE;
654
655 osSQL += CPLSPrintf(CPL_FRMT_GIB, poFeature->GetFID());
656 }
657 }
658
659 osSQL += ")";
660 }
661
662 if( bInDeferedInsert )
663 {
664 OGRErr eRet = OGRERR_NONE;
665 if( osDeferedInsertSQL.size() != 0 &&
666 (int)osDeferedInsertSQL.size() + (int)osSQL.size() > nMaxChunkSize )
667 {
668 osDeferedInsertSQL = "BEGIN;" + osDeferedInsertSQL + "COMMIT;";
669 json_object* poObj = poDS->RunSQL(osDeferedInsertSQL);
670 if( poObj != NULL )
671 json_object_put(poObj);
672 else
673 {
674 bInDeferedInsert = FALSE;
675 eRet = OGRERR_FAILURE;
676 }
677 osDeferedInsertSQL = "";
678 }
679
680 osDeferedInsertSQL += osSQL;
681 osDeferedInsertSQL += ";";
682
683 if( (int)osDeferedInsertSQL.size() > nMaxChunkSize )
684 {
685 osDeferedInsertSQL = "BEGIN;" + osDeferedInsertSQL + "COMMIT;";
686 json_object* poObj = poDS->RunSQL(osDeferedInsertSQL);
687 if( poObj != NULL )
688 json_object_put(poObj);
689 else
690 {
691 bInDeferedInsert = FALSE;
692 eRet = OGRERR_FAILURE;
693 }
694 osDeferedInsertSQL = "";
695 }
696
697 return eRet;
698 }
699
700 if( osFIDColName.size() )
701 {
702 osSQL += " RETURNING ";
703 osSQL += OGRCARTODBEscapeIdentifier(osFIDColName);
704
705 json_object* poObj = poDS->RunSQL(osSQL);
706 json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
707 if( poRowObj == NULL )
708 {
709 if( poObj != NULL )
710 json_object_put(poObj);
711 return OGRERR_FAILURE;
712 }
713
714 json_object* poID = json_object_object_get(poRowObj, osFIDColName);
715 if( poID != NULL && json_object_get_type(poID) == json_type_int )
716 {
717 poFeature->SetFID(json_object_get_int64(poID));
718 }
719
720 if( poObj != NULL )
721 json_object_put(poObj);
722
723 return OGRERR_NONE;
724 }
725 else
726 {
727 OGRErr eRet = OGRERR_FAILURE;
728 json_object* poObj = poDS->RunSQL(osSQL);
729 if( poObj != NULL )
730 {
731 json_object* poTotalRows = json_object_object_get(poObj, "total_rows");
732 if( poTotalRows != NULL && json_object_get_type(poTotalRows) == json_type_int )
733 {
734 int nTotalRows = json_object_get_int(poTotalRows);
735 if( nTotalRows == 1 )
736 {
737 eRet = OGRERR_NONE;
738 }
739 }
740 json_object_put(poObj);
741 }
742
743 return eRet;
744 }
745 }
746
747 /************************************************************************/
748 /* ISetFeature() */
749 /************************************************************************/
750
ISetFeature(OGRFeature * poFeature)751 OGRErr OGRCARTODBTableLayer::ISetFeature( OGRFeature *poFeature )
752
753 {
754 int i;
755
756 if( bDeferedCreation && RunDeferedCreationIfNecessary() != OGRERR_NONE )
757 return OGRERR_FAILURE;
758 FlushDeferedInsert();
759
760 GetLayerDefn();
761
762 if (!poDS->IsReadWrite())
763 {
764 CPLError(CE_Failure, CPLE_AppDefined,
765 "Operation not available in read-only mode");
766 return OGRERR_FAILURE;
767 }
768
769 if (poFeature->GetFID() == OGRNullFID)
770 {
771 CPLError( CE_Failure, CPLE_AppDefined,
772 "FID required on features given to SetFeature()." );
773 return OGRERR_FAILURE;
774 }
775
776 CPLString osSQL;
777 osSQL.Printf("UPDATE %s SET ", OGRCARTODBEscapeIdentifier(osName).c_str());
778 int bMustComma = FALSE;
779 for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
780 {
781 if( bMustComma )
782 osSQL += ", ";
783 else
784 bMustComma = TRUE;
785
786 osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
787 osSQL += " = ";
788
789 if( !poFeature->IsFieldSet(i) )
790 {
791 osSQL += "NULL";
792 }
793 else
794 {
795 OGRFieldType eType = poFeatureDefn->GetFieldDefn(i)->GetType();
796 if( eType == OFTString || eType == OFTDateTime || eType == OFTDate || eType == OFTTime )
797 {
798 osSQL += "'";
799 osSQL += OGRCARTODBEscapeLiteral(poFeature->GetFieldAsString(i));
800 osSQL += "'";
801 }
802 else if( (eType == OFTInteger || eType == OFTInteger64) &&
803 poFeatureDefn->GetFieldDefn(i)->GetSubType() == OFSTBoolean )
804 {
805 osSQL += poFeature->GetFieldAsInteger(i) ? "'t'" : "'f'";
806 }
807 else
808 osSQL += poFeature->GetFieldAsString(i);
809 }
810 }
811
812 for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
813 {
814 if( bMustComma )
815 osSQL += ", ";
816 else
817 bMustComma = TRUE;
818
819 osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
820 osSQL += " = ";
821
822 OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
823 if( poGeom == NULL )
824 {
825 osSQL += "NULL";
826 }
827 else
828 {
829 OGRCartoDBGeomFieldDefn* poGeomFieldDefn =
830 (OGRCartoDBGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(i);
831 int nSRID = poGeomFieldDefn->nSRID;
832 if( nSRID == 0 )
833 nSRID = 4326;
834 char* pszEWKB = OGRGeometryToHexEWKB(poGeom, nSRID, FALSE);
835 osSQL += "'";
836 osSQL += pszEWKB;
837 osSQL += "'";
838 CPLFree(pszEWKB);
839 }
840 }
841
842 osSQL += CPLSPrintf(" WHERE %s = " CPL_FRMT_GIB,
843 OGRCARTODBEscapeIdentifier(osFIDColName).c_str(),
844 poFeature->GetFID());
845
846 OGRErr eRet = OGRERR_FAILURE;
847 json_object* poObj = poDS->RunSQL(osSQL);
848 if( poObj != NULL )
849 {
850 json_object* poTotalRows = json_object_object_get(poObj, "total_rows");
851 if( poTotalRows != NULL && json_object_get_type(poTotalRows) == json_type_int )
852 {
853 int nTotalRows = json_object_get_int(poTotalRows);
854 if( nTotalRows > 0 )
855 {
856 eRet = OGRERR_NONE;
857 }
858 else
859 eRet = OGRERR_NON_EXISTING_FEATURE;
860 }
861 json_object_put(poObj);
862 }
863
864 return eRet;
865 }
866
867 /************************************************************************/
868 /* DeleteFeature() */
869 /************************************************************************/
870
DeleteFeature(GIntBig nFID)871 OGRErr OGRCARTODBTableLayer::DeleteFeature( GIntBig nFID )
872
873 {
874
875 if( bDeferedCreation && RunDeferedCreationIfNecessary() != OGRERR_NONE )
876 return OGRERR_FAILURE;
877 FlushDeferedInsert();
878
879 GetLayerDefn();
880
881 if (!poDS->IsReadWrite())
882 {
883 CPLError(CE_Failure, CPLE_AppDefined,
884 "Operation not available in read-only mode");
885 return OGRERR_FAILURE;
886 }
887
888 if( osFIDColName.size() == 0 )
889 return OGRERR_FAILURE;
890
891 CPLString osSQL;
892 osSQL.Printf("DELETE FROM %s WHERE %s = " CPL_FRMT_GIB,
893 OGRCARTODBEscapeIdentifier(osName).c_str(),
894 OGRCARTODBEscapeIdentifier(osFIDColName).c_str(),
895 nFID);
896
897 OGRErr eRet = OGRERR_FAILURE;
898 json_object* poObj = poDS->RunSQL(osSQL);
899 if( poObj != NULL )
900 {
901 json_object* poTotalRows = json_object_object_get(poObj, "total_rows");
902 if( poTotalRows != NULL && json_object_get_type(poTotalRows) == json_type_int )
903 {
904 int nTotalRows = json_object_get_int(poTotalRows);
905 if( nTotalRows > 0 )
906 {
907 eRet = OGRERR_NONE;
908 }
909 else
910 eRet = OGRERR_NON_EXISTING_FEATURE;
911 }
912 json_object_put(poObj);
913 }
914
915 return eRet;
916 }
917
918 /************************************************************************/
919 /* GetSRS_SQL() */
920 /************************************************************************/
921
GetSRS_SQL(const char * pszGeomCol)922 CPLString OGRCARTODBTableLayer::GetSRS_SQL(const char* pszGeomCol)
923 {
924 CPLString osSQL;
925
926 osSQL.Printf("SELECT srid, srtext FROM spatial_ref_sys WHERE srid IN "
927 "(SELECT Find_SRID('%s', '%s', '%s'))",
928 OGRCARTODBEscapeLiteral(poDS->GetCurrentSchema()).c_str(),
929 OGRCARTODBEscapeLiteral(osName).c_str(),
930 OGRCARTODBEscapeLiteral(pszGeomCol).c_str());
931
932 return osSQL;
933 }
934
935 /************************************************************************/
936 /* BuildWhere() */
937 /* */
938 /* Build the WHERE statement appropriate to the current set of */
939 /* criteria (spatial and attribute queries). */
940 /************************************************************************/
941
BuildWhere()942 void OGRCARTODBTableLayer::BuildWhere()
943
944 {
945 osWHERE = "";
946
947 if( m_poFilterGeom != NULL &&
948 m_iGeomFieldFilter >= 0 &&
949 m_iGeomFieldFilter < poFeatureDefn->GetGeomFieldCount() )
950 {
951 OGREnvelope sEnvelope;
952
953 m_poFilterGeom->getEnvelope( &sEnvelope );
954
955 CPLString osGeomColumn(poFeatureDefn->GetGeomFieldDefn(m_iGeomFieldFilter)->GetNameRef());
956
957 char szBox3D_1[128];
958 char szBox3D_2[128];
959 char* pszComma;
960
961 CPLsnprintf(szBox3D_1, sizeof(szBox3D_1), "%.18g %.18g", sEnvelope.MinX, sEnvelope.MinY);
962 while((pszComma = strchr(szBox3D_1, ',')) != NULL)
963 *pszComma = '.';
964 CPLsnprintf(szBox3D_2, sizeof(szBox3D_2), "%.18g %.18g", sEnvelope.MaxX, sEnvelope.MaxY);
965 while((pszComma = strchr(szBox3D_2, ',')) != NULL)
966 *pszComma = '.';
967 osWHERE.Printf("(%s && 'BOX3D(%s, %s)'::box3d)",
968 OGRCARTODBEscapeIdentifier(osGeomColumn).c_str(),
969 szBox3D_1, szBox3D_2 );
970 }
971
972 if( strlen(osQuery) > 0 )
973 {
974 if( osWHERE.size() > 0 )
975 osWHERE += " AND ";
976 osWHERE += osQuery;
977 }
978
979 if( osFIDColName.size() == 0 )
980 {
981 osBaseSQL = osSELECTWithoutWHERE;
982 if( osWHERE.size() )
983 {
984 osBaseSQL += " WHERE ";
985 osBaseSQL += osWHERE;
986 }
987 }
988 }
989
990 /************************************************************************/
991 /* GetFeature() */
992 /************************************************************************/
993
GetFeature(GIntBig nFeatureId)994 OGRFeature* OGRCARTODBTableLayer::GetFeature( GIntBig nFeatureId )
995 {
996
997 if( bDeferedCreation && RunDeferedCreationIfNecessary() != OGRERR_NONE )
998 return NULL;
999 FlushDeferedInsert();
1000
1001 GetLayerDefn();
1002
1003 if( osFIDColName.size() == 0 )
1004 return OGRCARTODBLayer::GetFeature(nFeatureId);
1005
1006 CPLString osSQL = osSELECTWithoutWHERE;
1007 osSQL += " WHERE ";
1008 osSQL += OGRCARTODBEscapeIdentifier(osFIDColName).c_str();
1009 osSQL += " = ";
1010 osSQL += CPLSPrintf(CPL_FRMT_GIB, nFeatureId);
1011
1012 json_object* poObj = poDS->RunSQL(osSQL);
1013 json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
1014 if( poRowObj == NULL )
1015 {
1016 if( poObj != NULL )
1017 json_object_put(poObj);
1018 return OGRCARTODBLayer::GetFeature(nFeatureId);
1019 }
1020
1021 OGRFeature* poFeature = BuildFeature(poRowObj);
1022 json_object_put(poObj);
1023
1024 return poFeature;
1025 }
1026
1027 /************************************************************************/
1028 /* GetFeatureCount() */
1029 /************************************************************************/
1030
GetFeatureCount(int bForce)1031 GIntBig OGRCARTODBTableLayer::GetFeatureCount(int bForce)
1032 {
1033
1034 if( bDeferedCreation && RunDeferedCreationIfNecessary() != OGRERR_NONE )
1035 return 0;
1036 FlushDeferedInsert();
1037
1038 GetLayerDefn();
1039
1040 CPLString osSQL(CPLSPrintf("SELECT COUNT(*) FROM %s",
1041 OGRCARTODBEscapeIdentifier(osName).c_str()));
1042 if( osWHERE.size() )
1043 {
1044 osSQL += " WHERE ";
1045 osSQL += osWHERE;
1046 }
1047
1048 json_object* poObj = poDS->RunSQL(osSQL);
1049 json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
1050 if( poRowObj == NULL )
1051 {
1052 if( poObj != NULL )
1053 json_object_put(poObj);
1054 return OGRCARTODBLayer::GetFeatureCount(bForce);
1055 }
1056
1057 json_object* poCount = json_object_object_get(poRowObj, "count");
1058 if( poCount == NULL || json_object_get_type(poCount) != json_type_int )
1059 {
1060 json_object_put(poObj);
1061 return OGRCARTODBLayer::GetFeatureCount(bForce);
1062 }
1063
1064 GIntBig nRet = (GIntBig)json_object_get_int64(poCount);
1065
1066 json_object_put(poObj);
1067
1068 return nRet;
1069 }
1070
1071 /************************************************************************/
1072 /* GetExtent() */
1073 /* */
1074 /* For PostGIS use internal Extend(geometry) function */
1075 /* in other cases we use standard OGRLayer::GetExtent() */
1076 /************************************************************************/
1077
GetExtent(int iGeomField,OGREnvelope * psExtent,int bForce)1078 OGRErr OGRCARTODBTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce )
1079 {
1080 CPLString osSQL;
1081
1082 if( bDeferedCreation && RunDeferedCreationIfNecessary() != OGRERR_NONE )
1083 return OGRERR_FAILURE;
1084 FlushDeferedInsert();
1085
1086 if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
1087 GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
1088 {
1089 if( iGeomField != 0 )
1090 {
1091 CPLError(CE_Failure, CPLE_AppDefined,
1092 "Invalid geometry field index : %d", iGeomField);
1093 }
1094 return OGRERR_FAILURE;
1095 }
1096
1097 OGRGeomFieldDefn* poGeomFieldDefn =
1098 poFeatureDefn->GetGeomFieldDefn(iGeomField);
1099
1100 /* Do not take the spatial filter into account */
1101 osSQL.Printf( "SELECT ST_Extent(%s) FROM %s",
1102 OGRCARTODBEscapeIdentifier(poGeomFieldDefn->GetNameRef()).c_str(),
1103 OGRCARTODBEscapeIdentifier(osName).c_str());
1104
1105 json_object* poObj = poDS->RunSQL(osSQL);
1106 json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
1107 if( poRowObj != NULL )
1108 {
1109 json_object* poExtent = json_object_object_get(poRowObj, "st_extent");
1110 if( poExtent != NULL && json_object_get_type(poExtent) == json_type_string )
1111 {
1112 const char* pszBox = json_object_get_string(poExtent);
1113 const char * ptr, *ptrEndParenthesis;
1114 char szVals[64*6+6];
1115
1116 ptr = strchr(pszBox, '(');
1117 if (ptr)
1118 ptr ++;
1119 if (ptr == NULL ||
1120 (ptrEndParenthesis = strchr(ptr, ')')) == NULL ||
1121 ptrEndParenthesis - ptr > (int)(sizeof(szVals) - 1))
1122 {
1123 CPLError( CE_Failure, CPLE_IllegalArg,
1124 "Bad extent representation: '%s'", pszBox);
1125
1126 json_object_put(poObj);
1127 return OGRERR_FAILURE;
1128 }
1129
1130 strncpy(szVals,ptr,ptrEndParenthesis - ptr);
1131 szVals[ptrEndParenthesis - ptr] = '\0';
1132
1133 char ** papszTokens = CSLTokenizeString2(szVals," ,",CSLT_HONOURSTRINGS);
1134 int nTokenCnt = 4;
1135
1136 if ( CSLCount(papszTokens) != nTokenCnt )
1137 {
1138 CPLError( CE_Failure, CPLE_IllegalArg,
1139 "Bad extent representation: '%s'", pszBox);
1140 CSLDestroy(papszTokens);
1141
1142 json_object_put(poObj);
1143 return OGRERR_FAILURE;
1144 }
1145
1146 // Take X,Y coords
1147 // For PostGis ver >= 1.0.0 -> Tokens: X1 Y1 X2 Y2 (nTokenCnt = 4)
1148 // For PostGIS ver < 1.0.0 -> Tokens: X1 Y1 Z1 X2 Y2 Z2 (nTokenCnt = 6)
1149 // => X2 index calculated as nTokenCnt/2
1150 // Y2 index caluclated as nTokenCnt/2+1
1151
1152 psExtent->MinX = CPLAtof( papszTokens[0] );
1153 psExtent->MinY = CPLAtof( papszTokens[1] );
1154 psExtent->MaxX = CPLAtof( papszTokens[nTokenCnt/2] );
1155 psExtent->MaxY = CPLAtof( papszTokens[nTokenCnt/2+1] );
1156
1157 CSLDestroy(papszTokens);
1158
1159 json_object_put(poObj);
1160 return OGRERR_NONE;
1161 }
1162 }
1163
1164 if( poObj != NULL )
1165 json_object_put(poObj);
1166
1167 if( iGeomField == 0 )
1168 return OGRLayer::GetExtent( psExtent, bForce );
1169 else
1170 return OGRLayer::GetExtent( iGeomField, psExtent, bForce );
1171 }
1172
1173 /************************************************************************/
1174 /* TestCapability() */
1175 /************************************************************************/
1176
TestCapability(const char * pszCap)1177 int OGRCARTODBTableLayer::TestCapability( const char * pszCap )
1178
1179 {
1180 if( EQUAL(pszCap, OLCFastFeatureCount) )
1181 return TRUE;
1182 if( EQUAL(pszCap, OLCFastGetExtent) )
1183 return TRUE;
1184 if( EQUAL(pszCap, OLCRandomRead) )
1185 {
1186 GetLayerDefn();
1187 return osFIDColName.size() != 0;
1188 }
1189
1190 if( EQUAL(pszCap,OLCSequentialWrite)
1191 || EQUAL(pszCap,OLCRandomWrite)
1192 || EQUAL(pszCap,OLCDeleteFeature)
1193 || EQUAL(pszCap,OLCCreateField) )
1194 {
1195 return poDS->IsReadWrite();
1196 }
1197
1198 return OGRCARTODBLayer::TestCapability(pszCap);
1199 }
1200
1201 /************************************************************************/
1202 /* SetDeferedCreation() */
1203 /************************************************************************/
1204
SetDeferedCreation(OGRwkbGeometryType eGType,OGRSpatialReference * poSRS,int bGeomNullable,int bCartoDBify)1205 void OGRCARTODBTableLayer::SetDeferedCreation (OGRwkbGeometryType eGType,
1206 OGRSpatialReference* poSRS,
1207 int bGeomNullable,
1208 int bCartoDBify)
1209 {
1210 bDeferedCreation = TRUE;
1211 nNextFID = 1;
1212 CPLAssert(poFeatureDefn == NULL);
1213 this->bCartoDBify = bCartoDBify;
1214 poFeatureDefn = new OGRFeatureDefn(osName);
1215 poFeatureDefn->Reference();
1216 poFeatureDefn->SetGeomType(wkbNone);
1217 if( eGType == wkbPolygon )
1218 eGType = wkbMultiPolygon;
1219 else if( eGType == wkbPolygon25D )
1220 eGType = wkbMultiPolygon25D;
1221 if( eGType != wkbNone )
1222 {
1223 OGRCartoDBGeomFieldDefn *poFieldDefn =
1224 new OGRCartoDBGeomFieldDefn("the_geom", eGType);
1225 poFieldDefn->SetNullable(bGeomNullable);
1226 poFeatureDefn->AddGeomFieldDefn(poFieldDefn, FALSE);
1227 if( poSRS != NULL )
1228 {
1229 poFieldDefn->nSRID = poDS->FetchSRSId( poSRS );
1230 poFeatureDefn->GetGeomFieldDefn(
1231 poFeatureDefn->GetGeomFieldCount() - 1)->SetSpatialRef(poSRS);
1232 }
1233 }
1234 osFIDColName = "cartodb_id";
1235 osBaseSQL.Printf("SELECT * FROM %s",
1236 OGRCARTODBEscapeIdentifier(osName).c_str());
1237 }
1238
1239 /************************************************************************/
1240 /* RunDeferedCreationIfNecessary() */
1241 /************************************************************************/
1242
RunDeferedCreationIfNecessary()1243 OGRErr OGRCARTODBTableLayer::RunDeferedCreationIfNecessary()
1244 {
1245 if( !bDeferedCreation )
1246 return OGRERR_NONE;
1247 bDeferedCreation = FALSE;
1248
1249 CPLString osSQL;
1250 osSQL.Printf("CREATE TABLE %s ( %s SERIAL,",
1251 OGRCARTODBEscapeIdentifier(osName).c_str(),
1252 osFIDColName.c_str());
1253
1254 int nSRID = 0;
1255 OGRwkbGeometryType eGType = GetGeomType();
1256 if( eGType != wkbNone )
1257 {
1258 CPLString osGeomType = OGRToOGCGeomType(eGType);
1259 if( wkbHasZ(eGType) )
1260 osGeomType += "Z";
1261
1262 OGRCartoDBGeomFieldDefn *poFieldDefn =
1263 (OGRCartoDBGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(0);
1264 nSRID = poFieldDefn->nSRID;
1265
1266 osSQL += CPLSPrintf("%s GEOMETRY(%s, %d)%s, %s GEOMETRY(%s, %d),",
1267 "the_geom",
1268 osGeomType.c_str(),
1269 nSRID,
1270 (!poFieldDefn->IsNullable()) ? " NOT NULL" : "",
1271 "the_geom_webmercator",
1272 osGeomType.c_str(),
1273 3857);
1274 }
1275
1276 for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
1277 {
1278 OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(i);
1279 if( strcmp(poFieldDefn->GetNameRef(), osFIDColName) != 0 )
1280 {
1281 osSQL += OGRCARTODBEscapeIdentifier(poFieldDefn->GetNameRef());
1282 osSQL += " ";
1283 osSQL += OGRPGCommonLayerGetType(*poFieldDefn, FALSE, TRUE);
1284 if( !poFieldDefn->IsNullable() )
1285 osSQL += " NOT NULL";
1286 if( poFieldDefn->GetDefault() != NULL && !poFieldDefn->IsDefaultDriverSpecific() )
1287 {
1288 osSQL += " DEFAULT ";
1289 osSQL += poFieldDefn->GetDefault();
1290 }
1291 osSQL += ",";
1292 }
1293 }
1294
1295 osSQL += CPLSPrintf("PRIMARY KEY (%s) )", osFIDColName.c_str());
1296
1297 CPLString osSeqName(OGRCARTODBEscapeIdentifier(CPLSPrintf("%s_%s_seq",
1298 osName.c_str(), osFIDColName.c_str())));
1299
1300 osSQL += ";";
1301 osSQL += CPLSPrintf("DROP SEQUENCE IF EXISTS %s CASCADE", osSeqName.c_str());
1302 osSQL += ";";
1303 osSQL += CPLSPrintf("CREATE SEQUENCE %s START 1", osSeqName.c_str());
1304 osSQL += ";";
1305 osSQL += CPLSPrintf("ALTER TABLE %s ALTER COLUMN %s SET DEFAULT nextval('%s')",
1306 OGRCARTODBEscapeIdentifier(osName).c_str(),
1307 osFIDColName.c_str(), osSeqName.c_str());
1308
1309 json_object* poObj = poDS->RunSQL(osSQL);
1310 if( poObj == NULL )
1311 return OGRERR_FAILURE;
1312 json_object_put(poObj);
1313
1314 if( bCartoDBify )
1315 {
1316 if( nSRID != 4326 )
1317 {
1318 if( eGType != wkbNone )
1319 {
1320 CPLError(CE_Warning, CPLE_AppDefined,
1321 "Cannot register table in dashboard with "
1322 "cdb_cartodbfytable() since its SRS is not EPSG:4326");
1323 }
1324 }
1325 else
1326 {
1327 if( poDS->GetCurrentSchema() == "public" )
1328 osSQL.Printf("SELECT cdb_cartodbfytable('%s')",
1329 OGRCARTODBEscapeLiteral(osName).c_str());
1330 else
1331 osSQL.Printf("SELECT cdb_cartodbfytable('%s', '%s')",
1332 OGRCARTODBEscapeLiteral(poDS->GetCurrentSchema()).c_str(),
1333 OGRCARTODBEscapeLiteral(osName).c_str());
1334
1335 poObj = poDS->RunSQL(osSQL);
1336 if( poObj == NULL )
1337 return OGRERR_FAILURE;
1338 json_object_put(poObj);
1339 }
1340 }
1341
1342 return OGRERR_NONE;
1343 }
1344