source: branches/prototype-v0/zoo-project/zoo-kernel/meta_sql.c @ 886

Last change on this file since 886 was 886, checked in by djay, 5 years ago

Check for md5sum of any file in the cache to avoid sending the same file on HPC server twice. Add the multiple LiteralData? inputs support for HPC services. Remove condition for defining SCALE for every band in the outputed MapServer? mapfile.

  • Property svn:keywords set to Id
File size: 18.7 KB
Line 
1/*
2 * Author : Gérald Fenoy
3 *
4 * Copyright 2017 GeoLabs SARL. All rights reserved.
5 *
6 * This work was supported by public funds received in the framework of GEOSUD,
7 * a project (ANR-10-EQPX-20) of the program "Investissements d'Avenir" managed
8 * by the French National Research Agency
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * THE SOFTWARE.
27 */
28
29#ifdef META_DB
30#include "ogr_api.h"
31#include "ogrsf_frmts.h"
32#include "ogr_p.h"
33#if GDAL_VERSION_MAJOR >= 2
34#include <gdal_priv.h>
35#endif
36
37#include "meta_sql.h"
38#include "sqlapi.h"
39#include "response_print.h"
40#ifdef USE_HPC
41#include "service_internal_hpc.h"
42#endif
43#define META_SERVICES_LIST_ALL \
44  "select id,identifier,title,abstract,service_type,service_provider,conf_id"\
45  " from ows_process"
46#define META_SERVICES_LIST_ALL_LENGTH strlen(META_SERVICES_LIST_ALL)
47
48#define META_SERVICES_KEYWORDS_FROM_PROCESS \
49  "SELECT keyword FROM CollectionDB.ows_Keywords where id in"\
50  " (SELECT keywords_id FROM CollectionDB.DescriptionsKeywordsAssignment"\
51  " where descriptions_id=%s) "
52#define META_SERVICES_KEYWORDS_FROM_PROCESS_LENGTH strlen(META_SERVICES_KEYWORDS_FROM_PROCESS)
53
54#define META_SERVICES_META_FROM_ANYTHING \
55  "SELECT title,role,href FROM CollectionDB.ows_Metadata where id in"\
56  " (SELECT metadata_id FROM CollectionDB.DescriptionsMetadataAssignment"\
57  " where descriptions_id=%s) "
58#define META_SERVICES_META_FROM_ANYTHING_LENGTH strlen(META_SERVICES_META_FROM_ANYTHING)
59
60#define META_SERVICES_AP_FROM_ANYTHING \
61  "SELECT id,title,role,href FROM CollectionDB.ows_AdditionalParameters where id in"\
62  " (SELECT additional_parameters_id FROM CollectionDB.DescriptionsAdditionalParametersAssignment"\
63  " where descriptions_id=%s) "
64#define META_SERVICES_AP_FROM_ANYTHING_LENGTH strlen(META_SERVICES_AP_FROM_ANYTHING)
65
66#define META_SERVICES_AP_FROM_AP \
67  "SELECT key,value FROM CollectionDB.ows_AdditionalParameter where additional_parameters_id =$q$%s$q$"
68#define META_SERVICES_AP_FROM_AP_LENGTH strlen(META_SERVICES_AP_FROM_AP)
69
70#define META_SERVICES_LIST_INPUTS_FROM_PROCESS                          \
71  "select id, identifier,title,abstract,min_occurs,max_occurs from CollectionDB.ows_Input where id in (SELECT input_id from CollectionDB.ProcessInputAssignment where process_id=%s) order by id"
72#define META_SERVICES_LIST_INPUTS_FROM_PROCESS_LENGTH strlen(META_SERVICES_LIST_INPUTS_FROM_PROCESS)
73
74#define META_SERVICES_LIST_INPUTS_FROM_INPUT                            \
75  "select id, identifier,title,abstract,min_occurs,max_occurs from CollectionDB.ows_Input where id in (SELECT child_input from CollectionDB.InputInputAssignment where parent_input=%s) order by id"
76#define META_SERVICES_LIST_INPUTS_FROM_INPUT_LENGTH strlen(META_SERVICES_LIST_INPUTS_FROM_INPUT)
77
78#define META_SERVICES_LIST_OUTPUTS_FROM_PROCESS \
79  "select id, identifier,title,abstract from CollectionDB.ows_Output where id in (SELECT output_id from CollectionDB.ProcessOutputAssignment where process_id=%s) order by id"
80#define META_SERVICES_LIST_OUTPUTS_FROM_PROCESS_LENGTH strlen(META_SERVICES_LIST_OUTPUTS_FROM_PROCESS)
81
82#define META_SERVICES_LIST_OUTPUTS_FROM_OUTPUT \
83  "select id, identifier,title,abstract from CollectionDB.ows_Output where id in (SELECT child_output from CollectionDB.OutputOutputAssignment where parent_output=%s) order by id"
84#define META_SERVICES_LIST_OUTPUTS_FROM_OUTPUT_LENGTH strlen(META_SERVICES_LIST_OUTPUTS_FROM_OUTPUT)
85
86#define META_SERVICES_LIST_LITERAL_FROM_IO \
87  "select (SELECT name as type FROM CollectionDB.PrimitiveDatatypes where CollectionDB.PrimitiveDatatypes.id=data_type_id),default_value,(SELECT uom from CollectionDB.PrimitiveUOM where id=CollectionDB.LiteralDataDomain.uom),translate(translate(ARRAY((SELECT allowed_Value from CollectionDB.AllowedValues where id in (SELECT allowed_value_id from CollectionDB.AllowedValuesAssignment where literal_data_domain_id=CollectionDB.LiteralDataDomain.id)))::varchar,'{',''),'}',''),def as allowedvalues from CollectionDB.LiteralDataDomain where id in (SELECT data_description_id from CollectionDB.%sDataDescriptionAssignment where %s_id = %s);"
88#define META_SERVICES_LIST_LITERAL_FROM_IO_LENGTH strlen(META_SERVICES_LIST_LITERAL_FROM_IO)
89
90#define META_SERVICES_LIST_FORMATS_FROM_IO \
91  "select mime_type,encoding,schema,maximum_megabytes,CASE WHEN use_mapserver THEN 'true' ELSE 'false' END, ms_styles, def from CollectionDB.ows_Format,CollectionDB.PrimitiveFormats where CollectionDB.ows_Format.primitive_format_id=CollectionDB.PrimitiveFormats.id and CollectionDB.ows_Format.id in (SELECT format_id from collectiondb.ows_datadescription where id in ( SELECT data_description_id from CollectionDB.%sDataDescriptionAssignment where %s_id = %s))"
92#define META_SERVICES_LIST_FORMATS_FROM_IO_LENGTH strlen(META_SERVICES_LIST_FORMATS_FROM_IO)
93
94/**
95 * Create a new iotype pointer using field names from an OGRFeature
96 *
97 * @param f the OGRFeature
98 * @param fields the fields names
99 * @return the iotype
100 */
101iotype* getIoType(OGRFeature* f,const char** fields){
102  iotype* io=(iotype*)malloc(IOTYPE_SIZE);
103  io->content=NULL;
104  io->next=NULL;
105  for(int i=0;i<6;i++){
106    if(fields[i]==NULL)
107      return io;
108    const char* tmpS=f->GetFieldAsString( i );
109    if(strlen(tmpS)>0){
110      if(io->content==NULL)
111        io->content=createMap(fields[i],tmpS);
112      else
113        addToMap(io->content,fields[i],tmpS);
114    }
115  }
116  return io;
117}
118
119/**
120 * Fill the AdditionalParameters map with the data extracted from metadb
121 *
122 * @param conf the main configuration maps
123 * @param ap the map to fill
124 * @param dref the description identifier
125 * @return the number of metadata field found
126 */
127int fillAdditionalParameters(maps* conf,map** ap,const char* dref){
128  int res=0;
129  char* ioQuery=(char*)malloc((META_SERVICES_AP_FROM_ANYTHING_LENGTH+strlen(dref)+1)*sizeof(char));
130  sprintf(ioQuery,META_SERVICES_AP_FROM_ANYTHING,dref);
131  OGRFeature  *meta = NULL;
132  OGRLayer *metas=fetchSql(conf,0,ioQuery);
133  free(ioQuery);
134  int cnt=0;
135  char fields[3][255]={
136    "title",
137    "role",
138    "href"
139  };
140  while( (meta = metas->GetNextFeature()) != NULL ){
141    int i=0;
142    for(i=0;i<3;i++){     
143      const char *tmp=meta->GetFieldAsString(i+1);
144      if(strlen(tmp)>0)
145        if(*ap==NULL){
146          (*ap)=createMap(fields[i],tmp);
147          addToMap(*ap,"fromDb","true");
148        }
149        else
150          setMapArray(*ap,fields[i],res,tmp);
151    }
152    char* apQuery=(char*)malloc((META_SERVICES_AP_FROM_AP_LENGTH+strlen(dref)+1)*sizeof(char));
153    sprintf(apQuery,META_SERVICES_AP_FROM_AP,meta->GetFieldAsString(0));
154    OGRFeature  *adp = NULL;
155    OGRLayer *adps=fetchSql(conf,0,apQuery);
156    free(apQuery);
157    while( (adp = adps->GetNextFeature()) != NULL ){
158      addToMap(*ap,adp->GetFieldAsString(0),adp->GetFieldAsString(1));
159      OGRFeature::DestroyFeature( adp );
160    }
161    cleanFetchSql(conf,0,adps);
162    res++;
163    OGRFeature::DestroyFeature( meta );
164  }
165  cleanFetchSql(conf,0,metas);
166  return res;
167}
168
169/**
170 * Fill the metadata map with the data extracted from metadb
171 *
172 * @param conf the main configuration maps
173 * @param metadata the map to fill
174 * @param dref the description identifier
175 * @return the number of metadata field found
176 */
177int fillMetadata(maps* conf,map** metadata,const char* dref){
178  int res=0;
179  char* ioQuery=(char*)malloc((META_SERVICES_META_FROM_ANYTHING_LENGTH+strlen(dref)+1)*sizeof(char));
180  sprintf(ioQuery,META_SERVICES_META_FROM_ANYTHING,dref);
181  OGRFeature  *meta = NULL;
182  OGRLayer *metas=fetchSql(conf,0,ioQuery);
183  free(ioQuery);
184  int cnt=0;
185  char fields[3][255]={
186    "title",
187    "role",
188    "href"
189  };
190  while( (meta = metas->GetNextFeature()) != NULL ){
191    int i=0;
192    for(i=0;i<3;i++){
193      const char *tmp=meta->GetFieldAsString(i);
194      if(strlen(tmp)>0)
195        if(*metadata==NULL)
196          *metadata=createMap(fields[i],tmp);
197        else
198          addToMap(*metadata,fields[i],tmp);
199    }
200    res++;
201    OGRFeature::DestroyFeature( meta );
202  }
203  cleanFetchSql(conf,0,metas);
204  return res;
205}
206
207/**
208 * Try to fill the default/supported map for the LiteralData with the data
209 * extracted from metadb.
210 *
211 * @param conf the main configuration maps
212 * @param in the element to fill default/supported
213 * @param input the OGRFeature corresponding to the input/output
214 * @param ltype the element type ("Input" or "Output")
215 * @return the number of default/supported definition found
216 */
217int fillLiteralData(maps* conf,elements* in,OGRFeature  *input,const char* ltype){
218  int res=0;
219  char* ioQuery=(char*)malloc((META_SERVICES_LIST_LITERAL_FROM_IO_LENGTH+(strlen(ltype)*2)+strlen(input->GetFieldAsString( 0 ))+1)*sizeof(char));
220  sprintf(ioQuery,META_SERVICES_LIST_LITERAL_FROM_IO,ltype,ltype,input->GetFieldAsString( 0 ));
221  OGRFeature  *io = NULL;
222  OGRLayer *ios=fetchSql(conf,0,ioQuery);
223  free(ioQuery);
224  int ioCnt=0;
225  const char* fields[5]={"dataType","value","uom","AllowedValues",NULL};
226  while( (io = ios->GetNextFeature()) != NULL ){
227    iotype* currentIoType;
228    if(strncmp(io->GetFieldAsString( 4 ),"1",1)==0){
229      in->defaults=getIoType(io,fields);
230    }else{
231      if(in->supported==NULL)
232        in->supported=getIoType(io,fields);
233      else{
234        iotype* p=in->supported;
235        while(p->next!=NULL){
236          p=p->next;
237        }
238        p->next=getIoType(io,fields);
239      }
240    }
241    in->format=strdup("LiteralData");
242    res++;
243    OGRFeature::DestroyFeature( io );
244  }
245  cleanFetchSql(conf,0,ios);
246  return res;
247}
248
249/**
250 * Try to fill the default/supported map for the ComplexData with the data
251 * extracted from metadb.
252 *
253 * @param conf the main configuration maps
254 * @param in the element to fill default/supported
255 * @param input the OGRFeature corresponding to the input/output
256 * @param ltype the element type ("Input" or "Output")
257 * @return the number of default/supported definition found
258 */
259int fillComplexData(maps* conf,elements* in,OGRFeature  *input,const char* ltype){
260  int res=0;
261  char* ioQuery=(char*)malloc((META_SERVICES_LIST_FORMATS_FROM_IO_LENGTH+(strlen(ltype)*2)+strlen(input->GetFieldAsString( 0 ))+1)*sizeof(char));
262  sprintf(ioQuery,META_SERVICES_LIST_FORMATS_FROM_IO,ltype,ltype,input->GetFieldAsString( 0 ));
263  OGRFeature  *io = NULL;
264  OGRLayer *ios=fetchSql(conf,0,ioQuery);
265  free(ioQuery);
266  int ioCnt=0;
267  const char* fields[6]={"mimeType","ecoding","schema","maximumMegabytes","useMapserver","msStyle"};
268  while( (io = ios->GetNextFeature()) != NULL ){
269    iotype* currentIoType;
270    if(strncmp(io->GetFieldAsString( 6 ),"1",1)==0){
271      in->defaults=getIoType(io,fields);
272    }else{
273      if(in->supported==NULL)
274        in->supported=getIoType(io,fields);
275      else{
276        iotype* p=in->supported;
277        while(p->next!=NULL){
278          p=p->next;
279        }
280        p->next=getIoType(io,fields);
281      }
282    }
283    in->format=strdup("ComplexData");
284    res++;
285    OGRFeature::DestroyFeature( io );
286  }
287  cleanFetchSql(conf,0,ios);
288  return res;
289}
290
291/**
292 * Extract input definition from metadb
293 *
294 * @param conf the main configuration maps
295 * @param input the OGRFeature pointing to an input
296 * @return a new elements* corresponding to the current input
297 */
298elements* extractInput(maps* conf,OGRFeature *input){
299  elements* res=createElements(input->GetFieldAsString( 1 ));
300  res->content=createMap("title",input->GetFieldAsString( 2 ));
301  addToMap(res->content,"abstract",input->GetFieldAsString( 3 ));
302  addToMap(res->content,"minOccurs",input->GetFieldAsString( 4 ));
303  addToMap(res->content,"maxOccurs",input->GetFieldAsString( 5 ));
304  // Extract metadata
305  fillMetadata(conf,&res->metadata,input->GetFieldAsString( 0 ));
306  res->additional_parameters=NULL;
307  fillAdditionalParameters(conf,&res->additional_parameters,input->GetFieldAsString( 0 ));
308  res->defaults=NULL;
309  res->supported=NULL;
310  res->child=NULL;
311  res->next=NULL;
312  // Extract iotypes
313  int ioCnt=fillLiteralData(conf,res,input,"Input");
314  if(ioCnt==0){
315    ioCnt=fillComplexData(conf,res,input,"Input");
316  }
317  if(ioCnt==0){
318    char* nestedInputsQuery=(char*)malloc((META_SERVICES_LIST_INPUTS_FROM_INPUT_LENGTH+strlen(input->GetFieldAsString( 0 ))+1)*sizeof(char));
319    sprintf(nestedInputsQuery,META_SERVICES_LIST_INPUTS_FROM_INPUT,input->GetFieldAsString( 0 ));
320    OGRFeature  *ninput = NULL;
321    OGRLayer *ninputs=fetchSql(conf,0,nestedInputsQuery);
322    free(nestedInputsQuery);
323    while( (ninput = ninputs->GetNextFeature()) != NULL ){
324      elements* nin=extractInput(conf,ninput);
325      addToElements(&res->child,nin);
326      freeElements(&nin);
327      free(nin);
328      OGRFeature::DestroyFeature( ninput );
329    }
330    cleanFetchSql(conf,0,ninputs);
331  }
332  return res;
333}
334
335/**
336 * Extract output definition from metadb
337 *
338 * @param conf the main configuration maps
339 * @param output the OGRFeature pointing to an output
340 * @return a new elements* corresponding to the current output
341 */
342elements* extractOutput(maps* conf,OGRFeature *output){
343  elements* res=createElements(output->GetFieldAsString( 1 ));
344  res->content=createMap("title",output->GetFieldAsString( 2 ));
345  addToMap(res->content,"abstract",output->GetFieldAsString( 3 ));
346  fillMetadata(conf,&res->metadata,output->GetFieldAsString( 0 ));
347  fillAdditionalParameters(conf,&res->additional_parameters,output->GetFieldAsString( 0 ));
348  int ioCnt=fillLiteralData(conf,res,output,"Output");
349  if(ioCnt==0)
350    ioCnt=fillComplexData(conf,res,output,"Output");
351  char* nestedOutputsQuery=(char*)malloc((META_SERVICES_LIST_OUTPUTS_FROM_OUTPUT_LENGTH+strlen(output->GetFieldAsString( 0 ))+1)*sizeof(char));
352  sprintf(nestedOutputsQuery,META_SERVICES_LIST_OUTPUTS_FROM_OUTPUT,output->GetFieldAsString( 0 ));
353  OGRFeature  *noutput = NULL;
354  OGRLayer *noutputs=fetchSql(conf,0,nestedOutputsQuery);
355  free(nestedOutputsQuery);
356  while( (noutput = noutputs->GetNextFeature()) != NULL ){
357    elements* nout=extractOutput(conf,noutput);
358    addToElements(&res->child,nout);
359    freeElements(&nout);
360    free(nout);
361    OGRFeature::DestroyFeature( noutput );
362  }
363  cleanFetchSql(conf,0,noutputs);
364  return res;
365}
366
367/**
368 * Extract service from metadb
369 *
370 * @param conf the main configuration maps
371 * @param serviceName the service name
372 * @param minimal 1 for minimal metadata extraction (GetCapabilities), 0 in other cases.
373 * @return a new service* corresponding to the service
374 */
375service* extractServiceFromDb(maps* conf,const char* serviceName,int minimal){
376  OGRFeature  *poFeature = NULL;
377  char* tmpQuery=(char*)malloc((META_SERVICES_LIST_ALL_LENGTH+strlen(serviceName)+21)*sizeof(char));
378  sprintf(tmpQuery,"%s WHERE identifier='%s'",META_SERVICES_LIST_ALL,serviceName); 
379  OGRLayer *res=fetchSql(conf,0,tmpQuery);
380  free(tmpQuery);
381  if(res!=NULL){
382    while( (poFeature = res->GetNextFeature()) != NULL ){
383      service* s = (service*) malloc(SERVICE_SIZE);
384      s->name = strdup(poFeature->GetFieldAsString( 1 ));
385      s->content = createMap("title",poFeature->GetFieldAsString( 2 ));
386      addToMap(s->content,"abstract",poFeature->GetFieldAsString( 3 ));
387      addToMap(s->content,"serviceType",poFeature->GetFieldAsString( 4 ));
388      addToMap(s->content,"serviceProvider",poFeature->GetFieldAsString( 5 ));
389      addToMap(s->content,"confId",poFeature->GetFieldAsString( 6 ));
390      addToMap(s->content,"fromDb","true");
391      s->metadata=NULL;
392      fillMetadata(conf,&s->metadata,poFeature->GetFieldAsString( 0 ));
393      s->additional_parameters=NULL;
394      fillAdditionalParameters(conf,&s->additional_parameters,poFeature->GetFieldAsString( 0 ));
395      s->inputs=NULL;
396      s->outputs=NULL;
397      if(minimal==1){
398        OGRFeature::DestroyFeature( poFeature );
399        cleanFetchSql(conf,0,res);
400        return s;
401      }
402      char* inputsQuery=(char*)malloc((META_SERVICES_LIST_INPUTS_FROM_PROCESS_LENGTH+strlen(poFeature->GetFieldAsString( 0 ))+1)*sizeof(char));
403      sprintf(inputsQuery,META_SERVICES_LIST_INPUTS_FROM_PROCESS,poFeature->GetFieldAsString( 0 ));
404      OGRFeature  *input = NULL;
405      OGRLayer *inputs=fetchSql(conf,0,inputsQuery);
406      free(inputsQuery);
407      while( (input = inputs->GetNextFeature()) != NULL ){
408        elements* in=extractInput(conf,input);
409        if(in!=NULL){
410          addToElements(&s->inputs,in);
411          freeElements(&in);
412          free(in);
413        }
414        OGRFeature::DestroyFeature( input );
415      }
416      cleanFetchSql(conf,0,inputs);
417      char* outputsQuery=(char*)malloc((META_SERVICES_LIST_OUTPUTS_FROM_PROCESS_LENGTH+strlen(poFeature->GetFieldAsString( 0 ))+1)*sizeof(char));
418      sprintf(outputsQuery,META_SERVICES_LIST_OUTPUTS_FROM_PROCESS,poFeature->GetFieldAsString( 0 ));
419      OGRFeature  *output = NULL;
420      OGRLayer *outputs=fetchSql(conf,0,outputsQuery);
421      free(outputsQuery);
422      s->outputs=NULL;
423      while( (output = outputs->GetNextFeature()) != NULL ){
424        elements* in=extractOutput(conf,output);
425        if(in!=NULL){
426          addToElements(&s->outputs,in);
427          freeElements(&in);
428          free(in);
429        }
430        OGRFeature::DestroyFeature( output );
431      }
432      cleanFetchSql(conf,0,outputs);
433      OGRFeature::DestroyFeature( poFeature );
434      cleanFetchSql(conf,0,res);
435      return s;
436    }
437  }
438  cleanFetchSql(conf,0,res);
439  return NULL;
440}
441
442/**
443 * Extract every service definitions from metadb
444 *
445 * @param reg the registry
446 * @param conf the main configuration maps
447 * @param n the node where to add the services found
448 * @param func the C function to call for each service found
449 * @param minimal 1 for minimal metadata extraction (GetCapabilities), 0 in other cases.
450 * @return the number of services found, -1 in case of failure
451 */
452int fetchServicesFromDb(registry* reg,maps* conf, xmlDocPtr doc, xmlNodePtr n,
453                        void (func) (registry *, maps *, xmlDocPtr, xmlNodePtr,
454                                     service *), int minimal ){
455  int result=0;
456  result=_init_sql(conf,"metadb");
457  if(getMapFromMaps(conf,"lenv","dbIssue")!=NULL || result < 0)
458    return -1;
459  // Fetch every services
460  OGRLayer *res=fetchSql(conf,0,META_SERVICES_LIST_ALL);
461  if(res!=NULL){
462    OGRFeature  *poFeature = NULL;
463    const char *tmp1;
464    poFeature = res->GetNextFeature();
465    while( poFeature != NULL ){
466      service* s=extractServiceFromDb(conf,poFeature->GetFieldAsString( 1 ),minimal);
467#ifdef USE_HPC
468      addNestedOutputs(&s);
469#endif
470      func(reg,conf,doc,n,s);
471      freeService(&s);
472      free(s);
473      OGRFeature::DestroyFeature( poFeature );
474      poFeature = res->GetNextFeature();
475      result++;
476    }
477    cleanFetchSql(conf,0,res);
478  }
479  return result;
480}
481
482#endif
Note: See TracBrowser for help on using the repository browser.

Search

Context Navigation

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png