| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Expand Up | @@ -13,6 +13,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # limitations under the License. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from unittest.mock import MagicMock | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import pytest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from sqlalchemy.testing import eq_ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from sqlalchemy.testing.plugin.plugin_base import fixtures | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from google.cloud.sqlalchemy_spanner.sqlalchemy_spanner import SpannerDialect | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Expand Down Expand Up | @@ -98,3 +99,72 @@ def test_max_size_exported(self): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eq_(SpannerDialect.max_size, MAX_SIZE) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eq_(int_from_size("MAX"), 2621440) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eq_(int_from_size("100"), 100) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @staticmethod | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _mock_connection(rows=None): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| connection = MagicMock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mock_snapshot = MagicMock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mock_snapshot.execute_sql.return_value = rows if rows is not None else [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| connection.connection.database.snapshot.return_value.__enter__.return_value = ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mock_snapshot | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return connection, mock_snapshot | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_get_columns_escapes_quote_in_table_name(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """A single quote in a reflected table name must not break out of the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| INFORMATION_SCHEMA string literal in get_columns.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dialect = SpannerDialect() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| connection, mock_snapshot = self._mock_connection() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dialect.get_columns(connection, table_name="t' OR '1'='1") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| executed_sql = mock_snapshot.execute_sql.call_args[0][0] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert "col.table_name = 't\\' OR \\'1\\'=\\'1'" in executed_sql | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert "col.table_name = 't' OR '1'='1'" not in executed_sql | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_has_table_escapes_quote_in_table_name(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """A double quote in a reflected table name must not break out of the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| INFORMATION_SCHEMA string literal in has_table.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dialect = SpannerDialect() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| connection, mock_snapshot = self._mock_connection() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dialect.has_table(connection, table_name='a" OR "1"="1') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| executed_sql = mock_snapshot.execute_sql.call_args[0][0] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert 'TABLE_NAME="a\\" OR \\"1\\"=\\"1"' in executed_sql | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert 'TABLE_NAME="a" OR "1"="1"' not in executed_sql | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_get_view_definition_escapes_quote(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """A quote in a reflected view name must not break out of the literal.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dialect = SpannerDialect() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| connection, mock_snapshot = self._mock_connection(rows=[["def"]]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dialect.get_view_definition(connection, view_name="v' OR '1'='1") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| executed_sql = mock_snapshot.execute_sql.call_args[0][0] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert "TABLE_NAME='v\\' OR \\'1\\'=\\'1'" in executed_sql | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_escape_sql_string_literal(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """The helper escapes backslashes, both quote styles and newlines.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from google.cloud.sqlalchemy_spanner.sqlalchemy_spanner import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _escape_sql_string_literal, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eq_(_escape_sql_string_literal("a'b"), "a\\'b") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eq_(_escape_sql_string_literal('a"b'), 'a\\"b') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eq_(_escape_sql_string_literal("a\\b"), "a\\\\b") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eq_(_escape_sql_string_literal("a\nb"), "a\\nb") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eq_(_escape_sql_string_literal("plain"), "plain") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment thread
Comment on lines
+147
to
+157
Copy link
Copy Markdown
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityLet's add test assertions to verify that _escape_sql_string_literal raises a ProgrammingError when receiving unsupported types like None or non-string inputs, ensuring fail-fast behavior.
Suggested change
Sorry, something went wrong.
All reactions
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_escape_sql_string_literal_rejects_non_string(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """A non-string name must fail fast rather than be silently coerced.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from google.cloud.sqlalchemy_spanner.sqlalchemy_spanner import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _escape_sql_string_literal, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from google.cloud.spanner_dbapi.exceptions import ProgrammingError | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with pytest.raises(ProgrammingError): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _escape_sql_string_literal(None) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with pytest.raises(ProgrammingError): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _escape_sql_string_literal(123) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Back | FazBrowse Home | New Git URL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityWhen _escape_sql_string_literal receives parameters of an unsupported type (such as None or non-string types), it should raise an error (e.g., ProgrammingError) instead of silently returning empty values or converting them. This ensures fail-fast behavior and prevents potential issues with missing parameter values in database operations.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityAdded an isinstance check that raises spanner_dbapi.exceptions.ProgrammingError for non-string input, matching the existing error usage in this file. Test for None and int added too.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.