Skip to content

Commit

Permalink
Merge pull request #32 from thombashi/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
thombashi authored Jul 3, 2016
2 parents e4084ad + 3f68f2a commit 8fe11d5
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 41 deletions.
15 changes: 11 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ Create a table from data matrix

.. code:: python
import json
from simplesqlite import SimpleSQLite
import six
con = SimpleSQLite("sample.sqlite", "w")
table_name = "sample_table"
con = SimpleSQLite("sample.sqlite", "w")
# create table -----
data_matrix = [
Expand All @@ -54,7 +55,7 @@ Create a table from data matrix
[3, 3.3, "ccc", 3, "ccc"],
]
con.create_table_with_data(
table_name="sample_table",
table_name,
attribute_name_list=["attr_a", "attr_b", "attr_c", "attr_d", "attr_e"],
data_matrix=data_matrix)
Expand All @@ -65,7 +66,7 @@ Create a table from data matrix
six.print_(record)
# display data type for each column in the table -----
six.print_(con.get_attribute_type_list(table_name))
six.print_(json.dumps(con.get_attr_type(table_name), indent=4))
.. code::
Expand All @@ -74,7 +75,13 @@ Create a table from data matrix
(1, 1.1, u'aaa', 1.0, u'1')
(2, 2.2, u'bbb', 2.2, u'2.2')
(3, 3.3, u'ccc', 3.0, u'ccc')
(u'integer', u'real', u'text', u'real', u'text')
{
"attr_b": " REAL",
"attr_c": " TEXT",
"attr_a": " INTEGER",
"attr_d": " REAL",
"attr_e": " TEXT"
}
Insert records into a table
---------------------------
Expand Down
15 changes: 11 additions & 4 deletions docs/pages/examples/create_table_from_data_matrix.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
.. code-block:: python
:caption: Sample code

import json
from simplesqlite import SimpleSQLite
import six

con = SimpleSQLite("sample.sqlite", "w")
table_name = "sample_table"
con = SimpleSQLite("sample.sqlite", "w")

# create table -----
data_matrix = [
Expand All @@ -14,7 +15,7 @@
[3, 3.3, "ccc", 3, "ccc"],
]
con.create_table_with_data(
table_name="sample_table",
table_name,
attribute_name_list=["attr_a", "attr_b", "attr_c", "attr_d", "attr_e"],
data_matrix=data_matrix)

Expand All @@ -25,7 +26,7 @@
six.print_(record)

# display data type for each column in the table -----
six.print_(con.get_attribute_type_list(table_name))
six.print_(json.dumps(con.get_attr_type(table_name), indent=4))


.. code-block:: none
Expand All @@ -35,4 +36,10 @@
(1, 1.1, u'aaa', 1.0, u'1')
(2, 2.2, u'bbb', 2.2, u'2.2')
(3, 3.3, u'ccc', 3.0, u'ccc')
(u'integer', u'real', u'text', u'real', u'text')
{
"attr_b": " REAL",
"attr_c": " TEXT",
"attr_a": " INTEGER",
"attr_d": " REAL",
"attr_e": " TEXT"
}
2 changes: 1 addition & 1 deletion requirements/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DataProperty>=0.4.0
DataProperty>=0.4.1
jsonschema
pathvalidate>=0.4.2
path.py
Expand Down
4 changes: 2 additions & 2 deletions sample/create_table/sample_create_table_nested_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
# encoding: utf-8


import json
from simplesqlite import SimpleSQLite
import six


table_name = "sample_table"
con = SimpleSQLite("sample.sqlite", "w")

Expand All @@ -27,4 +27,4 @@
six.print_(record)

# display data type for each column in the table -----
six.print_(con.get_attribute_type_list(table_name))
six.print_(json.dumps(con.get_attr_type(table_name), indent=4))
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

