LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/ogdi - ogrogdilayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 209 244 85.7 %
Date: 2024-11-25 13:07:18 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OGDI Bridge
       4             :  * Purpose:  Implements OGROGDILayer class.
       5             :  * Author:   Daniel Morissette, danmo@videotron.ca
       6             :  *           (Based on some code contributed by Frank Warmerdam :)
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2000, Daniel Morissette
      10             :  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ******************************************************************************
      14             :  */
      15             : 
      16             : #include "ogrogdi.h"
      17             : #include "cpl_conv.h"
      18             : #include "cpl_string.h"
      19             : 
      20             : /************************************************************************/
      21             : /*                           OGROGDILayer()                            */
      22             : /************************************************************************/
      23             : 
      24          19 : OGROGDILayer::OGROGDILayer(OGROGDIDataSource *poODS, const char *pszName,
      25          19 :                            ecs_Family eFamily)
      26          19 :     : m_poODS(poODS), m_nClientID(poODS->GetClientID()),
      27          38 :       m_pszOGDILayerName(CPLStrdup(pszName)), m_eFamily(eFamily),
      28             :       m_poFeatureDefn(nullptr),
      29             :       // Keep a reference on the SpatialRef (owned by the dataset).
      30          19 :       m_poSpatialRef(m_poODS->DSGetSpatialRef()),
      31          19 :       m_sFilterBounds(*(m_poODS->GetGlobalBounds())), m_iNextShapeId(0),
      32          19 :       m_nTotalShapeCount(-1), m_nFilteredOutShapes(0)
      33             : {
      34             : 
      35             :     // Select layer and feature family.
      36          19 :     OGROGDILayer::ResetReading();
      37             : 
      38          19 :     BuildFeatureDefn();
      39          19 : }
      40             : 
      41             : /************************************************************************/
      42             : /*                           ~OGROGDILayer()                           */
      43             : /************************************************************************/
      44             : 
      45          38 : OGROGDILayer::~OGROGDILayer()
      46             : 
      47             : {
      48          19 :     if (m_nFeaturesRead > 0 && m_poFeatureDefn != nullptr)
      49             :     {
      50          16 :         CPLDebug("OGDI", "%d features read on layer '%s'.",
      51           8 :                  (int)m_nFeaturesRead, m_poFeatureDefn->GetName());
      52             :     }
      53             : 
      54          19 :     if (m_poFeatureDefn)
      55          19 :         m_poFeatureDefn->Release();
      56             : 
      57          19 :     CPLFree(m_pszOGDILayerName);
      58             : 
      59             :     // Note: we do not delete m_poSpatialRef since it is owned by the dataset
      60          38 : }
      61             : 
      62             : /************************************************************************/
      63             : /*                          SetSpatialFilter()                          */
      64             : /************************************************************************/
      65             : 
      66         156 : void OGROGDILayer::SetSpatialFilter(OGRGeometry *poGeomIn)
      67             : 
      68             : {
      69         156 :     if (!InstallFilter(poGeomIn))
      70          84 :         return;
      71             : 
      72          72 :     ResetReading();
      73             : 
      74          72 :     m_nTotalShapeCount = -1;
      75             : }
      76             : 
      77             : /************************************************************************/
      78             : /*                         SetAttributeFilter()                         */
      79             : /************************************************************************/
      80             : 
      81         186 : OGRErr OGROGDILayer::SetAttributeFilter(const char *pszQuery)
      82             : {
      83         186 :     OGRErr eErr = OGRLayer::SetAttributeFilter(pszQuery);
      84             : 
      85         186 :     ResetReading();
      86             : 
      87         186 :     m_nTotalShapeCount = -1;
      88             : 
      89         186 :     return eErr;
      90             : }
      91             : 
      92             : /************************************************************************/
      93             : /*                            ResetReading()                            */
      94             : /************************************************************************/
      95             : 
      96         787 : void OGROGDILayer::ResetReading()
      97             : 
      98             : {
      99             :     ecs_LayerSelection sSelectionLayer;
     100             : 
     101         787 :     sSelectionLayer.Select = m_pszOGDILayerName;
     102         787 :     sSelectionLayer.F = m_eFamily;
     103             : 
     104         787 :     ecs_Result *psResult = cln_SelectLayer(m_nClientID, &sSelectionLayer);
     105         787 :     if (ECSERROR(psResult))
     106             :     {
     107           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     108             :                  "Access to layer '%s' Failed: %s\n", m_pszOGDILayerName,
     109           0 :                  psResult->message ? psResult->message : "(no message string)");
     110           0 :         return;
     111             :     }
     112             : 
     113             :     /* Reset spatial filter */
     114         787 :     if (m_poFilterGeom != nullptr)
     115             :     {
     116         198 :         OGREnvelope oEnv;
     117             : 
     118         198 :         m_poFilterGeom->getEnvelope(&oEnv);
     119             : 
     120         198 :         m_sFilterBounds.north = oEnv.MaxY;
     121         198 :         m_sFilterBounds.south = oEnv.MinY;
     122         198 :         m_sFilterBounds.west = oEnv.MinX;
     123         198 :         m_sFilterBounds.east = oEnv.MaxX;
     124             : 
     125         198 :         psResult = cln_SelectRegion(m_nClientID, &m_sFilterBounds);
     126         198 :         if (ECSERROR(psResult))
     127             :         {
     128           0 :             CPLError(CE_Failure, CPLE_AppDefined, "SelectRegion failed: %s",
     129           0 :                      psResult->message ? psResult->message
     130             :                                        : "(no message string)");
     131           0 :             return;
     132             :         }
     133             :     }
     134             :     else
     135             :     {
     136             :         /* Reset to global bounds */
     137         589 :         psResult = cln_SelectRegion(m_nClientID, m_poODS->GetGlobalBounds());
     138         589 :         if (ECSERROR(psResult))
     139             :         {
     140           0 :             CPLError(CE_Failure, CPLE_AppDefined, "SelectRegion failed: %s",
     141           0 :                      psResult->message ? psResult->message
     142             :                                        : "(no message string)");
     143           0 :             return;
     144             :         }
     145             :     }
     146             : 
     147         787 :     m_iNextShapeId = 0;
     148         787 :     m_nFilteredOutShapes = 0;
     149             : }
     150             : 
     151             : /************************************************************************/
     152             : /*                           GetNextFeature()                           */
     153             : /************************************************************************/
     154             : 
     155        1354 : OGRFeature *OGROGDILayer::GetNextFeature()
     156             : 
     157             : {
     158             : 
     159             :     /* Reset reading if we are not the current layer */
     160             :     /* WARNING : this does not allow interleaved reading of layers */
     161        1354 :     if (m_poODS->GetCurrentLayer() != this)
     162             :     {
     163           8 :         m_poODS->SetCurrentLayer(this);
     164           8 :         ResetReading();
     165             :     }
     166             : 
     167             :     while (true)
     168             :     {
     169        1630 :         OGRFeature *poFeature = GetNextRawFeature();
     170        1630 :         if (poFeature == nullptr)
     171         176 :             return nullptr;
     172             : 
     173             :         /* --------------------------------------------------------------------
     174             :          */
     175             :         /*      Do we need to apply an attribute test? */
     176             :         /* --------------------------------------------------------------------
     177             :          */
     178        2632 :         if ((m_poAttrQuery != nullptr && !m_poAttrQuery->Evaluate(poFeature)) ||
     179        1178 :             (m_poFilterGeom != nullptr &&
     180         270 :              !FilterGeometry(poFeature->GetGeometryRef())))
     181             :         {
     182         276 :             m_nFilteredOutShapes++;
     183         276 :             delete poFeature;
     184             :         }
     185             :         else
     186        1178 :             return poFeature;
     187         276 :     }
     188             : }
     189             : 
     190             : /************************************************************************/
     191             : /*                           GetNextFeature()                           */
     192             : /************************************************************************/
     193             : 
     194        1648 : OGRFeature *OGROGDILayer::GetNextRawFeature()
     195             : {
     196             :     /* -------------------------------------------------------------------- */
     197             :     /*      Retrieve object from OGDI server and create new feature         */
     198             :     /* -------------------------------------------------------------------- */
     199        1648 :     ecs_Result *psResult = cln_GetNextObject(m_nClientID);
     200        1648 :     if (!ECSSUCCESS(psResult))
     201             :     {
     202         176 :         if (ECSERROR(psResult) &&
     203         176 :             (psResult->message == nullptr ||
     204         176 :              strstr(psResult->message, "End of selection") == nullptr))
     205             :         {
     206           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     207             :                      "Access to next object of layer '%s' failed: %s\n",
     208             :                      m_pszOGDILayerName,
     209           0 :                      psResult->message ? psResult->message
     210             :                                        : "(no error string)");
     211             :         }
     212             :         // We probably reached EOF... keep track of shape count.
     213         176 :         m_nTotalShapeCount = m_iNextShapeId - m_nFilteredOutShapes;
     214         176 :         return nullptr;
     215             :     }
     216             : 
     217        1472 :     OGRFeature *poFeature = new OGRFeature(m_poFeatureDefn);
     218             : 
     219        1472 :     poFeature->SetFID(m_iNextShapeId++);
     220        1472 :     m_nFeaturesRead++;
     221             : 
     222             :     /* -------------------------------------------------------------------- */
     223             :     /*      Process geometry                                                */
     224             :     /* -------------------------------------------------------------------- */
     225        1472 :     if (m_eFamily == Point)
     226             :     {
     227        1033 :         ecs_Point *psPoint = &(ECSGEOM(psResult).point);
     228        1033 :         OGRPoint *poOGRPoint = new OGRPoint(psPoint->c.x, psPoint->c.y);
     229             : 
     230        1033 :         poOGRPoint->assignSpatialReference(m_poSpatialRef);
     231        1033 :         poFeature->SetGeometryDirectly(poOGRPoint);
     232             :     }
     233         439 :     else if (m_eFamily == Line)
     234             :     {
     235          62 :         ecs_Line *psLine = &(ECSGEOM(psResult).line);
     236          62 :         OGRLineString *poOGRLine = new OGRLineString();
     237             : 
     238          62 :         poOGRLine->setNumPoints(psLine->c.c_len);
     239             : 
     240         634 :         for (int i = 0; i < (int)psLine->c.c_len; i++)
     241             :         {
     242         572 :             poOGRLine->setPoint(i, psLine->c.c_val[i].x, psLine->c.c_val[i].y);
     243             :         }
     244             : 
     245          62 :         poOGRLine->assignSpatialReference(m_poSpatialRef);
     246          62 :         poFeature->SetGeometryDirectly(poOGRLine);
     247             :     }
     248         377 :     else if (m_eFamily == Area)
     249             :     {
     250         228 :         ecs_Area *psArea = &(ECSGEOM(psResult).area);
     251         228 :         OGRPolygon *poOGRPolygon = new OGRPolygon();
     252             : 
     253         456 :         for (int iRing = 0; iRing < (int)psArea->ring.ring_len; iRing++)
     254             :         {
     255         228 :             ecs_FeatureRing *psRing = &(psArea->ring.ring_val[iRing]);
     256         228 :             OGRLinearRing *poOGRRing = new OGRLinearRing();
     257             : 
     258         228 :             poOGRRing->setNumPoints(psRing->c.c_len);
     259             : 
     260       54559 :             for (int i = 0; i < (int)psRing->c.c_len; i++)
     261             :             {
     262       54331 :                 poOGRRing->setPoint(i, psRing->c.c_val[i].x,
     263       54331 :                                     psRing->c.c_val[i].y);
     264             :             }
     265         228 :             poOGRPolygon->addRingDirectly(poOGRRing);
     266             :         }
     267             : 
     268             :         // __TODO__
     269             :         // When OGR supports polygon centroids then we should carry them here
     270             : 
     271         228 :         poOGRPolygon->assignSpatialReference(m_poSpatialRef);
     272         228 :         poFeature->SetGeometryDirectly(poOGRPolygon);
     273             :     }
     274         149 :     else if (m_eFamily == Text)
     275             :     {
     276             :         // __TODO__
     277             :         // For now text is treated as a point and string is lost
     278             :         //
     279         149 :         ecs_Text *psText = &(ECSGEOM(psResult).text);
     280         149 :         OGRPoint *poOGRPoint = new OGRPoint(psText->c.x, psText->c.y);
     281             : 
     282         149 :         poOGRPoint->assignSpatialReference(m_poSpatialRef);
     283         149 :         poFeature->SetGeometryDirectly(poOGRPoint);
     284             :     }
     285             :     else
     286             :     {
     287           0 :         CPLAssert(false);
     288             :     }
     289             : 
     290             :     /* -------------------------------------------------------------------- */
     291             :     /*      Set attributes                                                  */
     292             :     /* -------------------------------------------------------------------- */
     293        1472 :     char *pszAttrList = ECSOBJECTATTR(psResult);
     294             : 
     295       11587 :     for (int iField = 0; iField < m_poFeatureDefn->GetFieldCount(); iField++)
     296             :     {
     297       10115 :         char *pszFieldStart = nullptr;
     298       10115 :         int nNameLen = 0;
     299             : 
     300             :         /* parse out the next attribute value */
     301       10115 :         if (!ecs_FindElement(pszAttrList, &pszFieldStart, &pszAttrList,
     302             :                              &nNameLen, nullptr))
     303             :         {
     304           0 :             nNameLen = 0;
     305           0 :             pszFieldStart = pszAttrList;
     306             :         }
     307             : 
     308             :         /* Skip any trailing white space (for string constants). */
     309             : 
     310       10115 :         if (nNameLen > 0 && pszFieldStart[nNameLen - 1] == ' ')
     311        2881 :             nNameLen--;
     312             : 
     313             :         /* skip leading white space */
     314       14128 :         while (pszFieldStart[0] == ' ' && nNameLen > 0)
     315             :         {
     316        4013 :             pszFieldStart++;
     317        4013 :             nNameLen--;
     318             :         }
     319             : 
     320             :         /* zero terminate the single field value, but save the          */
     321             :         /* character we overwrote, so we can restore it when done.      */
     322             : 
     323       10115 :         char chSavedChar = pszFieldStart[nNameLen];
     324       10115 :         pszFieldStart[nNameLen] = '\0';
     325             : 
     326             :         /* OGR takes care of all field type conversions for us! */
     327             : 
     328       10115 :         poFeature->SetField(iField, pszFieldStart);
     329             : 
     330       10115 :         pszFieldStart[nNameLen] = chSavedChar;
     331             :     }
     332             : 
     333             :     /* -------------------------------------------------------------------- */
     334             :     /*      Apply the text associated with text features if appropriate.    */
     335             :     /* -------------------------------------------------------------------- */
     336        1472 :     if (m_eFamily == Text)
     337             :     {
     338         149 :         poFeature->SetField("text", ECSGEOM(psResult).text.desc);
     339             :     }
     340             : 
     341        1472 :     return poFeature;
     342             : }
     343             : 
     344             : /************************************************************************/
     345             : /*                             GetFeature()                             */
     346             : /************************************************************************/
     347             : 
     348          36 : OGRFeature *OGROGDILayer::GetFeature(GIntBig nFeatureId)
     349             : 
     350             : {
     351             : 
     352          36 :     if (m_nTotalShapeCount != -1 && nFeatureId > m_nTotalShapeCount)
     353          12 :         return nullptr;
     354             : 
     355             :     /* Unset spatial filter */
     356             :     OGRGeometry *poOldFilterGeom =
     357          24 :         (m_poFilterGeom != nullptr) ? m_poFilterGeom->clone() : nullptr;
     358          24 :     if (poOldFilterGeom != nullptr)
     359           6 :         SetSpatialFilter(nullptr);
     360             : 
     361             :     /* Reset reading if we are not the current layer */
     362             :     /* WARNING : this does not allow interleaved reading of layers */
     363          24 :     if (m_poODS->GetCurrentLayer() != this)
     364             :     {
     365           0 :         m_poODS->SetCurrentLayer(this);
     366           0 :         ResetReading();
     367             :     }
     368          24 :     else if (nFeatureId < m_iNextShapeId)
     369          16 :         ResetReading();
     370             : 
     371          88 :     while (m_iNextShapeId != nFeatureId)
     372             :     {
     373          70 :         ecs_Result *psResult = cln_GetNextObject(m_nClientID);
     374          70 :         if (ECSSUCCESS(psResult))
     375          64 :             m_iNextShapeId++;
     376             :         else
     377             :         {
     378             :             // We probably reached EOF... keep track of shape count.
     379           6 :             m_nTotalShapeCount = m_iNextShapeId;
     380           6 :             if (poOldFilterGeom != nullptr)
     381             :             {
     382           0 :                 SetSpatialFilter(poOldFilterGeom);
     383           0 :                 delete poOldFilterGeom;
     384             :             }
     385           6 :             return nullptr;
     386             :         }
     387             :     }
     388             : 
     389             :     // OK, we're ready to read the requested feature...
     390          18 :     OGRFeature *poFeature = GetNextRawFeature();
     391          18 :     if (poOldFilterGeom != nullptr)
     392             :     {
     393           6 :         SetSpatialFilter(poOldFilterGeom);
     394           6 :         delete poOldFilterGeom;
     395             :     }
     396          18 :     return poFeature;
     397             : }
     398             : 
     399             : /************************************************************************/
     400             : /*                          GetFeatureCount()                           */
     401             : /*                                                                      */
     402             : /*      If a spatial filter is in effect, we turn control over to       */
     403             : /*      the generic counter.  Otherwise we return the total count.      */
     404             : /*      Eventually we should consider implementing a more efficient     */
     405             : /*      way of counting features matching a spatial query.              */
     406             : /************************************************************************/
     407             : 
     408          88 : GIntBig OGROGDILayer::GetFeatureCount(int bForce)
     409             : 
     410             : {
     411          88 :     if (m_nTotalShapeCount == -1)
     412             :     {
     413          44 :         m_nTotalShapeCount =
     414          44 :             static_cast<int>(OGRLayer::GetFeatureCount(bForce));
     415             :     }
     416             : 
     417          88 :     return m_nTotalShapeCount;
     418             : }
     419             : 
     420             : /************************************************************************/
     421             : /*                           TestCapability()                           */
     422             : /************************************************************************/
     423             : 
     424         210 : int OGROGDILayer::TestCapability(const char *pszCap)
     425             : 
     426             : {
     427             : /* -------------------------------------------------------------------- */
     428             : /*      Hummm... what are the proper capabilities...                    */
     429             : /*      Does OGDI have any idea of capabilities???                      */
     430             : /*      For now just return FALSE for everything.                       */
     431             : /* -------------------------------------------------------------------- */
     432             : #ifdef __TODO__
     433             :     if (EQUAL(pszCap, OLCFastFeatureCount))
     434             :         return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
     435             : 
     436             :     else if (EQUAL(pszCap, OLCFastSpatialFilter))
     437             :         return FALSE;
     438             : 
     439             :     else
     440             :         return FALSE;
     441             : #endif
     442             : 
     443         210 :     if (EQUAL(pszCap, OLCRandomRead))
     444           0 :         return TRUE;
     445             : 
     446             :     else
     447         210 :         return FALSE;
     448             : }
     449             : 
     450             : /************************************************************************/
     451             : /*                          BuildFeatureDefn()                          */
     452             : /*                                                                      */
     453             : /*      (private) Initializes the schema in m_poFeatureDefn             */
     454             : /************************************************************************/
     455             : 
     456          19 : void OGROGDILayer::BuildFeatureDefn()
     457             : {
     458          19 :     const char *pszGeomName = nullptr;
     459          19 :     OGRwkbGeometryType eLayerGeomType = wkbUnknown;
     460             : 
     461             :     /* -------------------------------------------------------------------- */
     462             :     /*      Feature Defn name will be "<OGDILyrName>_<FeatureFamily>"       */
     463             :     /* -------------------------------------------------------------------- */
     464             : 
     465          19 :     switch (m_eFamily)
     466             :     {
     467           3 :         case Point:
     468           3 :             pszGeomName = "point";
     469           3 :             eLayerGeomType = wkbPoint;
     470           3 :             break;
     471           3 :         case Line:
     472           3 :             pszGeomName = "line";
     473           3 :             eLayerGeomType = wkbLineString;
     474           3 :             break;
     475           7 :         case Area:
     476           7 :             pszGeomName = "area";
     477           7 :             eLayerGeomType = wkbPolygon;
     478           7 :             break;
     479           6 :         case Text:
     480           6 :             pszGeomName = "text";
     481           6 :             eLayerGeomType = wkbPoint;
     482           6 :             break;
     483           0 :         default:
     484           0 :             pszGeomName = "unknown";
     485           0 :             eLayerGeomType = wkbUnknown;
     486           0 :             break;
     487             :     }
     488             : 
     489          19 :     char *pszFeatureDefnName = nullptr;
     490          19 :     if (m_poODS->LaunderLayerNames())
     491             :     {
     492          12 :         pszFeatureDefnName = CPLStrdup(m_pszOGDILayerName);
     493          12 :         char *pszAt = strchr(pszFeatureDefnName, '@');
     494          12 :         if (pszAt)
     495          12 :             *pszAt = '_';
     496          12 :         char *pszLeftParenthesis = strchr(pszFeatureDefnName, '(');
     497          12 :         if (pszLeftParenthesis)
     498          12 :             *pszLeftParenthesis = '\0';
     499             :     }
     500             :     else
     501             :         pszFeatureDefnName =
     502           7 :             CPLStrdup(CPLSPrintf("%s_%s", m_pszOGDILayerName, pszGeomName));
     503             : 
     504          19 :     m_poFeatureDefn = new OGRFeatureDefn(pszFeatureDefnName);
     505          19 :     SetDescription(m_poFeatureDefn->GetName());
     506          19 :     CPLFree(pszFeatureDefnName);
     507          19 :     pszFeatureDefnName = nullptr;
     508             : 
     509          19 :     m_poFeatureDefn->SetGeomType(eLayerGeomType);
     510          19 :     m_poFeatureDefn->Reference();
     511          19 :     m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_poSpatialRef);
     512             : 
     513             :     /* -------------------------------------------------------------------- */
     514             :     /*      Fetch schema from OGDI server and map to OGR types              */
     515             :     /* -------------------------------------------------------------------- */
     516          19 :     ecs_Result *psResult = cln_GetAttributesFormat(m_nClientID);
     517          19 :     if (ECSERROR(psResult))
     518             :     {
     519           0 :         CPLError(CE_Failure, CPLE_AppDefined, "ECSERROR: %s\n",
     520           0 :                  psResult->message ? psResult->message : "(no message string)");
     521           0 :         return;
     522             :     }
     523             : 
     524          19 :     ecs_ObjAttributeFormat *oaf = &(ECSRESULT(psResult).oaf);
     525          19 :     const int numFields = oaf->oa.oa_len;
     526         131 :     for (int i = 0; i < numFields; i++)
     527             :     {
     528         224 :         OGRFieldDefn oField("", OFTInteger);
     529             : 
     530         112 :         oField.SetName(oaf->oa.oa_val[i].name);
     531         112 :         oField.SetPrecision(0);
     532             : 
     533         112 :         switch (oaf->oa.oa_val[i].type)
     534             :         {
     535          77 :             case Decimal:
     536             :             case Smallint:
     537             :             case Integer:
     538          77 :                 oField.SetType(OFTInteger);
     539             :                 // TODO: Fix spelling - lenght -> length
     540          77 :                 if (oaf->oa.oa_val[i].lenght > 0)
     541          77 :                     oField.SetWidth(oaf->oa.oa_val[i].lenght);
     542             :                 else
     543           0 :                     oField.SetWidth(11);
     544          77 :                 break;
     545             : 
     546           0 :             case Numeric:
     547             :             case Real:
     548             :             case Float:
     549             :             case Double:
     550           0 :                 oField.SetType(OFTReal);
     551           0 :                 if (oaf->oa.oa_val[i].lenght > 0)
     552             :                 {
     553           0 :                     oField.SetWidth(oaf->oa.oa_val[i].lenght);
     554           0 :                     oField.SetPrecision(oaf->oa.oa_val[i].precision);
     555             :                 }
     556             :                 else
     557             :                 {
     558           0 :                     oField.SetWidth(18);
     559           0 :                     oField.SetPrecision(7);
     560             :                 }
     561           0 :                 break;
     562             : 
     563          35 :             case Char:
     564             :             case Varchar:
     565             :             case Longvarchar:
     566             :             default:
     567          35 :                 oField.SetType(OFTString);
     568          35 :                 if (oaf->oa.oa_val[i].lenght > 0)
     569          19 :                     oField.SetWidth(oaf->oa.oa_val[i].lenght);
     570             :                 else
     571          16 :                     oField.SetWidth(64);
     572          35 :                 break;
     573             :         }
     574             : 
     575         112 :         m_poFeatureDefn->AddFieldDefn(&oField);
     576             :     }
     577             : 
     578             :     /* -------------------------------------------------------------------- */
     579             :     /*      Add a text attribute for text objects.                          */
     580             :     /* -------------------------------------------------------------------- */
     581          19 :     if (m_eFamily == Text)
     582             :     {
     583          12 :         OGRFieldDefn oField("text", OFTString);
     584             : 
     585           6 :         m_poFeatureDefn->AddFieldDefn(&oField);
     586             :     }
     587             : }

Generated by: LCOV version 1.14