diff options
Diffstat (limited to 'lib/sqlalchemy/sql/elements.py')
-rw-r--r-- | lib/sqlalchemy/sql/elements.py | 87 |
1 files changed, 59 insertions, 28 deletions
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 9e4f5d95d..a4623128f 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -37,6 +37,20 @@ def _clone(element, **kw): return element._clone() +def _document_text_coercion(paramname, meth_rst, param_rst): + return util.add_parameter_text( + paramname, + ( + ".. warning:: " + "The %s argument to %s can be passed as a Python string argument, " + "which will be treated " + "as **trusted SQL text** and rendered as given. **DO NOT PASS " + "UNTRUSTED INPUT TO THIS PARAMETER**." + ) + % (param_rst, meth_rst), + ) + + def collate(expression, collation): """Return the clause ``expression COLLATE collation``. @@ -1343,6 +1357,7 @@ class TextClause(Executable, ClauseElement): "refer to the :meth:`.TextClause.columns` method.", ), ) + @_document_text_coercion("text", ":func:`.text`", ":paramref:`.text.text`") def _create_text( self, text, bind=None, bindparams=None, typemap=None, autocommit=None ): @@ -4430,32 +4445,64 @@ def _literal_and_labels_as_label_reference(element): def _expression_literal_as_text(element): - return _literal_as_text(element, warn=True) + return _literal_as_text(element) -def _literal_as_text(element, warn=False): +def _literal_as(element, text_fallback): if isinstance(element, Visitable): return element elif hasattr(element, "__clause_element__"): return element.__clause_element__() elif isinstance(element, util.string_types): - if warn: - util.warn_limited( - "Textual SQL expression %(expr)r should be " - "explicitly declared as text(%(expr)r)", - {"expr": util.ellipses_string(element)}, - ) - - return TextClause(util.text_type(element)) + return text_fallback(element) elif isinstance(element, (util.NoneType, bool)): return _const_expr(element) else: raise exc.ArgumentError( - "SQL expression object or string expected, got object of type %r " + "SQL expression object expected, got object of type %r " "instead" % type(element) ) +def _literal_as_text(element, allow_coercion_to_text=False): + if allow_coercion_to_text: + return _literal_as(element, TextClause) + else: + return _literal_as(element, _no_text_coercion) + + +def _literal_as_column(element): + return _literal_as(element, ColumnClause) + + +def _no_column_coercion(element): + element = str(element) + guess_is_literal = not _guess_straight_column.match(element) + raise exc.ArgumentError( + "Textual column expression %(column)r should be " + "explicitly declared with text(%(column)r), " + "or use %(literal_column)s(%(column)r) " + "for more specificity" + % { + "column": util.ellipses_string(element), + "literal_column": "literal_column" + if guess_is_literal + else "column", + } + ) + + +def _no_text_coercion(element, exc_cls=exc.ArgumentError, extra=None): + raise exc_cls( + "%(extra)sTextual SQL expression %(expr)r should be " + "explicitly declared as text(%(expr)r)" + % { + "expr": util.ellipses_string(element), + "extra": "%s " % extra if extra else "", + } + ) + + def _no_literals(element): if hasattr(element, "__clause_element__"): return element.__clause_element__() @@ -4529,23 +4576,7 @@ def _interpret_as_column_or_from(element): elif isinstance(element, (numbers.Number)): return ColumnClause(str(element), is_literal=True) else: - element = str(element) - # give into temptation, as this fact we are guessing about - # is not one we've previously ever needed our users tell us; - # but let them know we are not happy about it - guess_is_literal = not _guess_straight_column.match(element) - util.warn_limited( - "Textual column expression %(column)r should be " - "explicitly declared with text(%(column)r), " - "or use %(literal_column)s(%(column)r) " - "for more specificity", - { - "column": util.ellipses_string(element), - "literal_column": "literal_column" - if guess_is_literal - else "column", - }, - ) + _no_column_coercion(element) return ColumnClause(element, is_literal=guess_is_literal) |