Skip to content

CAY-2541 Performing query with expression with ObjectId throws NPE in… #389

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: STABLE-4.1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Date:
Bug Fixes:

CAY-2417 Modeler: wrong title in attribute context menu
CAY-2541 Performing query with expression with ObjectId throws NPE in some cases
CAY-2553 Wrong disjoint prefetch query qualifier
CAY-2573 DI field injection is triggered when creating sql Driver
CAY-2580 Cgen: Can't use custom templates for client mode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import org.apache.cayenne.CayenneRuntimeException;
Expand Down Expand Up @@ -198,29 +199,43 @@ protected void appendObjectMatch() throws IOException {
// superclass's
// impl.
matchingObject = false;

boolean first = true;
boolean needToProcessLiterals = true;

DbRelationship relationship = objectMatchTranslator.getRelationship();
if (!relationship.isToMany() && !relationship.isToPK()) {
if (relationship != null && !relationship.isToMany() && !relationship.isToPK()) {
needToProcessLiterals = false;
queryAssembler.dbRelationshipAdded(relationship, JoinType.INNER, objectMatchTranslator.getJoinSplitAlias());
}

Iterator<String> it = objectMatchTranslator.keys();
while (it.hasNext()) {
if (first) {
first = false;
} else {
out.append(" AND ");
}
Map<String, DbAttribute> attributes = objectMatchTranslator.attributes;
if(attributes != null) {
needToProcessLiterals = false;
Iterator<String> it = objectMatchTranslator.keys();
while (it.hasNext()) {
if (first) {
first = false;
} else {
out.append(" AND ");
}

String key = it.next();
DbAttribute attr = objectMatchTranslator.getAttribute(key);
Object val = objectMatchTranslator.getValue(key);

String key = it.next();
DbAttribute attr = objectMatchTranslator.getAttribute(key);
Object val = objectMatchTranslator.getValue(key);
processColumn(attr);
out.append(objectMatchTranslator.getOperation());
appendLiteral(val, attr, objectMatchTranslator.getExpression());
}
}

processColumn(attr);
out.append(objectMatchTranslator.getOperation());
appendLiteral(val, attr, objectMatchTranslator.getExpression());
if(needToProcessLiterals) {
DbAttribute attribute = paramsDbType(objectMatchTranslator.getExpression());
matchingObject = false;
appendLiteral(
objectMatchTranslator.getValue(attribute.getName()),
attribute,
objectMatchTranslator.getExpression());
}

objectMatchTranslator.reset();
Expand All @@ -236,8 +251,10 @@ public void finishedChild(Expression node, int childIndex, boolean hasMoreChildr
if (!hasMoreChildren) {
return;
}

Appendable out = (matchingObject) ? new StringBuilder() : this.out;
boolean hasObjectsToMatch = objectMatchTranslator != null &&
(objectMatchTranslator.attributes != null ||
objectMatchTranslator.relationship != null);
Appendable out = (matchingObject && hasObjectsToMatch) ? new StringBuilder() : this.out;

try {
switch (node.getType()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
****************************************************************/
package org.apache.cayenne.query;

import java.util.List;

import org.apache.cayenne.ObjectId;
import org.apache.cayenne.access.DataContext;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.exp.parser.ASTDbPath;
import org.apache.cayenne.exp.parser.ASTEqual;
import org.apache.cayenne.exp.parser.ASTScalar;
import org.apache.cayenne.test.jdbc.DBHelper;
import org.apache.cayenne.test.jdbc.TableHelper;
import org.apache.cayenne.testdo.testmap.Artist;
import org.apache.cayenne.unit.di.server.CayenneProjects;
import org.apache.cayenne.unit.di.server.ServerCase;
import org.apache.cayenne.unit.di.server.UseServerRuntime;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
public class CAY2541IT extends ServerCase {

@Inject
private DataContext context;

@Inject
private DBHelper dbHelper;

@Before
public void createArtistsDataSet() throws Exception {
TableHelper tArtist = new TableHelper(dbHelper, "ARTIST");
tArtist.setColumns("ARTIST_ID", "ARTIST_NAME", "DATE_OF_BIRTH");

long dateBase = System.currentTimeMillis();
for (int i = 1; i <= 20; i++) {
tArtist.insert(i, "artist" + i, new java.sql.Date(dateBase + 10000 * i));
}

TableHelper tGallery = new TableHelper(dbHelper, "GALLERY");
tGallery.setColumns("GALLERY_ID", "GALLERY_NAME");
tGallery.insert(1, "tate modern");

TableHelper tPaintings = new TableHelper(dbHelper, "PAINTING");
tPaintings.setColumns("PAINTING_ID", "PAINTING_TITLE", "ARTIST_ID", "GALLERY_ID");
for (int i = 1; i <= 20; i++) {
tPaintings.insert(i, "painting" + i, i % 5 + 1, 1);
}
}

@Test
public void testCay2541() {
ObjectId id = new ObjectId("Artist", "ARTIST_ID", 1);
ASTDbPath astDbPath = new ASTDbPath("ARTIST_ID");
ASTScalar astScalar = new ASTScalar(id);
ASTEqual astEqual = new ASTEqual();
astEqual.setOperand(0, astDbPath);
astEqual.setOperand(1, astScalar);
List<Artist> artists = ObjectSelect.query(Artist.class)
.where(astEqual)
.select(context);
assertEquals(1, artists.size());
assertEquals("artist1", artists.get(0).getArtistName());
}
}