Java Code Examples for org.kie.api.runtime.KieSession#getQueryResults()

The following examples show how to use org.kie.api.runtime.KieSession#getQueryResults() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: QueryRulesJUnitTest.java    From drools-workshop with Apache License 2.0 6 votes vote down vote up
@Test
public void testQuery() {
    Assert.assertNotNull(kBase);
    KieSession kSession = kBase.newKieSession();
    System.out.println(" ---- Starting testQuery() Test ---");

    List<Person> generatePersons = generatePersons(100);
    for (Person p : generatePersons) {
        kSession.insert(p);
    }
    kSession.fireAllRules();
    QueryResults queryResults = kSession.getQueryResults("all persons older than", 50);
    for (QueryResultsRow row : queryResults) {
            System.out.println(" >>> Result : " + row.get("$p"));
    }

    System.out.println(" ---- Finished testQuery() Test ---");
    kSession.dispose();
}
 
Example 2
Source File: ClinicalRulesJUnitTest.java    From drools-workshop with Apache License 2.0 6 votes vote down vote up
@Test
public void testPatientWithBloodPressureObservations() {

    printGeneratedDRL( ClinicalRulesJUnitTest.class.getResourceAsStream( "/rules/clinical-decision-table.xls" ), System.out );

    Assert.assertNotNull( kBase );
    KieSession kSession = kBase.newKieSession();

    kSession.insert( generatePatients( 1 ).get( 0 ) );

    List<Observation> observations = generateObservations( "headache", 4 );
    for ( Observation observation : observations ) {
        kSession.insert( observation );
    }

    Assert.assertEquals( 2, kSession.fireAllRules() );

    QueryResults queryResults = kSession.getQueryResults( "getAllRecommendations", ( Object ) null );
    for ( QueryResultsRow row : queryResults ) {
        Recommendation r = ( Recommendation ) row.get( "$r" );
        System.out.println( " >>> Result : " + r );
    }

    kSession.dispose();
}
 
Example 3
Source File: QueryCommand.java    From kogito-runtimes with Apache License 2.0 6 votes vote down vote up
public QueryResults execute(Context context) {
    KieSession ksession = ((RegistryContext) context).lookup( KieSession.class );

    if ( this.arguments == null || this.arguments.isEmpty() ) {
        this.arguments = Collections.emptyList();
    }

    for (int j = 0; j < arguments.size(); j++) {
        if (arguments.get(j) instanceof Variable) {
            arguments.set(j, Variable.v);
        }
    }

    QueryResults results = ksession.getQueryResults( name, this.arguments.toArray() );

    if ( this.outIdentifier != null ) {
        ((RegistryContext) context).lookup( ExecutionResultImpl.class ).setResult( this.outIdentifier, new FlatQueryResults( (QueryResultsImpl) results) );
    }

    return results;
}
 
Example 4
Source File: RecursiveQueryBenchmark.java    From kogito-runtimes with Apache License 2.0 6 votes vote down vote up
public static long[] execTest(KieBase kbase, int n, boolean isRelational) {
    KieSession ksession = kbase.newKieSession();

    Node root = generateTree( ksession, n, isRelational );

    List list = new ArrayList();
    long start = System.nanoTime();
    ksession.getQueryResults( "findNodesWithValue", isRelational ? root.getId() : root, 0, list );
    ksession.fireAllRules();
    long[] result = new long[]{ (System.nanoTime() - start) };
    //System.out.println( list.size() );

    ksession.dispose();

    return result;
}
 
Example 5
Source File: OOPathQueriesTest.java    From kogito-runtimes with Apache License 2.0 6 votes vote down vote up
@Test
public void testQueryFromCode() {
    final String drl =
            "import org.drools.compiler.oopath.model.Thing;\n" +
                    "query isContainedIn( Thing $x, Thing $y )\n" +
                    "    $y := /$x/children\n" +
                    "or\n" +
                    "    ( $z := /$x/children and isContainedIn( $z, $y; ) )\n" +
                    "end\n";

    final Thing smartphone = new Thing("smartphone");
    final List<String> itemList = Arrays.asList(new String[] { "display", "keyboard", "processor" });
    itemList.stream().map(item -> new Thing(item)).forEach((thing) -> smartphone.addChild(thing));

    final KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL )
            .build()
            .newKieSession();
    ksession.insert(smartphone);

    final QueryResults queryResults = ksession.getQueryResults("isContainedIn", new Object[] { smartphone, Variable.v });
    final List<String> resultList = StreamSupport.stream(queryResults.spliterator(), false)
            .map(row -> ((Thing) row.get("$y")).getName()).collect(Collectors.toList());
    assertThat(resultList).as("Query does not contain all items").containsAll(itemList);

    ksession.dispose();
}
 
