Source code for simplesqlite.sqlquery

# encoding: utf-8

"""
.. codeauthor:: Tsuyoshi Hombashi <gogogo.vm@gmail.com>
"""


from __future__ import absolute_import
import re

import dataproperty
import six
from six.moves import map

import simplesqlite as sql


[docs]class SqlQuery: """ Support class for making SQLite query. """ __RE_SANITIZE = re.compile("[%s]" % (re.escape("%/()[]<>.:;'!\# -+=\n\r"))) __RE_TABLE_STR = re.compile("[%s]" % (re.escape("%()-+/."))) __RE_TO_ATTR_STR = re.compile("[%s0-9\s#]" % (re.escape("[%()-+/.]"))) __RE_SPACE = re.compile("[\s]+") __VALID_WHERE_OPERATION_LIST = [ "=", "==", "!=", "<>", ">", ">=", "<", "<=", ] @classmethod
[docs] def sanitize(cls, query_item): """ Sanitize SQLite query with an empty char. :param str query_item: String to be sanitized. :return: String that exclude invalid chars. Invalid operators are as follows: ``"%"``, ``"/"``, ``"("``, ``")"``, ``"["``, ``"]"``, ``"<"``, ``">"``, ``"."``, ``":"``, ``";"``, ``"'"``, ``"!"``, ``"\"``, ``"#"``, ``"-"``, ``"+"``, ``"="``, ``"\\n"``, ``"\\r"`` :rtype: str :Examples: >>> from simplesqlite.sqlquery import SqlQuery >>> SqlQuery.sanitize("k<e:y") 'key' """ return cls.__RE_SANITIZE.sub("", query_item)
@classmethod
[docs] def to_table_str(cls, name): """ :param str name: Table name. :return: String that suitable for table name of a SQLite query. :rtype: str :Examples: >>> from simplesqlite.sqlquery import SqlQuery >>> SqlQuery.to_table_str("length") 'length' >>> SqlQuery.to_table_str("length(cm)") '[length(cm)]' >>> SqlQuery.to_table_str("string length") "'string length'" """ if cls.__RE_TABLE_STR.search(name): return "[%s]" % (name) if cls.__RE_SPACE.search(name): return "'%s'" % (name) return name
@classmethod
[docs] def to_attr_str(cls, name, operation_query=""): """ :param str name: Attribute name. :param str operation_query: Used as a SQLite function if the value is not empty. :return: String that suitable for attribute name of a SQLite query. :rtype: str :Examples: >>> from simplesqlite.sqlquery import SqlQuery >>> SqlQuery.to_attr_str("key") 'key' >>> SqlQuery.to_attr_str("a+b") '[a+b]' >>> SqlQuery.to_attr_str("key", operation_query="SUM") 'SUM(key)' """ if cls.__RE_TO_ATTR_STR.search(name): sql_name = "[%s]" % (name) elif name == "join": sql_name = "[%s]" % (name) else: sql_name = name if dataproperty.is_not_empty_string(operation_query): sql_name = "%s(%s)" % (operation_query, sql_name) return sql_name
@classmethod
[docs] def to_attr_str_list(cls, name_list, operation_query=""): """ :param list/tuple name_list: List of attribute names. :param str operation_query: Used as a SQLite function if the value is not empty. :return: List of strings that suitable for attribute names of a SQLite query. :rtype: list/itertools.imap :Examples: >>> from simplesqlite.sqlquery import SqlQuery >>> list(SqlQuery.to_attr_str_list(["key", "a+b"])) ['key', '[a+b]'] >>> SqlQuery.to_attr_str_list(["key", "a+b"], operation_query="AVG") ['AVG(key)', 'AVG([a+b])'] .. seealso:: :py:meth:`.to_attr_str` """ if dataproperty.is_empty_string(operation_query): return map(cls.to_attr_str, name_list) return [ "%s(%s)" % (operation_query, cls.to_attr_str(name)) for name in name_list ]
@classmethod
[docs] def to_value_str(cls, value): """ :param str value: Value associated with a key. :return: String that suitable for a value of a key. Return ``"NULL"`` if the value is |None|. :rtype: str :Examples: >>> from simplesqlite.sqlquery import SqlQuery >>> SqlQuery.to_value_str(1.2) '1.2' >>> SqlQuery.to_value_str("value") "'value'" >>> SqlQuery.to_value_str(None) 'NULL' """ if value is None: return "NULL" if dataproperty.is_integer(value) or dataproperty.is_float(value): return str(value) return "'%s'" % (value)
@classmethod
[docs] def to_value_str_list(cls, value_list): """ :param list value_list: List of values associated with a key. :return: List of values that executed ``to_value_str`` method for each item. :rtype: itertools.imap :Examples: >>> from simplesqlite.sqlquery import SqlQuery >>> list(SqlQuery.to_value_str_list([1, "a", None])) ['1', "'a'", 'NULL'] .. seealso:: :py:meth:`.to_value_str` """ return map(cls.to_value_str, value_list)
@classmethod
[docs] def make_select(cls, select, table, where=None, extra=None): """ Make SELECT query. :param str select: Attribute for SELECT query. :param str table: Table name of executing the query. :param str where: Add a WHERE clause to execute query, if the value is not |None|. :param extra extra: Add additional clause to execute query, if the value is not |None|. :return: Query of SQLite. :rtype: str :raises ValueError: ``select`` is empty string. :raises ValueError: |raises_validate_table_name| :Examples: >>> from simplesqlite.sqlquery import SqlQuery >>> SqlQuery.make_select(select="value", table="example") 'SELECT value FROM example' >>> SqlQuery.make_select(select="value", table="example", where=SqlQuery.make_where("key", 1)) 'SELECT value FROM example WHERE key = 1' >>> SqlQuery.make_select(select="value", table="example", where=SqlQuery.make_where("key", 1), extra="ORDER BY value") 'SELECT value FROM example WHERE key = 1 ORDER BY value' """ sql.validate_table_name(table) if dataproperty.is_empty_string(select): raise ValueError("SELECT query is null") query_list = [ "SELECT " + select, "FROM " + cls.to_table_str(table), ] if dataproperty.is_not_empty_string(where): query_list.append("WHERE " + where) if dataproperty.is_not_empty_string(extra): query_list.append(extra) return " ".join(query_list)
@classmethod
[docs] def make_insert(cls, table, insert_tuple, is_insert_many=False): """ Make INSERT query. :param str table: Table name of executing the query. :param list/tuple insert_tuple: Insertion data. :param bool is_insert_many: Make query that insert multiple data at once, if the value is |True|. :return: Query of SQLite. :rtype: str :raises ValueError: If ``insert_tuple`` is empty |list|/|tuple|. :raises ValueError: |raises_validate_table_name| """ sql.validate_table_name(table) table = cls.to_table_str(table) if dataproperty.is_empty_list_or_tuple(insert_tuple): raise ValueError("empty insert list/tuple") if is_insert_many: value_list = ['?' for _i in insert_tuple] else: value_list = [ "'%s'" % (value) if isinstance(value, six.string_types) and value != "NULL" else str(value) for value in insert_tuple ] return "INSERT INTO %s VALUES (%s)" % ( table, ",".join(value_list))
@classmethod
[docs] def make_update(cls, table, set_query, where=None): """ Make UPDATE query. :param str table: Table name of executing the query. :param str set_query: SET part of the UPDATE query. :param str where: Add a WHERE clause to execute query, if the value is not |None|. :return: Query of SQLite. :rtype: str :raises ValueError: If ``set_query`` is empty string. :raises ValueError: |raises_validate_table_name| """ sql.validate_table_name(table) if dataproperty.is_empty_string(set_query): raise ValueError("SET query is null") query_list = [ "UPDATE " + cls.to_table_str(table), "SET " + set_query, ] if dataproperty.is_not_empty_string(where): query_list.append("WHERE " + where) return " ".join(query_list)
@classmethod
[docs] def make_where(cls, key, value, operation="="): """ Make part of WHERE query. :param str key: Attribute name of the key. :param str value: Value of the right hand side associated with the key. :param str operation: Operator of WHERE query. :return: Part of WHERE query of SQLite. :rtype: str :raises ValueError: If ``operation`` is invalid operator. Valid operators are as follows: ``"="``, ``"=="``, ``"!="``, ``"<>"``, ``">"``, ``">="``, ``"<"``, ``"<="`` :Examples: >>> from simplesqlite.sqlquery import SqlQuery >>> SqlQuery.make_where("key", "hoge") "key = 'hoge'" >>> SqlQuery.make_where("value", 1, operation=">") 'value > 1' """ if operation not in cls.__VALID_WHERE_OPERATION_LIST: raise ValueError("operation not supported: " + str(operation)) return "%s %s %s" % ( cls.to_attr_str(key), operation, cls.to_value_str(value))
@classmethod
[docs] def make_where_in(cls, key, value_list): """ Make part of WHERE IN query. :param str key: Attribute name of the key. :param str value_list: List of values that the right hand side associated with the key. :return: Part of WHERE query of SQLite. :rtype: str :Examples: >>> from simplesqlite.sqlquery import SqlQuery >>> SqlQuery.make_where_in("key", ["hoge", "foo", "bar"]) "key IN ('hoge', 'foo', 'bar')" """ return "%s IN (%s)" % ( cls.to_attr_str(key), ", ".join(cls.to_value_str_list(value_list)))
@classmethod
[docs] def make_where_not_in(cls, key, value_list): """ Make part of WHERE NOT IN query. :param str key: Attribute name of the key. :param str value_list: List of values that the right hand side associated with the key. :return: Part of WHERE query of SQLite. :rtype: str :Examples: >>> from simplesqlite.sqlquery import SqlQuery >>> SqlQuery.make_where_not_in("key", ["hoge", "foo", "bar"]) "key NOT IN ('hoge', 'foo', 'bar')" """ return "%s NOT IN (%s)" % ( cls.to_attr_str(key), ", ".join(cls.to_value_str_list(value_list)))