diff --git a/py_dbcn/connectors/core/records.py b/py_dbcn/connectors/core/records.py index ea585e77c5ef6262e985bb24a74d1d293d97bb6f..5df0e27da5ffc24ca19ba2e18cb0d92a078d2081 100644 --- a/py_dbcn/connectors/core/records.py +++ b/py_dbcn/connectors/core/records.py @@ -56,17 +56,7 @@ class BaseRecords: select_clause = self._base.validate.sanitize_select_identifier_clause(select_clause) # Check that provided WHERE clause is valid format. - # TODO: Implement proper clause sanitization. - if where_clause is None: - where_clause = '' - where_clause = str(where_clause).strip() - if where_clause.lower().startswith('where'): - where_clause = where_clause[5:] - where_clause = where_clause.strip() - if len(where_clause) > 1: - where_clause = '\nWHERE ({0})'.format(where_clause) - if not self._base.validate.where_clause(where_clause): - raise ValueError('Invalid WHERE clause of "{0}".'.format(where_clause)) + where_clause = self._base.validate.sanitize_where_clause(where_clause) # Check that provided ORDER BY clause is valid format. order_by_clause = self._base.validate.sanitize_order_by_clause(order_by_clause) @@ -102,15 +92,10 @@ class BaseRecords: raise ValueError('Invalid table name of "{0}".'.format(table_name)) # Check that provided COLUMNS clause is valid format. - if columns_clause is None: - columns_clause = '' - columns_clause = str(columns_clause).strip() - if not self._base.validate.columns_clause(columns_clause): - raise ValueError('Invalid COLUMNS clause of "{0}".'.format(columns_clause)) + columns_clause = self._base.validate.sanitize_columns_clause(columns_clause) # Check that provided VALUES clause is valid format. - if not self._base.validate.values_clause(values_clause): - raise ValueError('Invalid VALUES clause of "{0}".'.format(values_clause)) + values_clause = self._base.validate.sanitize_values_clause(values_clause) # Check for values that might need formatting. # For example, if we find date/datetime objects, we automatically convert to a str value that won't error. @@ -156,12 +141,10 @@ class BaseRecords: raise ValueError('Invalid table name of "{0}".'.format(table_name)) # Check that provided VALUES clause is valid format. - if not self._base.validate.values_clause(values_clause): - raise ValueError('Invalid VALUES clause of "{0}".'.format(values_clause)) + values_clause = self._base.validate.sanitize_values_clause(values_clause) # Check that provided WHERE clause is valid format. - if not self._base.validate.columns_clause(where_clause): - raise ValueError('Invalid WHERE clause of "{0}".'.format(where_clause)) + where_clause = self._base.validate.sanitize_where_clause(where_clause) # Check for values that might need formatting. # For example, if we find date/datetime objects, we automatically convert to a str value that won't error. @@ -182,10 +165,6 @@ class BaseRecords: # Replace original clause. values_clause = updated_values_clause - orig_where_clause = where_clause - if len(where_clause) > 0: - where_clause = ' WHERE {0}'.format(where_clause) - # Update record. query = """ UPDATE {0} @@ -196,7 +175,7 @@ class BaseRecords: # Do a select to get the updated values as results. results = self.select( table_name, - where_clause=orig_where_clause, + where_clause=where_clause, display_query=False, display_results=display_results, ) @@ -216,11 +195,7 @@ class BaseRecords: raise ValueError('Invalid table name of "{0}".'.format(table_name)) # Check that provided WHERE clause is valid format. - if not self._base.validate.columns_clause(where_clause): - raise ValueError('Invalid WHERE clause of "{0}".'.format(where_clause)) - - if len(where_clause) > 0: - where_clause = ' WHERE {0}'.format(where_clause) + where_clause = self._base.validate.sanitize_where_clause(where_clause) # Delete record. query = 'DELETE FROM {0}{1};'.format(table_name, where_clause) diff --git a/py_dbcn/connectors/core/validate.py b/py_dbcn/connectors/core/validate.py index 9688fe7d7d2eeac710129fd4c7fd039bae0a6ebe..1735e7fd6598d98e5363b729f4993d752e31ac5a 100644 --- a/py_dbcn/connectors/core/validate.py +++ b/py_dbcn/connectors/core/validate.py @@ -45,8 +45,9 @@ class BaseValidate: # Define inheritance variables. self._reserved_function_names = None self._quote_column_format = None - self._quote_str_literal_format = None self._quote_identifier_format = None + self._quote_order_by_format = None + self._quote_str_literal_format = None # region Name Validation @@ -428,7 +429,7 @@ class BaseValidate: raise ValueError('Invalid ORDER BY clause.') # Validate. - clause = self._inner_sanitize_columns(clause, allow_wildcard=False) + clause = self._inner_sanitize_columns(clause, allow_wildcard=False, order_by=True) # Handle empty clause. if clause == '': @@ -495,10 +496,12 @@ class BaseValidate: return is_quoted - def _inner_sanitize_columns(self, clause, allow_wildcard=False): + def _inner_sanitize_columns(self, clause, allow_wildcard=False, order_by=False): """""" if allow_wildcard: quote_format = self._quote_identifier_format + elif order_by: + quote_format = self._quote_order_by_format else: quote_format = self._quote_column_format @@ -586,8 +589,24 @@ class BaseValidate: raise ValueError('SELECT clause provided * with other params. * is only valid alone.') # Validate individual identifier. + item_identifier = item + order_by_descriptor = '' if item != '*': - results = self._identifier(item) + if order_by: + # To check identifier, trim possible ASC/DESC values. + if item_identifier.lower().endswith(' asc'): + # Handle for ASC syntax. + item_identifier = item_identifier[:-4].rstrip() + item = item_identifier + order_by_descriptor = ' ASC' + if item_identifier.lower().endswith(' desc'): + # Handle for DESC syntax. + item_identifier = item_identifier[:-5].rstrip() + item = item_identifier + order_by_descriptor = ' DESC' + + # Check for valid identifier. + results = self._identifier(item_identifier) if results[0] is False: raise ValueError('Invalid identifier. Identifier {0}'.format(results[1])) @@ -595,12 +614,12 @@ class BaseValidate: is_quoted = self._is_quoted(item) if is_quoted: # Was already quoted, but may not be with expected format. Reformat to guaranteed use expected format. - item = '{1}{0}{1}'.format(item[1:-1], quote_format) + item = '{1}{0}{1}{2}'.format(item[1:-1], quote_format, order_by_descriptor) elif item == '*': pass else: # Was not quoted. Add quotes. - item = '{1}{0}{1}'.format(item, quote_format) + item = '{1}{0}{1}{2}'.format(item, quote_format, order_by_descriptor) # Re-add function values. item = stripped_left.upper() + item + stripped_right diff --git a/py_dbcn/connectors/mysql/validate.py b/py_dbcn/connectors/mysql/validate.py index 531381adcb1ff5190747954270ca964cd89537fb..c4fb05e06520e8de0ec690f6f8de61b982d074ff 100644 --- a/py_dbcn/connectors/mysql/validate.py +++ b/py_dbcn/connectors/mysql/validate.py @@ -18,6 +18,7 @@ logger = init_logging(__name__) # Module Variables. QUOTE_COLUMN_FORMAT = """`""" # Used for quoting table columns. QUOTE_IDENTIFIER_FORMAT = """`""" # Used for quoting identifiers (such as SELECT clause field id's). +QUOTE_ORDER_BY_FORMAT = """`""" # Used for quoting values in ORDER BY clause. QUOTE_STR_LITERAL_FORMAT = """\"""" # Used for quoting actual strings. @@ -139,4 +140,5 @@ class MysqlValidate(BaseValidate): # Aka, what the database says is "okay" to surround string values with. self._quote_column_format = QUOTE_COLUMN_FORMAT self._quote_identifier_format = QUOTE_IDENTIFIER_FORMAT + self._quote_order_by_format = QUOTE_ORDER_BY_FORMAT self._quote_str_literal_format = QUOTE_STR_LITERAL_FORMAT diff --git a/py_dbcn/connectors/postgresql/validate.py b/py_dbcn/connectors/postgresql/validate.py index 045a8c3319c6eb6c63b88b71054ee9a6b858cdaa..b81048c191a147ac0632458b9e329be7689b6942 100644 --- a/py_dbcn/connectors/postgresql/validate.py +++ b/py_dbcn/connectors/postgresql/validate.py @@ -18,6 +18,7 @@ logger = init_logging(__name__) # Module Variables. QUOTE_COLUMN_FORMAT = """'""" # Used for quoting table columns. QUOTE_IDENTIFIER_FORMAT = """\"""" # Used for quoting identifiers (such as SELECT clause field id's). +QUOTE_ORDER_BY_FORMAT = """\"""" # Used for quoting values in ORDER BY clause. QUOTE_STR_LITERAL_FORMAT = """'""" # Used for quoting actual strings. @@ -97,4 +98,5 @@ class PostgresqlValidate(BaseValidate): # Aka, what the database says is "okay" to surround string values with. self._quote_column_format = QUOTE_COLUMN_FORMAT self._quote_identifier_format = QUOTE_IDENTIFIER_FORMAT + self._quote_order_by_format = QUOTE_ORDER_BY_FORMAT self._quote_str_literal_format = QUOTE_STR_LITERAL_FORMAT diff --git a/tests/connectors/core/test_validate.py b/tests/connectors/core/test_validate.py index 2619d9547788f5dea2cec2d305d51c3ecdf28971..fe9ddc7a9061a561188734f8524877ed1aa1bfc9 100644 --- a/tests/connectors/core/test_validate.py +++ b/tests/connectors/core/test_validate.py @@ -32,6 +32,18 @@ class CoreValidateTestMixin: cls._quote_select_identifier_format = None cls._quote_str_literal_format = None + def test__column_quote_format(self): + raise NotImplementedError('Check for column quote formatting not implemented.') + + def test__select_identifier_quote_format(self): + raise NotImplementedError('Check for SELECT identifier quote formatting not implemented.') + + def test__order_by_quote_format(self): + raise NotImplementedError('Check for order by quote formatting not implemented.') + + def test__str_literal_quote_format(self): + raise NotImplementedError('Check for str literal quote formatting not implemented.') + # region Name Validation def test__identifier__success(self): @@ -3112,24 +3124,24 @@ class CoreValidateTestMixin: with self.subTest('Values as str - Without quotes'): # Single val provided. result = self.connector.validate.sanitize_order_by_clause('id') - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With extra whitespace. result = self.connector.validate.sanitize_order_by_clause(' id ') - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With full statement - upper. result = self.connector.validate.sanitize_order_by_clause('ORDER BY id') - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With full statement - lower. result = self.connector.validate.sanitize_order_by_clause('order by id') - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # Two vals provided. result = self.connector.validate.sanitize_order_by_clause('id, name') self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name') + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name') ), ) # With extra whitespace. @@ -3137,8 +3149,8 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) @@ -3147,9 +3159,9 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) # With extra whitespace. @@ -3157,33 +3169,33 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) with self.subTest('Values as triple str - Without quotes'): # Single val provided. result = self.connector.validate.sanitize_order_by_clause("""id""") - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With extra whitespace. result = self.connector.validate.sanitize_order_by_clause(""" id """) - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With full statement - upper. result = self.connector.validate.sanitize_order_by_clause("""ORDER BY id""") - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With full statement - lower. result = self.connector.validate.sanitize_order_by_clause("""order by id""") - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # Two vals provided. result = self.connector.validate.sanitize_order_by_clause("""id, name""") self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) # With extra whitespace. @@ -3191,8 +3203,8 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) @@ -3201,9 +3213,9 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) # With extra whitespace. @@ -3211,27 +3223,27 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) with self.subTest('Values as list - Without quotes'): # Single val provided. result = self.connector.validate.sanitize_order_by_clause(['id']) - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With extra whitespace. result = self.connector.validate.sanitize_order_by_clause([' id ']) - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # Two vals provided. result = self.connector.validate.sanitize_order_by_clause(['id', 'name']) self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) # With extra whitespace. @@ -3239,8 +3251,8 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) @@ -3249,9 +3261,9 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) # With extra whitespace. @@ -3259,27 +3271,27 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) with self.subTest('Values as tuple - Without quotes'): # Single val provided. result = self.connector.validate.sanitize_order_by_clause(('id',)) - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With extra whitespace. result = self.connector.validate.sanitize_order_by_clause((' id ',)) - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # Two vals provided. result = self.connector.validate.sanitize_order_by_clause(('id', 'name')) self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) # With extra whitespace. @@ -3287,8 +3299,8 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) @@ -3297,9 +3309,9 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) # With extra whitespace. @@ -3307,30 +3319,30 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) with self.subTest('Values as str - With single quotes'): # Single val provided. result = self.connector.validate.sanitize_order_by_clause("'id'") - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With full statement - upper. result = self.connector.validate.sanitize_order_by_clause("ORDER BY 'id'") - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With full statement - lower. result = self.connector.validate.sanitize_order_by_clause("order by 'id'") - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # Two vals provided. result = self.connector.validate.sanitize_order_by_clause("'id', 'name'") self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) @@ -3339,24 +3351,24 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code') + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code') ), ) with self.subTest('Values as list - With single quotes'): # Single val provided. result = self.connector.validate.sanitize_order_by_clause(["'id'"]) - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # Two vals provided. result = self.connector.validate.sanitize_order_by_clause(["'id'", "'name'"]) self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) @@ -3365,24 +3377,24 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) with self.subTest('Values as tuple - With single quotes'): # Single val provided. result = self.connector.validate.sanitize_order_by_clause(("'id'",)) - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # Two vals provided. result = self.connector.validate.sanitize_order_by_clause(("'id'", "'name'")) self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) @@ -3391,30 +3403,30 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) with self.subTest('Values as str - With double quotes'): # Single val provided. result = self.connector.validate.sanitize_order_by_clause('"id"') - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With full statement - upper. result = self.connector.validate.sanitize_order_by_clause('ORDER BY "id"') - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With full statement - lower. result = self.connector.validate.sanitize_order_by_clause('order by "id"') - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # Two vals provided. result = self.connector.validate.sanitize_order_by_clause('"id", "name"') self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) @@ -3423,24 +3435,24 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) with self.subTest('Values as list - With double quotes'): # Single val provided. result = self.connector.validate.sanitize_order_by_clause(['"id"']) - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # Two vals provided. result = self.connector.validate.sanitize_order_by_clause(['"id"', '"name"']) self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) @@ -3449,23 +3461,23 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) with self.subTest('Values as tuple - With double quotes'): # Single val provided. result = self.connector.validate.sanitize_order_by_clause(('"id"',)) - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # Two vals provided. result = self.connector.validate.sanitize_order_by_clause(('"id"', '"name"')) self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) @@ -3474,30 +3486,30 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) with self.subTest('Values as str - With backtick quotes'): # Single val provided. result = self.connector.validate.sanitize_order_by_clause('`id`') - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With full statement - upper. result = self.connector.validate.sanitize_order_by_clause('ORDER BY `id`') - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # With full statement - lower. result = self.connector.validate.sanitize_order_by_clause('order by `id`') - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # Two vals provided. result = self.connector.validate.sanitize_order_by_clause('`id`, `name`') self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) @@ -3506,24 +3518,24 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) with self.subTest('Values as list - With backtick quotes'): # Single val provided. result = self.connector.validate.sanitize_order_by_clause(['`id`']) - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # Two vals provided. result = self.connector.validate.sanitize_order_by_clause(['`id`', '`name`']) self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) @@ -3532,24 +3544,24 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) with self.subTest('Values as tuple - With backtick quotes'): # Single val provided. result = self.connector.validate.sanitize_order_by_clause(('`id`',)) - self.assertText(result, '\nORDER BY {0}'.format(self._quote_columns_format.format('id'))) + self.assertText(result, '\nORDER BY {0}'.format(self._quote_order_by_format.format('id'))) # Two vals provided. result = self.connector.validate.sanitize_order_by_clause(('`id`', '`name`')) self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), ), ) @@ -3558,9 +3570,9 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}, {2}'.format( - self._quote_columns_format.format('id'), - self._quote_columns_format.format('name'), - self._quote_columns_format.format('code'), + self._quote_order_by_format.format('id'), + self._quote_order_by_format.format('name'), + self._quote_order_by_format.format('code'), ), ) @@ -3571,8 +3583,8 @@ class CoreValidateTestMixin: self.assertText( result, '\nORDER BY {0}, {1}'.format( - self._quote_columns_format.format(1), - self._quote_columns_format.format(True), + self._quote_order_by_format.format(1), + self._quote_order_by_format.format(True), ), ) diff --git a/tests/connectors/mysql/test_validate.py b/tests/connectors/mysql/test_validate.py index cfc7259ae9d0865841e6baf58061fd3fd5ce6ad1..f32fd49a542e8e932146c0a7b0b7ab19d38fc4bd 100644 --- a/tests/connectors/mysql/test_validate.py +++ b/tests/connectors/mysql/test_validate.py @@ -38,20 +38,28 @@ class TestMysqlValidate(TestMysqlDatabaseParent, CoreValidateTestMixin): from py_dbcn.connectors.mysql.validate import ( QUOTE_COLUMN_FORMAT, QUOTE_IDENTIFIER_FORMAT, + QUOTE_ORDER_BY_FORMAT, QUOTE_STR_LITERAL_FORMAT, ) # Initialize variables. cls._quote_columns_format = '{0}{1}{0}'.format(QUOTE_COLUMN_FORMAT, '{0}') cls._quote_select_identifier_format = '{0}{1}{0}'.format(QUOTE_IDENTIFIER_FORMAT, '{0}') + cls._quote_order_by_format = '{0}{1}{0}'.format(QUOTE_ORDER_BY_FORMAT, '{0}') cls._quote_str_literal_format = '{0}{1}{0}'.format(QUOTE_STR_LITERAL_FORMAT, '{0}') - def test__sanitize_select_identifier_clause__success(self): - """ - Test sanitizing a SELECT clause, in cases when it should succeed. - """ - # Verify identifier str is as we expect. + def test__column_quote_format(self): + # Verify quote str is as we expect. + self.assertText('`{0}`', self._quote_columns_format) + + def test__select_identifier_quote_format(self): + # Verify quote str is as we expect. self.assertText('`{0}`', self._quote_select_identifier_format) - # Call parent logic. - super().test__sanitize_select_identifier_clause__success() + def test__order_by_quote_format(self): + # Verify quote str is as we expect. + self.assertText('`{0}`', self._quote_order_by_format) + + def test__str_literal_quote_format(self): + # Verify quote str is as we expect. + self.assertText('"{0}"', self._quote_str_literal_format) diff --git a/tests/connectors/postgresql/test_validate.py b/tests/connectors/postgresql/test_validate.py index 42404f9064175d268d76441fa185ecf8d0dfad72..5131d318b10870f387ead60e5a58b8c0d062ecd4 100644 --- a/tests/connectors/postgresql/test_validate.py +++ b/tests/connectors/postgresql/test_validate.py @@ -38,20 +38,28 @@ class TestPostgresqlValidate(TestPostgresqlDatabaseParent, CoreValidateTestMixin from py_dbcn.connectors.postgresql.validate import ( QUOTE_COLUMN_FORMAT, QUOTE_IDENTIFIER_FORMAT, + QUOTE_ORDER_BY_FORMAT, QUOTE_STR_LITERAL_FORMAT, ) # Initialize variables. cls._quote_columns_format = '{0}{1}{0}'.format(QUOTE_COLUMN_FORMAT, '{0}') cls._quote_select_identifier_format = '{0}{1}{0}'.format(QUOTE_IDENTIFIER_FORMAT, '{0}') + cls._quote_order_by_format = '{0}{1}{0}'.format(QUOTE_ORDER_BY_FORMAT, '{0}') cls._quote_str_literal_format = '{0}{1}{0}'.format(QUOTE_STR_LITERAL_FORMAT, '{0}') - def test__sanitize_select_identifier_clause__success(self): - """ - Test sanitizing a SELECT clause, in cases when it should succeed. - """ - # Verify identifier str is as we expect. + def test__column_quote_format(self): + # Verify quote str is as we expect. + self.assertText("'{0}'", self._quote_columns_format) + + def test__select_identifier_quote_format(self): + # Verify quote str is as we expect. self.assertText('"{0}"', self._quote_select_identifier_format) - # Call parent logic. - super().test__sanitize_select_identifier_clause__success() + def test__order_by_quote_format(self): + # Verify quote str is as we expect. + self.assertText('"{0}"', self._quote_order_by_format) + + def test__str_literal_quote_format(self): + # Verify quote str is as we expect. + self.assertText("'{0}'", self._quote_str_literal_format)