setuptools.setup(
name="SimpleSQLite",
version="0.3.6",
version="0.4.0",
url="https://github.com/thombashi/SimpleSQLite",
bugtrack_url="https://github.com/thombashi/SimpleSQLite/issues",

Expand Down
56 changes: 54 additions & 2 deletions simplesqlite/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,33 @@ def get_attribute_name_list(self, table_name):

return self.__get_list_from_fetch(result.description)

def get_attr_type(self, table_name):
"""
:return:
Dictionary of attribute names and attribute types in the table.
:rtype: dict
:raises simplesqlite.NullDatabaseConnectionError:
|raises_check_connection|
:raises simplesqlite.TableNotFoundError:
|raises_verify_table_existence|
:raises sqlite3.OperationalError: |raises_operational_error|
"""

import re

self.verify_table_existence(table_name)

result = self.execute_query(
"SELECT sql FROM sqlite_master WHERE type='table' and name=%s" % (
SqlQuery.to_value_str(table_name)))
query = result.fetchone()[0]
match = re.search("[(].*[)]", query)

return dict([
item.split("'")[1:]
for item in match.group().strip("()").split(", ")
])

def get_attribute_type_list(self, table_name):
"""
:return: List of attribute names in the table.
Expand All @@ -490,6 +517,11 @@ def get_attribute_type_list(self, table_name):
:raises simplesqlite.TableNotFoundError:
|raises_verify_table_existence|
:raises sqlite3.OperationalError: |raises_operational_error|
.. warning::
This method will be deleted in the future.
Use :py:meth:`.get_attr_type` instead.
"""

self.verify_table_existence(table_name)
Expand All @@ -504,6 +536,17 @@ def get_attribute_type_list(self, table_name):

return result.fetchone()

def get_num_records(self, table_name, where=None):
"""
:param str table_name: Table name to get records.
:param str where: Where clause of the query.
:return: Number of records in the table.
:rtype: int
"""

return self.get_value(
select="COUNT(*)", table_name=table_name, where=where)

def get_profile(self, profile_count=50):
"""
Get profile of query execution time.
Expand Down Expand Up @@ -925,6 +968,12 @@ def create_index_list(self, table_name, attribute_name_list):
for attribute in list(table_attr_set.intersection(index_attr_set)):
self.create_index(table_name, attribute)

def __sanitize_attr_name_list(self, attr_name_list):
return [
SqlQuery.sanitize_attr(attr_name)
for attr_name in attr_name_list
]

def create_table_with_data(
self, table_name, attribute_name_list, data_matrix,
index_attribute_list=()):
Expand Down Expand Up @@ -960,9 +1009,12 @@ def create_table_with_data(

self.create_table(
table_name,
self.__get_attr_desc_list(attribute_name_list, data_matrix))
self.__get_attr_desc_list(
self.__sanitize_attr_name_list(attribute_name_list),
data_matrix))
self.insert_many(table_name, data_matrix)
self.create_index_list(table_name, index_attribute_list)
self.create_index_list(
table_name, self.__sanitize_attr_name_list(index_attribute_list))
self.commit()

def create_table_from_tabledata(self, tabledata):
Expand Down
17 changes: 12 additions & 5 deletions simplesqlite/sqlquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ class SqlQuery:

__RE_SANITIZE = re.compile(
"[%s]" % (re.escape("%/()[]<>.:;'\"!\# -+=\n\r")))
__RE_SANITIZE_ATTR = re.compile("[%s]" % (re.escape("'\"")))
__RE_TABLE_STR = re.compile("[%s]" % (re.escape("%()-+/.")))
__RE_BRACKET = re.compile("[%s]" % (re.escape("[]")))
__RE_TO_ATTR_STR = re.compile("[%s0-9\s#]" % (re.escape("%()-+/.'\"")))
__RE_TO_ATTR_QUOTE = re.compile("[%s]" % (re.escape("[_]")))
__RE_TO_ATTR_BRACKET = re.compile("[%s0-9\s#]" % (re.escape("%()-+/.'\"")))
__RE_SPACE = re.compile("[\s]+")

__VALID_WHERE_OPERATION_LIST = [
Expand Down Expand Up @@ -56,6 +57,10 @@ def sanitize(cls, query_item):

return cls.__RE_SANITIZE.sub("", query_item)

@classmethod
def sanitize_attr(cls, query_item):
return cls.__RE_SANITIZE_ATTR.sub("_", query_item)

@classmethod
def to_table_str(cls, name):
"""
Expand Down Expand Up @@ -102,9 +107,11 @@ def to_attr_str(cls, name, operation_query=""):
'SUM(key)'
"""

if cls.__RE_BRACKET.search(name):
name = cls.sanitize_attr(name)

if cls.__RE_TO_ATTR_QUOTE.search(name):
sql_name = '"%s"' % (name)
elif cls.__RE_TO_ATTR_STR.search(name):
elif cls.__RE_TO_ATTR_BRACKET.search(name):
sql_name = "[%s]" % (name)
elif name == "join":
sql_name = "[%s]" % (name)
Expand Down Expand Up @@ -141,7 +148,7 @@ def to_attr_str_list(cls, name_list, operation_query=""):
"""

if dataproperty.is_empty_string(operation_query):
return map(cls.to_attr_str, name_list)
return list(map(cls.to_attr_str, name_list))

return [
"%s(%s)" % (operation_query, cls.to_attr_str(name))
Expand Down
65 changes: 46 additions & 19 deletions test/test_simplesqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
.. codeauthor:: Tsuyoshi Hombashi <gogogo.vm@gmail.com>
"""

import datetime
import itertools
import sqlite3

Expand Down Expand Up @@ -296,11 +297,9 @@ class Test_SimpleSQLite_insert:
[NamedTupleEx(5, 6, 7), (5, 6)]
])
def test_normal(self, con, value, expeted):
assert con.get_value(
select="COUNT(*)", table_name=TEST_TABLE_NAME) == 2
assert con.get_num_records(TEST_TABLE_NAME) == 2
con.insert(TEST_TABLE_NAME, insert_record=value)
assert con.get_value(
select="COUNT(*)", table_name=TEST_TABLE_NAME) == 3
assert con.get_num_records(TEST_TABLE_NAME) == 3
result = con.select(select="*", table_name=TEST_TABLE_NAME)
result_tuple = result.fetchall()[2]
assert result_tuple == expeted
Expand All @@ -309,11 +308,9 @@ def test_normal(self, con, value, expeted):
[[5, 6.6, "c"], (5, 6.6, "c")],
])
def test_mix(self, con_mix, value, expeted):
assert con_mix.get_value(
select="COUNT(*)", table_name=TEST_TABLE_NAME) == 2
assert con_mix.get_num_records(TEST_TABLE_NAME) == 2
con_mix.insert(TEST_TABLE_NAME, insert_record=value)
assert con_mix.get_value(
select="COUNT(*)", table_name=TEST_TABLE_NAME) == 3
assert con_mix.get_num_records(TEST_TABLE_NAME) == 3
result = con_mix.select(select="*", table_name=TEST_TABLE_NAME)
result_tuple = result.fetchall()[2]
assert result_tuple == expeted
Expand Down Expand Up @@ -372,11 +369,9 @@ def test_normal(self, con, table_name, value):
(11, 12),
]

assert con.get_value(
select="COUNT(*)", table_name=TEST_TABLE_NAME) == 2
assert con.get_num_records(TEST_TABLE_NAME) == 2
con.insert_many(TEST_TABLE_NAME, value)
assert con.get_value(
select="COUNT(*)", table_name=TEST_TABLE_NAME) == 5
assert con.get_num_records(TEST_TABLE_NAME) == 5
result = con.select(select="*", table_name=TEST_TABLE_NAME)
result_tuple = result.fetchall()[2:]
assert result_tuple == expected
Expand Down Expand Up @@ -667,9 +662,13 @@ def test_null(self, con_null):


class Test_SimpleSQLite_create_table_with_data:
DATATIME_DATA = datetime.datetime(2017, 1, 1, 0, 0, 0)

@pytest.mark.parametrize(
["attr_name_list", "data_matrix", "index_attr_list"],
[
"attr_name_list", "data_matrix",
"index_attr_list", "expected_attr",
],
[
[
["attr_a", "attr_b", "attr_c"],
Expand All @@ -679,6 +678,11 @@ class Test_SimpleSQLite_create_table_with_data:
[3, 120.9, "ccc"],
],
["attr_a"],
{
u'attr_a': u' INTEGER',
u'attr_b': u' REAL',
u'attr_c': u' TEXT',
},
],
[
["attr_a", "attr_b", "attr_c"],
Expand All @@ -692,20 +696,42 @@ class Test_SimpleSQLite_create_table_with_data:
"attr_a", "attr_b", "attr_c",
"not_exist_attr_1",
],
{
u'attr_a': u' INTEGER',
u'attr_b': u' REAL',
u'attr_c': u' TEXT',
},
],
[
["attr'a", 'attr"b', "attr'c[%]", "attr($)"],
[
[1, 4, "a", None],
[2, 2.1, "bb", None],
[2, 2.1, "bb", None],
"attr'a", 'attr"b', "attr'c[%]", "attr($)",
"attr inf", "attr nan", "attr-f", "attr dt",
],
[
[1, 4, "a", None, inf, nan, 0, DATATIME_DATA],
[2, 2.1, "bb", None, inf, nan, inf, DATATIME_DATA],
[2, 2.1, "bb", None, inf, nan, nan, DATATIME_DATA],
],
[
"attr'a", 'attr"b', "attr'c[%]", "attr($)",
"attr inf", "attr nan", "attr-f", "attr dt",
],
["attr'a", 'attr"b', "attr[%]"],
{
u'attr_a': u' INTEGER',
u'attr_c[%]': u' TEXT',
u'attr_b': u' REAL',
u'attr($)': u' TEXT',
u'attr inf': u' TEXT',
u'attr nan': u' TEXT',
u'attr-f': u' REAL',
u'attr dt': u' TEXT',
},
],
]
)
def test_normal(
self, tmpdir, attr_name_list, data_matrix, index_attr_list):
self, tmpdir, attr_name_list, data_matrix, index_attr_list,
expected_attr):
p = tmpdir.join("tmp.db")
con = SimpleSQLite(str(p), "w")
table_name = TEST_TABLE_NAME
Expand All @@ -720,6 +746,7 @@ def test_normal(
table_name=table_name)
result_matrix = result.fetchall()
assert len(result_matrix) == 3
assert con.get_attr_type(table_name) == expected_attr

def test_null(self, con_null):
with pytest.raises(NullDatabaseConnectionError):
Expand Down
Loading

0 comments on commit 8fe11d5

Please sign in to comment.