.. _rfc33:

=======================================================
MS RFC 33: Removing msLayerWhichItems() from maplayer.c
=======================================================

:Date: 2007/07/09
:Author: Steve Lime
:Contact: steve.lime at dnr.state.mn.us
:Last Edited: 2007/07/09
:Status: draft
:Version: MapServer 5.0

Overview
~~~~~~~~

The function msLayerWhichItems() is a function in maplayer.c that determines
exactly which feature attributes need to be retrieved from a given data
source. All item-based properties (e.g. CLASSITEM, bound properties,
EXPRESSIONs, etc...) are checked and a master list (an array) is compiled. At
the same time index references are made (e.g. classitemindex, labelitemindex,
etc...). The item indexes are used instead of names to access attribute values
at runtime.

The problem with this method is that a feature (a shapeObj) used for drawing
or the first pass of a query is not the same as that used for presentation
(the second pass of a query). The second pass of a query uses
msLayerGetShape() which by default requests all attributes of a feature since
we don't know ahead of time which attributes might be output.

By removing msLayerWhichItems() and always retrieving all attributes a feature
is a feature whether drawing, querying or outputting via a template so caching
features now becomes practical.

Technical Solution
~~~~~~~~~~~~~~~~~~

As mentioned earlier msLayerWhichItems() does a couple of things. Some of
these functions would need to be retained somehow and are described below.

1) Layer items array: this array normally would be populated by the
   msLayerWhichItems() call. Instead it should be populated as a layer is opened
   in msLayerOpen. (makes sense?)

2) Index references: linking a attribute name to an index value would have to
   happen during the course of rendering or querying instead of ahead of time.
   Basically code that uses attributes would have to first check if the parameter
   is not NULL, and then if the index reference is not set it would have to call
   a function like that shown below. While this affects a good number of places
   in the code base the change is relatively minor. The use of attribute binding
   isolates much of this code so this change is smaller for version 5.0 that it
   otherwise would have been.

::

  int msGetItemIndex(char **itemlist, int numitems, char *item) {
    int i;

    if (!itemlist || numitems <= 0 || !item) return -1;

    for (i=0; i<numitems; i++)
      if(strcasecmp(itemlist[i], item) return i;

    return -1; /* failure */
  } 
  
3) Logical expression handling: expressions maintain their own individual list
   of items to process so like 2 above this list would have to be created during
   processing. The code to do this exists as part of msLayerWhichItems() and
   would be retained under some other name.

.. note:: 

    this RFC does not address single pass queries, but rather sets the
    stage for them. Subsequent drawing, query and template output processes would
    remain unaltered.

General C API Changes
~~~~~~~~~~~~~~~~~~~~~

maplayer.c - msLayerWhichItems() goes away. msLayerOpen() now sets the
layer->items array.

maputil.c - Binding functions now must assign index references when executed.
Same goes for the functions to assign a classObj to a feature.

mapdraw.c - Layeritemindex and classitemindex must now be dynamically assigned
values.

Input Driver Changes
~~~~~~~~~~~~~~~~~~~~

It is unclear how each driver made use of the output of msLayerWhichItems().
It may be as easy as calling msLayerGetItems() instead of using
msLayerGetItemInfo() in msLayerOpen() in which case we'd loose the
msLayerGetItemInfo() function for each driver too (and the main wrapper
function). TODO...

mapshape.c - 
mapsde.c - 
mapogr.cpp -
mappostgis.c -
maporaclespatial.c - 
mapmygis.c - 

MapScript
~~~~~~~~~

No changes.

Mapfiles
~~~~~~~~

No changes anticipated.

Backwards Compatibility Issues
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

None. This is a new feature.

Bug ID
~~~~~~

None assigned.

Voting History
~~~~~~~~~~~~~~

None