Example 6
Source File: Query3Test.java    From kogito-runtimes with Apache License 2.0 6 votes vote down vote up
private void doIt(Object o1,
                  Object o2,
                  String query,
                  int expected,
                  boolean doUpdate,
                  boolean doRetract) {
    KieSession knowledgeSession = knowledgeBase.newKieSession();
    try {
        knowledgeSession.insert( o1 );
        FactHandle handle2 = knowledgeSession.insert( o2 );
        if ( doUpdate ) {
            knowledgeSession.update( handle2,
                                     o2 );
        } else if ( doRetract ) {
            knowledgeSession.retract( handle2 );
            handle2 = knowledgeSession.insert( o2 );
        }
        QueryResults queryResults = knowledgeSession.getQueryResults( query );
        assertEquals( expected,
                      queryResults.size() );
    } finally {
        knowledgeSession.dispose();
    }
}
 
Example 7
Source File: QueryTest.java    From kogito-runtimes with Apache License 2.0 5 votes vote down vote up
@Test
public void testQueryWithOptionalOr() {
    // DROOLS-1386
    String str =
            "package org.test\n" +
            "import " + Question.class.getCanonicalName() + "\n" +
            "import " + QuestionVisible.class.getCanonicalName() + "\n" +
            "query QuestionsKnowledge\n" +
            "    $question: Question()\n" +
            "    $visible: QuestionVisible(question == $question) or not QuestionVisible(question == $question)\n" +
            "end\n";

    KieSession ksession = new KieHelper().addContent( str, ResourceType.DRL ).build().newKieSession();
    Question question = new Question();
    ksession.insert( question );
    QueryResults results = ksession.getQueryResults("QuestionsKnowledge");
    assertEquals( 1, results.size() );
    QueryResultsRow row = results.iterator().next();
    assertSame( question, row.get( "$question" ) );

    QuestionVisible questionVisible = new QuestionVisible( question );
    ksession.insert( questionVisible );
    results = ksession.getQueryResults("QuestionsKnowledge");
    assertEquals( 1, results.size() );
    row = results.iterator().next();
    assertSame( question, row.get( "$question" ) );
    assertSame( questionVisible, row.get( "$visible" ) );
}
 
Example 8
Source File: DeliveryServiceImpl.java    From drools-workshop with Apache License 2.0 5 votes vote down vote up
@Override
public Delivery getDelivery(String deliveryId) throws BusinessException {
    KieSession kieSession = onGoingDeliveries.get(deliveryId);
    QueryResults queryResults = kieSession.getQueryResults("getDelivery", new Object[]{});
    for (QueryResultsRow qrr : queryResults) {
        return (Delivery) qrr.get("$d");
    }
    return null;
}
 
Example 9
Source File: QueryTest.java    From kogito-runtimes with Apache License 2.0 5 votes vote down vote up
@Test
public void testQueryWithEval() throws IOException, ClassNotFoundException {
    // [Regression in 5.2.0.M2]: NPE during rule evaluation on MVELPredicateExpression.evaluate(MVELPredicateExpression.java:82)

    String str = "package org.drools.compiler.integrationtests\n" +
                 "import " + DomainObject.class.getCanonicalName() + " \n" +
                 "query queryWithEval \n" +
                 "    $do: DomainObject()\n" +
                 "    not DomainObject( id == $do.id, eval(interval.isAfter($do.getInterval())))\n" +
                 "end";

    KieBase kbase = SerializationHelper.serializeObject(loadKnowledgeBaseFromString(str));
    KieSession ksession = createKieSession( kbase );

    DomainObject do1 = new DomainObject();
    do1.setId( 1 );
    do1.setInterval( new Interval( 10,
                                   5 ) );
    DomainObject do2 = new DomainObject();
    do2.setId( 1 );
    do2.setInterval( new Interval( 20,
                                   5 ) );
    ksession.insert( do1 );
    ksession.insert( do2 );

    org.kie.api.runtime.rule.QueryResults results = ksession.getQueryResults( "queryWithEval" );
    assertEquals( 1,
                  results.size() );
    assertEquals( do2,
                  results.iterator().next().get( "$do" ) );

    ksession.dispose();
}
 
