Skip to content

Commit

Permalink
v1.0.0 changes
Browse files Browse the repository at this point in the history
1. Include lastrowdid in the response if available
2. Include rowcount in the response if available
3. Changed the key `row_count` -> `rowcount` to be inline with SQLite terminology
4. Removed unncessary list comprehension when generating a resultset.Now, we simply use `list`
5. Minor code formatting changes for better readability
  • Loading branch information
Abhishek Singh committed Dec 31, 2020
1 parent 2968a65 commit cc60ec6
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 40 deletions.
3 changes: 3 additions & 0 deletions .dockerignore
Expand Up @@ -11,3 +11,6 @@ docker_examples
.coverage
.pytest_cache
.coverage
sqlite_demo.py
example.db
venv/
5 changes: 4 additions & 1 deletion .gitignore
Expand Up @@ -7,4 +7,7 @@ build/
dist/
.coverage
.pytest_cache
.coverage
.coverage
sqlite_demo.py
example.db
venv/
4 changes: 3 additions & 1 deletion .travis.yml
Expand Up @@ -8,7 +8,9 @@ matrix:
- os: linux
python: 3.8
- os: linux
python: pypy3
python: 3.9
- os: linux
python: pypy3.6-7.1.1
install:
- pip install --upgrade pip
- pip install pytest coverage coveralls
Expand Down
39 changes: 20 additions & 19 deletions README.md
@@ -1,12 +1,13 @@
# sqlite_rx [![Travis](https://travis-ci.org/aosingh/sqlite_rx.svg?branch=master)](https://travis-ci.org/aosingh/sqlite_rx) [![PyPI version](https://badge.fury.io/py/sqlite-rx.svg)](https://pypi.python.org/pypi/sqlite-rx) [![Coverage Status](https://coveralls.io/repos/github/aosingh/sqlite_rx/badge.svg?branch=master)](https://coveralls.io/github/aosingh/sqlite_rx?branch=master)
# sqlite_rx [![Downloads](https://pepy.tech/badge/sqlite-rx)](https://pepy.tech/project/sqlite-rx) [![Travis](https://travis-ci.org/aosingh/sqlite_rx.svg?branch=master)](https://travis-ci.org/aosingh/sqlite_rx) [![PyPI version](https://badge.fury.io/py/sqlite-rx.svg)](https://pypi.python.org/pypi/sqlite-rx) [![Coverage Status](https://coveralls.io/repos/github/aosingh/sqlite_rx/badge.svg?branch=master)](https://coveralls.io/github/aosingh/sqlite_rx?branch=master)
[![Python 3.6](https://img.shields.io/badge/python-3.6-blue.svg)]((https://www.python.org/downloads/release/python-370/)) [![Python 3.7](https://img.shields.io/badge/python-3.7-blue.svg)](https://www.python.org/downloads/release/python-370/) [![Python 3.8](https://img.shields.io/badge/python-3.8-blue.svg)](https://www.python.org/downloads/release/python-380/)
[![Python 3.9](https://img.shields.io/badge/python-3.9-blue.svg)]((https://www.python.org/downloads/release/python-390/))
[![PyPy3](https://img.shields.io/badge/python-PyPy3-blue.svg)](https://www.pypy.org/index.html)
## Background

[SQLite](https://www.sqlite.org/index.html) is a lightweight database written in C.
The Python programming language has in-built support to interact with the database(locally) which is either stored on disk or in memory.

## Introducing sqlite_rx (SQLite remote execution)
## Introducing sqlite_rx - SQLite remote query execution
With `sqlite_rx`, clients should be able to communicate with an `SQLiteServer` in a fast, simple and secure manner and execute queries remotely.

Key Features
Expand Down Expand Up @@ -98,20 +99,6 @@ logging.config.dictConfig(get_default_logger_settings(logging.DEBUG))
client = SQLiteClient(connect_address="tcp://127.0.0.1:5000")
```

### SELECT statement: (Table not present)
```python
from pprint import pprint
result = client.execute("SELECT * FROM IDOLS")
pprint(result)

```
OUTPUT
```text
{'error': {'message': 'sqlite3.OperationalError: no such table: IDOLS',
'type': 'sqlite3.OperationalError'},
'items': []}
```

### CREATE TABLE statement

```python
Expand Down Expand Up @@ -164,7 +151,7 @@ pprint(result)
OUTPUT

```text
{'error': None, 'items': [], 'row_count': 27}
{'error': None, 'items': [], 'rowcount': 27}
```

### SELECT with WHERE clause
Expand All @@ -188,7 +175,7 @@ OUTPUT
['2006-03-28', 'BUY', 'IBM', 1000.0, 45.0]]}
```

### Execute a SCRIPT
### Execute an SQL script

```python
script = '''CREATE TABLE users(id INTEGER PRIMARY KEY, name TEXT, phone TEXT);
Expand Down Expand Up @@ -221,7 +208,7 @@ OUTPUT
```


### DROP a TABLE
### DROP a Table

Note: In the default authorization setting, a client is not allowed to drop any table.

Expand All @@ -238,6 +225,20 @@ OUTPUT
'items': []}
```

### SELECT statement; Table not present
```python
from pprint import pprint
result = client.execute("SELECT * FROM IDOLS")
pprint(result)

```
OUTPUT
```text
{'error': {'message': 'sqlite3.OperationalError: no such table: IDOLS',
'type': 'sqlite3.OperationalError'},
'items': []}
```

## Generic Default Authorization Policy


Expand Down
2 changes: 1 addition & 1 deletion sqlite_rx/__init__.py
@@ -1,4 +1,4 @@
__version__ = "0.9.99"
__version__ = "1.0.0"
__author__ = "Abhishek Singh"
__authoremail__ = "aosingh@asu.edu"

Expand Down
26 changes: 12 additions & 14 deletions sqlite_rx/server.py
Expand Up @@ -79,16 +79,12 @@ def stream(self,

if use_encryption or use_zap:

server_curve_id = server_curve_id if server_curve_id else "id_server_{}_curve".format(
socket.gethostname())
keymonkey = KeyMonkey(
key_id=server_curve_id,
destination_dir=curve_dir)
server_curve_id = server_curve_id if server_curve_id else "id_server_{}_curve".format(socket.gethostname())
keymonkey = KeyMonkey(key_id=server_curve_id, destination_dir=curve_dir)

if use_encryption:
LOG.info("Setting up encryption using CurveCP")
self.socket = keymonkey.setup_secure_server(
self.socket, address)
self.socket = keymonkey.setup_secure_server(self.socket, address)

if use_zap:
if not use_encryption:
Expand Down Expand Up @@ -241,18 +237,20 @@ def execute(self, message: dict, *args, **kwargs):
"items": [],
"error": error
}
if self._cursor.rowcount > -1:
result['row_count'] = self._cursor.rowcount

if error:
return zlib.compress(msgpack.dumps(result))

if self._cursor.lastrowid:
result['lastrowid'] = self._cursor.lastrowid

try:
result['items'] = [row for row in self._cursor.fetchall()]
result['items'] = list(self._cursor.fetchall())
# If rowcount attribute is set on the cursor object include it in the response
if self._cursor.rowcount > -1:
result['rowcount'] = self._cursor.rowcount
# If lastrowid attribute is set on the cursor include it in the response
if self._cursor.lastrowid:
result['lastrowid'] = self._cursor.lastrowid

return zlib.compress(msgpack.dumps(result))

except Exception:
LOG.exception("Exception while collecting rows")
result['error'] = self.capture_exception()
Expand Down
1 change: 1 addition & 0 deletions sqlite_rx/tests/curezmq/conftest.py
Expand Up @@ -17,6 +17,7 @@

LOG = logging.getLogger(__file__)


@pytest.fixture(scope="module")
def curvezmq_client():
with get_server_auth_files() as auth_files:
Expand Down
2 changes: 1 addition & 1 deletion sqlite_rx/tests/curezmq/test_queries.py
Expand Up @@ -54,6 +54,6 @@ def test_table_rows_insertion(curvezmq_client):
]

result = curvezmq_client.execute('INSERT INTO stocks VALUES (?,?,?,?,?)', *purchases, execute_many=True)
expected_result = {'error': None, 'items': [], 'row_count': 27}
expected_result = {'error': None, 'items': [], 'rowcount': 27}
assert result == expected_result

80 changes: 78 additions & 2 deletions sqlite_rx/tests/plain/test_queries.py
Expand Up @@ -36,7 +36,7 @@ def test_table_rows_insertion(plain_client):
]

result = plain_client.execute('INSERT INTO stocks VALUES (?,?,?,?,?)', *purchases, execute_many=True)
expected_result = {'error': None, 'items': [], 'row_count': 27}
expected_result = {'error': None, 'items': [], 'rowcount': 27}
assert result == expected_result


Expand All @@ -45,13 +45,89 @@ def test_table_not_present(plain_client):
assert type(result) == dict


def test_select_before_update(plain_client):
purchases = [['2006-03-28', 'BUY', 'IBM', 1000, 45.00],
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
]
result = plain_client.execute('SELECT * FROM stocks')
expected_result = {'error': None, 'items': [list(purchase) for purchase in purchases], 'lastrowid': 27}
assert result == expected_result


def test_update(plain_client):
args = ('IBM',)
result = plain_client.execute('UPDATE stocks SET price = 480 where symbol = ?', *args)
expected_result = {'error': None, 'items': [], 'lastrowid': 27, 'rowcount': 9}
assert result == expected_result


def test_select(plain_client):

purchases = [['2006-03-28', 'BUY', 'IBM', 1000, 480.00],
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 480.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 480.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 480.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 480.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 480.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 480.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 480.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
('2006-03-28', 'BUY', 'IBM', 1000, 480.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
]
result = plain_client.execute('SELECT * FROM stocks')
expected_result = {'error': None, 'items': [list(purchase) for purchase in purchases], 'lastrowid': 27}
assert result == expected_result


def test_sql_script(plain_client):
script = '''CREATE TABLE users(id INTEGER PRIMARY KEY, name TEXT, phone TEXT);
CREATE TABLE accounts(id INTEGER PRIMARY KEY, description TEXT);
INSERT INTO users(name, phone) VALUES ('John', '5557241'),
('Adam', '5547874'), ('Jack', '5484522');'''
expected_result = {"error": None, 'items': []}
expected_result = {"error": None, 'items': [], 'lastrowid': 27}
result = plain_client.execute(script, execute_script=True)
assert expected_result == result

2 changes: 1 addition & 1 deletion sqlite_rx/tests/zap/test_queries.py
Expand Up @@ -53,5 +53,5 @@ def test_table_rows_insertion(zap_client):
('2006-04-06', 'SELL', 'XOM', 500, 53.00),
]
result = zap_client.execute('INSERT INTO stocks VALUES (?,?,?,?,?)', *purchases, execute_many=True)
expected_result = {'error': None, 'items': [], 'row_count': 27}
expected_result = {'error': None, 'items': [], 'rowcount': 27}
assert result == expected_result

0 comments on commit cc60ec6

Please sign in to comment.