def sql(self,SQL,parameters=None,asrecarray=True,cache=True):
        """Execute sql statement.

        :Arguments:
           SQL : string
              Full SQL command; can contain the ``?`` place holder so that values
              supplied with the ``parameters`` keyword can be interpolated using
              the ``pysqlite`` interface.
           parameters : tuple
              Parameters for ``?`` interpolation.
           asrecarray : boolean
              ``True``: return a ``numpy.recarray`` if possible;
              ``False``: return records as a list of tuples. [``True``]
           cache : boolean
              Should the results be cached? Set to ``False`` for large queries to
              avoid memory issues. Queries with ``?`` place holders are never cached.
              [``True``]

        :Returns:
           For *asrecarray* = ``True`` a :class:`numpy.recarray` is returned; otherwise
           a simple list of tuples is returned.

        :Raises:
           :exc:`TypeError` if the conversion to :class:`~numpy.recarray` fails for
           any reason.

        .. warning::

           There are **no sanity checks** applied to the SQL.

        The last *cachesize* queries are cached (for *cache* = ``True``) and
        are returned directly unless the table has been modified.

        The string "__self__" in *SQL* is substituted with the table name. See
        the :meth:`SELECT` method for more details.
        """
        SQL = SQL.replace('__self__',self.name)

        # Cache the last N (query,result) tuples using a 'FIFO-dict'
        # of length N, where key = SQL; if we can use the cache
        # (cache=True) and if query in dict (AND cache
        # valid, ie it hasn't been emptied (??)) just return cache result.
        #
        # Never use the cache if place holders are used because then we
        # would return the same result for differing input!
        if not '?' in SQL and cache and SQL in self.__cache:
            return self.__cache[SQL]

        c = self.cursor

        if parameters is None:
            c.execute(SQL)              # no sanity checks!
        else:
            c.execute(SQL, parameters)  # no sanity checks; params should be tuple

        if c.rowcount > 0 or SQL.upper().find('DELETE') > -1:
            # table was (potentially) modified
            # rowcount does not change for DELETE, see
            # http://oss.itsystementwicklung.de/download/pysqlite/doc/sqlite3.html#cursor-objects
            # so we catch this case manually and invalidate the whole cache
            self.__cache.clear()
        result = c.fetchall()
        if not result:
            return []    # leaving here keeps cache invalidated
        if asrecarray:
            try:
                names = [x[0] for x in c.description]   # first elements are column names
                result = numpy.rec.fromrecords(result,names=names)
            except:
                raise TypeError("SQLArray.sql(): failed to return recarray, try setting asrecarray=False to return tuples instead")
        else:
            pass      # keep as tuples/data structure as requested
        if cache:
            self.__cache.append(SQL,result)
        return result
Execute sql statement.

        :Arguments:
           SQL : string
              Full SQL command; can contain the ``?`` place holder so that values
              supplied with the ``parameters`` keyword can be interpolated using
              the ``pysqlite`` interface.
           parameters : tuple
              Parameters for ``?`` interpolation.
           asrecarray : boolean
              ``True``: return a ``numpy.recarray`` if possible;
              ``False``: return records as a list of tuples. [``True``]
           cache : boolean
              Should the results be cached? Set to ``False`` for large queries to
              avoid memory issues. Queries with ``?`` place holders are never cached.
              [``True``]

        :Returns:
           For *asrecarray* = ``True`` a :class:`numpy.recarray` is returned; otherwise
           a simple list of tuples is returned.

        :Raises:
           :exc:`TypeError` if the conversion to :class:`~numpy.recarray` fails for
           any reason.

        .. warning::

           There are **no sanity checks** applied to the SQL.

        The last *cachesize* queries are cached (for *cache* = ``True``) and
        are returned directly unless the table has been modified.

        The string "__self__" in *SQL* is substituted with the table name. See
        the :meth:`SELECT` method for more details.