Skip to content

Commit 207978e

Browse files
authored
Fix NOT IN with Empy Subquery (#524)
1 parent 1e4c552 commit 207978e

File tree

5 files changed

+37
-12
lines changed

5 files changed

+37
-12
lines changed

core/src/main/java/org/polypheny/db/algebra/enumerable/EnumUtils.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,9 @@ public static Expression makeTernary( ExpressionType ternaryType, Expression e0,
389389

390390

391391
public static Expression unwrapPoly( Expression expression ) {
392-
return expression.type == PolyBoolean.class ? Expressions.convert_( Expressions.field( expression, "value" ), boolean.class ) : expression;
392+
return expression.type == PolyBoolean.class
393+
? Expressions.makeTernary( ExpressionType.Conditional, Expressions.call( expression, "isNull"), Expressions.constant( false ), Expressions.convert_( Expressions.field( expression, "value" ), boolean.class ) )
394+
: expression;
393395
}
394396

395397

core/src/main/java/org/polypheny/db/algebra/enumerable/RexImpTable.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ public Expression implement( RexToLixTranslator translator, RexCall call, NullAs
638638
if ( Objects.requireNonNull( nullAs ) == NullAs.NULL ) {
639639
return Expressions.call( BuiltInMethod.NOT.method, translator.translateList( call.getOperands(), nullAs ) );
640640
}
641-
return Expressions.not( translator.translate( call.getOperands().get( 0 ), negate( nullAs ) ) );
641+
return EnumUtils.not( translator.translate( call.getOperands().get( 0 ), negate( nullAs ) ) );
642642
}
643643

644644

@@ -2459,6 +2459,7 @@ public Expression implement( RexToLixTranslator translator, RexCall call, NullAs
24592459
final ParameterExpression _list = Expressions.parameter( Types.of( List.class, PolyValue.class ), "_list" );
24602460
final ParameterExpression par = Expressions.parameter( PolyValue.class, "_arr" );
24612461
final ParameterExpression get_ = Expressions.parameter( PolyValue.class, "_elem$" );
2462+
final ParameterExpression cond_ = Expressions.parameter( boolean.class, "_cond" );
24622463
builder.add( Expressions.declare( 0, par, translator.translate( call.getOperands().get( 0 ), NullAs.NOT_POSSIBLE, null ) ) );
24632464
builder.add(
24642465
Expressions.declare( 0, predicate, Expressions.constant( false ) ) );
@@ -2467,8 +2468,9 @@ public Expression implement( RexToLixTranslator translator, RexCall call, NullAs
24672468
);
24682469
BlockStatement _do = Expressions.block(
24692470
Expressions.declare( 0, get_, Expressions.convert_( Expressions.call( _list, "get", i_ ), PolyValue.class ) ),
2471+
Expressions.declare( 0, cond_, Expressions.field( translator.translateWithoutAttach( call.getOperands().get( 1 ), NullAs.NOT_POSSIBLE, null ), "value" ) ),
24702472
EnumUtils.ifThen(
2471-
translator.translate( call.getOperands().get( 1 ), NullAs.NOT_POSSIBLE, null ),
2473+
cond_,
24722474
Expressions.block( Expressions.return_( null, Expressions.constant( true ) ) ) )
24732475
);
24742476

core/src/main/java/org/polypheny/db/algebra/enumerable/RexToLixTranslator.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -247,13 +247,21 @@ Expression translate( RexNode expr, Type storageType ) {
247247

248248

249249
Expression translate( RexNode expr, RexImpTable.NullAs nullAs, Type storageType ) {
250-
Expression expression = translate0( expr, nullAs, storageType );
250+
Expression expression = translatePlain( expr, nullAs, storageType );
251251
expression = EnumUtils.enforce( storageType, expression );
252252
assert expression != null;
253253
return list.append( "v", expression );
254254
}
255255

256256

257+
Expression translateWithoutAttach( RexNode expr, RexImpTable.NullAs nullAs, Type storageType ) {
258+
Expression expression = translatePlain( expr, nullAs, storageType );
259+
expression = EnumUtils.enforce( storageType, expression );
260+
assert expression != null;
261+
return expression;
262+
}
263+
264+
257265
Expression translateCast( AlgDataType sourceType, AlgDataType targetType, Expression operand ) {
258266
Expression convert = null;
259267
convert = switch ( targetType.getPolyType() ) {
@@ -436,7 +444,7 @@ public Expression handleNull( Expression input, RexImpTable.NullAs nullAs ) {
436444
* @param nullAs If false, if expression is definitely not null at runtime. Therefore we can optimize. For example, we can cast to int using x.intValue().
437445
* @return Translated expression
438446
*/
439-
private Expression translate0( RexNode expr, RexImpTable.NullAs nullAs, Type storageType ) {
447+
private Expression translatePlain( RexNode expr, RexImpTable.NullAs nullAs, Type storageType ) {
440448
if ( nullAs == RexImpTable.NullAs.NULL && !expr.getType().isNullable() ) {
441449
nullAs = RexImpTable.NullAs.NOT_POSSIBLE;
442450
}

core/src/main/java/org/polypheny/db/plan/AlgOptUtil.java

-7
Original file line numberDiff line numberDiff line change
@@ -462,13 +462,6 @@ public static Exists createExistsPlan( AlgNode seekAlg, SubQueryType subQueryTyp
462462
return new Exists( seekAlg, false, true );
463463
}
464464

465-
switch ( logic ) {
466-
case TRUE_FALSE_UNKNOWN:
467-
case UNKNOWN_AS_TRUE:
468-
if ( notIn && !containsNullableFields( seekAlg ) ) {
469-
logic = Logic.TRUE_FALSE;
470-
}
471-
}
472465
AlgNode ret = seekAlg;
473466
final AlgCluster cluster = seekAlg.getCluster();
474467
final RexBuilder rexBuilder = cluster.getRexBuilder();

dbms/src/test/java/org/polypheny/db/sql/clause/SelectTest.java

+20
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818

1919

2020
import static org.junit.jupiter.api.Assertions.assertEquals;
21+
import static org.junit.jupiter.api.Assertions.assertTrue;
2122

2223
import com.google.common.collect.ImmutableList;
2324
import java.sql.Connection;
25+
import java.sql.ResultSet;
2426
import java.sql.SQLException;
2527
import java.sql.Statement;
2628
import java.util.List;
@@ -278,4 +280,22 @@ public void insertUpdateTest() throws SQLException {
278280
}
279281
}
280282

283+
284+
@Test
285+
public void selectNotInSubqueryTest() throws SQLException {
286+
try ( TestHelper.JdbcConnection polyphenyDbConnection = new TestHelper.JdbcConnection( true ) ) {
287+
Connection connection = polyphenyDbConnection.getConnection();
288+
try ( Statement statement = connection.createStatement() ) {
289+
statement.executeUpdate( "DROP TABLE IF EXISTS partsupp" );
290+
statement.executeUpdate( "DROP TABLE IF EXISTS supplier" );
291+
statement.executeUpdate( "CREATE TABLE partsupp ( ps_partkey INTEGER NOT NULL, ps_suppkey INTEGER NOT NULL, PRIMARY KEY (ps_partkey, ps_suppkey) );" );
292+
statement.executeUpdate( "CREATE TABLE supplier ( s_suppkey INTEGER PRIMARY KEY, s_comment VARCHAR(101) NOT NULL )" );
293+
statement.executeUpdate( "INSERT INTO partsupp VALUES (1, 1)" );
294+
statement.executeUpdate( "INSERT INTO supplier VALUES (1, '')" );
295+
ResultSet rs = statement.executeQuery( "SELECT * FROM partsupp WHERE ps_suppkey NOT IN (SELECT s_suppkey FROM supplier WHERE s_comment <> '')" );
296+
assertTrue( rs.next() );
297+
}
298+
}
299+
}
300+
281301
}

0 commit comments

Comments
 (0)