Example 10
Source File: QueryTest.java    From kogito-runtimes with Apache License 2.0 5 votes vote down vote up
public void runQueryListenerTest( QueryListenerOption option ) throws IOException, ClassNotFoundException {
    String str = "";
    str += "package org.drools.compiler.integrationtests\n";
    str += "import " + Cheese.class.getCanonicalName() + " \n";
    str += "query cheeses(String $type) \n";
    str += "    $cheese : Cheese(type == $type) \n";
    str += "end\n";

    KieBase kbase = SerializationHelper.serializeObject(loadKnowledgeBaseFromString(str));
    KieSession ksession = createKieSession( kbase, option );

    // insert some data into the session
    for ( int i = 0; i < 10000; i++ ) {
        ksession.insert( new Cheese( i % 2 == 0 ? "stilton" : "brie" ) );
    }

    // query the session
    List<Cheese> cheeses;
    for ( int i = 0; i < 100; i++ ) {
        org.kie.api.runtime.rule.QueryResults queryResults = ksession.getQueryResults( "cheeses",
                                                                                      new Object[]{"stilton"} );
        cheeses = new ArrayList<Cheese>();
        for ( QueryResultsRow row : queryResults ) {
            cheeses.add( (Cheese) row.get( "$cheese" ) );
        }

        assertEquals( 5000,
                      cheeses.size() );
    }
}
 
Example 11
Source File: QueryTest.java    From kogito-runtimes with Apache License 2.0 5 votes vote down vote up
@Test
public void testQueryWithParams() throws Exception {
    KieBase kbase = SerializationHelper.serializeObject(loadKnowledgeBase("test_QueryWithParams.drl"));
    KieSession session = createKieSession( kbase );

    session.fireAllRules();

    String queryName = "assertedobjquery";
    String [] arguments = new String[]{"value1"};
    QueryResultsImpl resultsImpl = (QueryResultsImpl) session.getQueryResults( queryName, arguments );

    QueryResults results = getQueryResults( session, queryName, arguments );

    assertEquals( 1,
                  results.size() );
    InsertedObject value = new InsertedObject( "value1" );
    assertEquals( value,
                  ((InternalFactHandle) results.iterator().next().getFactHandle( "assertedobj" )).getObject()  );
    assertEquals( value,
                  results.iterator().next().get("assertedobj") );

    results = getQueryResults( session, "assertedobjquery", new String[]{"value3"}  );

    assertEquals( 0,
                  results.size() );

    results = getQueryResults( session, "assertedobjquery2", new String[]{null, "value2"}  );
    assertEquals( 1,
                  results.size() );
    assertEquals( new InsertedObject( "value2" ),
                  ((InternalFactHandle) results.iterator().next().getFactHandle( "assertedobj" )).getObject() );

    results = getQueryResults(session, "assertedobjquery2", new String[]{"value3", "value2"}  );

    assertEquals( 1,
                  results.size() );
    assertEquals( new InsertedObject( "value2" ),
                  ((InternalFactHandle) results.iterator().next().getFactHandle( "assertedobj" )).getObject()  );
}
 
Example 12
Source File: ConcurrentBasesParallelTest.java    From kogito-runtimes with Apache License 2.0 5 votes vote down vote up
@ParameterizedConcurrentBasesParallelTest
public void testQueries2(Parameters params) throws InterruptedException {
    final int numberOfObjects = 100;

    final String queryTemplate = "import " + BeanA.class.getCanonicalName() + ";\n" +
            "query Query " +
            "    bean : BeanA( seed == ${seed} ) " +
            "end";

    final TestExecutor exec = counter -> {
        final int seed = counter % 2;
        final String seedString = "" + seed;
        final String queryDrl = queryTemplate.replace("${seed}", seedString);
        final KieBase base = getKieBase(params, queryDrl);
        final KieSession session = base.newKieSession();

        try {
            for (int i = 0; i < numberOfObjects; i++) {
                session.insert(new BeanA(seed));
            }
            final QueryResults results = session.getQueryResults("Query");
            assertThat(results).hasSize(numberOfObjects);
            for (final QueryResultsRow row : results) {
                final BeanA bean = (BeanA) row.get("bean");
                assertThat(bean.getSeed()).isEqualTo(seed);
            }
            return true;
        } finally {
            session.dispose();
        }
    };

    parallelTest(NUMBER_OF_THREADS, exec);
}
 
