def execute(queryString, argList=tuple(), fetch='N', connID='dbMetastore', useCache=False,
cacheExpireTime=consts.MEMCACHED_DEFAULT_EXPIRE_PERIOD, printQuery=False,
_alreadyInBacklog=False, many=False):
    """
    Executes a SQL statement on the database
    
    @param useCache: Set to True to use to cache the results of the query in memcached, or
    if the results are already cached in memcached, the cached version will be returned instead of having to
    make a query to the DB again.
    @param cacheExpireTime: The length of time that the result is valid in the memcache for (in seconds).
    This value is only used if memCacheKey is set to True.
    
    @see: The arguments for L{callProc}
    
    @param fetch: Same as the arguments for L{callProc}, with the addition of:
        - 'lid': Return the last insert ID (not in a tuple or list)
        
    @return: A deferred that yields the result of the query, or the data "DBEXECUTE-BACKLOG-ALREADYQUEUED" if we were executing
    a backlogged query (_alreadyInBacklog=True) and the DB was still downed (meaning it could still not be
    successfully processed)

    """
    assert queryString and len(queryString) >= 6
    assert fetch in ('N', 'o', 'om', 'a', 'am', 'lid')
    assert singleton.get(connID + 'Type') in ('direct', 'dbproxy')
    
    #decode any bytestrings passed in as querystring or within arglist into unicode strings
    #if isinstance(queryString, str):
        #decode into a unicode string
    #    queryString = queryString.decode('utf-8')
    #decode string args as well
    #for i in xrange(len(argList)):
    #    if isinstance(argList[i], str):
    #        argList[i] = argList[i].decode('utf-8')
    
    #some sanity checks
    if useCache and queryString.lstrip()[0:6].upper() != 'SELECT':
        raise Exception("useCache can only be set for SELECT queries. Failed query was: %s" % queryString)

    #make sure argList ends up being a tuple
    if not isinstance(argList, tuple):
        argList = tuple(argList)
    
    log.msg(u"Executing query: \"%s\"; Args: %s" % (queryString, argList,),
            lvl=printQuery and 'a' or 'd2', ss='ss_db')

    if     singleton.get('core', strict=False) \
       and singleton.get('core').getPlatformSetting('castdaemon_dbcache_interval', strict=False) == 0:
        #we are running as the castdaemon and caching is disabled
        useCache = False #override any True value

    #first, see if we are to use the memcache and try to pull the item from it if so
    if useCache:
        #use the query string itself, along with the args list as the hash key
        cacheHashKey = _produceCacheHashKey(queryString, argList, fetch)
        d = memcache.retrieve(cacheHashKey)
        d.addCallback(_cbExecute, queryString, argList, fetch, connID, useCache, cacheExpireTime, printQuery,
                      cacheHashKey, _alreadyInBacklog, many)
    else:
        cacheHashKey = ""
        d = defer.succeed(None)
        d.addCallback(_cbExecute, queryString, argList, fetch, connID, useCache, cacheExpireTime, printQuery,
                      cacheHashKey, _alreadyInBacklog, many)
    return d
def callProc(procName, inArgList=(), fetch='N', connID='dbMetastore', useCache=False,
cacheExpireTime=consts.MEMCACHED_DEFAULT_EXPIRE_PERIOD, printQuery=False):
    """
    I execute a stored procedure on the database, and optionally trigger a callback function to handle
    the results.
    
    How it works:
        - Some other code calls CallProc()
        - processingCbFunc called in database pool thread context to query the database, via runIteration
        - runInteraction returns requested data as a deferred

    @param procName: The name of the stored procedure to call
    @type procName: str
    
    @param inArgList: The arguments to the stored procedure. INOUT args not supported currently.
    @type inArgList: tuple
    
    @param fetch: How to fetch the data, one of the following:
        - N: Don't fetch anything back
        - o: Fetch one (as a tuple)
        - om: Fetch one as a map
        - a: Fetch All (as a tuple)
        - am: Fetch All as a map
    @type fetch: str
    
    @param printQuery: Set to True to print the query to be executed. False by default.    
    
    @return: A deferred that is triggered when the database operation is complete
    """
    assert isinstance(procName, basestring)
    assert isinstance(inArgList, tuple)
    assert fetch in ('N', 'o', 'om', 'a', 'am')
    assert singleton.get(connID + 'Type') in ('direct', 'dbproxy')
    
    #decode any bytestrings passed in as querystring or within arglist into unicode strings
    if isinstance(procName, str):
        #decode into a unicode string
        procName = procName.decode('utf-8')
    #decode string args as well
    for i in xrange(len(inArgList)):
        if isinstance(inArgList[i], str):
            inArgList[i] = inArgList[i].decode('utf-8')
    
    log.msg(u"Processing stored proc call: \"%s\"; InArgs: %s" % (procName, inArgList,),
            lvl=printQuery and 'a' or 'd2', ss='ss_db')

    if     singleton.get('core', strict=False) \
       and singleton.get('core').getPlatformSetting('castdaemon_dbcache_interval', strict=False) == 0:
        #we are running as the castdaemon and caching is disabled
        useCache = False #override any True value

    #first, see if we are to use the memcache and try to pull the item from it if so
    if useCache:
        #use the query string itself, along with the args list as the hash key, and the fetch mode
        cacheHashKey = _produceCacheHashKey(procName, inArgList, fetch) 
        d = memcache.retrieve(cacheHashKey)
        d.addCallback(_cbCallProc, procName, inArgList, fetch, connID, useCache, cacheExpireTime, printQuery,
                      cacheHashKey)
    else:
        cacheHashKey = ""
        d = defer.succeed(None)
        d.addCallback(_cbCallProc, procName, inArgList, fetch, connID, useCache, cacheExpireTime, printQuery,
                      cacheHashKey)
    return d