~launchpad-committers/storm/lp

« back to all changes in this revision

Viewing changes to storm/expr.py

  • Committer: Colin Watson
  • Date: 2023-07-06 10:51:34 UTC
  • mfrom: (386.34.138 storm)
  • Revision ID: cjwatson@canonical.com-20230706105134-rzpb4opv8nfpg56r
Merge Storm 0.26 release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
517
517
    def upper(self):
518
518
        return Upper(self)
519
519
 
520
 
    def startswith(self, prefix):
 
520
    def startswith(self, prefix, case_sensitive=None):
521
521
        if not isinstance(prefix, six.text_type):
522
522
            raise ExprError("Expected text argument, got %r" % type(prefix))
523
523
        pattern = prefix.translate(like_escape) + u"%"
524
 
        return Like(self, pattern, u"!")
 
524
        return Like(self, pattern, u"!", case_sensitive)
525
525
 
526
 
    def endswith(self, suffix):
 
526
    def endswith(self, suffix, case_sensitive=None):
527
527
        if not isinstance(suffix, six.text_type):
528
528
            raise ExprError("Expected text argument, got %r" % type(suffix))
529
529
        pattern = u"%" + suffix.translate(like_escape)
530
 
        return Like(self, pattern, u"!")
 
530
        return Like(self, pattern, u"!", case_sensitive)
531
531
 
532
 
    def contains_string(self, substring):
 
532
    def contains_string(self, substring, case_sensitive=None):
533
533
        if not isinstance(substring, six.text_type):
534
534
            raise ExprError("Expected text argument, got %r" % type(substring))
535
535
        pattern = u"%" + substring.translate(like_escape) + u"%"
536
 
        return Like(self, pattern, u"!")
 
536
        return Like(self, pattern, u"!", case_sensitive)
537
537
 
538
538
 
539
539
class ComparableExpr(Expr, Comparable):
1053
1053
    return compile(expr.exprs, state, join=expr.oper.lower())
1054
1054
 
1055
1055
 
 
1056
class Is(BinaryOper):
 
1057
    """The SQL C{IS ...} operators, e.g. C{IS NULL}.
 
1058
 
 
1059
    C{Is(expr, None)} is synonymous with C{expr == None}, but is less likely
 
1060
    to trip up linters.
 
1061
 
 
1062
    Unlike C{expr} or C{expr == True}, C{Is(expr, True)} returns C{FALSE}
 
1063
    when C{expr} is C{NULL}.
 
1064
 
 
1065
    Unlike C{Not(expr)} or C{expr == False}, C{Is(expr, False)} returns
 
1066
    C{FALSE} when C{expr} is C{NULL}.
 
1067
    """
 
1068
    __slots__ = ()
 
1069
    oper = " IS "
 
1070
 
 
1071
@compile.when(Is)
 
1072
def compile_is(compile, is_, state):
 
1073
    tokens = [compile(is_.expr1, state), "IS"]
 
1074
    if is_.expr2 is None:
 
1075
        tokens.append("NULL")
 
1076
    elif is_.expr2 is True:
 
1077
        tokens.append("TRUE")
 
1078
    elif is_.expr2 is False:
 
1079
        tokens.append("FALSE")
 
1080
    else:
 
1081
        raise CompileError("expr2 must be None, True, or False")
 
1082
    return " ".join(tokens)
 
1083
 
 
1084
@compile_python.when(Is)
 
1085
def compile_is(compile, is_, state):
 
1086
    return "%s is %s" % (compile(is_.expr1, state), compile(is_.expr2, state))
 
1087
 
 
1088
 
 
1089
class IsNot(BinaryOper):
 
1090
    """The SQL C{IS NOT ...} operators, e.g. C{IS NOT NULL}.
 
1091
 
 
1092
    C{IsNot(expr, None)} is synonymous with C{expr != None}, but is less
 
1093
    likely to trip up linters.
 
1094
 
 
1095
    Unlike C{Not(expr)} or C{expr != True}, C{IsNot(expr, True)} returns
 
1096
    C{TRUE} when C{expr} is C{NULL}.
 
1097
 
 
1098
    Unlike C{expr} or C{expr != False}, C{IsNot(expr, False)} returns
 
1099
    C{TRUE} when C{expr} is C{NULL}.
 
1100
    """
 
1101
    __slots__ = ()
 
1102
    oper = " IS NOT "
 
1103
 
 
1104
@compile.when(IsNot)
 
1105
def compile_is_not(compile, is_not, state):
 
1106
    tokens = [compile(is_not.expr1, state), "IS NOT"]
 
1107
    if is_not.expr2 is None:
 
1108
        tokens.append("NULL")
 
1109
    elif is_not.expr2 is True:
 
1110
        tokens.append("TRUE")
 
1111
    elif is_not.expr2 is False:
 
1112
        tokens.append("FALSE")
 
1113
    else:
 
1114
        raise CompileError("expr2 must be None, True, or False")
 
1115
    return " ".join(tokens)
 
1116
 
 
1117
@compile_python.when(IsNot)
 
1118
def compile_is_not(compile, is_not, state):
 
1119
    return "%s is not %s" % (
 
1120
        compile(is_not.expr1, state), compile(is_not.expr2, state)
 
1121
    )
 
1122
 
 
1123
 
1056
1124
class Eq(BinaryOper):
1057
1125
    __slots__ = ()
1058
1126
    oper = " = "
1580
1648
compile.set_precedence(20, SQL)
1581
1649
compile.set_precedence(30, Or)
1582
1650
compile.set_precedence(40, And)
 
1651
compile.set_precedence(45, Is, IsNot)
1583
1652
compile.set_precedence(50, Eq, Ne, Gt, Ge, Lt, Le, Like, In)
1584
1653
compile.set_precedence(60, LShift, RShift)
1585
1654
compile.set_precedence(70, Add, Sub)
1587
1656
 
1588
1657
compile_python.set_precedence(10, Or)
1589
1658
compile_python.set_precedence(20, And)
 
1659
compile_python.set_precedence(25, Is, IsNot)
1590
1660
compile_python.set_precedence(30, Eq, Ne, Gt, Ge, Lt, Le, Like, In)
1591
1661
compile_python.set_precedence(40, LShift, RShift)
1592
1662
compile_python.set_precedence(50, Add, Sub)