Example 13
Source File: ConcurrentBasesParallelTest.java    From kogito-runtimes with Apache License 2.0 5 votes vote down vote up
@ParameterizedConcurrentBasesParallelTest
public void testQueries(Parameters params) throws InterruptedException {
    final int numberOfObjects = 100;

    final TestExecutor exec = counter -> {
        final String query = "import " + BeanA.class.getCanonicalName() + ";\n" +
                "query Query " +
                "    bean : BeanA( seed == " + counter + " ) " +
                "end";

        final KieBase base = getKieBase(params, query);
        final KieSession session = base.newKieSession();

        try {
            final BeanA bean = new BeanA(counter);
            session.insert(bean);
            for (int i = 0; i < numberOfObjects; i++) {
                if (i != counter) {
                    session.insert(new BeanA(i));
                }
            }
            final QueryResults results = session.getQueryResults("Query");
            assertThat(results).hasSize(1);
            for (final QueryResultsRow row : results) {
                assertThat(row.get("bean")).isEqualTo(bean);
            }
            return true;
        } finally {
            session.dispose();
        }
    };

    parallelTest(NUMBER_OF_THREADS, exec);
}
 
Example 14
Source File: AbductionTest.java    From kogito-runtimes with Apache License 2.0 4 votes vote down vote up
@Test
public void testQueryAPIs() {
    String droolsSource =
            "package org.drools.abductive.test; \n" +
            "import " + Abducible.class.getName() + "; \n" +

            "" +

            "declare Foo " +
            "   @Abducible " +
            "   id : String " +
            "end " +

            "query foo( String $s ) " +
            "   @Abductive( target=Foo.class ) \n" +
            "end \n "+

            "query bar( String $s, Foo $foo ) " +
            "   $foo := Foo() " +
            "end \n "+

            "rule MoveAround " +
            "when " +
            "   $s : String() " +
            "   $f : foo( $s ; ) " +
            "   bar( $s, $f ; ) " +
            "then " +
            "   delete( $s ); " +
            "   System.out.println( 'Foo ' + $f ); " +
            "end " +

            "";

    /////////////////////////////////////

    KieSession session = getSessionFromString( droolsSource );

    session.insert( "faa" );
    session.fireAllRules();

    for ( Object o : session.getObjects() ) {
        System.out.println( ">>> " + o );
    }
    assertEquals( 1, session.getObjects().size() );

    Query q1 = session.getKieBase().getQuery( "org.drools.abductive.test", "foo" );
    Query q2 = session.getKieBase().getQuery( "org.drools.abductive.test", "bar" );

    assertNotNull( q1 );
    assertNotNull( q2 );

    QueryResults q10res = new FlatQueryResults((QueryResultsImpl) session.getQueryResults( "foo", "foo", null ));
    QueryResults q11res = new FlatQueryResults((QueryResultsImpl) session.getQueryResults( "foo", "foo", Variable.v ));
    QueryResults q20res = new FlatQueryResults((QueryResultsImpl) session.getQueryResults( "bar", "foo", Variable.v ));

    assertEquals( 1, q10res.size() );
    assertEquals( 1, q11res.size() );
    assertEquals( 1, q20res.size() );

    QueryResultsRow row10 = q10res.iterator().next();
    QueryResultsRow row11 = q11res.iterator().next();
    QueryResultsRow row20 = q20res.iterator().next();

    assertEquals( "foo", row10.get( "$s" ) );
    assertEquals( "foo", row11.get( "$s" ) );
    assertEquals( "foo", row20.get( "$s" ) );

    Object foo = row20.get( "$foo" );
    assertSame( foo, session.getObjects().iterator().next() );

    // the implicit return argument, the abduced/retrieved fact, is hidden
    assertNull( row11.get( "" ) );

}
 
