source: trunk/mapserver/mapsde.c

Last change on this file was 11880, checked in by sdlime, 13 years ago

Fix performance issue with Oracle and scrollable cursors (#3905).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 75.7 KB
Line 
1/******************************************************************************
2 * $Id: mapsde.c 11880 2011-07-07 19:51:37Z sdlime $
3 *
4 * Project: MapServer
5 * Purpose: Implements SDE CONNECTIONTYPE.
6 * Author: Steve Lime and Howard Butler
7 *
8 ******************************************************************************
9 * Copyright (c) 1996-2005 Regents of the University of Minnesota.
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 in
19 * all copies of this Software or works derived from this 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 <time.h>
31#include <assert.h>
32
33#include "mapserver.h"
34#include "maperror.h"
35#include "maptime.h"
36#include "mapthread.h"
37
38
39
40#ifdef USE_SDE
41#include <sdetype.h> /* ESRI SDE Client Includes */
42#include <sdeerno.h>
43
44#define MS_SDE_MAXBLOBSIZE 1024*50 /* 50 kbytes */
45#define MS_SDE_NULLSTRING "<null>"
46#define MS_SDE_SHAPESTRING "<shape>"
47#define MS_SDE_TIMEFMTSIZE 128 /* bytes */
48#define MS_SDE_TIMEFMT "%H:%M:%S %m/%d/%Y"
49#define MS_SDE_ROW_ID_COLUMN "SE_ROW_ID"
50
51typedef struct {
52 SE_CONNECTION connection;
53 SE_STREAM stream;
54} msSDEConnPoolInfo;
55
56typedef struct {
57 msSDEConnPoolInfo *connPoolInfo;
58 SE_CONNECTION connection;
59 SE_LAYERINFO layerinfo;
60 SE_COORDREF coordref;
61 SE_STREAM stream;
62 long state_id;
63 char *table;
64 char *column;
65 char *row_id_column;
66 char *join_table;
67 rectObj* extent;
68 SE_COLUMN_DEF *basedefs;
69 SE_COLUMN_DEF *joindefs;
70 short *nBaseColumns;
71 short *nJoinColumns;
72 int bBigEndian;
73} msSDELayerInfo;
74
75typedef struct {
76 long layerId;
77 char *table;
78 char *column;
79 char *connection;
80} layerId;
81
82/*
83 * Layer ID caching section.
84 */
85
86static int lcacheCount = 0;
87static int lcacheMax = 0;
88static layerId *lcache = NULL;
89
90#endif
91
92/* -------------------------------------------------------------------- */
93/* msSDELayerIsOpen */
94/* -------------------------------------------------------------------- */
95/* Returns MS_TRUE if layer is already opened, MS_FALSE otherwise */
96/* -------------------------------------------------------------------- */
97int msSDELayerIsOpen(layerObj *layer) {
98#ifdef USE_SDE
99
100 if(layer->layerinfo)
101 return(MS_TRUE);
102
103 return MS_FALSE;
104
105#else
106 msSetError(MS_MISCERR, "SDE support is not available.",
107 "msSDELayerIsOpen()");
108 return(MS_FALSE);
109#endif
110}
111
112#ifdef USE_SDE
113
114
115/************************************************************************/
116/* Start SDE/MapServer helper functions. */
117/* */
118/************************************************************************/
119
120
121
122/* -------------------------------------------------------------------- */
123/* msSDECloseConnection */
124/* -------------------------------------------------------------------- */
125/* Closes the SDE connection handle, which is given as a callback */
126/* function to the connection pooling API */
127/* -------------------------------------------------------------------- */
128static void msSDECloseConnection( void *conn_handle )
129{
130
131 long status;
132 msSDEConnPoolInfo *poolinfo = conn_handle;
133
134 if (poolinfo) {
135 if (poolinfo->stream) {
136 SE_stream_free(poolinfo->stream);
137 }
138 if (poolinfo->connection) {
139 status = SE_connection_free_all_locks (poolinfo->connection);
140 if (status == SE_SUCCESS) {
141 SE_connection_free(poolinfo->connection);
142 }
143 }
144 msFree(poolinfo);
145 }
146
147}
148
149/* -------------------------------------------------------------------- */
150/* sde_error */
151/* -------------------------------------------------------------------- */
152/* Reports more detailed error information from SDE */
153/* -------------------------------------------------------------------- */
154static void sde_error(long error_code, char *routine, char *sde_routine)
155{
156 char error_string[SE_MAX_MESSAGE_LENGTH];
157
158 error_string[0] = '\0';
159 SE_error_get_string(error_code, error_string);
160
161 msSetError( MS_SDEERR,
162 "%s: %s. (%ld)",
163 routine,
164 sde_routine,
165 error_string,
166 error_code);
167
168 return;
169}
170
171
172/* -------------------------------------------------------------------- */
173/* msSDELayerGetRowIDColumn */
174/* -------------------------------------------------------------------- */
175/* A helper function to return unique row ID column for */
176/* an opened SDE layer. The caller owns the string. */
177/* -------------------------------------------------------------------- */
178char *msSDELayerGetRowIDColumn(layerObj *layer)
179{
180#ifdef USE_SDE
181 long status, column_type;
182 char* column_name;
183 char* full_column_name;
184 char* proc_key;
185
186 SE_REGINFO registration;
187
188 msSDELayerInfo *sde=NULL;
189 sde = layer->layerinfo;
190
191 if(!msSDELayerIsOpen(layer)) {
192 msSetError( MS_SDEERR,
193 "SDE layer has not been opened.",
194 "msSDELayerGetRowIDColumn()");
195 return NULL;
196 }
197
198 column_name = (char*) msSmallMalloc(SE_QUALIFIED_COLUMN_LEN+1);
199 column_name[0]='\0';
200
201 proc_key = msLayerGetProcessingKey(layer,"OBJECTID");
202 if (proc_key)
203 strcpy(column_name,proc_key);
204
205 if (proc_key) {
206 if (layer->debug)
207 msDebug("msSDELayerGetRowIDColumn(): Column was manually set to %s\n", column_name);
208 return column_name;
209 }
210 full_column_name = (char*) msSmallMalloc(SE_QUALIFIED_COLUMN_LEN+1);
211 full_column_name[0]='\0';
212
213 /*
214 ** if the state_id is the SE_DEFAULT_STATE_ID, we are
215 ** assuming no versioned queries are happening at all
216 ** and we are using the hardcoded row_id column.
217 */
218 if (sde->state_id == SE_DEFAULT_STATE_ID) {
219 if(layer->debug) {
220 msDebug("msSDELayerGetRowIDColumn(): State ID was "
221 "SE_DEFAULT_STATE_ID, reverting to %s.\n",
222 MS_SDE_ROW_ID_COLUMN);
223 }
224 strcpy(column_name,MS_SDE_ROW_ID_COLUMN);
225 }
226
227 /*
228 ** if the state_id was not set to SE_DEFAULT_STATE_ID,
229 ** check if the table is registered, and if so, use the
230 ** registration info to tell us what the row_id column is.
231 */
232 status = SE_reginfo_create (&registration);
233 if(status != SE_SUCCESS) {
234 sde_error( status,
235 "msSDELayerGetRowIDColumn()",
236 "SE_reginfo_create()");
237 return(NULL);
238 }
239
240 status = SE_registration_get_info ( sde->connPoolInfo->connection,
241 sde->table,
242 registration);
243 if(status != SE_SUCCESS) {
244 sde_error( status,
245 "msSDELayerGetRowIDColumn()",
246 "SE_registration_get_info()");
247 SE_reginfo_free(registration);
248 return(NULL);
249 }
250
251 status= SE_reginfo_get_rowid_column ( registration,
252 column_name,
253 &column_type);
254
255 if(status != SE_SUCCESS) {
256 sde_error(status,
257 "msSDELayerGetRowIDColumn()",
258 "SE_reginfo_get_rowid_column()");
259 SE_reginfo_free(registration);
260 return(NULL);
261 }
262 /* Free up the reginfo now that we're done with it */
263 SE_reginfo_free(registration);
264
265 /* if the table wasn't registered, return the hard-coded row_id column. */
266 if (column_type == SE_REGISTRATION_ROW_ID_COLUMN_TYPE_NONE){
267 if(layer->debug) {
268 msDebug("msSDELayerGetRowIDColumn(): Table was not registered, "
269 "returning %s.\n",
270 MS_SDE_ROW_ID_COLUMN);
271 }
272 strcpy(column_name, MS_SDE_ROW_ID_COLUMN);
273 }
274
275
276 proc_key = msLayerGetProcessingKey(layer,"ATTRIBUTE_QUALIFIED");
277 if (sde->join_table ||
278 (proc_key && strcasecmp( proc_key, "TRUE") == 0)) {
279 strcat(full_column_name, sde->table);
280 strcat(full_column_name, ".");
281 strcat(full_column_name, column_name);
282 msFree(column_name);
283
284 }
285 else {
286 strcpy(full_column_name, column_name);
287 msFree(column_name);
288 }
289
290
291 if (full_column_name) {
292 return (full_column_name);
293 }
294 else {
295 msFree(full_column_name);
296 return(msStrdup(MS_SDE_ROW_ID_COLUMN));
297 }
298
299#else
300 msSetError( MS_MISCERR,
301 "SDE support is not available.",
302 "msSDELayerGetRowIDColumn()");
303 return(NULL);
304#endif
305}
306
307
308/* -------------------------------------------------------------------- */
309/* msSDELCacheAdd */
310/* -------------------------------------------------------------------- */
311/* Adds a SDE layer to the global layer cache. */
312/* -------------------------------------------------------------------- */
313long msSDELCacheAdd( layerObj *layer,
314 SE_LAYERINFO layerinfo,
315 char *tableName,
316 char *columnName,
317 char *connectionString)
318{
319
320 layerId *lid = NULL;
321 long status = 0;
322
323 msAcquireLock( TLOCK_SDE );
324
325 if (layer->debug){
326 msDebug( "%s: Caching id for %s, %s, %s\n", "msSDELCacheAdd()",
327 tableName, columnName, connectionString);
328 }
329
330 /* Ensure the cache is large enough to hold the new item. */
331 if(lcacheCount == lcacheMax)
332 {
333 lcacheMax += 10;
334 lcache = (layerId *)realloc(lcache, sizeof(layerId) * lcacheMax);
335 if(lcache == NULL)
336 {
337 msReleaseLock( TLOCK_SDE );
338 msSetError(MS_MEMERR, NULL, "msSDELCacheAdd()");
339 return (MS_FAILURE);
340 }
341 }
342
343 /* Population the new lcache object. */
344 lid = lcache + lcacheCount;
345 lcacheCount++;
346
347 status = SE_layerinfo_get_id(layerinfo, &lid->layerId);
348 if(status != SE_SUCCESS)
349 {
350 msReleaseLock( TLOCK_SDE );
351 sde_error(status, "msSDELCacheAdd()", "SE_layerinfo_get_id()");
352 return(MS_FAILURE);
353 }
354
355 lid->table = msStrdup(tableName);
356 lid->column = msStrdup(columnName);
357 lid->connection = msStrdup(connectionString);
358
359 msReleaseLock( TLOCK_SDE );
360 return (MS_SUCCESS);
361}
362
363/* -------------------------------------------------------------------- */
364/* msSDEGetLayerInfo */
365/* -------------------------------------------------------------------- */
366/* Get a LayerInfo for the layer. Cached layer is used if it */
367/* exists in the cache. */
368/* -------------------------------------------------------------------- */
369long msSDEGetLayerInfo(layerObj *layer,
370 SE_CONNECTION conn,
371 char *tableName,
372 char *columnName,
373 char *connectionString,
374 SE_LAYERINFO layerinfo)
375{
376 int i;
377 long status;
378 layerId *lid = NULL;
379
380 /* If table or column are null, nothing can be done. */
381 if(tableName == NULL)
382 {
383 msSetError( MS_MISCERR,
384 "Missing table name.\n",
385 "msSDEGetLayerInfo()");
386 return (MS_FAILURE);
387 }
388 if(columnName == NULL)
389 {
390 msSetError( MS_MISCERR,
391 "Missing column name.\n",
392 "msSDEGetLayerInfo()");
393 return (MS_FAILURE);
394 }
395 if(connectionString == NULL)
396 {
397 msSetError( MS_MISCERR,
398 "Missing connection string.\n",
399 "msSDEGetLayerInfo()");
400 return (MS_FAILURE);
401 }
402
403 if (layer->debug){
404 msDebug("%s: Looking for layer by %s, %s, %s\n",
405 "msSDEGetLayerInfo()",
406 tableName,
407 columnName,
408 connectionString);
409 }
410
411 /* Search the lcache for the layer id. */
412 for(i = 0; i < lcacheCount; i++)
413 {
414 lid = lcache + i;
415 if(strcasecmp(lid->table, tableName) == 0 &&
416 strcasecmp(lid->column, columnName) == 0 &&
417 strcasecmp(lid->connection, connectionString) == 0)
418 {
419 status = SE_layer_get_info_by_id(conn, lid->layerId, layerinfo);
420 if(status != SE_SUCCESS) {
421 sde_error(status, "msSDEGetLayerInfo()", "SE_layer_get_info()");
422 return(MS_FAILURE);
423 }
424 if (layer->debug){
425 msDebug( "%s: Matched layer to id %i.\n",
426 "msSDEGetLayerId()", lid->layerId);
427 }
428 return (MS_SUCCESS);
429
430 }
431 }
432 if (layer->debug){
433 msDebug("%s: No cached layerid found.\n", "msSDEGetLayerInfo()");
434 }
435
436 /* No matches found, create one. */
437 status = SE_layer_get_info( conn, tableName, columnName, layerinfo );
438 if(status != SE_SUCCESS) {
439 sde_error(status, "msSDEGetLayerInfo()", "SE_layer_get_info()");
440 return(MS_FAILURE);
441 }
442
443 status = msSDELCacheAdd(layer,
444 layerinfo,
445 tableName,
446 columnName,
447 connectionString);
448 return(MS_SUCCESS);
449
450}
451
452/* -------------------------------------------------------------------- */
453/* sdeShapeCopy */
454/* -------------------------------------------------------------------- */
455/* Copies a SDE shape into a MapServer shapeObj */
456/* -------------------------------------------------------------------- */
457static int sdeShapeCopy(SE_SHAPE inshp, shapeObj *outshp) {
458
459 SE_POINT *points=NULL;
460 SE_ENVELOPE envelope;
461 long type, status;
462 long *part_offsets = NULL;
463 long *subpart_offsets = NULL;
464 long num_parts = -1;
465 long num_subparts = -1;
466 long num_points = -1;
467
468 lineObj line={0,NULL};
469
470 int i,j,k;
471
472 status = SE_shape_get_type(inshp, &type);
473 if(status != SE_SUCCESS) {
474 sde_error(status,
475 "sdeCopyShape()",
476 "SE_shape_get_type()");
477 return(MS_FAILURE);
478 }
479
480 switch(type) {
481 case(SG_NIL_SHAPE):
482 return(MS_SUCCESS); /* skip null shapes */
483 break;
484 case(SG_POINT_SHAPE):
485 case(SG_MULTI_POINT_SHAPE):
486 outshp->type = MS_SHAPE_POINT;
487 break;
488 case(SG_LINE_SHAPE):
489 case(SG_SIMPLE_LINE_SHAPE):
490 case(SG_MULTI_LINE_SHAPE):
491 case(SG_MULTI_SIMPLE_LINE_SHAPE):
492 outshp->type = MS_SHAPE_LINE;
493 break;
494 case(SG_AREA_SHAPE):
495 case(SG_MULTI_AREA_SHAPE):
496 outshp->type = MS_SHAPE_POLYGON;
497 break;
498 default:
499 msSetError( MS_SDEERR,
500 "Unsupported SDE shape type (%ld).",
501 "sdeCopyShape()",
502 type);
503 return(MS_FAILURE);
504 }
505
506
507 status = SE_shape_get_num_parts (inshp, &num_parts, &num_subparts);
508 if(status != SE_SUCCESS) {
509 sde_error(status, "sdeShapeCopy()", "SE_shape_get_num_parts()");
510 return(MS_FAILURE);
511 }
512 status = SE_shape_get_num_points (inshp, 0, 0, &num_points);
513 if(status != SE_SUCCESS) {
514 sde_error(status, "sdeShapeCopy()", "SE_shape_get_num_points()");
515 return(MS_FAILURE);
516 }
517
518 part_offsets = (long *) msSmallMalloc( (num_parts + 1) * sizeof(long));
519 subpart_offsets = (long *) msSmallMalloc( (num_subparts + 1) * sizeof(long));
520 part_offsets[num_parts] = num_subparts;
521 subpart_offsets[num_subparts] = num_points;
522
523 points = (SE_POINT *) msSmallMalloc (num_points*sizeof(SE_POINT));
524 if(!points) {
525 msSetError( MS_MEMERR,
526 "Unable to allocate points array.",
527 "sdeCopyShape()");
528 return(MS_FAILURE);
529 }
530
531 status = SE_shape_get_all_points( inshp,
532 SE_DEFAULT_ROTATION,
533 part_offsets,
534 subpart_offsets,
535 points,
536 NULL,
537 NULL);
538 if(status != SE_SUCCESS) {
539 sde_error(status, "sdeCopyShape()", "SE_shape_get_all_points()");
540 return(MS_FAILURE);
541 }
542
543 k = 0; /* overall point counter */
544 for(i=0; i<num_subparts; i++)
545 {
546
547 if( i == num_subparts-1)
548 line.numpoints = num_points - subpart_offsets[i];
549 else
550 line.numpoints = subpart_offsets[i+1] - subpart_offsets[i];
551
552 line.point = (pointObj *)malloc(sizeof(pointObj)*line.numpoints);
553 MS_CHECK_ALLOC(line.point, sizeof(pointObj)*line.numpoints, MS_FAILURE);
554
555 for(j=0; j < line.numpoints; j++) {
556 line.point[j].x = points[k].x;
557 line.point[j].y = points[k].y;
558 k++;
559 }
560
561 msAddLine(outshp, &line);
562 msFree(line.point);
563 }
564
565 msFree(part_offsets);
566 msFree(subpart_offsets);
567 msFree(points);
568
569 /* finally copy the bounding box for the entire shape */
570 status = SE_shape_get_extent(inshp, 0, &envelope);
571 if(status != SE_SUCCESS) {
572 sde_error(status, "sdeCopyShape()", "SE_shape_get_extent()");
573 return(MS_FAILURE);
574 }
575 outshp->bounds.minx = envelope.minx;
576 outshp->bounds.miny = envelope.miny;
577 outshp->bounds.maxx = envelope.maxx;
578 outshp->bounds.maxy = envelope.maxy;
579
580 return(MS_SUCCESS);
581}
582
583/* -------------------------------------------------------------------- */
584/* sdeGetRecord */
585/* -------------------------------------------------------------------- */
586/* Retrieves the current row as setup via the SDE stream query */
587/* or row fetch routines. */
588/* -------------------------------------------------------------------- */
589static int sdeGetRecord(layerObj *layer, shapeObj *shape) {
590 int i;
591 long status;
592
593 double doubleval;
594 long longval;
595 struct tm dateval;
596
597 short shortval; /* new gdv */
598 float floatval;
599
600 SE_COLUMN_DEF *itemdefs;
601 SE_SHAPE shapeval=0;
602 msSDELayerInfo *sde;
603
604 SE_BLOB_INFO blobval;
605
606#ifdef SE_CLOB_TYPE
607 SE_CLOB_INFO clobval;
608#endif
609
610#ifdef SE_NCLOB_TYPE
611 SE_NCLOB_INFO nclobval;
612#endif
613
614#ifdef SE_NSTRING_TYPE
615 SE_WCHAR* wide=NULL;
616#endif
617
618
619 if(!msSDELayerIsOpen(layer)) {
620 msSetError( MS_SDEERR,
621 "SDE layer has not been opened.",
622 "sdeGetRecord()");
623 return MS_FAILURE;
624 }
625
626 sde = layer->layerinfo;
627
628 if(layer->numitems > 0) {
629 shape->numvalues = layer->numitems;
630 shape->values = (char **) malloc (sizeof(char *)*layer->numitems);
631 MS_CHECK_ALLOC(shape->values, sizeof(char *)*layer->numitems, MS_FAILURE);
632 }
633
634 status = SE_shape_create(NULL, &shapeval);
635 if(status != SE_SUCCESS) {
636 sde_error(status, "sdeGetRecord()", "SE_shape_create()");
637 return(MS_FAILURE);
638 }
639
640 itemdefs = layer->iteminfo;
641 for(i=0; i<layer->numitems; i++) {
642
643 /* do something special */
644 if(strcmp(layer->items[i],sde->row_id_column) == 0) {
645 status = SE_stream_get_integer(sde->connPoolInfo->stream, (short)(i+1), &shape->index);
646 if(status != SE_SUCCESS) {
647 sde_error(status, "sdeGetRecord()", "SE_stream_get_integer()");
648 return(MS_FAILURE);
649 }
650
651 shape->values[i] = (char *)msSmallMalloc(64); /* should be enough */
652 sprintf(shape->values[i], "%ld", shape->index);
653 continue;
654 }
655
656 switch(itemdefs[i].sde_type) {
657 case SE_SMALLINT_TYPE:
658 /* changed by gdv */
659 status = SE_stream_get_smallint(sde->connPoolInfo->stream,
660 (short)(i+1),
661 &shortval);
662 if(status == SE_SUCCESS)
663 shape->values[i] = msLongToString(shortval);
664 else if(status == SE_NULL_VALUE)
665 shape->values[i] = msStrdup(MS_SDE_NULLSTRING);
666 else {
667 sde_error( status,
668 "sdeGetRecord()",
669 "SE_stream_get_smallint()");
670 return(MS_FAILURE);
671 }
672 break;
673 case SE_INTEGER_TYPE:
674 status = SE_stream_get_integer( sde->connPoolInfo->stream,
675 (short)(i+1),
676 &longval);
677 if(status == SE_SUCCESS)
678 shape->values[i] = msLongToString(longval);
679 else if(status == SE_NULL_VALUE)
680 shape->values[i] = msStrdup(MS_SDE_NULLSTRING);
681 else {
682 sde_error( status,
683 "sdeGetRecord()",
684 "SE_stream_get_integer()");
685 return(MS_FAILURE);
686 }
687 break;
688 case SE_FLOAT_TYPE:
689 status = SE_stream_get_float( sde->connPoolInfo->stream,
690 (short)(i+1),
691 &floatval);
692 if(status == SE_SUCCESS)
693 shape->values[i] = msDoubleToString(floatval, MS_FALSE);
694 else if(status == SE_NULL_VALUE)
695 shape->values[i] = msStrdup(MS_SDE_NULLSTRING);
696 else {
697 sde_error( status,
698 "sdeGetRecord()",
699 "SE_stream_get_float()");
700 return(MS_FAILURE);
701 }
702 break;
703 case SE_DOUBLE_TYPE:
704 status = SE_stream_get_double( sde->connPoolInfo->stream,
705 (short) (i+1),
706 &doubleval);
707 if(status == SE_SUCCESS)
708 shape->values[i] = msDoubleToString(doubleval, MS_FALSE);
709 else if(status == SE_NULL_VALUE)
710 shape->values[i] = msStrdup(MS_SDE_NULLSTRING);
711 else {
712 sde_error( status,
713 "sdeGetRecord()",
714 "SE_stream_get_double()");
715 return(MS_FAILURE);
716 }
717 break;
718 case SE_STRING_TYPE:
719 shape->values[i] = (char *)msSmallMalloc(itemdefs[i].size+1);
720 status = SE_stream_get_string( sde->connPoolInfo->stream,
721 (short) (i+1),
722 shape->values[i]);
723 if(status == SE_NULL_VALUE)
724 shape->values[i][0] = '\0'; /* empty string */
725 else if(status != SE_SUCCESS) {
726 sde_error( status,
727 "sdeGetRecord()",
728 "SE_stream_get_string()");
729 return(MS_FAILURE);
730 }
731 break;
732#ifdef SE_NSTRING_TYPE
733 case SE_NSTRING_TYPE:
734 wide = (SE_WCHAR *)msSmallMalloc(itemdefs[i].size*2*sizeof(SE_WCHAR)+1);
735 memset(wide, 0, itemdefs[i].size*2*sizeof(SE_WCHAR)+1);
736 status = SE_stream_get_nstring( sde->connPoolInfo->stream,
737 (short) (i+1),
738 wide);
739 if(status == SE_NULL_VALUE) {
740 shape->values[i] = (char *)msSmallMalloc(itemdefs[i].size*sizeof(char)+1);
741 shape->values[i][0] = '\0'; /* empty string */
742 msFree(wide);
743 }
744 else if(status != SE_SUCCESS) {
745 sde_error( status,
746 "sdeGetRecord()",
747 "SE_stream_get_string()");
748 return(MS_FAILURE);
749 } else {
750 if (sde->bBigEndian)
751 shape->values[i] = msConvertWideStringToUTF8((const wchar_t*) wide, "UTF-16BE");
752 else
753 shape->values[i] = msConvertWideStringToUTF8((const wchar_t*) wide, "UTF-16LE");
754 msFree(wide);
755 if (!shape->values[i]) { /* There was an error */
756 msSetError( MS_SDEERR,
757 "msConvertWideStringToUTF8()==NULL.",
758 "sdeGetRecord()");
759 shape->values[i] = (char *)msSmallMalloc(itemdefs[i].size*sizeof(char)+1);
760 shape->values[i][0] = '\0'; /* empty string */
761 }
762 }
763 break;
764#endif
765
766#ifdef SE_UUID_TYPE
767
768 case SE_UUID_TYPE:
769 shape->values[i] = (char *)msSmallMalloc(itemdefs[i].size+1);
770 status = SE_stream_get_uuid ( sde->connPoolInfo->stream,
771 (short) (i+1),
772 shape->values[i]);
773 if(status == SE_NULL_VALUE)
774 shape->values[i][0] = '\0'; /* empty string */
775 else if(status != SE_SUCCESS) {
776 sde_error( status,
777 "sdeGetRecord()",
778 "SE_stream_get_uuid()");
779 return(MS_FAILURE);
780 }
781 break;
782
783#endif
784
785#ifdef SE_CLOB_TYPE
786
787 case SE_CLOB_TYPE:
788 status = SE_stream_get_clob(sde->connPoolInfo->stream, (short) (i+1), &clobval);
789 if(status == SE_SUCCESS) {
790 shape->values[i] = (char *)msSmallMalloc(sizeof(char)*clobval.clob_length);
791 shape->values[i] = memcpy( shape->values[i],
792 clobval.clob_buffer,
793 clobval.clob_length);
794 SE_clob_free(&clobval);
795 }
796 else if (status == SE_NULL_VALUE) {
797 shape->values[i] = msStrdup(MS_SDE_NULLSTRING);
798 }
799 else {
800 sde_error( status,
801 "sdeGetRecord()",
802 "SE_stream_get_clob()");
803 return(MS_FAILURE);
804 }
805 break;
806#endif
807
808#ifdef SE_CLOB_TYPE
809
810 case SE_NCLOB_TYPE:
811 status = SE_stream_get_nclob(sde->connPoolInfo->stream, (short) (i+1), &nclobval);
812 if(status == SE_SUCCESS) {
813 shape->values[i] = (char *)msSmallMalloc(sizeof(char)*nclobval.nclob_length);
814 shape->values[i] = memcpy( shape->values[i],
815 nclobval.nclob_buffer,
816 nclobval.nclob_length);
817 SE_nclob_free(&nclobval);
818 }
819 else if (status == SE_NULL_VALUE) {
820 shape->values[i] = msStrdup(MS_SDE_NULLSTRING);
821 }
822 else {
823 sde_error( status,
824 "sdeGetRecord()",
825 "SE_stream_get_nclob()");
826 return(MS_FAILURE);
827 }
828 break;
829#endif
830
831 case SE_BLOB_TYPE:
832 status = SE_stream_get_blob(sde->connPoolInfo->stream, (short) (i+1), &blobval);
833 if(status == SE_SUCCESS) {
834 shape->values[i] = (char *)msSmallMalloc(sizeof(char)*blobval.blob_length);
835 shape->values[i] = memcpy( shape->values[i],
836 blobval.blob_buffer,
837 blobval.blob_length);
838 SE_blob_free(&blobval);
839 }
840 else if (status == SE_NULL_VALUE) {
841 shape->values[i] = msStrdup(MS_SDE_NULLSTRING);
842 }
843 else {
844 sde_error( status,
845 "sdeGetRecord()",
846 "SE_stream_get_blob()");
847 return(MS_FAILURE);
848 }
849 break;
850
851 case SE_DATE_TYPE:
852 status = SE_stream_get_date(sde->connPoolInfo->stream, (short)(i+1), &dateval);
853 if(status == SE_SUCCESS) {
854 shape->values[i] = (char *)msSmallMalloc(sizeof(char)*MS_SDE_TIMEFMTSIZE);
855 strftime( shape->values[i],
856 MS_SDE_TIMEFMTSIZE,
857 MS_SDE_TIMEFMT,
858 &dateval);
859 }
860 else if(status == SE_NULL_VALUE)
861 shape->values[i] = msStrdup(MS_SDE_NULLSTRING);
862 else {
863 sde_error( status,
864 "sdeGetRecord()",
865 "SE_stream_get_date()");
866 return(MS_FAILURE);
867 }
868 break;
869 case SE_SHAPE_TYPE:
870 status = SE_stream_get_shape(sde->connPoolInfo->stream, (short)(i+1), shapeval);
871 if(status == SE_SUCCESS)
872 shape->values[i] = msStrdup(MS_SDE_SHAPESTRING);
873 else if(status == SE_NULL_VALUE)
874 shape->values[i] = msStrdup(MS_SDE_NULLSTRING);
875 else {
876 sde_error( status,
877 "sdeGetRecord()",
878 "SE_stream_get_shape()");
879 return(MS_FAILURE);
880 }
881 break;
882 default:
883 msSetError( MS_SDEERR,
884 "Unknown SDE column type.",
885 "sdeGetRecord()");
886 return(MS_FAILURE);
887 break;
888 } /* switch(itemdefs[i].sde_type) */
889 } /* for(i=0; i<layer->numitems; i++) { */
890
891 if(SE_shape_is_nil(shapeval)) return(MS_SUCCESS);
892
893 /* copy sde shape to a mapserver shape */
894 status = sdeShapeCopy(shapeval, shape);
895 if(status != MS_SUCCESS) return(MS_FAILURE);
896
897 /* clean up */
898 SE_shape_free(shapeval);
899
900
901 return(MS_SUCCESS);
902}
903
904static SE_QUERYINFO getSDEQueryInfo(layerObj *layer)
905{
906 SE_QUERYINFO query_info;
907 long status;
908
909 msSDELayerInfo *sde=NULL;
910
911 if(!msSDELayerIsOpen(layer)) {
912 msSetError( MS_SDEERR,
913 "SDE layer has not been opened.",
914 "getSDEQueryInfo()");
915 return(NULL);
916 }
917
918 sde = layer->layerinfo;
919
920 /*
921 ** See http://forums.esri.com/Thread.asp?c=2&f=59&t=108929&mc=4#msgid310273
922 ** SE_queryinfo is a new SDE struct in ArcSDE 8.x that is a bit easier
923 ** (and faster) to use. HCB
924 */
925 status = SE_queryinfo_create (&query_info);
926 if(status != SE_SUCCESS) {
927 sde_error( status,
928 "getSDEQueryInfo()",
929 "SE_queryinfo_create()");
930 return(NULL);
931 }
932
933 /* set the tables -- just one at this point */
934 status = SE_queryinfo_set_tables ( query_info,
935 1,
936 (const CHAR **) &(sde->table),
937 NULL);
938 if(status != SE_SUCCESS) {
939 sde_error( status,
940 "getSDEQueryInfo()",
941 "SE_queryinfo_create()");
942 return(NULL);
943 }
944
945 /* set the "where" clause */
946 if(!(layer->filter.string))
947 /* set to empty string */
948 status = SE_queryinfo_set_where_clause (query_info,
949 (const CHAR * ) "");
950 else
951 /* set to the layer's filter.string */
952 status = SE_queryinfo_set_where_clause (query_info,
953 (const CHAR * ) (layer->filter.string));
954 if(status != SE_SUCCESS) {
955 sde_error( status,
956 "getSDEQueryInfo()",
957 "SE_queryinfo_set_where_clause()");
958 return(NULL);
959 }
960
961 status = SE_queryinfo_set_columns( query_info,
962 layer->numitems,
963 (const char **)layer->items);
964 if(status != SE_SUCCESS) {
965 sde_error( status,
966 "getSDEQueryInfo()",
967 "SE_queryinfo_set_columns()");
968 return(NULL);
969 }
970
971 /* Join the spatial and feature tables. If we specify the type of join */
972 /* we'll query faster than querying all tables individually (old method) */
973 status = SE_queryinfo_set_query_type (query_info,SE_QUERYTYPE_JSF);
974 if(status != SE_SUCCESS) {
975 sde_error( status,
976 "getSDEQueryInfo()",
977 "SE_queryinfo_set_query_type()");
978 return(NULL);
979 }
980
981 return query_info;
982}
983
984static SE_SQL_CONSTRUCT* getSDESQLConstructInfo(layerObj *layer, long* id)
985{
986 SE_SQL_CONSTRUCT* sql;
987
988 char *full_filter=NULL;
989 char *pszId=NULL;
990 long status;
991
992 msSDELayerInfo *sde=NULL;
993 full_filter = (char*) msSmallMalloc((1000+1)*sizeof (char));
994 full_filter[0] = '\0';
995 if(!msSDELayerIsOpen(layer)) {
996 msSetError( MS_SDEERR,
997 "SDE layer has not been opened.",
998 "getSDESQLConstructInfo()");
999 return(NULL);
1000 }
1001
1002 sde = layer->layerinfo;
1003
1004 if (!sde->join_table) {
1005 msSetError( MS_SDEERR,
1006 "Join table is null, we should be using QueryInfo.",
1007 "getSDESQLConstructInfo()");
1008 return(NULL);
1009 }
1010
1011 status = SE_sql_construct_alloc( 2, &sql);
1012 if(status != SE_SUCCESS) {
1013 sde_error( status,
1014 "getSDESQLConstructInfo()",
1015 "SE_sql_construct_alloc()");
1016 return(NULL);
1017 }
1018
1019 strcpy(sql->tables[0], sde->table); /* main table */
1020 strcpy(sql->tables[1], sde->join_table); /* join table */
1021
1022 /* If we were given an ID *and* we have a join, we need to
1023 set our FILTER statement to reflect this. */
1024 if ((sde->join_table) && (id != NULL)) {
1025 pszId = msLongToString(*id);
1026 strcat(full_filter, layer->filter.string);
1027 strcat(full_filter, " AND ");
1028 strcat(full_filter, sde->row_id_column);
1029 strcat(full_filter, "=");
1030 strcat(full_filter, pszId);
1031 msFree(pszId);
1032 sql->where = msStrdup(full_filter);
1033
1034
1035 } else {
1036 sql->where = layer->filter.string;
1037 }
1038
1039 msFree(full_filter);
1040
1041 if (layer->debug) msDebug("WHERE statement: %s\n", sql->where);
1042 return sql;
1043}
1044#endif
1045
1046/************************************************************************/
1047/* Start SDE/MapServer library functions. */
1048/* */
1049/************************************************************************/
1050
1051/* -------------------------------------------------------------------- */
1052/* msSDELayerOpen */
1053/* -------------------------------------------------------------------- */
1054/* Connects to SDE using the SDE C API. Connections are pooled */
1055/* using the MapServer pooling API. After a connection is made, */
1056/* a query stream is created, using the SDE version specified in */
1057/* the DATA string, or SDE.DEFAULT if not specified. It is */
1058/* important to note that the SE_CONNECTION is shared across data */
1059/* layers, but the state_id for a layer's version is different, */
1060/* even for layers with the same version name. These are *not* */
1061/* shared across layers. */
1062/* -------------------------------------------------------------------- */
1063int msSDELayerOpen(layerObj *layer) {
1064#ifdef USE_SDE
1065 long status=-1;
1066 int endian_test=1;
1067 char **params=NULL;
1068 char **data_params=NULL;
1069 char *join_table=NULL;
1070
1071 int numparams=0;
1072 SE_ERROR hSDEError;
1073 SE_STATEINFO state;
1074 SE_VERSIONINFO version;
1075
1076 SE_ENVELOPE envelope;
1077
1078 msSDELayerInfo *sde = NULL;
1079 msSDEConnPoolInfo *poolinfo;
1080
1081 /* allocate space for SDE structures */
1082 sde = (msSDELayerInfo *) malloc(sizeof(msSDELayerInfo));
1083 MS_CHECK_ALLOC(sde, sizeof(msSDELayerInfo), MS_FAILURE);
1084
1085 sde->state_id = SE_BASE_STATE_ID;
1086
1087 /* initialize the table and spatial column names */
1088 sde->table = NULL;
1089 sde->column = NULL;
1090 sde->row_id_column = NULL;
1091 sde->join_table = NULL;
1092 sde->basedefs = NULL;
1093 sde->joindefs = NULL;
1094 sde->extent = (rectObj *) msSmallMalloc(sizeof(rectObj));
1095
1096 sde->nBaseColumns = (short *) msSmallMalloc(1*sizeof(short));
1097 *(sde->nBaseColumns) = 0;
1098 sde->nJoinColumns = (short *) msSmallMalloc(1*sizeof(short));
1099 *(sde->nJoinColumns) = 0;
1100
1101 if(!sde->extent) {
1102 msSetError( MS_MEMERR,
1103 "Error allocating extent for SDE layer",
1104 "msSDELayerOpen()");
1105 return(MS_FAILURE);
1106 }
1107
1108 /* request a connection and stream from the pool */
1109 poolinfo = (msSDEConnPoolInfo *)msConnPoolRequest( layer );
1110
1111#ifdef SE_connection_test_server
1112 /* check the connection */
1113 if (poolinfo && (SE_connection_test_server(poolinfo->connection, 30) != SE_SUCCESS)) {
1114 msSDECloseConnection(poolinfo->connection);
1115 }
1116#endif
1117
1118 /* If we weren't returned a connection and stream, initialize new ones */
1119 if (!poolinfo) {
1120 char *conn_decrypted;
1121
1122 if (layer->debug)
1123 msDebug("msSDELayerOpen(): "
1124 "Layer %s opened from scratch.\n", layer->name);
1125
1126
1127 poolinfo = (msSDEConnPoolInfo *)malloc(sizeof *poolinfo);
1128 MS_CHECK_ALLOC(poolinfo, sizeof *poolinfo, MS_FAILURE);
1129
1130 /* Decrypt any encrypted token in the connection string */
1131 conn_decrypted = msDecryptStringTokens(layer->map, layer->connection);
1132
1133 /* An error should already have been produced */
1134 if (conn_decrypted == NULL) {
1135 return(MS_FAILURE);
1136 }
1137 /* Split the connection parameters and make sure we have enough of them */
1138 params = msStringSplit(conn_decrypted, ',', &numparams);
1139 if(!params) {
1140 msSetError( MS_MEMERR,
1141 "Error splitting SDE connection information.",
1142 "msSDELayerOpen()");
1143 msFree(conn_decrypted);
1144 return(MS_FAILURE);
1145 }
1146 msFree(conn_decrypted);
1147 conn_decrypted = NULL;
1148
1149 if(numparams < 5) {
1150 msSetError( MS_SDEERR,
1151 "Not enough SDE connection parameters specified.",
1152 "msSDELayerOpen()");
1153 return(MS_FAILURE);
1154 }
1155
1156 /* Create the connection handle and put into poolinfo->connection */
1157 status = SE_connection_create(params[0],
1158 params[1],
1159 params[2],
1160 params[3],
1161 params[4],
1162 &(hSDEError),
1163 &(poolinfo->connection));
1164
1165 if(status != SE_SUCCESS) {
1166 sde_error( status,
1167 "msSDELayerOpen()",
1168 "SE_connection_create()");
1169 return(MS_FAILURE);
1170 }
1171
1172 /* ------------------------------------------------------------------------- */
1173 /* Set the concurrency type for the connection. SE_UNPROTECTED_POLICY is */
1174 /* suitable when only one thread accesses the specified connection. */
1175 /* ------------------------------------------------------------------------- */
1176 status = SE_connection_set_concurrency( poolinfo->connection,
1177 SE_UNPROTECTED_POLICY);
1178
1179
1180 if(status != SE_SUCCESS) {
1181 sde_error( status,
1182 "msSDELayerOpen()",
1183 "SE_connection_set_concurrency()");
1184 return(MS_FAILURE);
1185 }
1186
1187
1188 status = SE_stream_create(poolinfo->connection, &(poolinfo->stream));
1189 if(status != SE_SUCCESS) {
1190 sde_error( status,
1191 "msSDELayerOpen()",
1192 "SE_stream_create()");
1193 return(MS_FAILURE);
1194 }
1195
1196 /* Register the connection with the connection pooling API. Give */
1197 /* msSDECloseConnection as the function to call when we run out of layer */
1198 /* instances using it */
1199 msConnPoolRegister(layer, poolinfo, msSDECloseConnection);
1200 msFreeCharArray(params, numparams); /* done with parameter list */
1201 } /* !poolinfo */
1202
1203 /* Split the DATA member into its parameters using the comma */
1204 /* Periods (.) are used to denote table names and schemas in SDE, */
1205 /* as are underscores (_). */
1206 data_params = msStringSplit(layer->data, ',', &numparams);
1207 if(!data_params) {
1208 msSetError( MS_MEMERR,
1209 "Error splitting SDE layer information.",
1210 "msSDELayerOpen()");
1211 return(MS_FAILURE);
1212 }
1213
1214 if(numparams < 2) {
1215 msSetError( MS_SDEERR,
1216 "Not enough SDE layer parameters specified.",
1217 "msSDELayerOpen()");
1218 return(MS_FAILURE);
1219 }
1220
1221 sde->table = msStrdup(data_params[0]);
1222 sde->column = msStrdup(data_params[1]);
1223
1224 join_table = msLayerGetProcessingKey(layer,"JOINTABLE");
1225 if (join_table) {
1226 sde->join_table = msStrdup(join_table);
1227 /* msFree(join_table); */
1228 }
1229 if (numparams < 3){
1230 /* User didn't specify a version, we won't use one */
1231 if (layer->debug) {
1232 msDebug("msSDELayerOpen(): Layer %s did not have a "
1233 "specified version.\n",
1234 layer->name);
1235 }
1236 sde->state_id = SE_DEFAULT_STATE_ID;
1237 }
1238 else {
1239 /* A version was specified... obtain the state_id */
1240 /* for it. */
1241 if (layer->debug) {
1242 msDebug("msSDELayerOpen(): Layer %s specified version %s.\n",
1243 layer->name,
1244 data_params[2]);
1245 }
1246 status = SE_versioninfo_create (&(version));
1247 if(status != SE_SUCCESS) {
1248 sde_error( status,
1249 "msSDELayerOpen()",
1250 "SE_versioninfo_create()");
1251 return(MS_FAILURE);
1252 }
1253 status = SE_version_get_info(poolinfo->connection, data_params[2], version);
1254
1255 if(status != SE_SUCCESS) {
1256
1257 if (status == SE_INVALID_RELEASE) {
1258 /* The user has incongruent versions of SDE, ie 8.2 client and */
1259 /* 8.3 server set the state_id to SE_DEFAULT_STATE_ID, which means */
1260 /* no version queries are done */
1261 sde->state_id = SE_DEFAULT_STATE_ID;
1262 }
1263 else {
1264 sde_error( status,
1265 "msSDELayerOpen()",
1266 "SE_version_get_info()");
1267 SE_versioninfo_free(version);
1268 return(MS_FAILURE);
1269 }
1270 } /* couldn't get version info */
1271
1272 } /* version was specified */
1273
1274 /* Get the STATEID from the given version and set the stream to */
1275 /* that if we didn't already set it to SE_DEFAULT_STATE_ID. */
1276 if (sde->state_id != SE_DEFAULT_STATE_ID){
1277 status = SE_versioninfo_get_state_id(version, &sde->state_id);
1278 if(status != SE_SUCCESS) {
1279 sde_error( status,
1280 "msSDELayerOpen()",
1281 "SE_versioninfo_get_state_id()");
1282 SE_versioninfo_free(version);
1283 return(MS_FAILURE);
1284 }
1285
1286 SE_versioninfo_free(version);
1287 status = SE_stateinfo_create (&state);
1288 if(status != SE_SUCCESS) {
1289 sde_error( status,
1290 "msSDELayerOpen()",
1291 "SE_stateinfo_create()");
1292 return(MS_FAILURE);
1293 }
1294 status = SE_state_get_info( poolinfo->connection,
1295 sde->state_id,
1296 state);
1297 if(status != SE_SUCCESS) {
1298 sde_error(status, "msSDELayerOpen()", "SE_state_get_info()");
1299 SE_stateinfo_free (state);
1300 return(MS_FAILURE);
1301 }
1302 if (SE_stateinfo_is_open (state)) {
1303 /* If the state is open for edits, we shouldn't be querying from it */
1304 sde_error( status,
1305 "msSDELayerOpen()",
1306 "SE_stateinfo_is_open() -- State for version is open");
1307 SE_stateinfo_free (state);
1308 return(MS_FAILURE);
1309 }
1310 SE_stateinfo_free (state);
1311 } /* if (!(sde->state_id == SE_DEFAULT_STATE_ID)) */
1312
1313
1314 /* done with the DATA stuff now */
1315 msFreeCharArray(data_params, numparams);
1316
1317 status = SE_layerinfo_create(NULL, &(sde->layerinfo));
1318 if(status != SE_SUCCESS) {
1319 sde_error(status, "msSDELayerOpen()", "SE_layerinfo_create()");
1320 return(MS_FAILURE);
1321 }
1322
1323
1324 status = msSDEGetLayerInfo( layer,
1325 poolinfo->connection,
1326 sde->table,
1327 sde->column,
1328 layer->connection,
1329 sde->layerinfo);
1330
1331 if(status != MS_SUCCESS) {
1332 sde_error(status, "msSDELayerOpen()", "msSDEGetLayerInfo()");
1333 return(MS_FAILURE);
1334 }
1335
1336 status = SE_coordref_create(&(sde->coordref));
1337 if(status != SE_SUCCESS) {
1338 sde_error(status, "msSDELayerOpen()", "SE_coordref_create()");
1339 return(MS_FAILURE);
1340 }
1341
1342 status = SE_layerinfo_get_coordref(sde->layerinfo, sde->coordref);
1343 if(status != SE_SUCCESS) {
1344 sde_error(status, "msSDELayerOpen()", "SE_layerinfo_get_coordref()");
1345 return(MS_FAILURE);
1346 }
1347
1348 /* Get the layer extent and hang it on the layerinfo */
1349 status = SE_layerinfo_get_envelope(sde->layerinfo, &envelope);
1350 if(status != SE_SUCCESS) {
1351 sde_error(status,
1352 "msSDELayerOpen()",
1353 "SE_layerinfo_get_envelope()");
1354 return(MS_FAILURE);
1355 }
1356
1357 sde->extent->minx = envelope.minx;
1358 sde->extent->miny = envelope.miny;
1359 sde->extent->maxx = envelope.maxx;
1360 sde->extent->maxy = envelope.maxy;
1361
1362 /* reset the stream */
1363 status = SE_stream_close(poolinfo->stream, 1);
1364 if(status != SE_SUCCESS) {
1365 sde_error(status, "msSDELayerOpen()", "SE_stream_close()");
1366 return(MS_FAILURE);
1367 }
1368
1369 /* Determine if we are big or little- endian for */
1370 /* working with the encoding */
1371 if( *((unsigned char *) &endian_test) == 1 )
1372 sde->bBigEndian = MS_FALSE;
1373 else
1374 sde->bBigEndian = MS_TRUE;
1375
1376 /* point to the SDE layer information */
1377 /* (note this might actually be in another layer) */
1378 layer->layerinfo = sde;
1379 sde->connPoolInfo = poolinfo;
1380 return(MS_SUCCESS);
1381#else
1382 msSetError(MS_MISCERR, "SDE support is not available.", "msSDELayerOpen()");
1383 return(MS_FAILURE);
1384#endif
1385}
1386
1387
1388
1389
1390/* -------------------------------------------------------------------- */
1391/* msSDELayerClose */
1392/* -------------------------------------------------------------------- */
1393/* Closes the MapServer layer. This doesn't necessarily close the */
1394/* connection to the layer. */
1395/* -------------------------------------------------------------------- */
1396int msSDELayerClose(layerObj *layer) {
1397#ifdef USE_SDE
1398
1399
1400 msSDELayerInfo *sde=NULL;
1401
1402 sde = layer->layerinfo;
1403
1404 /* Silently return if layer not opened. */
1405 if (!msSDELayerIsOpen(layer)) return MS_SUCCESS;
1406
1407 if(layer->debug)
1408 msDebug("msSDELayerClose(): Closing layer %s.\n", layer->name);
1409
1410 if (sde->layerinfo) SE_layerinfo_free(sde->layerinfo);
1411 if (sde->coordref) SE_coordref_free(sde->coordref);
1412 if (sde->table) msFree(sde->table);
1413 if (sde->column) msFree(sde->column);
1414 if (sde->row_id_column) msFree(sde->row_id_column);
1415 if (sde->join_table) msFree(sde->join_table);
1416 if (sde->extent) msFree(sde->extent);
1417 if (sde->nBaseColumns) msFree(sde->nBaseColumns);
1418 if (sde->nJoinColumns) msFree(sde->nJoinColumns);
1419
1420 msConnPoolRelease( layer, sde->connPoolInfo );
1421 if (layer->layerinfo) msFree(layer->layerinfo);
1422 layer->layerinfo = NULL;
1423 return MS_SUCCESS;
1424
1425#else
1426 msSetError( MS_MISCERR,
1427 "SDE support is not available.",
1428 "msSDELayerClose()");
1429 return(MS_FALSE);
1430#endif
1431}
1432
1433
1434/* -------------------------------------------------------------------- */
1435/* msSDELayerCloseConnection */
1436/* -------------------------------------------------------------------- */
1437/* Virtual table function */
1438/* -------------------------------------------------------------------- */
1439int msSDELayerCloseConnection(layerObj *layer)
1440{
1441
1442
1443#ifdef USE_SDE
1444
1445
1446 msSDELayerInfo *sde=NULL;
1447
1448 if(!msSDELayerIsOpen(layer)) {
1449 return MS_SUCCESS; /* already closed */
1450 }
1451
1452 sde = layer->layerinfo;
1453
1454 if(layer->debug)
1455 msDebug("msSDELayerCloseConnection(): Closing connection for layer %s.\n", layer->name);
1456
1457 msConnPoolRelease( layer, sde->connPoolInfo );
1458 sde->connPoolInfo = NULL;
1459 return (MS_SUCCESS);
1460#else
1461 msSetError( MS_MISCERR,
1462 "SDE support is not available.",
1463 "msSDELayerClose()");
1464 return MS_FAILURE;
1465#endif
1466
1467 return MS_SUCCESS;
1468}
1469
1470
1471/* -------------------------------------------------------------------- */
1472/* msSDELayerWhichShapes */
1473/* -------------------------------------------------------------------- */
1474/* starts a stream query using spatial filter. Also limits the */
1475/* query by the layer's FILTER item as well. */
1476/* -------------------------------------------------------------------- */
1477int msSDELayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) {
1478#ifdef USE_SDE
1479 long status;
1480 SE_ENVELOPE envelope;
1481 SE_SHAPE shape=0;
1482 SE_FILTER constraint;
1483 SE_QUERYINFO query_info = NULL;
1484 SE_SQL_CONSTRUCT* sql = NULL;
1485 char* proc_value=NULL;
1486 int query_order=SE_SPATIAL_FIRST;
1487
1488 msSDELayerInfo *sde=NULL;
1489
1490 if(!msSDELayerIsOpen(layer)) {
1491 msSetError( MS_SDEERR,
1492 "SDE layer has not been opened.",
1493 "msSDELayerWhichShapes()");
1494 return(MS_FAILURE);
1495 }
1496
1497 sde = layer->layerinfo;
1498
1499 /* use the cached layer's extent. */
1500 /* there is NO overlap, return MS_DONE */
1501 /* (FIX: use this in ALL which shapes functions) */
1502 if(sde->extent->minx > rect.maxx) return(MS_DONE);
1503 if(sde->extent->maxx < rect.minx) return(MS_DONE);
1504 if(sde->extent->miny > rect.maxy) return(MS_DONE);
1505 if(sde->extent->maxy < rect.miny) return(MS_DONE);
1506
1507 /* set spatial constraint search shape */
1508 /* crop against SDE layer extent *argh* */
1509 envelope.minx = MS_MAX(rect.minx, sde->extent->minx);
1510 envelope.miny = MS_MAX(rect.miny, sde->extent->miny);
1511 envelope.maxx = MS_MIN(rect.maxx, sde->extent->maxx);
1512 envelope.maxy = MS_MIN(rect.maxy, sde->extent->maxy);
1513
1514 if( envelope.minx == envelope.maxx && envelope.miny == envelope.maxy){
1515 /* fudge a rectangle so we have a valid one for generate_rectangle */
1516 /* FIXME: use the real shape for the query and set the filter_type
1517 to be an appropriate type */
1518 envelope.minx = envelope.minx - 0.001;
1519 envelope.maxx = envelope.maxx + 0.001;
1520 envelope.miny = envelope.miny - 0.001;
1521 envelope.maxy = envelope.maxy + 0.001;
1522 }
1523
1524 status = SE_shape_create(sde->coordref, &shape);
1525 if(status != SE_SUCCESS) {
1526 sde_error( status,
1527 "msSDELayerWhichShapes()",
1528 "SE_shape_create()");
1529 return(MS_FAILURE);
1530 }
1531
1532 status = SE_shape_generate_rectangle(&envelope, shape);
1533 if(status != SE_SUCCESS) {
1534 sde_error( status,
1535 "msSDELayerWhichShapes()",
1536 "SE_shape_generate_rectangle()");
1537 return(MS_FAILURE);
1538 }
1539 constraint.filter.shape = shape;
1540
1541 /* set spatial constraint column and table */
1542 strcpy(constraint.table, sde->table);
1543 strcpy(constraint.column, sde->column);
1544
1545 /* set a couple of other spatial constraint properties */
1546 constraint.method = SM_ENVP;
1547 constraint.filter_type = SE_SHAPE_FILTER;
1548 constraint.truth = TRUE;
1549
1550 if (!sde->join_table) {
1551 query_info = getSDEQueryInfo(layer);
1552 if (!query_info) {
1553 sde_error( status,
1554 "msSDELayerWhichShapes()",
1555 "getSDEQueryInfo()");
1556 return(MS_FAILURE);
1557 }
1558 } else {
1559 if (!layer->filter.string) {
1560 sde_error( -51,
1561 "msSDELayerWhichShapes()",
1562 "A join table is specified, but no FILTER is"
1563 " defined that joins the two tables together");
1564 return(MS_FAILURE);
1565 }
1566 sql = getSDESQLConstructInfo(layer, NULL);
1567 }
1568
1569 /* reset the stream */
1570 status = SE_stream_close(sde->connPoolInfo->stream, 1);
1571 if(status != SE_SUCCESS) {
1572 sde_error( status,
1573 "msSDELayerWhichShapes()",
1574 "SE_stream_close()");
1575 return(MS_FAILURE);
1576 }
1577 /* Set the stream state back to the state_id of our user-specified version */
1578 /* This must be done every time after the stream is reset before the */
1579 /* query happens. */
1580
1581 if (sde->state_id != SE_DEFAULT_STATE_ID){
1582
1583 status = SE_stream_set_state(sde->connPoolInfo->stream,
1584 sde->state_id,
1585 sde->state_id,
1586 SE_STATE_DIFF_NOCHECK);
1587 if(status != SE_SUCCESS) {
1588 sde_error( status,
1589 "msSDELayerOpen()",
1590 "SE_stream_set_state()");
1591 return(MS_FAILURE);
1592 }
1593 }
1594
1595 if (!sql) {
1596 status = SE_stream_query_with_info(sde->connPoolInfo->stream, query_info);
1597 if(status != SE_SUCCESS) {
1598 sde_error(status,
1599 "msSDELayerWhichShapes()",
1600 "SE_stream_query_with_info()");
1601 return(MS_FAILURE);
1602 }
1603 } else {
1604 status = SE_stream_query(sde->connPoolInfo->stream, layer->numitems, (const CHAR**) layer->items, sql);
1605 if(status != SE_SUCCESS) {
1606 sde_error(status,
1607 "msSDELayerWhichShapes()",
1608 "SE_stream_query()");
1609 return(MS_FAILURE);
1610 }
1611 /* Free up the sql now that we've queried */
1612 SE_sql_construct_free(sql);
1613 }
1614 proc_value = msLayerGetProcessingKey(layer,"QUERYORDER");
1615 if(proc_value && strcasecmp(proc_value, "ATTRIBUTE") == 0)
1616 query_order = SE_ATTRIBUTE_FIRST;
1617
1618 status = SE_stream_set_spatial_constraints( sde->connPoolInfo->stream,
1619 query_order,
1620 FALSE,
1621 1,
1622 &constraint);
1623
1624 if(status != SE_SUCCESS) {
1625 sde_error( status,
1626 "msSDELayerWhichShapes()",
1627 "SE_stream_set_spatial_constraints()");
1628 return(MS_FAILURE);
1629 }
1630
1631 /* *should* be ready to step through shapes now */
1632 status = SE_stream_execute(sde->connPoolInfo->stream);
1633 if(status != SE_SUCCESS) {
1634 sde_error( status,
1635 "msSDELayerWhichShapes()",
1636 "SE_stream_execute()");
1637 return(MS_FAILURE);
1638 }
1639
1640 /* clean-up */
1641 SE_shape_free(shape);
1642 SE_queryinfo_free (query_info);
1643
1644 return(MS_SUCCESS);
1645#else
1646 msSetError(MS_MISCERR,
1647 "SDE support is not available.",
1648 "msSDELayerWhichShapes()");
1649 return(MS_FAILURE);
1650#endif
1651}
1652
1653/* -------------------------------------------------------------------- */
1654/* msSDELayerNextShape */
1655/* -------------------------------------------------------------------- */
1656/* Recursively gets the shapes for the SDE layer */
1657/* -------------------------------------------------------------------- */
1658int msSDELayerNextShape(layerObj *layer, shapeObj *shape) {
1659#ifdef USE_SDE
1660 long status;
1661
1662 msSDELayerInfo *sde=NULL;
1663
1664 if(!msSDELayerIsOpen(layer)) {
1665 msSetError( MS_SDEERR,
1666 "SDE layer has not been opened.",
1667 "msSDELayerNextShape()");
1668 return(MS_FAILURE);
1669 }
1670
1671 sde = layer->layerinfo;
1672
1673 /* fetch the next record from the stream */
1674 status = SE_stream_fetch(sde->connPoolInfo->stream);
1675
1676 if(status == SE_FINISHED)
1677 return(MS_DONE);
1678 else if(status != MS_SUCCESS) {
1679 sde_error( status,
1680 "msSDELayerNextShape()",
1681 "SE_stream_fetch()");
1682 return(MS_FAILURE);
1683 }
1684
1685 /* get the shape and values (first column is the shape id, */
1686 /* second is the shape itself) */
1687 status = sdeGetRecord(layer, shape);
1688 if(status != MS_SUCCESS)
1689 return(MS_FAILURE); /* something went wrong fetching the record/shape */
1690
1691 if(shape->numlines == 0) /* null shape, skip it */
1692 return(msSDELayerNextShape(layer, shape));
1693
1694 return(MS_SUCCESS);
1695#else
1696 msSetError( MS_MISCERR,
1697 "SDE support is not available.",
1698 "msSDELayerNextShape()");
1699 return(MS_FAILURE);
1700#endif
1701}
1702
1703/* -------------------------------------------------------------------- */
1704/* msSDELayerGetExtent */
1705/* -------------------------------------------------------------------- */
1706/* Returns the extent of the SDE layer */
1707/* -------------------------------------------------------------------- */
1708int msSDELayerGetExtent(layerObj *layer, rectObj *extent) {
1709#ifdef USE_SDE
1710
1711 msSDELayerInfo *sde = NULL;
1712
1713 if(!msSDELayerIsOpen(layer)) {
1714 msSetError( MS_SDEERR,
1715 "SDE layer has not been opened.",
1716 "msSDELayerGetExtent()");
1717 return(MS_FAILURE);
1718 }
1719
1720 sde = layer->layerinfo;
1721
1722 /* copy our cached extent members into the caller's extent */
1723 extent->minx = sde->extent->minx;
1724 extent->miny = sde->extent->miny;
1725 extent->maxx = sde->extent->maxx;
1726 extent->maxy = sde->extent->maxy;
1727
1728 return(MS_SUCCESS);
1729#else
1730 msSetError( MS_MISCERR,
1731 "SDE support is not available.",
1732 "msSDELayerGetExtent()");
1733 return(MS_FAILURE);
1734#endif
1735}
1736
1737/* -------------------------------------------------------------------- */
1738/* msSDELayerGetShape */
1739/* -------------------------------------------------------------------- */
1740/* Queries SDE for a shape (and its attributes, if requested) */
1741/* given the ID (which is the MS_SDE_ROW_ID_COLUMN column */
1742/* -------------------------------------------------------------------- */
1743int msSDELayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) {
1744#ifdef USE_SDE
1745 long status;
1746
1747 SE_SQL_CONSTRUCT* sql;
1748
1749 msSDELayerInfo *sde=NULL;
1750
1751 long shapeindex = record->shapeindex;
1752
1753 if(!msSDELayerIsOpen(layer)) {
1754 msSetError( MS_SDEERR,
1755 "SDE layer has not been opened.",
1756 "msSDELayerGetShape()");
1757 return(MS_FAILURE);
1758 }
1759
1760 sde = layer->layerinfo;
1761
1762 /* must be at least one thing to retrieve (i.e. spatial column) */
1763 if(layer->numitems < 1) {
1764 msSetError( MS_MISCERR,
1765 "No items requested, SDE requires at least one item.",
1766 "msSDELayerGetShape()");
1767 return(MS_FAILURE);
1768 }
1769
1770 /* reset the stream */
1771 status = SE_stream_close(sde->connPoolInfo->stream, 1);
1772 if(status != SE_SUCCESS) {
1773 sde_error( status,
1774 "msSDELayerGetShape()",
1775 "SE_stream_close()");
1776 return(MS_FAILURE);
1777 }
1778
1779 if (!sde->join_table) {
1780
1781 status = SE_stream_fetch_row( sde->connPoolInfo->stream,
1782 sde->table,
1783 shapeindex,
1784 (short)(layer->numitems),
1785 (const char **)layer->items);
1786
1787 if(status != SE_SUCCESS) {
1788 sde_error( status,
1789 "msSDELayerGetShape()",
1790 "SE_stream_fetch_row()");
1791 return(MS_FAILURE);
1792 }
1793 } else {
1794 sql = getSDESQLConstructInfo(layer, &shapeindex);
1795
1796 status = SE_stream_query(sde->connPoolInfo->stream, layer->numitems, (const CHAR**) layer->items, sql);
1797;
1798 if(status != SE_SUCCESS) {
1799 sde_error(status,
1800 "msSDELayerWhichShapes()",
1801 "SE_stream_query()");
1802 return(MS_FAILURE);
1803 }
1804
1805 /* Free up the sql now that we've queried */
1806 SE_sql_construct_free(sql);
1807
1808 /* *should* be ready to step through shapes now */
1809 status = SE_stream_execute(sde->connPoolInfo->stream);
1810
1811 if(status != SE_SUCCESS) {
1812 sde_error(status,
1813 "SE_stream_execute()",
1814 "SE_stream_execute()");
1815 return(MS_FAILURE);
1816 }
1817
1818 /* fetch the next record from the stream */
1819 status = SE_stream_fetch(sde->connPoolInfo->stream);
1820
1821 }
1822 status = sdeGetRecord(layer, shape);
1823 if(status != MS_SUCCESS)
1824 return(MS_FAILURE); /* something went wrong fetching the record/shape */
1825
1826 return(MS_SUCCESS);
1827#else
1828 msSetError( MS_MISCERR,
1829 "SDE support is not available.",
1830 "msSDELayerGetShape()");
1831 return(MS_FAILURE);
1832#endif
1833}
1834
1835/* -------------------------------------------------------------------- */
1836/* msSDELayerGetSpatialColumn */
1837/* -------------------------------------------------------------------- */
1838/* A helper function to return the spatial column for */
1839/* an opened SDE layer */
1840/* */
1841/* The caller owns the string after it is returned. */
1842/* -------------------------------------------------------------------- */
1843char *msSDELayerGetSpatialColumn(layerObj *layer)
1844{
1845#ifdef USE_SDE
1846
1847 msSDELayerInfo *sde=NULL;
1848
1849 if(!msSDELayerIsOpen(layer)) {
1850 msSetError( MS_SDEERR,
1851 "SDE layer has not been opened.",
1852 "msSDELayerGetSpatialColumn()");
1853 return NULL;
1854 }
1855
1856 sde = layer->layerinfo;
1857
1858 return(msStrdup(sde->column));
1859#else
1860 msSetError( MS_MISCERR,
1861 "SDE support is not available.",
1862 "msSDELayerGetSpatialColumn()");
1863 return(NULL);
1864#endif
1865}
1866/* -------------------------------------------------------------------- */
1867/* msSDELayerInitItemInfo */
1868/* -------------------------------------------------------------------- */
1869/* Connects to SDE and returns the column names and SDE's column */
1870/* descriptions. It stores them on layer->items and layer->iteminfo */
1871/* If a join table has been specified through the processing option, */
1872/* it's column definitions are appended to both lists. */
1873/* -------------------------------------------------------------------- */
1874int
1875msSDELayerInitItemInfo(layerObj *layer)
1876{
1877#ifdef USE_SDE
1878
1879 int i,j;
1880/* short nBaseColumns, nJoinColumns; */
1881 long status;
1882short nbasecol, njoincol;
1883 SE_COLUMN_DEF *all_itemdefs = NULL;
1884
1885 msSDELayerInfo *sde = NULL;
1886/* nBaseColumns = 0; */
1887/* nJoinColumns = 0; */
1888
1889 char *proc_key = NULL;
1890
1891 if (!msSDELayerIsOpen(layer)) {
1892 msSetError( MS_SDEERR,
1893 "SDE layer has not been opened.",
1894 "msSDELayerInitItemInfo()");
1895 return(MS_FAILURE);
1896 }
1897
1898 sde = layer->layerinfo;
1899
1900 /*
1901 ** This insanity is because we keep around the number of
1902 ** columns we have along with the layer info. If the total
1903 ** number of columns that we have doesn't match when we're
1904 ** called the second time around, we have to throw an error or
1905 ** msWhichShape will add an item onto our layer->items list, which
1906 ** in turn doesn't match the layer->iteminfo list of SDE column definitions.
1907 */
1908
1909 nbasecol =*(sde->nBaseColumns);
1910 njoincol =*(sde->nJoinColumns);
1911
1912 /* Hop right out again if we've already gotten the layer->iteminfo */
1913 if (layer->iteminfo && layer->items) {
1914 if (layer->debug)
1915 msDebug("Column information has already been gotten..."
1916 " returning from msSDELayerInitItemInfo\n");
1917 if (layer->numitems != ( nbasecol+ njoincol)) {
1918 /* if someone has modified the size of the items list,
1919 ** it is because it didn't find a column name (and we have
1920 ** already given them all because we have iteminfo and items
1921 ** If this is the case, we can't continue. */
1922
1923 msSetError( MS_SDEERR,
1924 "A specified CLASSITEM, FILTERITEM, or expression key cannot be found",
1925 "msSDELayerInitItemInfo()");
1926 return(MS_FAILURE);
1927 }
1928 return (MS_SUCCESS);
1929 }
1930 if (layer->debug)
1931 msDebug("Getting all column information in msSDELayerInitItemInfo\n");
1932
1933 if (!(sde->row_id_column)) {
1934
1935 sde->row_id_column = msSDELayerGetRowIDColumn(layer);
1936 } else {
1937 /* Don't think this should happen. If it does, it'd be good to know why. */
1938 if (layer->debug)
1939 msDebug ("RowID column has already been gotten... msSDELayerInitItemInfo\n");
1940 }
1941
1942 status = SE_table_describe( sde->connPoolInfo->connection,
1943 sde->table,
1944 (short*)&(nbasecol),
1945 &(sde->basedefs));
1946 if(status != SE_SUCCESS) {
1947 sde_error( status,
1948 "msSDELayerInitItemInfo()",
1949 "SE_table_describe() (base table)");
1950 return(MS_FAILURE);
1951 }
1952
1953 if (sde->join_table) {
1954 status = SE_table_describe( sde->connPoolInfo->connection,
1955 sde->join_table,
1956 (short*)&(njoincol),
1957 &(sde->joindefs));
1958
1959 if(status != SE_SUCCESS) {
1960 sde_error( status,
1961 "msSDELayerInitItemInfo()",
1962 "SE_table_describe() (join table). Did you specify the name of the join table properly?");
1963 return(MS_FAILURE);
1964 }
1965 }
1966
1967 layer->numitems = nbasecol + njoincol;
1968
1969 /* combine the itemdefs of both tables into one */
1970 all_itemdefs = (SE_COLUMN_DEF *) calloc( layer->numitems, sizeof(SE_COLUMN_DEF));
1971 MS_CHECK_ALLOC(all_itemdefs, sizeof(SE_COLUMN_DEF), MS_FAILURE);
1972
1973 for(i=0;i<nbasecol;i++) all_itemdefs[i] = sde->basedefs[i];
1974
1975 if (njoincol > 0) {
1976 for(i=0;i<njoincol;i++) {
1977 all_itemdefs[i+nbasecol]=sde->joindefs[i];
1978 }
1979 }
1980
1981 if (!layer->iteminfo){
1982 layer->iteminfo = (SE_COLUMN_DEF *) calloc( layer->numitems, sizeof(SE_COLUMN_DEF));
1983 if(!layer->iteminfo) {
1984 msSetError( MS_MEMERR,
1985 "Error allocating SDE item information.",
1986 "msSDELayerInitItemInfo()");
1987 free(all_itemdefs);
1988 return(MS_FAILURE);
1989 }
1990 } else {
1991 /* Don't think this should happen. If it does, it'd be good to know why. */
1992 if (layer->debug)
1993 msDebug ("layer->iteminfo has already been initialized... msSDELayerInitItemInfo\n");
1994 }
1995
1996 if (!(layer->items)) {
1997 /* gather up all of the column names and put them onto layer->items */
1998 layer->items = (char **)malloc(layer->numitems*sizeof(char *)+10);
1999 MS_CHECK_ALLOC(layer->items, layer->numitems*sizeof(char *)+10, MS_FAILURE);
2000 } else {
2001 msDebug("layer->items has already been initialized!!!");
2002 }
2003
2004 proc_key = msLayerGetProcessingKey(layer,"ATTRIBUTE_QUALIFIED");
2005 if (!sde->join_table &&
2006 (proc_key == NULL || strcasecmp( proc_key, "TRUE") != 0)) {
2007 for(i=0; i<layer->numitems; i++) layer->items[i] = msStrdup(all_itemdefs[i].column_name);
2008 for(i=0; i<layer->numitems; i++) { /* requested columns */
2009 for(j=0; j<layer->numitems; j++) { /* all columns */
2010 if(strcasecmp(layer->items[i], all_itemdefs[j].column_name) == 0) {
2011 /* found it */
2012 ((SE_COLUMN_DEF *)(layer->iteminfo))[i] = all_itemdefs[j];
2013 break;
2014 }
2015 }
2016 }
2017 }
2018 else {
2019 for(i=0;i<nbasecol;i++) {
2020 layer->items[i] = (char*) msSmallMalloc((SE_QUALIFIED_COLUMN_LEN+1)*sizeof (char));
2021 layer->items[i][0] = '\0';
2022 strcat(layer->items[i], sde->table);
2023 strcat(layer->items[i], ".");
2024 strcat(layer->items[i], all_itemdefs[i].column_name);
2025 ((SE_COLUMN_DEF *)(layer->iteminfo))[i] = all_itemdefs[i];
2026
2027 }
2028 for(i=nbasecol;i<layer->numitems;i++) {
2029 layer->items[i] = (char*) msSmallMalloc((SE_QUALIFIED_COLUMN_LEN+1)*sizeof (char));
2030 layer->items[i][0] = '\0';
2031
2032 strcat(layer->items[i], sde->join_table);
2033 strcat(layer->items[i], ".");
2034 strcat(layer->items[i], all_itemdefs[i].column_name);
2035 ((SE_COLUMN_DEF *)(layer->iteminfo))[i] = all_itemdefs[i];
2036
2037 }
2038 }
2039 /* Tell the user which columns we've gotten */
2040 if (layer->debug)
2041 for(i=0; i<layer->numitems; i++)
2042 msDebug("msSDELayerInitItemInfo(): getting info for %s\n", layer->items[i]);
2043
2044 *(sde->nJoinColumns) = njoincol;
2045 *(sde->nBaseColumns) = nbasecol;
2046 msFree(all_itemdefs);
2047 return MS_SUCCESS;
2048
2049#else
2050 msSetError( MS_MISCERR,
2051 "SDE support is not available.",
2052 "msSDELayerInitItemInfo()");
2053 return(MS_FAILURE);
2054#endif
2055}
2056
2057
2058
2059/* -------------------------------------------------------------------- */
2060/* msSDELayerCreateItems */
2061/* -------------------------------------------------------------------- */
2062/* Inits the stuff we'll be querying from SDE */
2063/* -------------------------------------------------------------------- */
2064int msSDELayerCreateItems(layerObj *layer, int nt){
2065 int status;
2066 /* status = msSDELayerCreateItems(layer, 0); */
2067 status = msSDELayerInitItemInfo(layer);
2068 if (status != MS_SUCCESS) {
2069 msSetError( MS_MISCERR,
2070 "Unable to create SDE column info",
2071 "msSDELayerCreateItemsInfo()");
2072 return(MS_FAILURE);
2073 }
2074 return (MS_SUCCESS);
2075}
2076
2077/* -------------------------------------------------------------------- */
2078/* msSDELayerGetItems */
2079/* -------------------------------------------------------------------- */
2080/* Queries the SDE table's column names into layer->iteminfo */
2081/* -------------------------------------------------------------------- */
2082int msSDELayerGetItems(layerObj *layer) {
2083#ifdef USE_SDE
2084 int status;
2085 status = msSDELayerInitItemInfo(layer);
2086
2087 if (status != MS_SUCCESS) {
2088 msSetError( MS_MISCERR,
2089 "Unable to create SDE column info",
2090 "msSDELayerGetItems()");
2091 return(MS_FAILURE);
2092 }
2093 return (MS_SUCCESS);
2094
2095#else
2096 msSetError( MS_MISCERR,
2097 "SDE support is not available.",
2098 "msSDELayerGetItems()");
2099 return(MS_FAILURE);
2100#endif
2101}
2102
2103/* -------------------------------------------------------------------- */
2104/* msSDELayerFreeItemInfo */
2105/* -------------------------------------------------------------------- */
2106void msSDELayerFreeItemInfo(layerObj *layer)
2107{
2108#ifdef USE_SDE
2109 msSDELayerInfo *sde = NULL;
2110 int i;
2111 if (!msSDELayerIsOpen(layer)) {
2112 msSetError( MS_SDEERR,
2113 "SDE layer has not been opened.",
2114 "msSDELayerFreeItemInfo()");
2115 }
2116 sde = layer->layerinfo;
2117 if (sde->basedefs) {
2118 SE_table_free_descriptions(sde->basedefs);
2119 sde->basedefs = NULL;
2120 }
2121 if (sde->joindefs) {
2122 SE_table_free_descriptions(sde->joindefs);
2123 sde->joindefs = NULL;
2124 }
2125 if (layer->iteminfo) {
2126 msFree(layer->iteminfo);
2127 layer->iteminfo = NULL;
2128 }
2129
2130 if (layer->items) {
2131 for (i=0; i< layer->numitems; i++) {
2132 msFree(layer->items[i]);
2133 }
2134 msFree(layer->items);
2135 layer->items = NULL;
2136 layer->numitems = 0;
2137 }
2138
2139#else
2140 msSetError( MS_MISCERR,
2141 "SDE support is not available.",
2142 "msSDELayerFreeItemInfo()");
2143#endif
2144}
2145
2146#ifdef USE_SDE_PLUGIN
2147MS_DLL_EXPORT int
2148PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj *layer)
2149{
2150 assert(layer != NULL);
2151 assert(vtable != NULL);
2152
2153 vtable->LayerInitItemInfo = msSDELayerInitItemInfo;
2154 vtable->LayerFreeItemInfo = msSDELayerFreeItemInfo;
2155 vtable->LayerOpen = msSDELayerOpen;
2156 vtable->LayerIsOpen = msSDELayerIsOpen;
2157 vtable->LayerWhichShapes = msSDELayerWhichShapes;
2158 vtable->LayerNextShape = msSDELayerNextShape;
2159 vtable->LayerGetShape = msSDELayerGetShape;
2160 vtable->LayerClose = msSDELayerClose;
2161 vtable->LayerGetItems = msSDELayerGetItems;
2162 vtable->LayerGetExtent = msSDELayerGetExtent;
2163
2164 /* layer->vtable->LayerGetAutoStyle, use default */
2165 /* layer->vtable->LayerApplyFilterToLayer, use default */
2166
2167 /* SDE uses pooled connections, close from msCloseConnections */
2168 vtable->LayerCloseConnection = msSDELayerCloseConnection;
2169
2170 vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter;
2171 vtable->LayerCreateItems = msSDELayerCreateItems;
2172 /* layer->vtable->LayerGetNumFeatures, use default */
2173
2174 return MS_SUCCESS;
2175}
2176#endif
2177
2178int
2179msSDELayerInitializeVirtualTable(layerObj *layer)
2180{
2181 assert(layer != NULL);
2182 assert(layer->vtable != NULL);
2183
2184 layer->vtable->LayerInitItemInfo = msSDELayerInitItemInfo;
2185 layer->vtable->LayerFreeItemInfo = msSDELayerFreeItemInfo;
2186 layer->vtable->LayerOpen = msSDELayerOpen;
2187 layer->vtable->LayerIsOpen = msSDELayerIsOpen;
2188 layer->vtable->LayerWhichShapes = msSDELayerWhichShapes;
2189 layer->vtable->LayerNextShape = msSDELayerNextShape;
2190 layer->vtable->LayerGetShape = msSDELayerGetShape;
2191 layer->vtable->LayerClose = msSDELayerClose;
2192 layer->vtable->LayerGetItems = msSDELayerGetItems;
2193 layer->vtable->LayerGetExtent = msSDELayerGetExtent;
2194 /* layer->vtable->LayerGetAutoStyle, use default */
2195 /* layer->vtable->LayerApplyFilterToLayer, use default */
2196 layer->vtable->LayerCloseConnection = msSDELayerCloseConnection; /* SDE uses pooled connections, close from msCloseConnections */
2197 layer->vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter;
2198 layer->vtable->LayerCreateItems = msSDELayerCreateItems;
2199 /* layer->vtable->LayerGetNumFeatures, use default */
2200
2201 return MS_SUCCESS;
2202}
2203
2204
2205
Note: See TracBrowser for help on using the repository browser.