"select node.[jcr:path] from [mix:title] as node where node.[jcr:title] = 'title1'", Query.JCR_SQL2); validateQuery().hasNodesAtPaths("/repo1_node1").useIndex("titleIndex").validate(query, query.execute()); "select node.[jcr:path] from [mix:title] as node where node.[jcr:title] = 'title2'", Query.JCR_SQL2); validateQuery().rowCount(0).useIndex("titleIndex").validate(query, query.execute()); "select node.[jcr:path] from [mix:title] as node where node.[jcr:title] = 'title2'", Query.JCR_SQL2); validateQuery().hasNodesAtPaths("/repo1_node2").useIndex("titleIndex").validate(query, query.execute()); "select node.[jcr:path] from [mix:title] as node where node.[jcr:title] = 'title2'", Query.JCR_SQL2); validateQuery().hasNodesAtPaths("/repo1_node2").useIndex("titleIndex").validate(query, query.execute()); } finally { TestingUtil.killRepositories(repository1, repository2);
@Test public void shouldUseSingleColumnNodePathIndexInQueryAgainstSameNodeType() throws Exception { registerValueIndex("pathIndex", "nt:unstructured", "Node path index", "*", "jcr:path", PropertyType.PATH); // print = true; // Add a node that uses this type ... Node book1 = session().getRootNode().addNode("myFirstBook"); book1.addMixin("mix:title"); book1.setProperty("jcr:title", "The Title"); Node book2 = session().getRootNode().addNode("mySecondBook"); book2.addMixin("mix:title"); book2.setProperty("jcr:title", "A Different Title"); Node other = book2.addNode("chapter"); other.setProperty("propA", "a value for property A"); other.setProperty("jcr:title", "The Title"); session.save(); // Issues a query that should NOT use this index because direct lookup by path is lower cost ... Query query = jcrSql2Query("SELECT * FROM [nt:unstructured] WHERE [jcr:path] = '/myFirstBook'"); validateQuery().rowCount(1L).useIndex("NodeByPath").considerIndex("pathIndex").validate(query, query.execute()); // Issues a query that should NOT use this index ... query = jcrSql2Query("SELECT * FROM [nt:unstructured] WHERE [jcr:path] LIKE '/my%Book'"); validateQuery().rowCount(2L).useNoIndexes().validate(query, query.execute()); // Issues some queries that should use this index ... query = jcrSql2Query("SELECT * FROM [nt:unstructured] WHERE [jcr:path] > '/mySecondBook'"); validateQuery().rowCount(1L).useIndex("pathIndex").validate(query, query.execute()); query = jcrSql2Query("SELECT * FROM [nt:unstructured] WHERE PATH() > '/mySecondBook'"); validateQuery().rowCount(1L).useIndex("pathIndex").validate(query, query.execute()); }
validateQuery().rowCount(1L).useIndex("refIndex").validate(query, query.execute()); validateQuery().rowCount(1L).useIndex("refIndex").validate(query, query.execute()); validateQuery().rowCount(1L).useIndex("sysIndex").validate(query, query.execute()); validateQuery().rowCount(1L).considerIndexes("refIndex", "sysIndex").validate(query, query.execute());
QueryResult result = query.execute(); final Map<String, Node> nodesById = new HashMap<>(); validateQuery().rowCount(24).noWarnings().hasColumns("reallylongvaluethatwillprintcompletely").onEachRow(new Predicate() { @Override public void validate( int rowNumber, nodesById.put(id, nodeFromQuery); }).validate(query, result); query = session.getWorkspace().getQueryManager().createQuery(sql, Query.JCR_SQL2); result = query.execute(); validateQuery().rowCount(1).noWarnings().hasColumns("reallylongvaluethatwillprintcompletely") .onEachRow(new Predicate() { @Override public void validate( int rowNumber, assertSame(nodeId, id); }).validate(query, result); query.bindValue("id", session().getValueFactory().createValue(id)); result = query.execute(); validateQuery().rowCount(1).noWarnings().hasColumns("mode:id").onEachRow(new Predicate() { @Override public void validate( int rowNumber, }).validate(query, result);
Query.JCR_SQL2); validateQuery().hasNodesAtPaths("/repo1_node1").useIndex("titleIndex").validate(query, query.execute()); session2.logout(); "select node.[jcr:path] from [mix:title] as node where node.[jcr:title] = 'title2'", Query.JCR_SQL2); validateQuery().rowCount(0).useIndex("titleIndex").validate(query, query.execute()); Query.JCR_SQL2); validateQuery().hasNodesAtPaths("/repo1_node2").useIndex("titleIndex").validate(query, query.execute()); } finally { TestingUtil.killRepositories(repository1, repository2);
query.bindValue("author", session.getValueFactory().createValue("author1")); validateQuery() .useNoIndexes() .rowCount(1) .hasNodesAtPaths("/book1") .validate(query, query.execute()); .useNoIndexes() .rowCount(2) .onEachRow(new ValidateQuery.Predicate() { @Override public void validate( int rowNumber, Row row ) throws RepositoryException { .validate(query, query.execute()); assertTrue("Not all paths found: " + expectedPaths, expectedPaths.isEmpty());
QueryResult result = query.execute(); validateQuery() .rowCount(4) .hasNodesAtPaths("/words/word1", "/words/word2", "/words/word3", "/words/word4").validate(query, result); .rowCount(4) .hasNodesAtPaths("/words/word1", "/words/word3", "/words/word2", "/words/word4").validate(query, result); } finally { session.getNode("/words").remove();
@Test @FixFor( "MODE-2435" ) public void shouldCorrectlyExecuteOrderByWithOffsetAndLimit() throws RepositoryException { // no order by String sql = "SELECT [jcr:path] FROM [car:Car] LIMIT 10 OFFSET 15"; Query query = session.getWorkspace().getQueryManager().createQuery(sql, Query.JCR_SQL2); QueryResult result = query.execute(); assertThat("result should contain zero rows", result.getRows().getSize(), is(0L)); // with order by sql = "SELECT [jcr:path] FROM [car:Car] ORDER BY [jcr:path] LIMIT 10 OFFSET 15"; query = session.getWorkspace().getQueryManager().createQuery(sql, Query.JCR_SQL2); result = query.execute(); assertThat("result should contain zero rows", result.getRows().getSize(), is(0L)); sql = "SELECT [jcr:path] FROM [car:Car] ORDER BY [jcr:path] LIMIT 1 OFFSET 0"; query = session.getWorkspace().getQueryManager().createQuery(sql, Query.JCR_SQL2); result = query.execute(); validateQuery().hasNodesAtPaths("/Cars/Hybrid/Nissan Altima").validate(query, result); sql = "SELECT [jcr:path] FROM [car:Car] ORDER BY [jcr:path] LIMIT 1 OFFSET 1"; query = session.getWorkspace().getQueryManager().createQuery(sql, Query.JCR_SQL2); result = query.execute(); validateQuery().hasNodesAtPaths("/Cars/Hybrid/Toyota Highlander").validate(query, result); sql = "SELECT [jcr:path] FROM [car:Car] ORDER BY [jcr:path] LIMIT 3 OFFSET 0"; query = session.getWorkspace().getQueryManager().createQuery(sql, Query.JCR_SQL2); result = query.execute(); validateQuery().hasNodesAtPaths("/Cars/Hybrid/Nissan Altima", "/Cars/Hybrid/Toyota Highlander", "/Cars/Hybrid/Toyota Prius").validate(query, result); }
@FixFor( "MODE-2346" ) @Test public void shouldUseImplicitIndexesWithLowerCardinalityOverExplicitIndexes() throws Exception { String explicitNodesById = "explicitNodesById"; registerValueIndex(explicitNodesById, "nt:unstructured", "Nodes by id explicit index", "*", "jcr:uuid", PropertyType.STRING); String explicitNodesByPath = "explicitNodesByPath"; registerValueIndex(explicitNodesByPath, "nt:unstructured", "Nodes by path explicit index", "*", "jcr:path", PropertyType.PATH); Node root = session().getRootNode(); Node nodeA = root.addNode("nodeA"); nodeA.addMixin("mix:referenceable"); session().save(); // print = true; // Compute a query plan that should use this index ... final String uuid = nodeA.getIdentifier(); Query query = jcrSql2Query("SELECT [jcr:path] FROM [nt:unstructured] WHERE [jcr:uuid] = '" + uuid + "'"); validateQuery() .rowCount(1L) .considerIndexes(IndexPlanners.NODE_BY_ID_INDEX_NAME, explicitNodesById) .useIndex(IndexPlanners.NODE_BY_ID_INDEX_NAME) .validate(query, query.execute()); query = jcrSql2Query("SELECT [jcr:path] FROM [nt:unstructured] WHERE [jcr:path] = '/nodeA'"); validateQuery() .rowCount(1L) .considerIndexes(IndexPlanners.NODE_BY_PATH_INDEX_NAME, explicitNodesByPath) .useIndex(IndexPlanners.NODE_BY_PATH_INDEX_NAME) .validate(query, query.execute()); }
.rowCount(2L) .useIndex("booleanIndex") .hasNodesAtPaths("/node1", "/node2") .validate(query, query.execute()); .rowCount(1L) .useIndex("booleanIndex") .hasNodesAtPaths("/node1") .validate(query, query.execute()); .rowCount(1L) .useIndex("booleanIndex") .hasNodesAtPaths("/node1") .validate(query, query.execute());
@Test @FixFor( "MODE-2682" ) public void shouldUseEnumeratedIndexes() throws Exception { registerNodeTypes("cnd/images.cnd"); registerEnumeratedIndex("imageFormat", "image:metadata", null, "*", "image:formatName", PropertyType.STRING); List<String> formats = Arrays.asList("JPEG", "GIF", "PNG", "BMP", "PCX", "IFF", "RAS", "PBM", "PGM", "PPM", "PSD"); int nodeCountPerFormat = 2; formats.forEach(format -> { try { for (int i = 0; i < nodeCountPerFormat; i++) { Node image = session.getRootNode().addNode("image_" + i, "image:metadata"); image.setProperty("image:formatName", format); } } catch (RepositoryException e) { throw new RuntimeException(e); } }); session.save(); waitForIndexes(); formats.forEach(format -> { try { Query query = jcrSql2Query("select image.[jcr:path] from [image:metadata] as image where image.[image:formatName] = '" + format + "'"); validateQuery().rowCount(nodeCountPerFormat).useIndex("imageFormat").validate(query, query.execute()); } catch (RepositoryException e) { throw new RuntimeException(e); } }); }
Query query = session.getWorkspace().getQueryManager().createQuery(sql, Query.JCR_SQL2); QueryResult result = query.execute(); validateQuery().rowCount(2).hasNodesAtPaths(node1.getPath(), node2.getPath()).validate(query, result); validateQuery().rowCount(2).hasNodesAtPaths(node1.getPath(), node2.getPath()).validate(query, result); validateQuery().rowCount(2).hasNodesAtPaths(node1.getPath(), node2.getPath()).validate(query, result); } finally { testRoot.remove();
private RepositoryOperation reindexingExternalContentOperation() { return repository -> { JcrSession session = repository.login(); // sleep a bit to make sure reindexing completes Thread.sleep(300); try { AbstractJcrNode node = session.getNode("/fs2/file.txt"); String createdBy = node.getProperty("jcr:createdBy").getString(); assertNotNull(createdBy); JcrQueryManager jcrQueryManager = session.getWorkspace().getQueryManager(); Query query = jcrQueryManager.createQuery("select file.[jcr:path] from [nt:file] as file where file.[jcr:createdBy]='" + createdBy + "'", JcrQuery.JCR_SQL2); ValidateQuery.validateQuery() .useIndex("nodesByAuthor") .hasNodesAtPaths("/fs2/file.txt") .validate(query, query.execute()); session.getWorkspace().reindex(); ValidateQuery.validateQuery() .useIndex("nodesByAuthor") .hasNodesAtPaths("/fs2/file.txt") .validate(query, query.execute()); } finally { session.logout(); } }; }
.rowCount(1L) .useIndex("typesIndex") .hasNodesAtPaths("/node101") .validate(query1, query1.execute()); .rowCount(1L) .useIndex("typesIndex") .hasNodesAtPaths("/node51") .validate(query2, query2.execute()); .rowCount(1L) .useIndex("typesIndex") .hasNodesAtPaths("/node1") .validate(query3, query3.execute());
@FixFor( "MODE-2296" ) @Test public void shouldUseIndexesEvenWhenLocalIndexDoesNotContainValueUsedInCriteria() throws Exception { registerValueIndex("pathIndex", "nt:unstructured", "Node path index", "*", "someProperty", PropertyType.STRING); // print = true; // Add a node that uses this type ... Node book1 = session().getRootNode().addNode("myFirstBook"); book1.addMixin("mix:title"); book1.setProperty("jcr:title", "The Title"); book1.setProperty("someProperty", "value1"); Node book2 = session().getRootNode().addNode("mySecondBook"); book2.addMixin("mix:title"); book2.setProperty("jcr:title", "A Different Title"); book2.setProperty("someProperty", "value2"); Node other = book2.addNode("chapter"); other.setProperty("propA", "a value for property A"); other.setProperty("jcr:title", "The Title"); other.setProperty("someProperty", "value1"); session.save(); // Issues some queries that should use this index ... String queryStr = "SELECT * FROM [nt:unstructured] WHERE someProperty = 'non-existant'"; Query query = jcrSql2Query(queryStr); validateQuery().rowCount(0L).useIndex("pathIndex").validate(query, query.execute()); // Try with a join ... queryStr = "SELECT a.* FROM [nt:unstructured] AS a JOIN [nt:unstructured] AS b ON a.someProperty = b.someProperty WHERE b.someProperty = 'non-existant-value'"; query = jcrSql2Query(queryStr); validateQuery().rowCount(0L).useIndex("pathIndex").validate(query, query.execute()); }
@FixFor( "MODE-2062" ) @Test public void fullTextShouldWorkWithBindVar() throws Exception { Node n1 = session.getRootNode().addNode("n1"); n1.setProperty("n1-prop-1", "wow"); n1.setProperty("n1-prop-2", "any"); Node n2 = session.getRootNode().addNode("n2"); n2.setProperty("n2-prop-1", "test"); try { session.save(); // test with literal String queryString = "select * from [nt:unstructured] as a where contains(a.*, 'wow')"; assertNodesAreFound(queryString, Query.JCR_SQL2, "/n1"); // test with bind String queryStringWithBind = "select * from [nt:unstructured] as a where contains(a.*, $text)"; QueryManager queryManager = session.getWorkspace().getQueryManager(); Query query = queryManager.createQuery(queryStringWithBind, Query.JCR_SQL2); query.bindValue("text", session.getValueFactory().createValue("wow")); QueryResult result = query.execute(); validateQuery().rowCount(1).hasNodesAtPaths("/n1").validate(query, result); } finally { n1.remove(); n2.remove(); session.save(); } }
@FixFor( "MODE-2314" ) @Test public void shouldIndexNodeAfterChange() throws Exception { // print = true; registerValueIndex("ref1", "nt:unstructured", "", null, "ref1", PropertyType.STRING); registerValueIndex("ref2", "nt:unstructured", "", null, "ref2", PropertyType.STRING); // Wait until all content has been indexed ... waitForIndexes(500L); Node newNode1 = session.getRootNode().addNode("nodeWithSysName", "nt:unstructured"); session.save(); // THIS IS CAUSING the node not being indexed printMessage("Node Created ..."); final String uuId1 = "cccccccccccccccccccccc-0000-1111-1234-123456789abcd"; newNode1.setProperty("ref1", uuId1); newNode1.setProperty("ref2", uuId1); session.save(); printMessage("Node updated ..."); Query query = jcrSql2Query("SELECT A.ref1 FROM [nt:unstructured] AS A WHERE A.ref2 = $ref2"); query.bindValue("ref2", session().getValueFactory().createValue(uuId1)); validateQuery().rowCount(1L).useIndex("ref2").onEachRow(new ValidateQuery.Predicate() { @Override public void validate( int rowNumber, Row row ) throws RepositoryException { if (rowNumber == 1) { assertThat(row.getValue("ref1").getString(), is(uuId1)); } } }).validate(query, query.execute()); }
@Test public void shouldUseSingleColumnNodeTypeIndexForQueryWithNoCriteriaOtherThanPrimaryTypeViaFromClause() throws Exception { registerNodeTypeIndex("primaryTypes", "nt:base", null, "*", "jcr:primaryType", PropertyType.STRING); registerNodeTypeIndex("mixinTypes", "nt:base", null, "*", "jcr:mixinTypes", PropertyType.STRING); // print = true; // Add a node that uses this type ... Node root = session().getRootNode(); Node book1 = root.addNode("myFirstBook"); book1.addMixin("mix:title"); book1.setProperty("jcr:title", "The Title"); Node book2 = root.addNode("mySecondBook"); book2.addMixin("mix:title"); book2.setProperty("jcr:title", "A Different Title"); // Create a node that is not a 'mix:title' and therefore won't be included in the SELECT clauses ... Node other = root.addNode("somethingElse"); other.setProperty("propA", "a value for property A"); other.setProperty("jcr:title", "The Title"); session.save(); // Compute a query plan that should use this index ... Query query = jcrSql2Query("SELECT * FROM [mix:title]"); validateQuery().rowCount(2L).useIndex("mixinTypes").validate(query, query.execute()); // Compute a query plan that should use this index ... query = jcrSql2Query("SELECT * FROM [nt:unstructured]"); validateQuery().rowCount(3L).useIndex("primaryTypes").validate(query, query.execute()); }
@FixFor( "MODE-2401" ) @Test public void shouldNotConsiderNonQueryableNodeTypes() throws RepositoryException, InterruptedException { String typeName = "nt:nonQueryableFolder"; registerNodeType(typeName, false, false, "nt:folder"); registerNodeTypeIndex("typesIndex", "nt:folder", null, "*", "jcr:primaryType", PropertyType.STRING); session.getRootNode().addNode("nonQueryableFolder", typeName); session.getRootNode().addNode("regularFolder1", "nt:folder"); Node folder2 = session.getRootNode().addNode("regularFolder2", typeName); folder2.addNode("subFolder", "nt:folder"); session.save(); final List<String> expectedResults = new ArrayList<>(Arrays.asList("/regularFolder1", "/regularFolder2/subFolder")); Query query = jcrSql2Query("select folder.[jcr:name] FROM [nt:folder] as folder"); validateQuery() .rowCount(2L) .useIndex("typesIndex") .onEachRow(new ValidateQuery.Predicate() { @Override public void validate( int rowNumber, Row row ) throws RepositoryException { expectedResults.remove(row.getPath()); } }) .validate(query, query.execute()); assertTrue("Not all expected nodes found: " + expectedResults, expectedResults.isEmpty()); }