_identifiers = frozenset({
    'add',
    'aggregate',
    'all',
    'alter',
    'and',
    'as',
    'asc',
    'between',
    'by',
    'cached',
    'case',
    'cast',
    'change',
    'class',
    'column',
    'columns',
    'comment',
    'create',
    'cross',
    'data',
    'database',
    'databases',
    'date',
    'datetime',
    'desc',
    'describe',
    'distinct',
    'div',
    'double',
    'drop',
    'else',
    'end',
    'escaped',
    'exists',
    'explain',
    'external',
    'fields',
    'fileformat',
    'first',
    'float',
    'format',
    'from',
    'full',
    'function',
    'functions',
    'group',
    'having',
    'if',
    'in',
    'inner',
    'inpath',
    'insert',
    'int',
    'integer',
    'intermediate',
    'interval',
    'into',
    'is',
    'join',
    'last',
    'left',
    'like',
    'limit',
    'lines',
    'load',
    'location',
    'metadata',
    'not',
    'null',
    'offset',
    'on',
    'or',
    'order',
    'outer',
    'partition',
    'partitioned',
    'partitions',
    'real',
    'refresh',
    'regexp',
    'rename',
    'replace',
    'returns',
    'right',
    'row',
    'schema',
    'schemas',
    'select',
    'set',
    'show',
    'stats',
    'stored',
    'string',
    'symbol',
    'table',
    'tables',
    'then',
    'to',
    'union',
    'use',
    'using',
    'values',
    'view',
    'when',
    'where',
    'with'
})


def quote_identifier(name, quotechar='`', force=False):
    if force or name.count(' ') or name in _identifiers:
        return '{0}{1}{0}'.format(quotechar, name)
    else:
        return name
