Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-py-partiql-parser for
openSUSE:Factory checked in at 2024-02-04 19:09:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-py-partiql-parser (Old)
and /work/SRC/openSUSE:Factory/.python-py-partiql-parser.new.1815 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-py-partiql-parser"
Sun Feb 4 19:09:54 2024 rev:6 rq:1143990 version:0.5.1
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-py-partiql-parser/python-py-partiql-parser.changes
2023-12-28 23:03:39.443253542 +0100
+++
/work/SRC/openSUSE:Factory/.python-py-partiql-parser.new.1815/python-py-partiql-parser.changes
2024-02-04 19:12:22.943485976 +0100
@@ -1,0 +2,9 @@
+Sun Feb 4 11:43:50 UTC 2024 - Dirk Müller <[email protected]>
+
+- update to 0.5.1:
+ * Support INSERT/DELETE/UPDATE queries:
+ * that contain a table name without quotes
+ * that contain parameters
+ * when calling get_query_metadata()
+
+-------------------------------------------------------------------
Old:
----
py-partiql-parser-0.5.0.tar.gz
New:
----
py-partiql-parser-0.5.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-py-partiql-parser.spec ++++++
--- /var/tmp/diff_new_pack.SqXZhf/_old 2024-02-04 19:12:23.339500247 +0100
+++ /var/tmp/diff_new_pack.SqXZhf/_new 2024-02-04 19:12:23.339500247 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-py-partiql-parser
#
-# Copyright (c) 2023 SUSE LLC
+# Copyright (c) 2024 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-py-partiql-parser
-Version: 0.5.0
+Version: 0.5.1
Release: 0
Summary: Pure Python PartiQL Parser
License: MIT
++++++ py-partiql-parser-0.5.0.tar.gz -> py-partiql-parser-0.5.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/py-partiql-parser-0.5.0/CHANGELOG.md
new/py-partiql-parser-0.5.1/CHANGELOG.md
--- old/py-partiql-parser-0.5.0/CHANGELOG.md 2023-12-17 01:06:55.000000000
+0100
+++ new/py-partiql-parser-0.5.1/CHANGELOG.md 2024-02-01 22:30:48.000000000
+0100
@@ -1,6 +1,16 @@
CHANGELOG
=========
+0.5.1
+-----
+
+ - Support INSERT/DELETE/UPDATE queries:
+
+ - that contain a table name without quotes
+ - that contain parameters
+ - when calling get_query_metadata()
+
+
0.5.0
-----
- Improved typing support
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py-partiql-parser-0.5.0/py_partiql_parser/__init__.py
new/py-partiql-parser-0.5.1/py_partiql_parser/__init__.py
--- old/py-partiql-parser-0.5.0/py_partiql_parser/__init__.py 2023-12-17
01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/py_partiql_parser/__init__.py 2024-02-01
22:30:48.000000000 +0100
@@ -1,4 +1,4 @@
-__version__ = "0.5.0"
+__version__ = "0.5.1"
from ._internal.parser import DynamoDBStatementParser, S3SelectParser # noqa
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/delete_parser.py
new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/delete_parser.py
--- old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/delete_parser.py
2023-12-17 01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/delete_parser.py
2024-02-01 22:30:48.000000000 +0100
@@ -48,6 +48,11 @@
assert current_phrase.upper() == "AND"
section = "WHERE"
current_phrase = ""
+ if section == "TABLE_NAME":
+ table_name = current_phrase
+ current_phrase = ""
+ tokenizer.skip_white_space()
+ section = "SECTION_WHERE"
continue
elif c in ["'", '"']:
if section == "TABLE_NAME":
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/insert_parser.py
new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/insert_parser.py
--- old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/insert_parser.py
2023-12-17 01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/insert_parser.py
2024-02-01 22:30:48.000000000 +0100
@@ -41,6 +41,11 @@
attr = JsonParser().parse(tokenizer.give_remaining())
for key, value in attr.items():
attr[key] = serializer.serialize(value)
+ if section == "TABLE_NAME":
+ table_name = current_phrase
+ current_phrase = ""
+ tokenizer.skip_white_space()
+ section = "SECTION_VALUE"
continue
elif c in ["'", '"']:
if section == "TABLE_NAME":
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/parser.py
new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/parser.py
--- old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/parser.py
2023-12-17 01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/parser.py
2024-02-01 22:30:48.000000000 +0100
@@ -2,6 +2,7 @@
from typing import Dict, Any, List, Optional, Tuple
+from ..exceptions import ParserException
from .delete_parser import DeleteParser
from .from_parser import DynamoDBFromParser, S3FromParser, FromParser
from .insert_parser import InsertParser
@@ -86,7 +87,7 @@
return return_data, updates
if query.lower().startswith("update"):
- return self._parse_update(query)
+ return self._parse_update(query, parameters)
if query.lower().startswith("delete"):
return self._parse_delete(query)
@@ -123,11 +124,31 @@
] = {}
return queried_data, updates
- def _parse_update(self, query: str) -> TYPE_RESPONSE:
+ def _parse_update(
+ self, query: str, parameters: Optional[List[Dict[str, Any]]] = None
+ ) -> TYPE_RESPONSE:
query = query.replace("\n", " ")
table_name, attrs_to_update, attrs_to_filter =
UpdateParser().parse(query)
+ parameters_requested = len(
+ [_ for _, val in attrs_to_update + attrs_to_filter if val == "?"]
+ )
+ if parameters_requested and len(parameters) != parameters_requested:
# type: ignore
+ raise ParserException(
+ name="ValidationError",
+ message="Number of parameters in request and statement don't
match.",
+ )
+
+ attrs_to_update = [
+ (key, parameters.pop(0) if val == "?" else val) # type: ignore
+ for key, val in attrs_to_update
+ ]
+ attrs_to_filter = [
+ (key, parameters.pop(0) if val == "?" else val) # type: ignore
+ for key, val in attrs_to_filter
+ ]
+
source_data = self.documents[table_name]
updates_per_table: Dict[
str, List[Tuple[Optional[Dict[str, Any]], Optional[Dict[str,
Any]]]]
@@ -172,15 +193,31 @@
@classmethod
def get_query_metadata(cls, query: str) -> QueryMetadata:
query = query.replace("\n", " ")
- clauses = re.split("SELECT | FROM | WHERE ", query,
flags=re.IGNORECASE)
-
- from_parser = FromParser(clauses[2])
+ if query.lower().startswith("select"):
+ clauses = re.split("SELECT | FROM | WHERE ", query,
flags=re.IGNORECASE)
- # WHERE
- if len(clauses) > 3:
- where_clause = clauses[3]
- where = WhereParser.parse_where_clause(where_clause)
- else:
- where = None
+ from_parser = FromParser(clauses[2])
+ # WHERE
+ if len(clauses) > 3:
+ where_clause = clauses[3]
+ where = WhereParser.parse_where_clause(where_clause)
+ else:
+ where = None
- return QueryMetadata(tables=from_parser.clauses, where_clause=where)
+ return QueryMetadata(
+ tables=from_parser.clauses, where_clause=where,
is_select_query=True
+ )
+ elif query.lower().startswith("update"):
+ table_name, attrs_to_update, attrs_to_filter =
UpdateParser().parse(query)
+ return QueryMetadata(tables={table_name: table_name},
where_clause=None)
+ elif query.lower().startswith("delete"):
+ query = query.replace("\n", " ")
+
+ table_name, attrs_to_filter = DeleteParser().parse(query)
+ return QueryMetadata(tables={table_name: table_name})
+ elif query.lower().startswith("insert"):
+ query = query.replace("\n", " ")
+
+ table_name, new_item = InsertParser().parse(query)
+ return QueryMetadata(tables={table_name: table_name})
+ raise Exception
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/update_parser.py
new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/update_parser.py
--- old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/update_parser.py
2023-12-17 01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/update_parser.py
2024-02-01 22:30:48.000000000 +0100
@@ -1,4 +1,4 @@
-from typing import Any, Dict, List, Tuple, Optional
+from typing import Any, List, Tuple
from .clause_tokenizer import ClauseTokenizer
from .utils import serializer
@@ -7,19 +7,15 @@
class UpdateParser:
def parse(
self, query: str
- ) -> Tuple[
- str,
- List[Tuple[str, Optional[Dict[str, Any]]]],
- List[Tuple[str, Dict[str, Any]]],
- ]:
+ ) -> Tuple[str, List[Tuple[str, Any]], List[Tuple[str, Any]]]:
tokenizer = ClauseTokenizer(query)
section = "START"
current_phrase = ""
table_name = ""
- attrs_to_update: List[Tuple[str, Optional[Dict[str, Any]]]] = []
- attr_filters = []
+ attrs_to_update: List[Tuple[str, Any]] = []
+ attr_filters: List[Tuple[str, Any]] = []
while True:
c = tokenizer.next()
@@ -33,6 +29,7 @@
), f"{current_phrase} should be UPDATE"
current_phrase = ""
section = "TABLE_NAME"
+ continue
if section == "ACTION":
assert current_phrase.upper() in ["SET", "REMOVE"]
section = f"ACTION_{current_phrase.upper()}"
@@ -42,6 +39,7 @@
assert current_phrase.upper() == "WHERE"
section = "WHERE"
current_phrase = ""
+ continue
if section == "WHERE_AND":
assert current_phrase.upper() == "AND"
section = "WHERE"
@@ -54,38 +52,64 @@
tokenizer.skip_white_space()
section = "SECTION_WHERE"
+ if section == "TABLE_NAME":
+ table_name = current_phrase
+ current_phrase = ""
+ tokenizer.skip_white_space()
+ section = "ACTION"
continue
elif c in ["'", '"']:
if section == "TABLE_NAME":
table_name = tokenizer.next_until([c])
tokenizer.skip_white_space()
section = "ACTION"
+ if section == "ACTION_SET":
+ current_phrase = tokenizer.next_until([c])
+ tokenizer.skip_white_space()
+ if section == "WHERE":
+ current_phrase = tokenizer.next_until([c])
+ tokenizer.skip_white_space()
continue
elif c == "=":
if section == "ACTION_SET":
attr_name = current_phrase
tokenizer.skip_white_space()
- quote_type = tokenizer.current()
- assert quote_type in ["'", '"']
-
- tokenizer.next()
- attr_value = tokenizer.next_until([quote_type])
- attrs_to_update.append(
- (attr_name, serializer.serialize(attr_value))
- )
+ if tokenizer.current() == "?":
+ attrs_to_update.append((attr_name, "?"))
+ tokenizer.next_until(["?"])
+ else:
+ quote_type = tokenizer.current()
+ assert quote_type in ["'", '"', "?"]
+
+ tokenizer.next()
+ attr_value = tokenizer.next_until([quote_type])
+ attrs_to_update.append(
+ (attr_name, serializer.serialize(attr_value))
+ )
current_phrase = ""
tokenizer.skip_white_space()
- section = "SECTION_WHERE"
+ if tokenizer.current() == ",":
+ tokenizer.next_until([","])
+ # Another attr to update
+ pass
+ else:
+ section = "SECTION_WHERE"
elif section == "WHERE":
attr_name = current_phrase
tokenizer.skip_white_space()
- quote_type = tokenizer.current()
- assert quote_type in ["'", '"']
-
- tokenizer.next()
- attr_value = tokenizer.next_until([quote_type])
- attr_filters.append((attr_name,
serializer.serialize(attr_value)))
+ if tokenizer.current() == "?":
+ attr_filters.append((current_phrase, "?"))
+ tokenizer.next_until(["?"])
+ else:
+ quote_type = tokenizer.current()
+ assert quote_type in ["'", '"']
+
+ tokenizer.next()
+ attr_value = tokenizer.next_until([quote_type])
+ attr_filters.append(
+ (attr_name, serializer.serialize(attr_value))
+ )
tokenizer.skip_white_space()
current_phrase = ""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/utils.py
new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/utils.py
--- old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/utils.py
2023-12-17 01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/utils.py
2024-02-01 22:30:48.000000000 +0100
@@ -133,9 +133,11 @@
self,
tables: Dict[str, str],
where_clause: Optional["AbstractWhereClause"] = None,
+ is_select_query: bool = False,
):
self._tables = tables
self._where_clause = where_clause
+ self._is_select_query = is_select_query
def get_table_names(self) -> List[str]:
return list(self._tables.values())
@@ -145,6 +147,9 @@
return self._where_clause.get_filter_names()
return []
+ def is_select_query(self) -> bool:
+ return self._is_select_query
+
class Variable:
def __init__(self, value: Any) -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/py-partiql-parser-0.5.0/pyproject.toml
new/py-partiql-parser-0.5.1/pyproject.toml
--- old/py-partiql-parser-0.5.0/pyproject.toml 2023-12-17 01:06:55.000000000
+0100
+++ new/py-partiql-parser-0.5.1/pyproject.toml 2024-02-01 22:30:48.000000000
+0100
@@ -1,6 +1,6 @@
[project]
name = "py-partiql-parser"
-version = "0.5.0"
+version = "0.5.1"
description = "Pure Python PartiQL Parser"
readme = "README.md"
keywords = ["pypartiql", "parser"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/py-partiql-parser-0.5.0/tests/test_dynamodb_examples.py
new/py-partiql-parser-0.5.1/tests/test_dynamodb_examples.py
--- old/py-partiql-parser-0.5.0/tests/test_dynamodb_examples.py 2023-12-17
01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/tests/test_dynamodb_examples.py 2024-02-01
22:30:48.000000000 +0100
@@ -259,6 +259,32 @@
assert updates == {"table": [(items[1], updated_item)]}
+def test_update_with_quoted_attributes_and_parameters() -> None:
+ # Note that the table is without parameters
+ query = 'UPDATE users SET "first_name" = ?, "last_name" = ? WHERE "id"= ?'
+ items = [
+ {"id": {"S": "yes"}, "first_name": {"S": "old"}, "last_name": {"S":
"old"}},
+ {"id": {"S": "no"}, "first_name": {"S": "old"}, "last_name": {"S":
"old"}},
+ ]
+ return_value, updates = DynamoDBStatementParser(source_data={"users":
items}).parse(
+ query, parameters=[{"S": "fn"}, {"S": "ln"}, {"S": "yes"}]
+ )
+
+ assert return_value == []
+ assert len(updates["users"]) == 1
+ old, new = updates["users"][0]
+ assert old == {
+ "id": {"S": "yes"},
+ "first_name": {"S": "old"},
+ "last_name": {"S": "old"},
+ }
+ assert new == {
+ "id": {"S": "yes"},
+ "first_name": {"S": "fn"},
+ "last_name": {"S": "ln"},
+ }
+
+
def test_update_remove() -> None:
query = "UPDATE 'table' REMOVE attr WHERE Id='id1'"
items = [
@@ -276,8 +302,11 @@
assert updates == {"table": [(items[0], updated_item)]}
-def test_delete() -> None:
- query = "DELETE FROM 'tablename' WHERE Id='id1'"
[email protected](
+ "query",
+ ["DELETE FROM 'tablename' WHERE Id='id1'", "DELETE FROM tablename WHERE
Id='id1'"],
+)
+def test_delete(query: str) -> None:
items = [
{"id": {"S": "id1"}, "attr": {"S": "sth"}},
{"id": {"S": "id2"}, "attr": {"S": "oth"}},
@@ -317,8 +346,14 @@
assert updates == {"tablename": []}
-def test_insert() -> None:
- query = "INSERT INTO 'mytable' value {'id': 'id1'}"
[email protected](
+ "query",
+ [
+ "INSERT INTO 'mytable' value {'id': 'id1'}",
+ "INSERT INTO mytable value {'id': 'id1'}",
+ ],
+)
+def test_insert(query: str) -> None:
items = [{"id": {"S": "asdf"}}]
return_value, updates = DynamoDBStatementParser(
source_data={"mytable": items}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/py-partiql-parser-0.5.0/tests/test_query_metadata.py
new/py-partiql-parser-0.5.1/tests/test_query_metadata.py
--- old/py-partiql-parser-0.5.0/tests/test_query_metadata.py 2023-12-17
01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/tests/test_query_metadata.py 2024-02-01
22:30:48.000000000 +0100
@@ -41,3 +41,27 @@
metadata = DynamoDBStatementParser.get_query_metadata(query)
assert metadata.get_filter_names() == ["k1", "k2.sth"]
+
+
+def test_update_statement() -> None:
+ query = 'UPDATE users SET "first_name" = ?, "last_name" = ? WHERE
"username"= ?'
+ metadata = DynamoDBStatementParser.get_query_metadata(query)
+
+ assert metadata.get_table_names() == ["users"]
+ assert metadata.get_filter_names() == []
+
+
+def test_insert_statement() -> None:
+ query = "INSERT INTO 'mytable' value {'id': 'id1'}"
+ metadata = DynamoDBStatementParser.get_query_metadata(query)
+
+ assert metadata.get_table_names() == ["mytable"]
+ assert metadata.get_filter_names() == []
+
+
+def test_delete_statement() -> None:
+ query = "DELETE FROM 'tablename' WHERE Id='id1'"
+ metadata = DynamoDBStatementParser.get_query_metadata(query)
+
+ assert metadata.get_table_names() == ["tablename"]
+ assert metadata.get_filter_names() == []