Changeset 129

Show
Ignore:
Timestamp:
04/20/09 19:14:20 (3 years ago)
Author:
ol
Message:

Handle idgen WFS 1.1.0 behaviour. Switch by default on Generate New? option. Still need to improve random id mechanism. Cf #15

Location:
src/wfs
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • src/wfs/wfs_request.c

    r119 r129  
    141141    if (wr->insert_results != NULL) { 
    142142        fprintf(output, " insert_results -> "); 
    143         mlist_flush(wr->insert_results, output); 
     143        alist_flush(wr->insert_results, output); 
    144144        fprintf(output, "\n"); 
    145145    } 
    146  
    147146 
    148147    fprintf(output, "]\n"); 
     
    189188 
    190189    if (wr->insert_results != NULL) 
    191         mlist_free(wr->insert_results); 
     190        alist_free(wr->insert_results); 
    192191 
    193192    free(wr); 
  • src/wfs/wfs_transaction.c

    r123 r129  
    2727#include <string.h> 
    2828#include <ctype.h> 
     29#include <time.h> 
    2930 
    3031#include "../ows/ows.h" 
     
    8081                                    buffer * result) 
    8182{ 
    82     mlist_node *mln; 
    83     int insert_nb; 
     83    int nb = 0;  
     84    alist_node *an; 
    8485 
    8586    assert(o != NULL); 
     
    8788    assert(result != NULL); 
    8889 
    89     mln = NULL; 
    90     insert_nb = 0; 
    91  
    9290    fprintf(o->output, "<wfs:TransactionSummary>\n"); 
    9391 
     
    9593 
    9694        if (wr->insert_results != NULL) { 
    97             for (mln = wr->insert_results->first; mln != NULL; mln = mln->next) 
    98                 insert_nb = insert_nb + mln->value->size; 
    99  
    100             fprintf(o->output, " <wfs:totalInserted>%d</wfs:totalInserted>\n", 
    101                     insert_nb); 
    102         } 
    103  
    104         if (wr->delete_results != 0) 
    105             fprintf(o->output, " <wfs:totalDeleted>%d</wfs:totalDeleted>\n", 
     95            for (an = wr->insert_results->first; an != NULL; an = an->next) 
     96                nb += an->value->size; 
     97 
     98            fprintf(o->output, " <wfs:totalInserted>%d</wfs:totalInserted>\n", nb); 
     99        } 
     100 
     101        fprintf(o->output, " <wfs:totalDeleted>%d</wfs:totalDeleted>\n", 
    106102                    wr->delete_results); 
    107103 
    108         if (wr->update_results != 0) 
    109             fprintf(o->output, "<wfs:totalUpdated>%d</wfs:totalUpdated>\n", 
     104        fprintf(o->output, "<wfs:totalUpdated>%d</wfs:totalUpdated>\n", 
    110105                    wr->update_results); 
    111106    } 
     
    118113 * Report newly created feature instances 
    119114 */ 
    120 static void wfs_transaction_insert_result(ows * o, wfs_request * wr, 
    121         buffer * result) 
    122 { 
    123     mlist_node *mln; 
    124     list_node *hdl, *ln; 
     115static void wfs_transaction_insert_result(ows * o, wfs_request * wr, buffer * result) 
     116{ 
     117    list_node *ln; 
     118    alist_node *an; 
    125119 
    126120    assert(o != NULL); 
     
    128122    assert(result != NULL); 
    129123 
    130     mln = NULL; 
    131     hdl = NULL; 
    132124    ln = NULL; 
    133125 
    134126    /* check if there were Insert operations and if the command succeeded */ 
    135127    if ((!cgi_method_get()) && (buffer_cmp(result, "PGRES_COMMAND_OK") 
    136                                 && (wr->insert_results != NULL))) { 
    137         if (wr->handle != NULL) 
    138             hdl = wr->handle->first; 
     128            && (wr->insert_results != NULL))) { 
    139129 
    140130        if (ows_version_get(o->request->version) == 110) 
    141131            fprintf(o->output, "<wfs:InsertResults>\n"); 
    142132 
    143         for (mln = wr->insert_results->first; mln != NULL; mln = mln->next) { 
    144             if (ows_version_get(o->request->version) == 100) { 
    145                 if (wr->handle != NULL) 
    146                     fprintf(o->output, "<wfs:InsertResult handle=\"%s\">", 
    147                             hdl->value->buf); 
    148                 else 
    149                     fprintf(o->output, "<wfs:InsertResult>"); 
    150             } else { 
    151                 if (wr->handle != NULL) 
    152                     fprintf(o->output, "<wfs:Feature handle=\"%s\">", 
    153                             hdl->value->buf); 
    154                 else 
    155                     fprintf(o->output, "<wfs:Feature>"); 
    156             } 
    157  
    158             for (ln = mln->value->first; ln != NULL; ln = ln->next) 
    159                 fprintf(o->output, "<ogc:FeatureId fid=\"%s\"/>", 
    160                         ln->value->buf); 
     133        for (an = wr->insert_results->first; an != NULL; an = an->next) { 
     134 
     135            if (ows_version_get(o->request->version) == 100) 
     136                    fprintf(o->output, "<wfs:InsertResult handle=\"%s\">", an->key->buf); 
     137            else  
     138                    fprintf(o->output, "<wfs:Feature handle=\"%s\">", an->key->buf); 
     139 
     140            for (ln = an->value->first; ln != NULL; ln = ln->next) 
     141                fprintf(o->output, "<ogc:FeatureId fid=\"%s\"/>", ln->value->buf); 
    161142 
    162143            if (ows_version_get(o->request->version) == 100) 
     
    164145            else 
    165146                fprintf(o->output, "</wfs:Feature>\n"); 
    166  
    167             if (wr->handle != NULL) 
    168                 hdl = hdl->next; 
    169147        } 
    170148 
    171149        if (ows_version_get(o->request->version) == 110) 
    172             fprintf(o->output, "<wfs:InsertResults>"); 
     150            fprintf(o->output, "</wfs:InsertResults>"); 
    173151    } 
    174152} 
     
    337315static buffer *wfs_insert_xml(ows * o, wfs_request * wr, xmlNodePtr n) 
    338316{ 
    339     buffer *values, *column, *layer_name, *result, *sql, *id, *tmp, *id_column; 
    340     list *fid; 
     317    buffer *values, *column, *layer_name, *layer_prefix, *result, *sql; 
     318    buffer *id, *handle, *id_column, *fid_full_name; 
    341319    filter_encoding *fe; 
    342320    xmlNodePtr node, elemt; 
    343     xmlChar *content; 
     321    xmlChar *attr = NULL; 
     322    enum wfs_insert_idgen idgen = WFS_GENERATE_NEW; 
    344323 
    345324    assert(o != NULL); 
     
    348327 
    349328    sql = buffer_init(); 
    350     fid = list_init(); 
    351     content = NULL; 
     329    handle = buffer_init(); 
    352330 
    353331    /* retrieve handle attribute to report it in transaction response */ 
    354     if (n->properties != NULL) { 
    355         if (strcmp((char *) n->properties->name, "handle") == 0) { 
    356             wr->handle = list_init(); 
    357             content = xmlNodeGetContent(n->properties->children); 
    358             tmp = buffer_init(); 
    359             buffer_add_str(tmp, (char *) content); 
    360             list_add_by_copy(wr->handle, tmp); 
    361             xmlFree(content); 
    362             buffer_free(tmp); 
    363         } 
     332    if (xmlHasProp(n, (xmlChar *) "handle")) { 
     333        attr =  xmlGetProp(n, (xmlChar *) "handle"); 
     334        buffer_add_str(handle, (char *) attr); 
     335        xmlFree(attr); 
     336    /* handle is optional in WFS Schema */ 
     337    } else buffer_add_str(handle, "TinyOWS-WFS-default-handle"); 
     338 
     339    /* idgen appears in WFS 1.1.0, default behaviour is GenerateNew id 
     340       It is safe to not test WFS version, as schema validation  
     341       already do the job for us. 
     342    */ 
     343    if (xmlHasProp(n, (xmlChar *) "idgen")) { 
     344        attr =  xmlGetProp(n, (xmlChar *) "idgen"); 
     345        if (strcmp((char *) attr, "ReplaceDuplicate") == 0) 
     346                idgen = WFS_REPLACE_DUPLICATE; 
     347        else if (strcmp((char *) attr, "UseExisting") == 0) 
     348                idgen = WFS_USE_EXISTING; 
     349        xmlFree(attr); 
    364350    } 
    365351 
     
    386372         */  
    387373        id = buffer_init(); 
    388         if ((n->properties != NULL) && ( 
    389                     (strcmp((char *) n->properties->name, "id") == 0 || 
    390                     (strcmp((char *) n->properties->name, "fid") == 0 )))) { 
    391             content = xmlNodeGetContent(n->properties->children); 
    392             buffer_add_str(id, (char *) content); 
    393             xmlFree(content);  
    394         } 
     374        if (xmlHasProp(n, (xmlChar *) "id")) 
     375            attr =  xmlGetProp(n, (xmlChar *) "id"); 
     376        else if (xmlHasProp(n, (xmlChar *) "fid")) 
     377            attr =  xmlGetProp(n, (xmlChar *) "fid"); 
     378         
     379        if (attr != NULL) { 
     380            buffer_add_str(id, (char *) attr); 
     381            xmlFree(attr);  
     382        } else idgen = WFS_GENERATE_NEW; 
     383        /* TODO should add error if UseExisting  
     384           or Replace without id set ? */ 
    395385 
    396386        id_column = ows_psql_id_column(o, layer_name); 
    397  
    398         /* retrieve the id of the inserted feature 
     387        layer_prefix = ows_layer_prefix(o->layers, layer_name); 
     388 
     389        /* 
     390         * Delete previous feature if idgen is ReplaceExisting 
     391         */ 
     392        if (idgen == WFS_REPLACE_DUPLICATE) { 
     393             buffer_add_str(sql, "DELETE FROM \""); 
     394             buffer_copy(sql, layer_name); 
     395             buffer_add_str(sql, "\" WHERE "); 
     396             buffer_copy(sql, id_column); 
     397             buffer_add_str(sql, "='"); 
     398             buffer_copy(sql, id); 
     399             buffer_add_str(sql, "';"); 
     400        } else if (idgen == WFS_GENERATE_NEW) { 
     401             srandom((int) (time(NULL) ^ random() % 1000) + 42); 
     402             srandom((random() % 1000 ^ random() % 1000) + 42); 
     403             buffer_add_int(id, random()); 
     404             /* FIXME: use something more clever than that 
     405                to prevent collission ! 
     406             */ 
     407        } 
     408 
     409        /* Retrieve the id of the inserted feature 
    399410         * to report it in transaction respons 
    400411         */ 
    401         tmp = buffer_init(); 
    402         buffer_copy(tmp, layer_name); 
    403         buffer_add(tmp, '.'); 
    404         buffer_copy(tmp, id); 
    405         list_add(fid, tmp); 
     412        fid_full_name = buffer_init(); 
     413        buffer_copy(fid_full_name, layer_name); 
     414        buffer_add(fid_full_name, '.'); 
     415        buffer_copy(fid_full_name, id); 
     416        alist_add(wr->insert_results, handle, fid_full_name); 
    406417 
    407418        buffer_add_str(sql, "INSERT INTO \""); 
     
    411422        buffer_add_str(sql, "\""); 
    412423        buffer_copy(sql, id_column); 
    413         buffer_add_str(sql, "\","); 
     424        buffer_add_str(sql, "\""); 
    414425 
    415426        node = n->children; 
    416427 
    417428        /* jump to the next element if there are spaces */ 
    418         while (node->type != XML_ELEMENT_NODE) 
    419             node = node->next; 
     429        while (node->type != XML_ELEMENT_NODE) node = node->next; 
    420430 
    421431        /* fill fields and values at the same time */ 
    422432        for (; node; node = node->next) { 
    423             if (node->type == XML_ELEMENT_NODE) { 
     433            if (node->type == XML_ELEMENT_NODE &&  
     434                buffer_cmp(layer_prefix, (char *) node->ns->prefix)) { 
     435 
     436                buffer_add(sql, ','); 
     437                buffer_add(values, ','); 
     438 
    424439                column = buffer_init(); 
    425440                buffer_add_str(column, (char *) node->name); 
     
    434449 
    435450                    /* jump to the next element if there are spaces */ 
    436                     while (elemt->type != XML_ELEMENT_NODE) 
    437                         elemt = elemt->next; 
     451                    while (elemt->type != XML_ELEMENT_NODE) elemt = elemt->next; 
    438452 
    439453                    fe = filter_encoding_init(); 
     
    448462                    } else { 
    449463                        fe->sql = fe_transform_geometry_gml_to_psql(o, layer_name, fe, elemt); 
     464                        /* Carefull no error test on transform ! */ 
    450465                        buffer_copy(values, fe->sql); 
    451466                    } 
     
    458473                buffer_free(column); 
    459474            } 
    460  
    461             if (node->next != NULL) 
    462                 if (node->next->type == XML_ELEMENT_NODE) { 
    463                     buffer_add_str(sql, ","); 
    464                     buffer_add_str(values, ","); 
    465                 } 
    466475        } 
    467476 
    468477        /* As id could be NULL in GML */ 
    469478        if (id->use > 0) {   
    470             buffer_add_str(sql, " ) VALUES ('"); 
     479            buffer_add_str(sql, ") VALUES ('"); 
    471480            buffer_copy(sql, id); 
    472             buffer_add_str(sql, "',"); 
     481            buffer_add_str(sql, "'"); 
    473482        } else  
    474             buffer_add_str(sql, " ) VALUES (null,"); 
     483            buffer_add_str(sql, ") VALUES (null"); 
    475484 
    476485        buffer_copy(sql, values); 
     
    479488        buffer_free(values); 
    480489        buffer_free(layer_name); 
     490        buffer_free(layer_prefix); 
    481491        buffer_free(id); 
    482492    } 
    483  
    484     /* list of featureid inserted to be used during transaction response */ 
    485     wr->insert_results = mlist_init(); 
    486     mlist_add(wr->insert_results, fid); 
    487493 
    488494    /* run the request to insert all features at the same time */ 
     
    845851    sql = buffer_init(); 
    846852    locator = buffer_init(); 
    847     wr->featureid = mlist_init(); 
     853    wr->insert_results = alist_init(); 
    848854    content = NULL; 
    849855 
     
    854860        xmlFreeDoc(xmldoc); 
    855861        xmlCleanupParser(); 
    856         wfs_error(o, wr, WFS_ERROR_NO_MATCHING, "xml isn't valid", 
    857                   "transaction"); 
     862        wfs_error(o, wr, WFS_ERROR_NO_MATCHING, "xml isn't valid", "transaction"); 
    858863    } 
    859864 
     
    861866 
    862867    /* jump to the next element if there are spaces */ 
    863     while (n->type != XML_ELEMENT_NODE) 
    864         n = n->next; 
     868    while (n->type != XML_ELEMENT_NODE) n = n->next; 
    865869 
    866870    n = n->children; 
    867871 
    868872    /* jump to the next element if there are spaces */ 
    869     while (n->type != XML_ELEMENT_NODE) 
    870         n = n->next; 
     873    while (n->type != XML_ELEMENT_NODE) n = n->next; 
    871874 
    872875    /* initialize the transaction inside postgresql */ 
     
    879882 
    880883    /* go through the operations while transaction is successful */ 
    881     for (; (n != NULL) && (buffer_cmp(result, "PGRES_COMMAND_OK")); 
    882             n = n->next) { 
    883         if (n->type != XML_ELEMENT_NODE) 
    884             continue; 
     884    for ( /* empty */ ; (n != NULL) && (buffer_cmp(result, "PGRES_COMMAND_OK")); n = n->next) { 
     885        if (n->type != XML_ELEMENT_NODE) continue; 
    885886 
    886887        if (strcmp((char *) n->name, "Insert") == 0) { 
     
    915916                buffer_add_str(locator, (char *) n->name); 
    916917        } 
    917  
    918918    } 
    919919