1290 # we have to generate unification expression |
1290 # we have to generate unification expression |
1291 lhssql = self._inlined_var_sql(relation.children[0].variable, |
1291 lhssql = self._inlined_var_sql(relation.children[0].variable, |
1292 relation.r_type) |
1292 relation.r_type) |
1293 try: |
1293 try: |
1294 self._state.ignore_varmap = True |
1294 self._state.ignore_varmap = True |
1295 return '%s%s' % (lhssql, relation.children[1].accept(self)) |
1295 sql = lhssql + relation.children[1].accept(self) |
1296 finally: |
1296 finally: |
1297 self._state.ignore_varmap = False |
1297 self._state.ignore_varmap = False |
|
1298 if relation.optional == 'right': |
|
1299 leftalias = self._var_table(principal.children[0].variable) |
|
1300 rightalias = self._var_table(relation.children[0].variable) |
|
1301 self._state.replace_tables_by_outer_join( |
|
1302 leftalias, rightalias, 'LEFT', sql) |
|
1303 return '' |
|
1304 return sql |
1298 return '' |
1305 return '' |
1299 |
1306 |
1300 def _visit_attribute_relation(self, rel): |
1307 def _visit_attribute_relation(self, rel): |
1301 """generate SQL for an attribute relation""" |
1308 """generate SQL for an attribute relation""" |
1302 lhs, rhs = rel.get_parts() |
1309 lhs, rhs = rel.get_parts() |
1370 return self.dbhelper.fti_restriction_sql(alias, query, |
1377 return self.dbhelper.fti_restriction_sql(alias, query, |
1371 jointo, not_) + restriction |
1378 jointo, not_) + restriction |
1372 |
1379 |
1373 def visit_comparison(self, cmp): |
1380 def visit_comparison(self, cmp): |
1374 """generate SQL for a comparison""" |
1381 """generate SQL for a comparison""" |
|
1382 optional = getattr(cmp, 'optional', None) # rql < 0.30 |
1375 if len(cmp.children) == 2: |
1383 if len(cmp.children) == 2: |
1376 # XXX occurs ? |
1384 # simplified expression from HAVING clause |
1377 lhs, rhs = cmp.children |
1385 lhs, rhs = cmp.children |
1378 else: |
1386 else: |
1379 lhs = None |
1387 lhs = None |
1380 rhs = cmp.children[0] |
1388 rhs = cmp.children[0] |
|
1389 assert not optional |
|
1390 sql = None |
1381 operator = cmp.operator |
1391 operator = cmp.operator |
1382 if operator in ('LIKE', 'ILIKE'): |
1392 if operator in ('LIKE', 'ILIKE'): |
1383 if operator == 'ILIKE' and not self.dbhelper.ilike_support: |
1393 if operator == 'ILIKE' and not self.dbhelper.ilike_support: |
1384 operator = ' LIKE ' |
1394 operator = ' LIKE ' |
1385 else: |
1395 else: |
1386 operator = ' %s ' % operator |
1396 operator = ' %s ' % operator |
1387 elif operator == 'REGEXP': |
1397 elif operator == 'REGEXP': |
1388 return ' %s' % self.dbhelper.sql_regexp_match_expression(rhs.accept(self)) |
1398 sql = ' %s' % self.dbhelper.sql_regexp_match_expression(rhs.accept(self)) |
1389 elif (operator == '=' and isinstance(rhs, Constant) |
1399 elif (operator == '=' and isinstance(rhs, Constant) |
1390 and rhs.eval(self._args) is None): |
1400 and rhs.eval(self._args) is None): |
1391 if lhs is None: |
1401 if lhs is None: |
1392 return ' IS NULL' |
1402 sql = ' IS NULL' |
1393 return '%s IS NULL' % lhs.accept(self) |
1403 else: |
|
1404 sql = '%s IS NULL' % lhs.accept(self) |
1394 elif isinstance(rhs, Function) and rhs.name == 'IN': |
1405 elif isinstance(rhs, Function) and rhs.name == 'IN': |
1395 assert operator == '=' |
1406 assert operator == '=' |
1396 operator = ' ' |
1407 operator = ' ' |
1397 if lhs is None: |
1408 if sql is None: |
1398 return '%s%s'% (operator, rhs.accept(self)) |
1409 if lhs is None: |
1399 return '%s%s%s'% (lhs.accept(self), operator, rhs.accept(self)) |
1410 sql = '%s%s'% (operator, rhs.accept(self)) |
|
1411 else: |
|
1412 sql = '%s%s%s'% (lhs.accept(self), operator, rhs.accept(self)) |
|
1413 if optional is None: |
|
1414 return sql |
|
1415 leftvars = cmp.children[0].get_nodes(VariableRef) |
|
1416 assert len(leftvars) == 1 |
|
1417 leftalias = self._var_table(leftvars[0].variable.stinfo['attrvar']) |
|
1418 rightvars = cmp.children[1].get_nodes(VariableRef) |
|
1419 assert len(rightvars) == 1 |
|
1420 rightalias = self._var_table(rightvars[0].variable.stinfo['attrvar']) |
|
1421 if optional == 'right': |
|
1422 self._state.replace_tables_by_outer_join( |
|
1423 leftalias, rightalias, 'LEFT', sql) |
|
1424 elif optional == 'left': |
|
1425 self._state.replace_tables_by_outer_join( |
|
1426 rightalias, leftalias, 'LEFT', sql) |
|
1427 else: |
|
1428 self._state.replace_tables_by_outer_join( |
|
1429 leftalias, rightalias, 'FULL', sql) |
|
1430 return '' |
1400 |
1431 |
1401 def visit_mathexpression(self, mexpr): |
1432 def visit_mathexpression(self, mexpr): |
1402 """generate SQL for a mathematic expression""" |
1433 """generate SQL for a mathematic expression""" |
1403 lhs, rhs = mexpr.get_parts() |
1434 lhs, rhs = mexpr.get_parts() |
1404 # check for string concatenation |
1435 # check for string concatenation |