Return the SQL version of the where clause and the value to be substituted in. Return '', [] if this node matches everything, None, [] if this node is empty, and raise EmptyResultSet if this node can't match anything.
(self, compiler, connection)
| 114 | return where_node, having_node, qualify_node |
| 115 | |
| 116 | def as_sql(self, compiler, connection): |
| 117 | """ |
| 118 | Return the SQL version of the where clause and the value to be |
| 119 | substituted in. Return '', [] if this node matches everything, |
| 120 | None, [] if this node is empty, and raise EmptyResultSet if this |
| 121 | node can't match anything. |
| 122 | """ |
| 123 | result = [] |
| 124 | result_params = [] |
| 125 | if self.connector == AND: |
| 126 | full_needed, empty_needed = len(self.children), 1 |
| 127 | else: |
| 128 | full_needed, empty_needed = 1, len(self.children) |
| 129 | |
| 130 | if self.connector == XOR and not connection.features.supports_logical_xor: |
| 131 | # Convert if the database doesn't support XOR: |
| 132 | # a XOR b XOR c XOR ... |
| 133 | # to: |
| 134 | # (a OR b OR c OR ...) AND MOD(a + b + c + ..., 2) == 1 |
| 135 | # The result of an n-ary XOR is true when an odd number of operands |
| 136 | # are true. |
| 137 | lhs = self.__class__(self.children, OR) |
| 138 | rhs_sum = reduce( |
| 139 | operator.add, |
| 140 | (Case(When(c, then=1), default=0) for c in self.children), |
| 141 | ) |
| 142 | if len(self.children) > 2: |
| 143 | rhs_sum = Mod(rhs_sum, 2) |
| 144 | rhs = Exact(1, rhs_sum) |
| 145 | return self.__class__([lhs, rhs], AND, self.negated).as_sql( |
| 146 | compiler, connection |
| 147 | ) |
| 148 | |
| 149 | for child in self.children: |
| 150 | try: |
| 151 | sql, params = compiler.compile(child) |
| 152 | except EmptyResultSet: |
| 153 | empty_needed -= 1 |
| 154 | except FullResultSet: |
| 155 | full_needed -= 1 |
| 156 | else: |
| 157 | if sql: |
| 158 | result.append(sql) |
| 159 | result_params.extend(params) |
| 160 | else: |
| 161 | full_needed -= 1 |
| 162 | # Check if this node matches nothing or everything. |
| 163 | # First check the amount of full nodes and empty nodes |
| 164 | # to make this node empty/full. |
| 165 | # Now, check if this node is full/empty using the |
| 166 | # counts. |
| 167 | if empty_needed == 0: |
| 168 | if self.negated: |
| 169 | raise FullResultSet |
| 170 | else: |
| 171 | raise EmptyResultSet |
| 172 | if full_needed == 0: |
| 173 | if self.negated: |