Package com.orientechnologies.orient.test.database.auto

Source Code of com.orientechnologies.orient.test.database.auto.IndexTest

/*
* Copyright 2010-2012 Luca Garulli (l.garulli--at--orientechnologies.com)
*
* Licensed 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 com.orientechnologies.orient.test.database.auto;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.orientechnologies.orient.core.index.hashindex.local.cache.ODiskCache;
import com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

import com.orientechnologies.orient.client.remote.OStorageRemote;
import com.orientechnologies.orient.client.remote.OStorageRemoteThread;
import com.orientechnologies.orient.core.Orient;
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.id.OClusterPosition;
import com.orientechnologies.orient.core.id.ORID;
import com.orientechnologies.orient.core.id.ORecordId;
import com.orientechnologies.orient.core.index.OCompositeKey;
import com.orientechnologies.orient.core.index.OIndex;
import com.orientechnologies.orient.core.index.OIndexException;
import com.orientechnologies.orient.core.index.OIndexManager;
import com.orientechnologies.orient.core.index.OSimpleKeyIndexDefinition;
import com.orientechnologies.orient.core.iterator.ORecordIteratorCluster;
import com.orientechnologies.orient.core.metadata.schema.OClass;
import com.orientechnologies.orient.core.metadata.schema.OClass.INDEX_TYPE;
import com.orientechnologies.orient.core.metadata.schema.OProperty;
import com.orientechnologies.orient.core.metadata.schema.OSchema;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.record.ORecord;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.sql.OCommandSQL;
import com.orientechnologies.orient.core.sql.query.OSQLSynchQuery;
import com.orientechnologies.orient.core.storage.ORecordDuplicatedException;
import com.orientechnologies.orient.core.tx.OTransaction;
import com.orientechnologies.orient.enterprise.channel.binary.OResponseProcessingException;
import com.orientechnologies.orient.test.database.base.OrientTest;
import com.orientechnologies.orient.test.domain.business.Account;
import com.orientechnologies.orient.test.domain.whiz.Profile;

@Test(groups = { "index" })
public class IndexTest extends ObjectDBBaseTest {
  @Parameters(value = "url")
  public IndexTest(@Optional String url) {
    super(url);
  }

  @BeforeClass
  public void beforeClass() throws Exception {
    super.beforeClass();

    database.getEntityManager().registerEntityClasses("com.orientechnologies.orient.test.domain.business");
    database.getEntityManager().registerEntityClasses("com.orientechnologies.orient.test.domain.whiz");
    database.getEntityManager().registerEntityClasses("com.orientechnologies.orient.test.domain.base");
  }

  public void testDuplicatedIndexOnUnique() {
    Profile jayMiner = new Profile("Jay", "Jay", "Miner", null);
    database.save(jayMiner);

    Profile jacobMiner = new Profile("Jay", "Jacob", "Miner", null);

    try {
      database.save(jacobMiner);

      // IT SHOULD GIVE ERROR ON DUPLICATED KEY
      Assert.assertTrue(false);

    } catch (OResponseProcessingException e) {
      Assert.assertTrue(e.getCause() instanceof ORecordDuplicatedException);
    } catch (ORecordDuplicatedException e) {
      Assert.assertTrue(true);
    }
  }

  @Test(dependsOnMethods = "populateIndexDocuments")
  public void testIndexInUniqueIndex() {
    final OProperty nickProperty = database.getMetadata().getSchema().getClass("Profile").getProperty("nick");
    Assert.assertEquals(nickProperty.getIndexes().iterator().next().getType(), OClass.INDEX_TYPE.UNIQUE.toString());

    final boolean localStorage = !(database.getStorage() instanceof OStorageRemote || database.getStorage() instanceof OStorageRemoteThread);

    boolean oldRecording = true;
    long indexQueries = 0L;
    if (localStorage) {
      oldRecording = Orient.instance().getProfiler().isRecording();

      if (!oldRecording) {
        Orient.instance().getProfiler().startRecording();
      }

      indexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
      if (indexQueries < 0) {
        indexQueries = 0;
      }
    }

    final List<Profile> result = database.command(
        new OSQLSynchQuery<Profile>(
            "SELECT * FROM Profile WHERE nick in ['ZZZJayLongNickIndex0' ,'ZZZJayLongNickIndex1', 'ZZZJayLongNickIndex2']"))
        .execute();

    final List<String> expectedSurnames = new ArrayList<String>(Arrays.asList("NolteIndex0", "NolteIndex1", "NolteIndex2"));

    if (localStorage && !oldRecording) {
      Orient.instance().getProfiler().stopRecording();
    }

    Assert.assertEquals(result.size(), 3);
    for (final Profile profile : result) {
      expectedSurnames.remove(profile.getSurname());
    }

    Assert.assertEquals(expectedSurnames.size(), 0);

    if (localStorage) {
      final long newIndexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
      Assert.assertEquals(newIndexQueries, indexQueries + 1);
    }
  }

  @Test(dependsOnMethods = "testDuplicatedIndexOnUnique")
  public void testUseOfIndex() {
    final List<Profile> result = database.command(new OSQLSynchQuery<Profile>("select * from Profile where nick = 'Jay'"))
        .execute();

    Assert.assertFalse(result.isEmpty());

    Profile record;
    for (int i = 0; i < result.size(); ++i) {
      record = result.get(i);

      OrientTest.printRecord(i, record);

      Assert.assertTrue(record.getName().toString().equalsIgnoreCase("Jay"));
    }
  }

  @Test(dependsOnMethods = "testDuplicatedIndexOnUnique")
  public void testIndexEntries() {
    List<Profile> result = database.command(new OSQLSynchQuery<Profile>("select * from Profile where nick is not null")).execute();

    OIndex<?> idx = database.getMetadata().getIndexManager().getIndex("Profile.nick");

    Assert.assertEquals(idx.getSize(), result.size());
  }

  @Test(dependsOnMethods = "testDuplicatedIndexOnUnique")
  public void testIndexSize() {
    List<Profile> result = database.command(new OSQLSynchQuery<Profile>("select * from Profile where nick is not null")).execute();

    int profileSize = result.size();

    database.getMetadata().getIndexManager().reload();
    Assert.assertEquals(database.getMetadata().getIndexManager().getIndex("Profile.nick").getSize(), profileSize);
    for (int i = 0; i < 10; i++) {
      Profile profile = new Profile("Yay-" + i, "Jay", "Miner", null);
      database.save(profile);
      profileSize++;
      Assert.assertNotNull(database.getMetadata().getIndexManager().getIndex("Profile.nick").get("Yay-" + i));
    }
  }

  @Test(dependsOnMethods = "testUseOfIndex")
  public void testChangeOfIndexToNotUnique() {
    database.getMetadata().getSchema().getClass("Profile").getProperty("nick").dropIndexes();
    database.getMetadata().getSchema().getClass("Profile").getProperty("nick").createIndex(OClass.INDEX_TYPE.NOTUNIQUE);
  }

  @Test(dependsOnMethods = "testChangeOfIndexToNotUnique")
  public void testDuplicatedIndexOnNotUnique() {
    Profile nickNolte = new Profile("Jay", "Nick", "Nolte", null);
    database.save(nickNolte);
  }

  @Test(dependsOnMethods = "testDuplicatedIndexOnNotUnique")
  public void testQueryIndex() {
    List<?> result = database.query(new OSQLSynchQuery<Object>("select from index:profile.nick where key = 'Jay'"));
    Assert.assertTrue(result.size() > 0);
  }

  @Test
  public void testIndexSQL() {
    database.command(new OCommandSQL("create index idx unique")).execute();
    database.getMetadata().getIndexManager().reload();
    Assert.assertNotNull(database.getMetadata().getIndexManager().getIndex("idx"));

    final List<OClusterPosition> positions = getValidPositions(3);

    database.command(new OCommandSQL("insert into index:IDX (key,rid) values (10,#3:" + positions.get(0) + ')')).execute();
    database.command(new OCommandSQL("insert into index:IDX (key,rid) values (20,#3:" + positions.get(1) + ')')).execute();

    List<ODocument> result = database.command(new OCommandSQL("select from index:IDX")).execute();
    Assert.assertNotNull(result);
    Assert.assertEquals(result.size(), 2);
    for (ODocument d : result) {
      Assert.assertTrue(d.containsField("key"));
      Assert.assertTrue(d.containsField("rid"));

      if (d.field("key").equals(10))
        Assert.assertEquals(d.rawField("rid"), new ORecordId(3, positions.get(0)));
      else if (d.field("key").equals(20))
        Assert.assertEquals(d.rawField("rid"), new ORecordId(3, positions.get(1)));
      else
        Assert.assertTrue(false);
    }

    result = database.command(new OCommandSQL("select key, rid from index:IDX")).execute();
    Assert.assertNotNull(result);
    Assert.assertEquals(result.size(), 2);
    for (ODocument d : result) {
      Assert.assertTrue(d.containsField("key"));
      Assert.assertTrue(d.containsField("rid"));

      if (d.field("key").equals(10))
        Assert.assertEquals(d.rawField("rid"), new ORecordId(3, positions.get(0)));
      else if (d.field("key").equals(20))
        Assert.assertEquals(d.rawField("rid"), new ORecordId(3, positions.get(1)));
      else
        Assert.assertTrue(false);
    }

    result = database.command(new OCommandSQL("select key from index:IDX")).execute();
    Assert.assertNotNull(result);
    Assert.assertEquals(result.size(), 2);
    for (ODocument d : result) {
      Assert.assertTrue(d.containsField("key"));
      Assert.assertFalse(d.containsField("rid"));
    }

    result = database.command(new OCommandSQL("select rid from index:IDX")).execute();
    Assert.assertNotNull(result);
    Assert.assertEquals(result.size(), 2);
    for (ODocument d : result) {
      Assert.assertFalse(d.containsField("key"));
      Assert.assertTrue(d.containsField("rid"));
    }

    result = database.command(new OCommandSQL("select rid from index:IDX where key = 10")).execute();
    Assert.assertNotNull(result);
    Assert.assertEquals(result.size(), 1);
    for (ODocument d : result) {
      Assert.assertFalse(d.containsField("key"));
      Assert.assertTrue(d.containsField("rid"));
    }
  }

  @Test(dependsOnMethods = "testQueryIndex")
  public void testChangeOfIndexToUnique() {
    try {
      database.getMetadata().getSchema().getClass("Profile").getProperty("nick").dropIndexes();
      database.getMetadata().getSchema().getClass("Profile").getProperty("nick").createIndex(OClass.INDEX_TYPE.UNIQUE);
      Assert.assertTrue(false);
    } catch (OResponseProcessingException e) {
      Assert.assertTrue(e.getCause() instanceof OIndexException);
    } catch (OIndexException e) {
      Assert.assertTrue(true);
    }
  }

  @Test(dependsOnMethods = "populateIndexDocuments")
  public void testIndexInMajorSelect() {
    if (database.getStorage() instanceof OStorageRemote || database.getStorage() instanceof OStorageRemoteThread) {
      return;
    }

    final boolean oldRecording = Orient.instance().getProfiler().isRecording();

    if (!oldRecording) {
      Orient.instance().getProfiler().startRecording();
    }

    long indexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    if (indexQueries < 0) {
      indexQueries = 0;
    }

    final List<Profile> result = database.command(
        new OSQLSynchQuery<Profile>("select * from Profile where nick > 'ZZZJayLongNickIndex3'")).execute();
    final List<String> expectedNicks = new ArrayList<String>(Arrays.asList("ZZZJayLongNickIndex4", "ZZZJayLongNickIndex5"));

    if (!oldRecording) {
      Orient.instance().getProfiler().stopRecording();
    }

    Assert.assertEquals(result.size(), 2);
    for (Profile profile : result) {
      expectedNicks.remove(profile.getNick());
    }

    Assert.assertEquals(expectedNicks.size(), 0);
    long newIndexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    Assert.assertEquals(newIndexQueries, indexQueries + 1);
  }

  @Test(dependsOnMethods = "populateIndexDocuments")
  public void testIndexInMajorEqualsSelect() {
    if (database.getStorage() instanceof OStorageRemote || database.getStorage() instanceof OStorageRemoteThread) {
      return;
    }

    final boolean oldRecording = Orient.instance().getProfiler().isRecording();

    if (!oldRecording) {
      Orient.instance().getProfiler().startRecording();
    }

    long indexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    if (indexQueries < 0) {
      indexQueries = 0;
    }

    final List<Profile> result = database.command(
        new OSQLSynchQuery<Profile>("select * from Profile where nick >= 'ZZZJayLongNickIndex3'")).execute();
    final List<String> expectedNicks = new ArrayList<String>(Arrays.asList("ZZZJayLongNickIndex3", "ZZZJayLongNickIndex4",
        "ZZZJayLongNickIndex5"));

    if (!oldRecording) {
      Orient.instance().getProfiler().stopRecording();
    }

    Assert.assertEquals(result.size(), 3);
    for (Profile profile : result) {
      expectedNicks.remove(profile.getNick());
    }

    Assert.assertEquals(expectedNicks.size(), 0);
    long newIndexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    Assert.assertEquals(newIndexQueries, indexQueries + 1);
  }

  @Test(dependsOnMethods = "populateIndexDocuments")
  public void testIndexInMinorSelect() {
    if (database.getStorage() instanceof OStorageRemote || database.getStorage() instanceof OStorageRemoteThread) {
      return;
    }

    final boolean oldRecording = Orient.instance().getProfiler().isRecording();

    if (!oldRecording) {
      Orient.instance().getProfiler().startRecording();
    }

    long indexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    if (indexQueries < 0) {
      indexQueries = 0;
    }

    final List<Profile> result = database.command(new OSQLSynchQuery<Profile>("select * from Profile where nick < '002'"))
        .execute();
    final List<String> expectedNicks = new ArrayList<String>(Arrays.asList("000", "001"));

    if (!oldRecording) {
      Orient.instance().getProfiler().stopRecording();
    }

    Assert.assertEquals(result.size(), 2);
    for (Profile profile : result) {
      expectedNicks.remove(profile.getNick());
    }

    Assert.assertEquals(expectedNicks.size(), 0);
    long newIndexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    Assert.assertEquals(newIndexQueries, indexQueries + 1);
  }

  @Test(dependsOnMethods = "populateIndexDocuments")
  public void testIndexInMinorEqualsSelect() {
    if (database.getStorage() instanceof OStorageRemote || database.getStorage() instanceof OStorageRemoteThread) {
      return;
    }

    final boolean oldRecording = Orient.instance().getProfiler().isRecording();

    if (!oldRecording) {
      Orient.instance().getProfiler().startRecording();
    }

    long indexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    if (indexQueries < 0) {
      indexQueries = 0;
    }

    final List<Profile> result = database.command(new OSQLSynchQuery<Profile>("select * from Profile where nick <= '002'"))
        .execute();
    final List<String> expectedNicks = new ArrayList<String>(Arrays.asList("000", "001", "002"));

    if (!oldRecording) {
      Orient.instance().getProfiler().stopRecording();
    }

    Assert.assertEquals(result.size(), 3);
    for (Profile profile : result) {
      expectedNicks.remove(profile.getNick());
    }

    Assert.assertEquals(expectedNicks.size(), 0);
    long newIndexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    Assert.assertEquals(newIndexQueries, indexQueries + 1);
  }

  @Test(dependsOnMethods = "populateIndexDocuments")
  public void testIndexBetweenSelect() {
    if (database.getStorage() instanceof OStorageRemote || database.getStorage() instanceof OStorageRemoteThread) {
      return;
    }

    final boolean oldRecording = Orient.instance().getProfiler().isRecording();

    if (!oldRecording) {
      Orient.instance().getProfiler().startRecording();
    }

    long indexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    if (indexQueries < 0) {
      indexQueries = 0;
    }

    final List<Profile> result = database.command(
        new OSQLSynchQuery<Profile>("select * from Profile where nick between '001' and '004'")).execute();
    final List<String> expectedNicks = new ArrayList<String>(Arrays.asList("001", "002", "003", "004"));

    if (!oldRecording) {
      Orient.instance().getProfiler().stopRecording();
    }

    Assert.assertEquals(result.size(), 4);
    for (Profile profile : result) {
      expectedNicks.remove(profile.getNick());
    }

    Assert.assertEquals(expectedNicks.size(), 0);
    long newIndexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    Assert.assertEquals(newIndexQueries, indexQueries + 1);
  }

  @Test(dependsOnMethods = "populateIndexDocuments")
  public void testIndexInComplexSelectOne() {
    if (database.getStorage() instanceof OStorageRemote || database.getStorage() instanceof OStorageRemoteThread) {
      return;
    }

    final boolean oldRecording = Orient.instance().getProfiler().isRecording();

    if (!oldRecording) {
      Orient.instance().getProfiler().startRecording();
    }

    long indexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    if (indexQueries < 0) {
      indexQueries = 0;
    }

    final List<Profile> result = database.command(
        new OSQLSynchQuery<Profile>("select * from Profile where (name = 'Giuseppe' OR name <> 'Napoleone')"
            + " AND (nick is not null AND (name = 'Giuseppe' OR name <> 'Napoleone') AND (nick >= 'ZZZJayLongNickIndex3'))"))
        .execute();
    if (!oldRecording) {
      Orient.instance().getProfiler().stopRecording();
    }

    final List<String> expectedNicks = new ArrayList<String>(Arrays.asList("ZZZJayLongNickIndex3", "ZZZJayLongNickIndex4",
        "ZZZJayLongNickIndex5"));
    Assert.assertEquals(result.size(), 3);
    for (Profile profile : result) {
      expectedNicks.remove(profile.getNick());
    }

    Assert.assertEquals(expectedNicks.size(), 0);
    long newIndexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    Assert.assertEquals(newIndexQueries, indexQueries + 1);
  }

  @Test(dependsOnMethods = "populateIndexDocuments")
  public void testIndexInComplexSelectTwo() {
    if (database.getStorage() instanceof OStorageRemote || database.getStorage() instanceof OStorageRemoteThread) {
      return;
    }

    final boolean oldRecording = Orient.instance().getProfiler().isRecording();

    if (!oldRecording) {
      Orient.instance().getProfiler().startRecording();
    }

    long indexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    if (indexQueries < 0) {
      indexQueries = 0;
    }

    final List<Profile> result = database
        .command(
            new OSQLSynchQuery<Profile>(
                "select * from Profile where "
                    + "((name = 'Giuseppe' OR name <> 'Napoleone')"
                    + " AND (nick is not null AND (name = 'Giuseppe' OR name <> 'Napoleone') AND (nick >= 'ZZZJayLongNickIndex3' OR nick >= 'ZZZJayLongNickIndex4')))"))
        .execute();
    if (!oldRecording) {
      Orient.instance().getProfiler().stopRecording();
    }

    final List<String> expectedNicks = new ArrayList<String>(Arrays.asList("ZZZJayLongNickIndex3", "ZZZJayLongNickIndex4",
        "ZZZJayLongNickIndex5"));
    Assert.assertEquals(result.size(), 3);
    for (Profile profile : result) {
      expectedNicks.remove(profile.getNick());
    }

    Assert.assertEquals(expectedNicks.size(), 0);
    long newIndexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
    Assert.assertEquals(newIndexQueries, indexQueries);
  }

  public void populateIndexDocuments() {
    for (int i = 0; i <= 5; i++) {
      final Profile profile = new Profile("ZZZJayLongNickIndex" + i, "NickIndex" + i, "NolteIndex" + i, null);
      database.save(profile);
    }

    for (int i = 0; i <= 5; i++) {
      final Profile profile = new Profile("00" + i, "NickIndex" + i, "NolteIndex" + i, null);
      database.save(profile);
    }
  }

  @Test(dependsOnMethods = "testChangeOfIndexToUnique")
  public void removeNotUniqueIndexOnNick() {
    database.getMetadata().getSchema().getClass("Profile").getProperty("nick").dropIndexes();
    database.getMetadata().getSchema().save();
  }

  @Test(dependsOnMethods = "removeNotUniqueIndexOnNick")
  public void testQueryingWithoutNickIndex() {
    Assert.assertTrue(database.getMetadata().getSchema().getClass("Profile").getProperty("name").isIndexed());
    Assert.assertTrue(!database.getMetadata().getSchema().getClass("Profile").getProperty("nick").isIndexed());

    List<Profile> result = database.command(new OSQLSynchQuery<ODocument>("SELECT FROM Profile WHERE nick = 'Jay'")).execute();
    Assert.assertEquals(result.size(), 2);

    result = database.command(new OSQLSynchQuery<ODocument>("SELECT FROM Profile WHERE nick = 'Jay' AND name = 'Jay'")).execute();
    Assert.assertEquals(result.size(), 1);

    result = database.command(new OSQLSynchQuery<ODocument>("SELECT FROM Profile WHERE nick = 'Jay' AND name = 'Nick'")).execute();
    Assert.assertEquals(result.size(), 1);
  }

  @Test(dependsOnMethods = "testQueryingWithoutNickIndex")
  public void createNotUniqueIndexOnNick() {
    database.getMetadata().getSchema().getClass("Profile").getProperty("nick").createIndex(OClass.INDEX_TYPE.NOTUNIQUE);
    database.getMetadata().getSchema().save();
  }

  @Test(dependsOnMethods = { "createNotUniqueIndexOnNick", "populateIndexDocuments" })
  public void testIndexInNotUniqueIndex() {
    final OProperty nickProperty = database.getMetadata().getSchema().getClass("Profile").getProperty("nick");
    Assert.assertEquals(nickProperty.getIndexes().iterator().next().getType(), OClass.INDEX_TYPE.NOTUNIQUE.toString());

    final boolean localStorage = !(database.getStorage() instanceof OStorageRemote || database.getStorage() instanceof OStorageRemoteThread);

    boolean oldRecording = true;
    long indexQueries = 0L;
    if (localStorage) {
      oldRecording = Orient.instance().getProfiler().isRecording();

      if (!oldRecording) {
        Orient.instance().getProfiler().startRecording();
      }

      indexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
      if (indexQueries < 0) {
        indexQueries = 0;
      }
    }

    final List<Profile> result = database.command(
        new OSQLSynchQuery<Profile>(
            "SELECT * FROM Profile WHERE nick in ['ZZZJayLongNickIndex0' ,'ZZZJayLongNickIndex1', 'ZZZJayLongNickIndex2']"))
        .execute();

    final List<String> expectedSurnames = new ArrayList<String>(Arrays.asList("NolteIndex0", "NolteIndex1", "NolteIndex2"));

    if (localStorage && !oldRecording) {
      Orient.instance().getProfiler().stopRecording();
    }

    Assert.assertEquals(result.size(), 3);
    for (final Profile profile : result) {
      expectedSurnames.remove(profile.getSurname());
    }

    Assert.assertEquals(expectedSurnames.size(), 0);

    if (localStorage) {
      final long newIndexQueries = Orient.instance().getProfiler().getCounter("db.demo.query.indexUsed");
      Assert.assertEquals(newIndexQueries, indexQueries + 1);
    }
  }

  @Test
  public void testIndexCount() {
    final OIndex<?> nickIndex = database.getMetadata().getIndexManager().getIndex("Profile.nick");
    final List<ODocument> result = database.query(new OSQLSynchQuery<Object>("select count(*) from index:Profile.nick"));
    Assert.assertEquals(result.size(), 1);
    Assert.assertEquals(result.get(0).<Long> field("count").longValue(), nickIndex.getSize());
  }

  public void indexLinks() {
    database.getMetadata().getSchema().getClass("Whiz").getProperty("account").createIndex(OClass.INDEX_TYPE.NOTUNIQUE);

    final List<Account> result = database.command(new OSQLSynchQuery<Account>("select * from Account limit 1")).execute();

    final OIndex<?> idx = database.getMetadata().getIndexManager().getIndex("Whiz.account");

    for (int i = 0; i < 5; i++) {
      final ODocument whiz = new ODocument("Whiz");

      whiz.field("id", i);
      whiz.field("text", "This is a test");
      whiz.field("account", result.get(0).getRid());

      whiz.save();
    }

    Assert.assertEquals(idx.getSize(), 5);

    final List<ODocument> indexedResult = database.getUnderlying()
        .command(new OSQLSynchQuery<Profile>("select * from Whiz where account = ?")).execute(result.get(0).getRid());

    Assert.assertEquals(indexedResult.size(), 5);

    for (final ODocument resDoc : indexedResult) {
      resDoc.delete();
    }

    final ODocument whiz = new ODocument("Whiz");
    whiz.field("id", 100);
    whiz.field("text", "This is a test!");
    whiz.field("account", new ODocument("Company").field("id", 9999));
    whiz.save();

    Assert.assertTrue(((ODocument) whiz.field("account")).getIdentity().isValid());

    ((ODocument) whiz.field("account")).delete();
    whiz.delete();
  }

  public void linkedIndexedProperty() {
    ODatabaseDocument db = new ODatabaseDocumentTx(database.getURL());
    db.open("admin", "admin");

    if (!db.getMetadata().getSchema().existsClass("TestClass")) {
      OClass testClass = db.getMetadata().getSchema().createClass("TestClass");
      OClass testLinkClass = db.getMetadata().getSchema().createClass("TestLinkClass");
      testClass.createProperty("testLink", OType.LINK, testLinkClass).createIndex(OClass.INDEX_TYPE.NOTUNIQUE);
      testClass.createProperty("name", OType.STRING).createIndex(OClass.INDEX_TYPE.UNIQUE);
      testLinkClass.createProperty("testBoolean", OType.BOOLEAN);
      testLinkClass.createProperty("testString", OType.STRING);
      db.getMetadata().getSchema().save();
    }
    ODocument testClassDocument = db.newInstance("TestClass");
    testClassDocument.field("name", "Test Class 1");
    ODocument testLinkClassDocument = new ODocument("TestLinkClass");
    testLinkClassDocument.field("testString", "Test Link Class 1");
    testLinkClassDocument.field("testBoolean", true);
    testClassDocument.field("testLink", testLinkClassDocument);
    testClassDocument.save();
    // THIS WILL THROW A java.lang.ClassCastException: com.orientechnologies.orient.core.id.ORecordId cannot be cast to
    // java.lang.Boolean
    List<ODocument> result = db.query(new OSQLSynchQuery<ODocument>("select from TestClass where testLink.testBoolean = true"));
    Assert.assertEquals(result.size(), 1);
    // THIS WILL THROW A java.lang.ClassCastException: com.orientechnologies.orient.core.id.ORecordId cannot be cast to
    // java.lang.String
    result = db.query(new OSQLSynchQuery<ODocument>("select from TestClass where testLink.testString = 'Test Link Class 1'"));
    Assert.assertEquals(result.size(), 1);

    db.close();
  }

  @Test(dependsOnMethods = "linkedIndexedProperty")
  public void testLinkedIndexedPropertyInTx() {
    ODatabaseDocument db = new ODatabaseDocumentTx(database.getURL());
    db.open("admin", "admin");

    db.begin();
    ODocument testClassDocument = db.newInstance("TestClass");
    testClassDocument.field("name", "Test Class 2");
    ODocument testLinkClassDocument = new ODocument("TestLinkClass");
    testLinkClassDocument.field("testString", "Test Link Class 2");
    testLinkClassDocument.field("testBoolean", true);
    testClassDocument.field("testLink", testLinkClassDocument);
    testClassDocument.save();
    db.commit();

    // THIS WILL THROW A java.lang.ClassCastException: com.orientechnologies.orient.core.id.ORecordId cannot be cast to
    // java.lang.Boolean
    List<ODocument> result = db.query(new OSQLSynchQuery<ODocument>("select from TestClass where testLink.testBoolean = true"));
    Assert.assertEquals(result.size(), 2);
    // THIS WILL THROW A java.lang.ClassCastException: com.orientechnologies.orient.core.id.ORecordId cannot be cast to
    // java.lang.String
    result = db.query(new OSQLSynchQuery<ODocument>("select from TestClass where testLink.testString = 'Test Link Class 2'"));
    Assert.assertEquals(result.size(), 1);

    db.close();
  }

  public void testDictionary() {
    ODatabaseDocument db = new ODatabaseDocumentTx(database.getURL());
    db.open("admin", "admin");

    OClass pClass = db.getMetadata().getSchema().createClass("Person2");
    pClass.createProperty("firstName", OType.STRING);
    pClass.createProperty("lastName", OType.STRING);
    pClass.createProperty("age", OType.INTEGER);
    pClass.createIndex("testIdx", INDEX_TYPE.DICTIONARY, "firstName", "lastName");

    ODocument person = new ODocument("Person2");
    person.field("firstName", "foo").field("lastName", "bar").save();

    person = new ODocument("Person2");
    person.field("firstName", "foo").field("lastName", "bar").field("age", 32).save();

    db.close();
  }

  public void testConcurrentRemoveDelete() {
    ODatabaseDocument db = new ODatabaseDocumentTx(database.getURL());
    db.open("admin", "admin");

    if (!db.getMetadata().getSchema().existsClass("MyFruit")) {
      OClass fruitClass = db.getMetadata().getSchema().createClass("MyFruit");
      fruitClass.createProperty("name", OType.STRING);
      fruitClass.createProperty("color", OType.STRING);

      db.getMetadata().getSchema().getClass("MyFruit").getProperty("name").createIndex(OClass.INDEX_TYPE.UNIQUE);

      db.getMetadata().getSchema().getClass("MyFruit").getProperty("color").createIndex(OClass.INDEX_TYPE.NOTUNIQUE);

      db.getMetadata().getSchema().save();
    }

    long expectedIndexSize = 0;

    final int passCount = 10;
    final int chunkSize = 1000;
    for (int pass = 0; pass < passCount; pass++) {
      List<ODocument> recordsToDelete = new ArrayList<ODocument>();
      db.begin();
      for (int i = 0; i < chunkSize; i++) {
        ODocument d = new ODocument("MyFruit").field("name", "ABC" + pass + 'K' + i).field("color", "FOO" + pass);
        d.save();
        if (i < chunkSize / 2) {
          recordsToDelete.add(d);
        }
      }
      db.commit();

      expectedIndexSize += chunkSize;
      Assert.assertEquals(db.getMetadata().getIndexManager().getClassIndex("MyFruit", "MyFruit.color").getSize(),
          expectedIndexSize, "After add");

      // do delete
      db.begin();
      for (final ODocument recordToDelete : recordsToDelete) {
        Assert.assertNotNull(db.delete(recordToDelete));
      }
      db.commit();

      expectedIndexSize -= recordsToDelete.size();
      Assert.assertEquals(db.getMetadata().getIndexManager().getClassIndex("MyFruit", "MyFruit.color").getSize(),
          expectedIndexSize, "After delete");
    }

    db.close();
  }

  public void testIndexParamsAutoConversion() {
    ODatabaseDocument db = new ODatabaseDocumentTx(database.getURL());
    db.open("admin", "admin");

    if (!db.getMetadata().getSchema().existsClass("IndexTestTerm")) {
      final OClass termClass = db.getMetadata().getSchema().createClass("IndexTestTerm");
      termClass.createProperty("label", OType.STRING);
      termClass.createIndex("idxTerm", INDEX_TYPE.UNIQUE, "label");

      db.getMetadata().getSchema().save();
    }

    final ODocument doc = new ODocument("IndexTestTerm");
    doc.field("label", "42");
    doc.save();

    final ORecordId result = (ORecordId) db.getMetadata().getIndexManager().getIndex("idxTerm").get("42");
    Assert.assertNotNull(result);
    Assert.assertEquals(result.getIdentity(), doc.getIdentity());
  }

  public void testTransactionUniqueIndexTestOne() {
    ODatabaseDocumentTx db = new ODatabaseDocumentTx(database.getURL());
    db.open("admin", "admin");

    if (!db.getMetadata().getSchema().existsClass("TransactionUniqueIndexTest")) {
      final OClass termClass = db.getMetadata().getSchema().createClass("TransactionUniqueIndexTest");
      termClass.createProperty("label", OType.STRING);
      termClass.createIndex("idxTransactionUniqueIndexTest", INDEX_TYPE.UNIQUE, "label");
      db.getMetadata().getSchema().save();
    }

    ODocument docOne = new ODocument("TransactionUniqueIndexTest");
    docOne.field("label", "A");
    docOne.save();

    final List<ODocument> resultBeforeCommit = db.query(new OSQLSynchQuery<ODocument>(
        "select from index:idxTransactionUniqueIndexTest"));
    Assert.assertEquals(resultBeforeCommit.size(), 1);

    db.begin();
    try {
      ODocument docTwo = new ODocument("TransactionUniqueIndexTest");
      docTwo.field("label", "A");
      docTwo.save();

      db.commit();
      Assert.fail();
    } catch (OResponseProcessingException e) {
      Assert.assertTrue(e.getCause() instanceof ORecordDuplicatedException);
    } catch (ORecordDuplicatedException oie) {
    }

    final List<ODocument> resultAfterCommit = db.query(new OSQLSynchQuery<ODocument>(
        "select from index:idxTransactionUniqueIndexTest"));
    Assert.assertEquals(resultAfterCommit.size(), 1);
  }

  @Test(dependsOnMethods = "testTransactionUniqueIndexTestOne")
  public void testTransactionUniqueIndexTestTwo() {
    ODatabaseDocumentTx db = new ODatabaseDocumentTx(database.getURL());
    db.open("admin", "admin");

    if (!db.getMetadata().getSchema().existsClass("TransactionUniqueIndexTest")) {
      final OClass termClass = db.getMetadata().getSchema().createClass("TransactionUniqueIndexTest");
      termClass.createProperty("label", OType.STRING);
      termClass.createIndex("idxTransactionUniqueIndexTest", INDEX_TYPE.UNIQUE, "label");
      db.getMetadata().getSchema().save();
    }

    final List<ODocument> resultBeforeCommit = db.query(new OSQLSynchQuery<ODocument>(
        "select from index:idxTransactionUniqueIndexTest"));
    Assert.assertEquals(resultBeforeCommit.size(), 1);

    db.begin();

    try {
      ODocument docOne = new ODocument("TransactionUniqueIndexTest");
      docOne.field("label", "B");
      docOne.save();

      ODocument docTwo = new ODocument("TransactionUniqueIndexTest");
      docTwo.field("label", "B");
      docTwo.save();

      db.commit();
      Assert.fail();
    } catch (OResponseProcessingException e) {
      Assert.assertTrue(e.getCause() instanceof ORecordDuplicatedException);
      db.rollback();
    } catch (ORecordDuplicatedException oie) {
      db.rollback();
    }

    final List<ODocument> resultAfterCommit = db.query(new OSQLSynchQuery<ODocument>(
        "select from index:idxTransactionUniqueIndexTest"));
    Assert.assertEquals(resultAfterCommit.size(), 1);
  }

  public void testTransactionUniqueIndexTestWithDotNameOne() {
    ODatabaseDocumentTx db = new ODatabaseDocumentTx(database.getURL());
    db.open("admin", "admin");

    if (!db.getMetadata().getSchema().existsClass("TransactionUniqueIndexWithDotTest")) {
      final OClass termClass = db.getMetadata().getSchema().createClass("TransactionUniqueIndexWithDotTest");
      termClass.createProperty("label", OType.STRING).createIndex(INDEX_TYPE.UNIQUE);
      db.getMetadata().getSchema().save();
    }

    ODocument docOne = new ODocument("TransactionUniqueIndexWithDotTest");
    docOne.field("label", "A");
    docOne.save();

    final List<ODocument> resultBeforeCommit = db.query(new OSQLSynchQuery<ODocument>(
        "select from  index:TransactionUniqueIndexWithDotTest.label"));
    Assert.assertEquals(resultBeforeCommit.size(), 1);

    long countClassBefore = db.countClass("TransactionUniqueIndexWithDotTest");
    db.begin();
    try {
      ODocument docTwo = new ODocument("TransactionUniqueIndexWithDotTest");
      docTwo.field("label", "A");
      docTwo.save();

      db.commit();
      Assert.fail();
    } catch (OResponseProcessingException e) {
      Assert.assertTrue(e.getCause() instanceof ORecordDuplicatedException);
    } catch (ORecordDuplicatedException oie) {
    }

    Assert.assertEquals(
        ((List<ODocument>) db.command(new OCommandSQL("select from TransactionUniqueIndexWithDotTest")).execute()).size(),
        countClassBefore);

    final List<ODocument> resultAfterCommit = db.query(new OSQLSynchQuery<ODocument>(
        "select from  index:TransactionUniqueIndexWithDotTest.label"));
    Assert.assertEquals(resultAfterCommit.size(), 1);
  }

  @Test(dependsOnMethods = "testTransactionUniqueIndexTestWithDotNameOne")
  public void testTransactionUniqueIndexTestWithDotNameTwo() {
    ODatabaseDocumentTx db = new ODatabaseDocumentTx(database.getURL());
    db.open("admin", "admin");

    if (!db.getMetadata().getSchema().existsClass("TransactionUniqueIndexWithDotTest")) {
      final OClass termClass = db.getMetadata().getSchema().createClass("TransactionUniqueIndexWithDotTest");
      termClass.createProperty("label", OType.STRING).createIndex(INDEX_TYPE.UNIQUE);
      db.getMetadata().getSchema().save();
    }

    final List<ODocument> resultBeforeCommit = db.query(new OSQLSynchQuery<ODocument>(
        "select from index:TransactionUniqueIndexWithDotTest.label"));
    Assert.assertEquals(resultBeforeCommit.size(), 1);

    db.begin();

    try {
      ODocument docOne = new ODocument("TransactionUniqueIndexWithDotTest");
      docOne.field("label", "B");
      docOne.save();

      ODocument docTwo = new ODocument("TransactionUniqueIndexWithDotTest");
      docTwo.field("label", "B");
      docTwo.save();

      db.commit();
      Assert.fail();
    } catch (OResponseProcessingException e) {
      Assert.assertTrue(e.getCause() instanceof ORecordDuplicatedException);
      db.rollback();
    } catch (ORecordDuplicatedException oie) {
      db.rollback();
    }

    final List<ODocument> resultAfterCommit = db.query(new OSQLSynchQuery<ODocument>(
        "select from  index:TransactionUniqueIndexWithDotTest.label"));
    Assert.assertEquals(resultAfterCommit.size(), 1);
  }

  @Test(dependsOnMethods = "linkedIndexedProperty")
  public void testIndexRemoval() {
    List<ODocument> result = database.command(new OCommandSQL("select rid from index:Profile.nick")).execute();
    Assert.assertNotNull(result);

    ODocument firstProfile = null;

    for (ODocument d : result) {
      if (firstProfile == null)
        firstProfile = d.field("rid");

      Assert.assertFalse(d.containsField("key"));
      Assert.assertTrue(d.containsField("rid"));
    }

    result = database.command(new OCommandSQL("select rid from index:Profile.nick where key = ?")).execute(
        firstProfile.field("nick"));

    Assert.assertNotNull(result);
    Assert.assertEquals(result.get(0).field("rid"), firstProfile.getIdentity());

    firstProfile.delete();

    result = database.command(new OCommandSQL("select rid from index:Profile.nick where key = ?")).execute(
        firstProfile.field("nick"));
    Assert.assertTrue(result.isEmpty());

  }

  public void createInheritanceIndex() {
    ODatabaseDocument db = new ODatabaseDocumentTx(database.getURL());
    try {
      db.open("admin", "admin");

      if (!db.getMetadata().getSchema().existsClass("BaseTestClass")) {
        OClass baseClass = db.getMetadata().getSchema().createClass("BaseTestClass");
        OClass childClass = db.getMetadata().getSchema().createClass("ChildTestClass");
        OClass anotherChildClass = db.getMetadata().getSchema().createClass("AnotherChildTestClass");

        if (!baseClass.isSuperClassOf(childClass))
          childClass.setSuperClass(baseClass);
        if (!baseClass.isSuperClassOf(anotherChildClass))
          anotherChildClass.setSuperClass(baseClass);

        baseClass.createProperty("testParentProperty", OType.LONG).createIndex(OClass.INDEX_TYPE.NOTUNIQUE);

        db.getMetadata().getSchema().save();
      }

      ODocument childClassDocument = db.newInstance("ChildTestClass");
      childClassDocument.field("testParentProperty", 10L);
      childClassDocument.save();

      ODocument anotherChildClassDocument = db.newInstance("AnotherChildTestClass");
      anotherChildClassDocument.field("testParentProperty", 11L);
      anotherChildClassDocument.save();

      Assert.assertFalse(new ORecordId(-1, ORID.CLUSTER_POS_INVALID).equals(childClassDocument.getIdentity()));
      Assert.assertFalse(new ORecordId(-1, ORID.CLUSTER_POS_INVALID).equals(anotherChildClassDocument.getIdentity()));
    } finally {
      db.close();
    }
  }

  @Test(dependsOnMethods = "createInheritanceIndex")
  public void testIndexReturnOnlySpecifiedClass() throws Exception {
    List<ODocument> result;

    ODatabaseDocument db = database.getUnderlying();

    result = db.command(new OSQLSynchQuery("select * from ChildTestClass where testParentProperty = 10")).execute();
    Assert.assertNotNull(result);
    Assert.assertEquals(1, result.size());
    Assert.assertEquals(10L, result.get(0).field("testParentProperty"));

    result = db.command(new OCommandSQL("select * from AnotherChildTestClass where testParentProperty = 11")).execute();
    Assert.assertNotNull(result);
    Assert.assertEquals(1, result.size());
    Assert.assertEquals(11L, result.get(0).field("testParentProperty"));
  }

  @Test
  public void testManualIndexInTx() {
    if (database.getURL().startsWith("remote:"))
      return;

    ODatabaseDocumentTx db = (ODatabaseDocumentTx) database.getUnderlying();

    database.getMetadata().getSchema().createClass("ManualIndexTxClass");

    OIndexManager idxManager = db.getMetadata().getIndexManager();
    idxManager.createIndex("manualTxIndexTest", "UNIQUE", new OSimpleKeyIndexDefinition(OType.INTEGER), null, null, null);
    OIndex<OIdentifiable> idx = (OIndex<OIdentifiable>) idxManager.getIndex("manualTxIndexTest");

    ODocument v0 = new ODocument("ManualIndexTxClass");
    v0.field("counter", 0);
    v0.save();
    idx.put(0, v0);
    Assert.assertTrue(idx.contains(0));

    db.begin(OTransaction.TXTYPE.OPTIMISTIC);
    ODocument v = new ODocument("ManualIndexTxClass");
    v.field("counter", 52);
    v.save();

    ODocument v2 = new ODocument("ManualIndexTxClass");
    v2.field("counter", 54);
    v2.save();

    Assert.assertNotNull(idx);
    idx.remove(0);
    idx.put(52, v);

    db.commit();

    Assert.assertTrue(idx.contains(52));
    Assert.assertFalse(idx.contains(0));
    Assert.assertTrue(idx.get(52).getIdentity().isPersistent());
    Assert.assertEquals(idx.get(52).getIdentity(), v.getIdentity());
  }

  @Test
  public void testManualIndexInTxRecursiveStore() {
    if (database.getURL().startsWith("remote:"))
      return;

    ODatabaseDocumentTx db = (ODatabaseDocumentTx) database.getUnderlying();

    database.getMetadata().getSchema().createClass("ManualIndexTxRecursiveStoreClass");

    OIndexManager idxManager = db.getMetadata().getIndexManager();
    idxManager.createIndex("manualTxIndexRecursiveStoreTest", "UNIQUE", new OSimpleKeyIndexDefinition(OType.INTEGER), null, null,
        null);

    OIndex<OIdentifiable> idx = (OIndex<OIdentifiable>) idxManager.getIndex("manualTxIndexRecursiveStoreTest");

    ODocument v0 = new ODocument("ManualIndexTxRecursiveStoreClass");
    v0.field("counter", 0);
    v0.save();
    idx.put(0, v0);
    Assert.assertTrue(idx.contains(0));

    db.begin(OTransaction.TXTYPE.OPTIMISTIC);
    ODocument v = new ODocument("ManualIndexTxRecursiveStoreClass");
    v.field("counter", 52);

    ODocument v2 = new ODocument("ManualIndexTxRecursiveStoreClass");
    v2.field("counter", 54);
    v2.field("link", v);
    v2.save();

    v.field("link", v2);
    v.save();

    Assert.assertNotNull(idx);
    idx.remove(0);

    idx.put(52, v);
    idx.put(54, v2);

    db.commit();

    Assert.assertTrue(idx.contains(52));
    Assert.assertTrue(idx.contains(54));

    Assert.assertFalse(idx.contains(0));

    Assert.assertTrue(idx.get(52).getIdentity().isPersistent());
    Assert.assertEquals(idx.get(52).getIdentity(), v.getIdentity());

    Assert.assertTrue(idx.get(54).getIdentity().isPersistent());
    Assert.assertEquals(idx.get(54).getIdentity(), v2.getIdentity());
  }

  public void testIndexCountPlusCondition() {
    OIndexManager idxManager = database.getMetadata().getIndexManager();
    idxManager.createIndex("IndexCountPlusCondition", "NOTUNIQUE", new OSimpleKeyIndexDefinition(OType.INTEGER), null, null, null);

    final OIndex<OIdentifiable> idx = (OIndex<OIdentifiable>) idxManager.getIndex("IndexCountPlusCondition");

    final Map<Integer, Long> keyDocsCount = new HashMap<Integer, Long>();
    for (int i = 1; i < 100; i++) {
      final Integer key = (int) Math.log(i);

      final ODocument doc = new ODocument();
      doc.save();

      idx.put(key, doc);

      if (keyDocsCount.containsKey(key))
        keyDocsCount.put(key, keyDocsCount.get(key) + 1);
      else
        keyDocsCount.put(key, 1L);
    }

    for (Map.Entry<Integer, Long> entry : keyDocsCount.entrySet()) {
      List<ODocument> result = database.query(new OSQLSynchQuery<ODocument>(
          "select count(*) from index:IndexCountPlusCondition where key = ?"), entry.getKey());
      Assert.assertEquals(result.get(0).<Long> field("count"), entry.getValue());
    }
  }

  public void testNotUniqueIndexKeySize() {
    OIndexManager idxManager = database.getMetadata().getIndexManager();
    idxManager.createIndex("IndexNotUniqueIndexKeySize", "NOTUNIQUE", new OSimpleKeyIndexDefinition(OType.INTEGER), null, null,
        null);

    final OIndex<OIdentifiable> idx = (OIndex<OIdentifiable>) idxManager.getIndex("IndexNotUniqueIndexKeySize");

    final Set<Integer> keys = new HashSet<Integer>();
    for (int i = 1; i < 100; i++) {
      final Integer key = (int) Math.log(i);

      final ODocument doc = new ODocument();
      doc.save();

      idx.put(key, doc);

      keys.add(key);
    }

    Assert.assertEquals(idx.getKeySize(), keys.size());
  }

  public void testNotUniqueIndexSize() {
    OIndexManager idxManager = database.getMetadata().getIndexManager();
    idxManager.createIndex("IndexNotUniqueIndexSize", "NOTUNIQUE", new OSimpleKeyIndexDefinition(OType.INTEGER), null, null, null);

    final OIndex<OIdentifiable> idx = (OIndex<OIdentifiable>) idxManager.getIndex("IndexNotUniqueIndexSize");

    for (int i = 1; i < 100; i++) {
      final Integer key = (int) Math.log(i);

      final ODocument doc = new ODocument();
      doc.save();

      idx.put(key, doc);
    }

    Assert.assertEquals(idx.getSize(), 99);
  }

  @Test
  public void testIndexRebuildDuringNonProxiedObjectDelete() {
    Profile profile = new Profile("NonProxiedObjectToDelete", "NonProxiedObjectToDelete", "NonProxiedObjectToDelete", null);
    profile = database.save(profile);

    OIndexManager idxManager = database.getMetadata().getIndexManager();
    OIndex<?> nickIndex = idxManager.getIndex("Profile.nick");

    Assert.assertTrue(nickIndex.contains("NonProxiedObjectToDelete"));

    final Profile loadedProfile = database.load(new ORecordId(profile.getId()));
    database.delete(database.detach(loadedProfile, true));

    Assert.assertFalse(nickIndex.contains("NonProxiedObjectToDelete"));
  }

  @Test(dependsOnMethods = "testIndexRebuildDuringNonProxiedObjectDelete")
  public void testIndexRebuildDuringDetachAllNonProxiedObjectDelete() {
    Profile profile = new Profile("NonProxiedObjectToDelete", "NonProxiedObjectToDelete", "NonProxiedObjectToDelete", null);
    profile = database.save(profile);

    OIndexManager idxManager = database.getMetadata().getIndexManager();
    OIndex<?> nickIndex = idxManager.getIndex("Profile.nick");

    Assert.assertTrue(nickIndex.contains("NonProxiedObjectToDelete"));

    final Profile loadedProfile = database.load(new ORecordId(profile.getId()));
    database.delete(database.detachAll(loadedProfile, true));

    Assert.assertFalse(nickIndex.contains("NonProxiedObjectToDelete"));
  }

  @Test(dependsOnMethods = "testIndexRebuildDuringDetachAllNonProxiedObjectDelete")
  public void testRestoreUniqueIndex() {
    database.getMetadata().getSchema().getClass("Profile").getProperty("nick").dropIndexes();
    database.getMetadata().getSchema().getClass("Profile").getProperty("nick").createIndex(OClass.INDEX_TYPE.UNIQUE);
  }

  @Test
  public void testIndexInCompositeQuery() {
    OClass classOne = database.getMetadata().getSchema().createClass("CompoundSQLIndexTest1");
    OClass classTwo = database.getMetadata().getSchema().createClass("CompoundSQLIndexTest2");

    classTwo.createProperty("address", OType.LINK, classOne);

    classTwo.createIndex("CompoundSQLIndexTestIndex", INDEX_TYPE.UNIQUE, "address");

    ODocument docOne = new ODocument("CompoundSQLIndexTest1");
    docOne.field("city", "Montreal");

    docOne.save();

    ODocument docTwo = new ODocument("CompoundSQLIndexTest2");
    docTwo.field("address", docOne);
    docTwo.save();

    List<ODocument> result = database.getUnderlying().query(
        new OSQLSynchQuery<ODocument>(
            "select from CompoundSQLIndexTest2 where address in (select from CompoundSQLIndexTest1 where city='Montreal')"));
    Assert.assertEquals(result.size(), 1);

    Assert.assertEquals(result.get(0).getIdentity(), docTwo.getIdentity());
  }

  public void testIndexWithLimitAndOffset() {
    ODatabaseDocumentTx databaseDocumentTx = (ODatabaseDocumentTx) database.getUnderlying();

    final OSchema schema = databaseDocumentTx.getMetadata().getSchema();
    final OClass indexWithLimitAndOffset = schema.createClass("IndexWithLimitAndOffsetClass");
    indexWithLimitAndOffset.createProperty("val", OType.INTEGER);
    indexWithLimitAndOffset.createProperty("index", OType.INTEGER);

    databaseDocumentTx.command(new OCommandSQL(
        "create index IndexWithLimitAndOffset on IndexWithLimitAndOffsetClass (val) notunique"));

    for (int i = 0; i < 30; i++) {
      final ODocument document = new ODocument("IndexWithLimitAndOffsetClass");
      document.field("val", i / 10);
      document.field("index", i);
      document.save();
    }

    final List<ODocument> result = databaseDocumentTx.query(new OSQLSynchQuery<ODocument>(
        "select from IndexWithLimitAndOffsetClass where val = 1 offset 5 limit 2"));
    Assert.assertEquals(result.size(), 2);

    for (int i = 0; i < 2; i++) {
      final ODocument document = result.get(i);
      Assert.assertEquals(document.field("val"), 1);
      Assert.assertEquals(document.field("index"), 15 + i);
    }
  }

  public void testIndexPaginationTest() {
    ODatabaseDocumentTx databaseDocumentTx = (ODatabaseDocumentTx) database.getUnderlying();

    final OSchema schema = databaseDocumentTx.getMetadata().getSchema();
    final OClass indexPaginationTest = schema.createClass("IndexPaginationTestClass");
    indexPaginationTest.createProperty("prop", OType.INTEGER);
    indexPaginationTest.createIndex("IndexPaginationTest", INDEX_TYPE.UNIQUE, "prop", "@rid");

    List<ORID> rids = new ArrayList<ORID>();

    for (int i = 99; i >= 0; i--) {
      final ODocument document = new ODocument("IndexPaginationTestClass");
      document.field("prop", i / 2);
      document.save();

      rids.add(document.getIdentity());
    }

    List<ODocument> result = databaseDocumentTx.query(new OSQLSynchQuery<ODocument>(
        "select from index:IndexPaginationTest limit 5 order by key"));

    Assert.assertEquals(result.size(), 5);

    int lastKey = -1;
    ORID lastRid = null;
    for (ODocument document : result) {
      document.setLazyLoad(false);
      if (lastKey > -1)
        Assert.assertTrue(lastKey <= (Integer) document.<OCompositeKey> field("key").getKeys().get(0));

      lastKey = (Integer) document.<OCompositeKey> field("key").getKeys().get(0);
      lastRid = document.field("rid");

      Assert.assertTrue(rids.remove(document.<OIdentifiable> field("rid").getIdentity()));
    }

    while (true) {
      result = databaseDocumentTx.query(new OSQLSynchQuery<ODocument>(
          "select from index:IndexPaginationTest where key > ? limit 5  order by key"), new OCompositeKey(lastKey, lastRid));
      if (result.isEmpty())
        break;

      Assert.assertEquals(result.size(), 5);

      for (ODocument document : result) {
        document.setLazyLoad(false);
        if (lastKey > -1)
          Assert.assertTrue(lastKey <= (Integer) document.<OCompositeKey> field("key").getKeys().get(0));

        lastKey = (Integer) document.<OCompositeKey> field("key").getKeys().get(0);
        lastRid = document.field("rid", OType.LINK);

        Assert.assertTrue(rids.remove(document.<ORID> field("rid", OType.LINK)));
      }
    }

    Assert.assertTrue(rids.isEmpty());
  }

  public void testIndexPaginationTestDescOrder() {
    ODatabaseDocumentTx databaseDocumentTx = (ODatabaseDocumentTx) database.getUnderlying();

    final OSchema schema = databaseDocumentTx.getMetadata().getSchema();
    final OClass indexPaginationTest = schema.createClass("IndexPaginationTestDescOrderClass");
    indexPaginationTest.createProperty("prop", OType.INTEGER);
    indexPaginationTest.createIndex("IndexPaginationTestDescOrder", INDEX_TYPE.UNIQUE, "prop", "@rid");

    List<ORID> rids = new ArrayList<ORID>();

    for (int i = 99; i >= 0; i--) {
      final ODocument document = new ODocument("IndexPaginationTestDescOrderClass");
      document.field("prop", i / 2);
      document.save();

      rids.add(document.getIdentity());
    }

    List<ODocument> result = databaseDocumentTx.query(new OSQLSynchQuery<ODocument>(
        "select from index:IndexPaginationTestDescOrder limit 5 order by key desc"));

    Assert.assertEquals(result.size(), 5);

    int lastKey = -1;
    ORID lastRid = null;
    for (ODocument document : result) {
      document.setLazyLoad(false);
      if (lastKey > -1)
        Assert.assertTrue(lastKey >= (Integer) document.<OCompositeKey> field("key").getKeys().get(0));

      lastKey = (Integer) document.<OCompositeKey> field("key").getKeys().get(0);
      lastRid = document.field("rid");

      Assert.assertTrue(rids.remove(document.<ORID> field("rid")));
    }

    while (true) {
      result = databaseDocumentTx.query(new OSQLSynchQuery<ODocument>(
          "select from index:IndexPaginationTestDescOrder where key < ? limit 5  order by key desc"), new OCompositeKey(lastKey,
          lastRid));
      if (result.isEmpty())
        break;

      Assert.assertEquals(result.size(), 5);

      for (ODocument document : result) {
        document.setLazyLoad(false);
        if (lastKey > -1)
          Assert.assertTrue(lastKey >= (Integer) document.<OCompositeKey> field("key").getKeys().get(0));

        lastKey = (Integer) document.<OCompositeKey> field("key").getKeys().get(0);
        lastRid = document.field("rid", OType.LINK);

        Assert.assertTrue(rids.remove(document.<ORID> field("rid", OType.LINK)));
      }
    }

    Assert.assertTrue(rids.isEmpty());
  }

  public void testNullIndexKeysSupport() {
    final ODatabaseDocumentTx databaseDocumentTx = (ODatabaseDocumentTx) database.getUnderlying();

    final OSchema schema = databaseDocumentTx.getMetadata().getSchema();
    final OClass clazz = schema.createClass("NullIndexKeysSupport");
    clazz.createProperty("nullField", OType.STRING);

    ODocument metadata = new ODocument();
    metadata.field("ignoreNullValues", false);

    clazz.createIndex("NullIndexKeysSupportIndex", INDEX_TYPE.NOTUNIQUE.toString(), null, metadata, new String[] { "nullField" });
    for (int i = 0; i < 20; i++) {
      if (i % 5 == 0) {
        ODocument document = new ODocument("NullIndexKeysSupport");
        document.field("nullField", (Object) null);
        document.save();
      } else {
        ODocument document = new ODocument("NullIndexKeysSupport");
        document.field("nullField", "val" + i);
        document.save();
      }
    }

    List<ODocument> result = databaseDocumentTx.query(new OSQLSynchQuery<ODocument>(
        "select from NullIndexKeysSupport where nullField = 'val3'"));
    Assert.assertEquals(result.size(), 1);

    Assert.assertEquals(result.get(0).field("nullField"), "val3");

    final String query = "select from NullIndexKeysSupport where nullField is null";
    result = databaseDocumentTx.query(new OSQLSynchQuery<ODocument>("select from NullIndexKeysSupport where nullField is null"));

    Assert.assertEquals(result.size(), 4);
    for (ODocument document : result)
      Assert.assertNull(document.field("nullField"));

    final ODocument explain = databaseDocumentTx.command(new OCommandSQL("explain " + query)).execute();
    Assert.assertTrue(explain.<Set<String>> field("involvedIndexes").contains("NullIndexKeysSupportIndex"));
  }

  public void testNullHashIndexKeysSupport() {
    final ODatabaseDocumentTx databaseDocumentTx = (ODatabaseDocumentTx) database.getUnderlying();

    final OSchema schema = databaseDocumentTx.getMetadata().getSchema();
    final OClass clazz = schema.createClass("NullHashIndexKeysSupport");
    clazz.createProperty("nullField", OType.STRING);

    ODocument metadata = new ODocument();
    metadata.field("ignoreNullValues", false);

    clazz.createIndex("NullHashIndexKeysSupportIndex", INDEX_TYPE.NOTUNIQUE.toString(), null, metadata,
        new String[] { "nullField" });
    for (int i = 0; i < 20; i++) {
      if (i % 5 == 0) {
        ODocument document = new ODocument("NullHashIndexKeysSupport");
        document.field("nullField", (Object) null);
        document.save();
      } else {
        ODocument document = new ODocument("NullHashIndexKeysSupport");
        document.field("nullField", "val" + i);
        document.save();
      }
    }

    List<ODocument> result = databaseDocumentTx.query(new OSQLSynchQuery<ODocument>(
        "select from NullHashIndexKeysSupport where nullField = 'val3'"));
    Assert.assertEquals(result.size(), 1);

    Assert.assertEquals(result.get(0).field("nullField"), "val3");

    final String query = "select from NullHashIndexKeysSupport where nullField is null";
    result = databaseDocumentTx
        .query(new OSQLSynchQuery<ODocument>("select from NullHashIndexKeysSupport where nullField is null"));

    Assert.assertEquals(result.size(), 4);
    for (ODocument document : result)
      Assert.assertNull(document.field("nullField"));

    final ODocument explain = databaseDocumentTx.command(new OCommandSQL("explain " + query)).execute();
    Assert.assertTrue(explain.<Set<String>> field("involvedIndexes").contains("NullHashIndexKeysSupportIndex"));
  }

  public void testNullIndexKeysSupportInTx() {
    final ODatabaseDocumentTx databaseDocumentTx = (ODatabaseDocumentTx) database.getUnderlying();

    final OSchema schema = databaseDocumentTx.getMetadata().getSchema();
    final OClass clazz = schema.createClass("NullIndexKeysSupportInTx");
    clazz.createProperty("nullField", OType.STRING);

    ODocument metadata = new ODocument();
    metadata.field("ignoreNullValues", false);

    clazz.createIndex("NullIndexKeysSupportInTxIndex", INDEX_TYPE.NOTUNIQUE.toString(), null, metadata,
        new String[] { "nullField" });

    database.begin();

    for (int i = 0; i < 20; i++) {
      if (i % 5 == 0) {
        ODocument document = new ODocument("NullIndexKeysSupportInTx");
        document.field("nullField", (Object) null);
        document.save();
      } else {
        ODocument document = new ODocument("NullIndexKeysSupportInTx");
        document.field("nullField", "val" + i);
        document.save();
      }
    }

    database.commit();

    List<ODocument> result = databaseDocumentTx.query(new OSQLSynchQuery<ODocument>(
        "select from NullIndexKeysSupportInTx where nullField = 'val3'"));
    Assert.assertEquals(result.size(), 1);

    Assert.assertEquals(result.get(0).field("nullField"), "val3");

    final String query = "select from NullIndexKeysSupportInTx where nullField is null";
    result = databaseDocumentTx
        .query(new OSQLSynchQuery<ODocument>("select from NullIndexKeysSupportInTx where nullField is null"));

    Assert.assertEquals(result.size(), 4);
    for (ODocument document : result)
      Assert.assertNull(document.field("nullField"));

    final ODocument explain = databaseDocumentTx.command(new OCommandSQL("explain " + query)).execute();
    Assert.assertTrue(explain.<Set<String>> field("involvedIndexes").contains("NullIndexKeysSupportInTxIndex"));
  }

  public void testNullIndexKeysSupportInMiddleTx() {
    if (database.getURL().startsWith("remote:"))
      return;

    final ODatabaseDocumentTx databaseDocumentTx = (ODatabaseDocumentTx) database.getUnderlying();

    final OSchema schema = databaseDocumentTx.getMetadata().getSchema();
    final OClass clazz = schema.createClass("NullIndexKeysSupportInMiddleTx");
    clazz.createProperty("nullField", OType.STRING);

    ODocument metadata = new ODocument();
    metadata.field("ignoreNullValues", false);

    clazz.createIndex("NullIndexKeysSupportInMiddleTxIndex", INDEX_TYPE.NOTUNIQUE.toString(), null, metadata,
        new String[] { "nullField" });

    database.begin();

    for (int i = 0; i < 20; i++) {
      if (i % 5 == 0) {
        ODocument document = new ODocument("NullIndexKeysSupportInMiddleTx");
        document.field("nullField", (Object) null);
        document.save();
      } else {
        ODocument document = new ODocument("NullIndexKeysSupportInMiddleTx");
        document.field("nullField", "val" + i);
        document.save();
      }
    }

    List<ODocument> result = databaseDocumentTx.query(new OSQLSynchQuery<ODocument>(
        "select from NullIndexKeysSupportInMiddleTx where nullField = 'val3'"));
    Assert.assertEquals(result.size(), 1);

    Assert.assertEquals(result.get(0).field("nullField"), "val3");

    final String query = "select from NullIndexKeysSupportInMiddleTx where nullField is null";
    result = databaseDocumentTx.query(new OSQLSynchQuery<ODocument>(
        "select from NullIndexKeysSupportInMiddleTx where nullField is null"));

    Assert.assertEquals(result.size(), 4);
    for (ODocument document : result)
      Assert.assertNull(document.field("nullField"));

    final ODocument explain = databaseDocumentTx.command(new OCommandSQL("explain " + query)).execute();
    Assert.assertTrue(explain.<Set<String>> field("involvedIndexes").contains("NullIndexKeysSupportInMiddleTxIndex"));

    database.commit();
  }

  public void testCreateIndexAbstractClass() {
    final ODatabaseDocumentTx databaseDocumentTx = (ODatabaseDocumentTx) database.getUnderlying();
    final OSchema schema = databaseDocumentTx.getMetadata().getSchema();

    OClass abstractClass = schema.createAbstractClass("TestCreateIndexAbstractClass");
    abstractClass.createProperty("value", OType.STRING).setMandatory(true).createIndex(INDEX_TYPE.UNIQUE);

    schema.createClass("TestCreateIndexAbstractClassChildOne", abstractClass);
    schema.createClass("TestCreateIndexAbstractClassChildTwo", abstractClass);

    ODocument docOne = new ODocument("TestCreateIndexAbstractClassChildOne");
    docOne.field("value", "val1");
    docOne.save();

    ODocument docTwo = new ODocument("TestCreateIndexAbstractClassChildTwo");
    docTwo.field("value", "val2");
    docTwo.save();

    final String queryOne = "select from TestCreateIndexAbstractClass where value = 'val1'";

    List<ODocument> resultOne = databaseDocumentTx.query(new OSQLSynchQuery<ODocument>(queryOne));
    Assert.assertEquals(resultOne.size(), 1);
    Assert.assertEquals(resultOne.get(0), docOne);

    ODocument explain = databaseDocumentTx.command(new OCommandSQL("explain " + queryOne)).execute();
    Assert.assertTrue(explain.<Collection<String>> field("involvedIndexes").contains("TestCreateIndexAbstractClass.value"));

    final String queryTwo = "select from TestCreateIndexAbstractClass where value = 'val2'";

    List<ODocument> resultTwo = databaseDocumentTx.query(new OSQLSynchQuery<ODocument>(queryTwo));
    Assert.assertEquals(resultTwo.size(), 1);
    Assert.assertEquals(resultTwo.get(0), docTwo);

    explain = databaseDocumentTx.command(new OCommandSQL("explain " + queryTwo)).execute();
    Assert.assertTrue(explain.<Collection<String>> field("involvedIndexes").contains("TestCreateIndexAbstractClass.value"));
  }

  public void testValuesContainerIsRemovedIfIndexIsRemoved() {
    if (database.getURL().startsWith("remote:"))
      return;

    final OSchema schema = database.getMetadata().getSchema();
    OClass clazz = schema.createClass("ValuesContainerIsRemovedIfIndexIsRemovedClass");
    clazz.createProperty("val", OType.STRING);

    database
        .command(
            new OCommandSQL(
                "create index ValuesContainerIsRemovedIfIndexIsRemovedIndex on ValuesContainerIsRemovedIfIndexIsRemovedClass (val) notunique"))
        .execute();

    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 100; j++) {
        ODocument document = new ODocument("ValuesContainerIsRemovedIfIndexIsRemovedClass");
        document.field("val", "value" + i);
        document.save();
      }
    }

    final OAbstractPaginatedStorage storageLocalAbstract = (OAbstractPaginatedStorage) database.getStorage();
    final ODiskCache diskCache = storageLocalAbstract.getDiskCache();

    Assert.assertTrue(diskCache.exists("ValuesContainerIsRemovedIfIndexIsRemovedIndex.irs"));

    database.command(new OCommandSQL("drop index ValuesContainerIsRemovedIfIndexIsRemovedIndex")).execute();

    Assert.assertTrue(!diskCache.exists("ValuesContainerIsRemovedIfIndexIsRemovedIndex.irs"));
  }

  private List<OClusterPosition> getValidPositions(int clusterId) {
    final List<OClusterPosition> positions = new ArrayList<OClusterPosition>();

    final ORecordIteratorCluster<?> iteratorCluster = database.getUnderlying()
        .browseCluster(database.getClusterNameById(clusterId));

    for (int i = 0; i < 7; i++) {
      if (!iteratorCluster.hasNext())
        break;

      ORecord doc = iteratorCluster.next();
      positions.add(doc.getIdentity().getClusterPosition());
    }
    return positions;
  }
}
TOP

Related Classes of com.orientechnologies.orient.test.database.auto.IndexTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.