'Take in input a query string and return its limited query string.
Example:
Input:  SELECT user FROM mysql.users
Output: SELECT user FROM mysql.users LIMIT <num>, 1
@param num: limit number
@type num: C{int}
@param query: query to be processed
@type query: C{str}
@param field: field within the query
@type field: C{list}
@return: limited query string
@rtype: C{str}'

def limitQuery(self, num, query, field=None, uniqueField=None):

    if ('    FROM    ' not in query):
        return query
    limitedQuery = query
    limitStr = queries[Backend.getIdentifiedDbms()].limit.query
    fromIndex = limitedQuery.index('    FROM    ')
    untilFrom = limitedQuery[:fromIndex]
    fromFrom = limitedQuery[(fromIndex + 1):]
    orderBy = None
    if (Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE)):
        limitStr = (queries[Backend.getIdentifiedDbms()].limit.query % (num, 1))
        limitedQuery += ('    %s' % limitStr)
    elif Backend.isDbms(DBMS.HSQLDB):
        match = re.search('ORDER    BY    [^    ]+', limitedQuery)
        if match:
            limitedQuery = re.sub(('\\s*%s\\s*' % match.group(0)), '    ', limitedQuery).strip()
            limitedQuery += ('    %s' % match.group(0))
        if query.startswith('SELECT    '):
            limitStr = (queries[Backend.getIdentifiedDbms()].limit.query % (num, 1))
            limitedQuery = limitedQuery.replace('SELECT    ', ('SELECT    %s    ' % limitStr), 1)
        else:
            limitStr = (queries[Backend.getIdentifiedDbms()].limit.query2 % (1, num))
            limitedQuery += ('    %s' % limitStr)
        if (not match):
            match = re.search(('%s\\s+(\\w+)' % re.escape(limitStr)), limitedQuery)
            if match:
                orderBy = ('    ORDER    BY    %s' % match.group(1))
    elif Backend.isDbms(DBMS.FIREBIRD):
        limitStr = (queries[Backend.getIdentifiedDbms()].limit.query % ((num + 1), (num + 1)))
        limitedQuery += ('    %s' % limitStr)
    elif (Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2)):
        if (not ('    ORDER    BY    ' in limitedQuery)):
            limitStr = limitStr.replace(')    WHERE    LIMIT', '    ORDER    BY    1    ASC)    WHERE    LIMIT')
        elif (('    ORDER    BY    ' in limitedQuery) and ('SELECT    ' in limitedQuery)):
            limitedQuery = limitedQuery[:limitedQuery.index('    ORDER    BY    ')]
        if query.startswith('SELECT    '):
            delimiter = queries[Backend.getIdentifiedDbms()].delimiter.query
            limitedQuery = ('%s    FROM    (%s,%s' % (untilFrom, untilFrom.replace(delimiter, ','), limitStr))
        else:
            limitedQuery = ('%s    FROM    (SELECT    %s,%s' % (untilFrom, ','.join((f for f in field)), limitStr))
        limitedQuery = safeStringFormat(limitedQuery, (fromFrom,))
        limitedQuery += ('=%d' % (num + 1))
    elif Backend.isDbms(DBMS.MSSQL):
        forgeNotIn = True
        if ('    ORDER    BY    ' in limitedQuery):
            orderBy = limitedQuery[limitedQuery.index('    ORDER    BY    '):]
            limitedQuery = limitedQuery[:limitedQuery.index('    ORDER    BY    ')]
        notDistincts = re.findall('DISTINCT[\\(\\s+](.+?)\\)*\\s+', limitedQuery, re.I)
        for notDistinct in notDistincts:
            limitedQuery = limitedQuery.replace(('DISTINCT(%s)' % notDistinct), notDistinct)
            limitedQuery = limitedQuery.replace(('DISTINCT    %s' % notDistinct), notDistinct)
        if (limitedQuery.startswith('SELECT    TOP    ') or limitedQuery.startswith('TOP    ')):
            topNums = re.search(queries[Backend.getIdentifiedDbms()].limitregexp.query, limitedQuery, re.I)
            if topNums:
                topNums = topNums.groups()
                quantityTopNums = topNums[0]
                limitedQuery = limitedQuery.replace(('TOP    %s' % quantityTopNums), 'TOP    1', 1)
                startTopNums = topNums[1]
                limitedQuery = limitedQuery.replace(('    (SELECT    TOP    %s' % startTopNums), ('    (SELECT    TOP    %d' % num))
                forgeNotIn = False
            else:
                topNum = re.search('TOP\\s+([\\d]+)\\s+', limitedQuery, re.I).group(1)
                limitedQuery = limitedQuery.replace(('TOP    %s    ' % topNum), '')
        if forgeNotIn:
            limitedQuery = limitedQuery.replace('SELECT    ', (limitStr % 1), 1)
            if ('    ORDER    BY    ' not in fromFrom):
                if ('    WHERE    ' in limitedQuery):
                    limitedQuery = ('%s    AND    %s    ' % (limitedQuery, self.nullAndCastField((uniqueField or field))))
                else:
                    limitedQuery = ('%s    WHERE    %s    ' % (limitedQuery, self.nullAndCastField((uniqueField or field))))
                limitedQuery += ('NOT    IN    (%s' % (limitStr % num))
                limitedQuery += ('%s    %s    ORDER    BY    %s)    ORDER    BY    %s' % (self.nullAndCastField((uniqueField or field)), fromFrom, (uniqueField or '1'), (uniqueField or '1')))
            else:
                match = re.search('    ORDER    BY    (\\w+)\\Z', query)
                field = (match.group(1) if match else field)
                if ('    WHERE    ' in limitedQuery):
                    limitedQuery = ('%s    AND    %s    ' % (limitedQuery, field))
                else:
                    limitedQuery = ('%s    WHERE    %s    ' % (limitedQuery, field))
                limitedQuery += ('NOT    IN    (%s' % (limitStr % num))
                limitedQuery += ('%s    %s)' % (field, fromFrom))
    if orderBy:
        limitedQuery += orderBy
    return limitedQuery
