public virtual NeoDatis.Odb.Objects <T> Execute <T>(bool inMemory, int startIndex, int endIndex, bool returnObjects, NeoDatis.Odb.Core.Query.Execution.IMatchingObjectAction queryResultAction) { if (storageEngine.IsClosed()) { throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.OdbIsClosed .AddParameter(storageEngine.GetBaseIdentification().GetIdentification())); } if (session.IsRollbacked()) { throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.OdbHasBeenRollbacked ); } // When used as MultiClass Executor, classInfo is already set if (classInfo == null) { // Class to execute query on string fullClassName = NeoDatis.Odb.Core.Query.QueryManager.GetFullClassName(query ); // If the query class does not exist in meta model, return an empty // collection if (!session.GetMetaModel().ExistClass(fullClassName)) { queryResultAction.Start(); queryResultAction.End(); query.SetExecutionPlan(new NeoDatis.Odb.Core.Query.Execution.EmptyExecutionPlan() ); return(queryResultAction.GetObjects <T>()); } classInfo = session.GetMetaModel().GetClassInfo(fullClassName, true); } // Get the query execution plan NeoDatis.Odb.Core.Query.Execution.IQueryExecutionPlan plan = GetExecutionPlan(); plan.Start(); try { if (plan.UseIndex() && NeoDatis.Odb.OdbConfiguration.UseIndex()) { return(ExecuteUsingIndex <T>(plan.GetIndex(), inMemory, startIndex, endIndex, returnObjects , queryResultAction)); } // When query must be applied to a single object if (query.IsForSingleOid()) { return(ExecuteForOneOid <T>(inMemory, returnObjects, queryResultAction)); } return(ExecuteFullScan <T>(inMemory, startIndex, endIndex, returnObjects, queryResultAction )); } finally { plan.End(); } }
/// <summary>The main query execution method</summary> /// <param name="query"></param> /// <param name="inMemory"></param> /// <param name="startIndex"></param> /// <param name="endIndex"></param> /// <param name="returnObjects"></param> /// <returns></returns> /// <exception cref="System.Exception">System.Exception</exception> public virtual NeoDatis.Odb.Objects <T> Execute <T>(bool inMemory, int startIndex, int endIndex, bool returnObjects, NeoDatis.Odb.Core.Query.Execution.IMatchingObjectAction queryResultAction) { if (executor.GetStorageEngine().IsClosed()) { throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.OdbIsClosed .AddParameter(executor.GetStorageEngine().GetBaseIdentification().GetIdentification ())); } if (executor.GetStorageEngine().GetSession(true).IsRollbacked()) { throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.OdbHasBeenRollbacked ); } // Get the main class string fullClassName = NeoDatis.Odb.Core.Query.QueryManager.GetFullClassName(executor .GetQuery()); // this is done once. queryResultAction.Start(); NeoDatis.Tool.Wrappers.List.IOdbList <NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo > allClassInfos = executor.GetStorageEngine().GetSession(true).GetMetaModel().GetPersistentSubclassesOf (fullClassName); int nbClasses = allClassInfos.Count; NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo ci = null; for (int i = 0; i < nbClasses; i++) { ci = allClassInfos[i]; // Sets the class info to the current executor.SetClassInfo(ci); // Then execute query executor.Execute <T>(inMemory, startIndex, endIndex, returnObjects, queryResultAction ); } queryResultAction.End(); return(queryResultAction.GetObjects <T>()); }
/// <summary>Execute query using index</summary> /// <param name="inMemory"></param> /// <param name="returnObjects"></param> /// <returns></returns> /// <exception cref="System.Exception">System.Exception</exception> private NeoDatis.Odb.Objects <T> ExecuteForOneOid <T>(bool inMemory, bool returnObjects , NeoDatis.Odb.Core.Query.Execution.IMatchingObjectAction queryResultAction) { if (NeoDatis.Odb.OdbConfiguration.IsDebugEnabled(LogId)) { NeoDatis.Tool.DLogger.Debug("loading Object with oid " + query.GetOidOfObjectToQuery () + " - class " + classInfo.GetFullClassName()); } if (ExecuteStartAndEndOfQueryAction()) { queryResultAction.Start(); } PrepareQuery(); NeoDatis.Odb.OID oid = query.GetOidOfObjectToQuery(); // FIXME Why calling this method long position = objectReader.GetObjectPositionFromItsOid(oid, true, true); bool objectMatches = MatchObjectWithOid(oid, returnObjects, inMemory); queryResultAction.ObjectMatch(oid, GetCurrentObjectMetaRepresentation(), orderByKey ); queryResultAction.End(); return(queryResultAction.GetObjects <T>()); }
/// <summary>Execute query using index</summary> /// <param name="index"></param> /// <param name="inMemory"></param> /// <param name="startIndex"></param> /// <param name="endIndex"></param> /// <param name="returnObjects"></param> /// <returns></returns> /// <exception cref="System.Exception">System.Exception</exception> private NeoDatis.Odb.Objects <T> ExecuteUsingIndex <T>(NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfoIndex index, bool inMemory, int startIndex, int endIndex, bool returnObjects, NeoDatis.Odb.Core.Query.Execution.IMatchingObjectAction queryResultAction) { // Index that have not been used yet do not have persister! if (index.GetBTree().GetPersister() == null) { index.GetBTree().SetPersister(new NeoDatis.Odb.Impl.Core.Btree.LazyODBBTreePersister (storageEngine)); } bool objectMatches = false; long nbObjects = classInfo.GetNumberOfObjects(); long btreeSize = index.GetBTree().GetSize(); // the two values should be equal if (nbObjects != btreeSize) { NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo ci = storageEngine.GetSession(true ).GetMetaModel().GetClassInfoFromId(index.GetClassInfoId()); throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.IndexIsCorrupted .AddParameter(index.GetName()).AddParameter(ci.GetFullClassName()).AddParameter( nbObjects).AddParameter(btreeSize)); } if (NeoDatis.Odb.OdbConfiguration.IsDebugEnabled(LogId)) { NeoDatis.Tool.DLogger.Debug("loading " + nbObjects + " instance(s) of " + classInfo .GetFullClassName()); } if (ExecuteStartAndEndOfQueryAction()) { queryResultAction.Start(); } PrepareQuery(); if (query != null) { queryHasOrderBy = query.HasOrderBy(); } NeoDatis.Btree.IBTree tree = index.GetBTree(); bool isUnique = index.IsUnique(); // Iterator iterator = new BTreeIterator(tree, // OrderByConstants.ORDER_BY_ASC); System.IComparable key = ComputeIndexKey(classInfo, index); System.Collections.IList list = null; // If index is unique, get the object if (isUnique) { NeoDatis.Btree.IBTreeSingleValuePerKey treeSingle = (NeoDatis.Btree.IBTreeSingleValuePerKey )tree; object o = treeSingle.Search(key); if (o != null) { list = new System.Collections.ArrayList(); list.Add(o); } } else { NeoDatis.Btree.IBTreeMultipleValuesPerKey treeMultiple = (NeoDatis.Btree.IBTreeMultipleValuesPerKey )tree; list = treeMultiple.Search(key); } if (list != null) { System.Collections.IEnumerator iterator = list.GetEnumerator(); while (iterator.MoveNext()) { NeoDatis.Odb.OID oid = (NeoDatis.Odb.OID)iterator.Current; // FIXME Why calling this method long position = objectReader.GetObjectPositionFromItsOid(oid, true, true); orderByKey = null; objectMatches = MatchObjectWithOid(oid, returnObjects, inMemory); if (objectMatches) { queryResultAction.ObjectMatch(oid, GetCurrentObjectMetaRepresentation(), orderByKey ); } } queryResultAction.End(); return(queryResultAction.GetObjects <T>()); } if (ExecuteStartAndEndOfQueryAction()) { queryResultAction.End(); } return(queryResultAction.GetObjects <T>()); }
/// <summary> /// Query execution full scan /// <pre> /// startIndex & endIndex /// A B C D E F G H I J K L /// [1,3] : nb >=1 && nb<3 /// 1) /// analyze A /// nb = 0 /// nb E [1,3] ? no /// r=[] /// 2) /// analyze B /// nb = 1 /// nb E [1,3] ? yes /// r=[B] /// 3) analyze C /// nb = 2 /// nb E [1,3] ? yes /// r=[B,C] /// 4) analyze C /// nb = 3 /// nb E [1,3] ? no and 3> upperBound([1,3]) => exit /// </pre> /// </summary> /// <param name="inMemory"></param> /// <param name="startIndex"></param> /// <param name="endIndex"></param> /// <param name="returnObjects"></param> /// <returns></returns> /// <exception cref="System.Exception">System.Exception</exception> private NeoDatis.Odb.Objects <T> ExecuteFullScan <T>(bool inMemory, int startIndex, int endIndex, bool returnObjects, NeoDatis.Odb.Core.Query.Execution.IMatchingObjectAction queryResultAction) { bool objectInRange = false; bool objectMatches = false; if (storageEngine.IsClosed()) { throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.OdbIsClosed .AddParameter(storageEngine.GetBaseIdentification().GetIdentification())); } long nbObjects = classInfo.GetNumberOfObjects(); if (NeoDatis.Odb.OdbConfiguration.IsDebugEnabled(LogId)) { NeoDatis.Tool.DLogger.Debug("loading " + nbObjects + " instance(s) of " + classInfo .GetFullClassName()); } if (ExecuteStartAndEndOfQueryAction()) { queryResultAction.Start(); } NeoDatis.Odb.OID currentOID = null; NeoDatis.Odb.OID prevOID = null; // TODO check if all instances are in the cache! and then load from the // cache nextOID = classInfo.GetCommitedZoneInfo().first; if (nbObjects > 0 && nextOID == null) { // This means that some changes have not been commited! // Take next position from uncommited zone nextOID = classInfo.GetUncommittedZoneInfo().first; } PrepareQuery(); if (query != null) { queryHasOrderBy = query.HasOrderBy(); } bool monitorMemory = NeoDatis.Odb.OdbConfiguration.IsMonitoringMemory(); // used when startIndex and endIndex are not negative int nbObjectsInResult = 0; for (int i = 0; i < nbObjects; i++) { //Console.WriteLine(i); if (monitorMemory && i % 10000 == 0) { NeoDatis.Odb.Impl.Tool.MemoryMonitor.DisplayCurrentMemory(string.Empty + (i + 1), true); } // Reset the order by key orderByKey = null; objectMatches = false; prevOID = currentOID; currentOID = nextOID; // This is an error if (currentOID == null) { if (NeoDatis.Odb.OdbConfiguration.ThrowExceptionWhenInconsistencyFound()) { throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.NullNextObjectOid .AddParameter(classInfo.GetFullClassName()).AddParameter(i).AddParameter(nbObjects ).AddParameter(prevOID)); } break; } // If there is an endIndex condition if (endIndex != -1 && nbObjectsInResult >= endIndex) { break; } // If there is a startIndex condition if (startIndex != -1 && nbObjectsInResult < startIndex) { objectInRange = false; } else { objectInRange = true; } // There is no query if (!inMemory && query == null) { nbObjectsInResult++; // keep object position if we must if (objectInRange) { orderByKey = BuildOrderByKey(currentNnoi); // TODO Where is the key for order by queryResultAction.ObjectMatch(nextOID, orderByKey); } nextOID = objectReader.GetNextObjectOID(currentOID); } else { objectMatches = MatchObjectWithOid(currentOID, returnObjects, inMemory); if (objectMatches) { nbObjectsInResult++; if (objectInRange) { if (queryHasOrderBy) { orderByKey = BuildOrderByKey(GetCurrentObjectMetaRepresentation()); } queryResultAction.ObjectMatch(currentOID, GetCurrentObjectMetaRepresentation(), orderByKey ); if (callback != null) { callback.ReadingObject(i, -1); } } } } } if (ExecuteStartAndEndOfQueryAction()) { queryResultAction.End(); } return(queryResultAction.GetObjects <T>()); }