Example 15
Source File: QueryBuilderTest.java    From kogito-runtimes with Apache License 2.0 4 votes vote down vote up
@Test
public void testQuery() throws Exception {
    final KnowledgeBuilderImpl builder = new KnowledgeBuilderImpl();

    final PackageDescr packageDescr = new PackageDescr( "p1" );
    final QueryDescr queryDescr = new QueryDescr( "query1" );
    queryDescr.addParameter( "String",
                             "$type" );

    packageDescr.addRule( queryDescr );

    final AndDescr lhs = new AndDescr();
    queryDescr.setLhs( lhs );

    final PatternDescr pattern = new PatternDescr( Cheese.class.getName(),
                                                   "stilton" );
    lhs.addDescr( pattern );

    pattern.addConstraint( new ExprConstraintDescr("type == $type") );

    // Another query, no parameters
    QueryDescr queryDescr2 = new QueryDescr( "query2" );
    packageDescr.addRule( queryDescr2 );
    AndDescr lhs2 = new AndDescr();
    queryDescr2.setLhs( lhs2 );
    PatternDescr pattern2 = new PatternDescr( Cheese.class.getName() );
    lhs2.addDescr( pattern2 );

    builder.addPackage( packageDescr );

    assertThat((Object[]) builder.getErrors().getErrors()).hasSize(0);

    InternalKnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
    kbase.addPackages(Arrays.asList( new KiePackage[] { builder.getPackage(packageDescr.getName()) } ) );

    final KieSession session = kbase.newKieSession();

    session.insert( new Cheese( "stilton",
                                15 ) );

    QueryResults results = session.getQueryResults( "query1",
                                                    "stilton" );
    assertEquals( 1,
                  results.size() );

    Object object = results.iterator().next().get("stilton");
    assertEquals( new Cheese( "stilton",
                              15 ),
                  object );

    results = session.getQueryResults( "query1",
                                       new Object[]{"cheddar"} );
    assertEquals( 0,
                  results.size() );

    session.insert(new Cheese("dolcelatte",
                              20));
    results = session.getQueryResults( "query2",
                                       new Object[]{} );
    assertEquals( 2,
                  results.size() );
}
 
Example 16
Source File: QueryTest.java    From kogito-runtimes with Apache License 2.0 4 votes vote down vote up
@Test
public void testDroolsQueryCleanup() throws Exception {
    KieBase kbase = SerializationHelper.serializeObject(loadKnowledgeBase("test_QueryMemoryLeak.drl"));
    KieSession session = createKieSession( kbase );

    KieSession ksession = kbase.newKieSession();

    String workerId = "B1234";
    Worker worker = new Worker();
    worker.setId( workerId );

    FactHandle handle = ksession.insert( worker );
    ksession.fireAllRules();

    assertNotNull( handle );

    Object retractedWorker = null;
    for ( int i = 0; i < 100; i++ ) {
        retractedWorker = (Object) ksession.getQueryResults( "getWorker",
                                                             new Object[]{workerId} );
    }

    assertNotNull( retractedWorker );

    StatefulKnowledgeSessionImpl sessionImpl = (StatefulKnowledgeSessionImpl) ksession;

    Collection<EntryPointNode> entryPointNodes = sessionImpl.getKnowledgeBase().getRete().getEntryPointNodes().values();

    EntryPointNode defaultEntryPointNode = null;
    for ( EntryPointNode epNode : entryPointNodes ) {
        if ( epNode.getEntryPoint().getEntryPointId().equals( EntryPoint.DEFAULT_NAME ) ) {
            defaultEntryPointNode = epNode;
            break;
        }
    }
    assertNotNull( defaultEntryPointNode );

    Map<ObjectType, ObjectTypeNode> obnodes = defaultEntryPointNode.getObjectTypeNodes();

    ObjectType key = new ClassObjectType( DroolsQuery.class );
    ObjectTypeNode droolsQueryNode = obnodes.get( key );
    Iterator<InternalFactHandle> it = ((ObjectTypeNodeMemory) sessionImpl.getNodeMemory( droolsQueryNode )).iterator();
    assertFalse( it.hasNext() );
}
 
