<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''It contains the builders of addational SQL statements.

.. deprecated:: 0.1.6
    Use :mod:`mosql.common` instead. It will be removed after 0.2.
'''

__all__ = ['or_', 'join', 'join_tmpl', 'natural', 'left', 'right', 'inner', 'cross']

from .util import ___, dumps, SQLTemplate

join_tmpl = SQLTemplate(
    ('<type>', ),
    ('join'  , '<table>'),
    ('on'    , '<on>'),
    ('using' , '<using>'),
)
'''The template for :py:func:`mosql.ext.join`.'''

def join(table, on=None, using=None, type=None, **fields):
    '''It is a shortcut for the SQL statement, ``join ...`` .

    :param type: It can be 'cross', 'natural', 'inner', 'left' or 'right'.
    :type type: str
    :rtype: str

    Without giving ``type``, it determines type automatically. It uses `left` join by default:

    >>> print join('another', 'table.c1 = another.c1')
    LEFT JOIN another ON table.c1 = another.c1

    >>> print join('another', ('table.c1 = another.c1', 'table.c2 = another.c2'))
    LEFT JOIN another ON table.c1 = another.c1 AND table.c2 = another.c2

    >>> print join('table', using='c1')
    LEFT JOIN table USING (c1)

    >>> print join('table', using=('c1', 'c2'))
    LEFT JOIN table USING (c1, c2)

    But if you give ``table`` only, it will switch to `natural` join.

    >>> print join('table')
    NATURAL JOIN table

    All of the fields:

    >>> print join_tmpl
    SQLTemplate(('<type>',), ('join', '<table>'), ('on', '<on>'), ('using', '<using>'))

    .. seealso::
        :py:func:`mosql.ext.cross`, :py:func:`mosql.ext.natural`, :py:func:`mosql.ext.inner`, :py:func:`mosql.ext.left` and :py:func:`mosql.ext.right`

    '''

    fields['table'] = table

    if on:
        fields['on'] = on
    if using:
        fields['using'] = using

    if type:
        fields['type'] = type
    else:
        if on or using:
            fields['type'] = 'left'
        else:
            fields['type'] = 'natural'

    return join_tmpl.format_from_dict(fields)

def cross(table):
    '''It is a shortcut for the SQL statement, ``cross join ...`` .

    :rtype: str

    >>> print cross('table')
    CROSS JOIN table
    '''
    return join(table, type='cross')

def natural(table):
    '''It is a shortcut for the SQL statement, ``natural join ...`` .

    :rtype: str

    >>> print natural('table')
    NATURAL JOIN table
    '''
    return join(table, type='natural')

def inner(table, on=None, using=None):
    '''It is a shortcut for the SQL statement, ``inner join ...`` .

    :rtype: str

    >>> print inner('table', using='c1')
    INNER JOIN table USING (c1)
    '''
    return join(table, type='inner', on=on, using=using)

def left(table, on=None, using=None):
    '''It is a shortcut for the SQL statement, ``left join ...`` .

    :rtype: str

    >>> print left('table', using='c1')
    LEFT JOIN table USING (c1)
    '''
    return join(table, type='left', on=on, using=using)

def right(table, on=None, using=None):
    '''It is a shortcut for the SQL statement, ``right join ...`` .

    :rtype: str

    >>> print right('table', using='c1')
    RIGHT JOIN table USING (c1)
    '''
    return join(table, type='right', on=on, using=using)

def or_(*x, **format_spec):
    '''Concat expressions by operator, `OR`.

    :rtype: str

    The exmaples:

    >>> print or_("x = 'a'", 'y > 1')
    (x = 'a') OR (y > 1)

    >>> print or_({'x': 'a'}, {'y >': 1})
    (x = 'a') OR (y > 1)

    >>> str_exp = dumps({'x': 'a', 'y': 'b'}, condition=True)
    >>> print or_(str_exp, {'z': 'c', 't >': 0})
    (y = 'b' AND x = 'a') OR (t > 0 AND z = 'c')
    '''

    return ' OR '.join('(%s)' % dumps(i, condition=True, **format_spec) for i in x)

if __name__ == '__main__':
    import doctest<commit_msg>ensured the backward compatibility of ext.py<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''It contains the builders of addational SQL statements.

.. deprecated:: 0.1.6
    Use :mod:`mosql.common` instead. It will be removed after 0.2.
'''

__all__ = ['or_', 'natural', 'left', 'right', 'inner', 'cross']

from .util import concat_by_or, build_where
from .common import join

def cross(table):
    '''It is a shortcut for the SQL statement, ``cross join ...`` .

    :rtype: str

    >>> print cross('table')
    CROSS JOIN "table"
    '''
    return join(table, type='cross')

def natural(table):
    '''It is a shortcut for the SQL statement, ``natural join ...`` .

    :rtype: str

    >>> print natural('table')
    NATURAL JOIN "table"
    '''
    return join(table, type='natural')

def inner(table, on=None, using=None):
    '''It is a shortcut for the SQL statement, ``inner join ...`` .

    :rtype: str

    >>> print inner('table', using='c1')
    INNER JOIN "table" USING ("c1")
    '''
    return join(table, type='inner', on=on, using=using)

def left(table, on=None, using=None):
    '''It is a shortcut for the SQL statement, ``left join ...`` .

    :rtype: str

    >>> print left('table', using='c1')
    LEFT JOIN "table" USING ("c1")
    '''
    return join(table, type='left', on=on, using=using)

def right(table, on=None, using=None):
    '''It is a shortcut for the SQL statement, ``right join ...`` .

    :rtype: str

    >>> print right('table', using='c1')
    RIGHT JOIN "table" USING ("c1")
    '''
    return join(table, type='right', on=on, using=using)

def or_(*x, **format_spec):
    '''Concat expressions by operator, `OR`.

    :rtype: str

    The exmaples:

    >>> print or_("\\"x\\" = 'a'", '"y" > 1')
    ("x" = 'a') OR ("y" > 1)

    >>> print or_({'x': 'a'}, {'y >': 1})
    ("x" = 'a') OR ("y" > 1)

    >>> str_exp = build_where({'x': 'a', 'y': 'b'})
    >>> print or_(str_exp, {'z': 'c', 't >': 0})
    ("y" = 'b' AND "x" = 'a') OR ("t" > 0 AND "z" = 'c')
    '''

    return concat_by_or('(%s)' % build_where(i) for i in x)

if __name__ == '__main__':
    import doctest
{'fraction_non_alphanumeric': 0.20152155536770922, 'fraction_numerical': 0.009129332206255282, 'mean_word_length': 2.925680159256802, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3975884', 'n_tokens_mistral': 2153, 'n_tokens_neox': 2041, 'n_words': 641}