Example 17
Source File: QueryTest.java    From kogito-runtimes with Apache License 2.0 4 votes vote down vote up
@Test
public void testDoubleQueryWithExists() throws Exception {
    KieBase kbase = SerializationHelper.serializeObject(loadKnowledgeBase("test_DoubleQueryWithExists.drl"));
    KieSession session = createKieSession( kbase );

    final Person p1 = new Person( "p1",
                                  "stilton",
                                  20 );
    p1.setStatus( "europe" );
    final FactHandle c1FactHandle = session.insert( p1 );
    final Person p2 = new Person( "p2",
                                  "stilton",
                                  30 );
    p2.setStatus( "europe" );
    final FactHandle c2FactHandle = session.insert( p2 );
    final Person p3 = new Person( "p3",
                                  "stilton",
                                  40 );
    p3.setStatus( "europe" );
    final FactHandle c3FactHandle = session.insert( p3 );
    session.fireAllRules();

    QueryResults results = session.getQueryResults( "2 persons with the same status" );
    assertEquals( 2,
                  results.size() );

    // europe=[ 1, 2 ], america=[ 3 ]
    p3.setStatus( "america" );
    session.update( c3FactHandle,
                          p3 );
    session.fireAllRules();
    results = session.getQueryResults(  "2 persons with the same status" );
    assertEquals( 1,
                  results.size() );

    // europe=[ 1 ], america=[ 2, 3 ]
    p2.setStatus( "america" );
    session.update( c2FactHandle,
                          p2 );
    session.fireAllRules();
    results = session.getQueryResults( "2 persons with the same status" );
    assertEquals( 1,
                  results.size() );

    // europe=[ ], america=[ 1, 2, 3 ]
    p1.setStatus( "america" );
    session.update( c1FactHandle,
                          p1 );
    session.fireAllRules();
    results = getQueryResults( session, "2 persons with the same status" );
    assertEquals( 2,
                  results.size() );

    // europe=[ 2 ], america=[ 1, 3 ]
    p2.setStatus( "europe" );
    session.update( c2FactHandle,
                          p2 );
    session.fireAllRules();
    results = getQueryResults( session, "2 persons with the same status" );
    assertEquals( 1,
                  results.size() );

    // europe=[ 1, 2 ], america=[ 3 ]
    p1.setStatus( "europe" );
    session.update( c1FactHandle,
                          p1 );
    session.fireAllRules();
    results = session.getQueryResults( "2 persons with the same status" );
    assertEquals( 1,
                  results.size() );

    // europe=[ 1, 2, 3 ], america=[ ]
    p3.setStatus( "europe" );
    session.update( c3FactHandle,
                          p3 );
    session.fireAllRules();
    results = session.getQueryResults( "2 persons with the same status" );
    assertEquals( 2,
                  results.size() );
}
 
Example 18
Source File: QueryTest.java    From kogito-runtimes with Apache License 2.0 4 votes vote down vote up
private static QueryResults getQueryResults(KieSession session, String queryName, Object... arguments ) throws Exception {
    QueryResultsImpl results = (QueryResultsImpl) session.getQueryResults( queryName, arguments );

    FlatQueryResults flatResults = new FlatQueryResults(results);

    assertEquals(results.size(), flatResults.size(), "Query results size");
    assertEquals(results.getIdentifiers().length, flatResults.getIdentifiers().length, "Query results identifiers");
    Set<String> resultIds = new TreeSet<String>(Arrays.asList(results.getIdentifiers()));
    Set<String> flatIds = new TreeSet<String>(Arrays.asList(flatResults.getIdentifiers()));
    assertArrayEquals(resultIds.toArray(), flatIds.toArray(), "Flat query results identifiers");

    FlatQueryResults copyFlatResults = roundTrip(flatResults);
    String [] identifiers = results.getIdentifiers();
    Iterator<QueryResultsRow> copyFlatIter = copyFlatResults.iterator();
    for( int i = 0; i < results.size(); ++i ) {
        QueryResultsRow row = results.get(i);
        assertTrue(copyFlatIter.hasNext(),  "Round-tripped flat query results contain less rows than original query results");
        QueryResultsRow copyRow = copyFlatIter.next();
        for( String id : identifiers ) {
            Object obj = row.get(id);
            if( obj != null ) {
                Object copyObj = copyRow.get(id);
                assertTrue(obj != null && obj.equals(copyObj), "Flat query result [" + i + "] does not contain result: '" + id + "': " + obj + "/" + copyObj);
            }
            FactHandle fh = row.getFactHandle(id);
            FactHandle copyFh = copyRow.getFactHandle(id);
            if( fh != null ) {
                assertNotNull(copyFh, "Flat query result [" + i + "] does not contain facthandle: '" + ((InternalFactHandle) fh).getId() + "'");
                String fhStr = fh.toExternalForm();
                fhStr = fhStr.substring(0, fhStr.lastIndexOf(":"));
                String copyFhStr = copyFh.toExternalForm();
                copyFhStr = copyFhStr.substring(0, copyFhStr.lastIndexOf(":"));
                assertEquals(fhStr, copyFhStr, "Unequal fact handles for fact handle '" + ((InternalFactHandle) fh).getId() + "':");
            }
        }
    }

    // check identifiers
    Set<String> copyFlatIds = new TreeSet<String>(Arrays.asList(copyFlatResults.getIdentifiers()));
    assertArrayEquals(flatIds.toArray(), copyFlatIds.toArray(), "Flat query results identifiers");
    return copyFlatResults;
}