/// <summary> /// Record the current parse timestamp of a whole collection of StTexts /// Equivalent to calling RecordParseTimestamp on each of them. /// </summary> /// <param name="texts"></param> public static void RecordParseTimestamps(List <IStText> texts) { if (texts.Count == 0) { return; } FdoCache cache = texts[0].Cache; int[] targetHvos = new int[texts.Count]; for (int i = 0; i < targetHvos.Length; i++) { targetHvos[i] = texts[i].Hvo; } int index = 0; string Hvos = DbOps.MakePartialIdList(ref index, targetHvos); string whereClause = ""; if (index == targetHvos.Length) { // If we can make a single where clause we'll do it; otherwise do them all. whereClause = " where Owner$ in (" + Hvos + ")"; } string sql = "select owner$, max(UpdStmp) from StTxtPara_ " + whereClause + " group by owner$"; IDbColSpec dcs = DbColSpecClass.Create(); dcs.Push((int)DbColType.koctBaseId, 0, 0, 0); int modifyTimestampTag = ParagraphsModifiedTimestampTag(cache); dcs.Push((int)DbColType.koctInt64, 1, modifyTimestampTag, 0); cache.VwOleDbDaAccessor.Load(sql, dcs, 0, 0, null, false); ISilDataAccess sda = cache.MainCacheAccessor; foreach (StText text in texts) { // Much of the logic of RecordParseTimestamp, but can assume modify timestamp is already loaded. text.LastParsedTimestamp = sda.get_Int64Prop(text.Hvo, modifyTimestampTag); text.ClearLastModifiedTimestamp(); } }
/// <summary> /// Required method to load the data. /// </summary> /// <param name="hvo"></param> /// <param name="tag"></param> /// <param name="ws"></param> /// <param name="_cda"></param> public override void Load(int hvo, int tag, int ws, SIL.FieldWorks.Common.COMInterfaces.IVwCacheDa _cda) { // Need to get stem.PartOfSpeech instead of cn.Obj because cn.Obj and cn.Txt may be null! See LT-6828. string sql = "select ls.id, ls.MorphoSyntaxAnalysis, msao.Owner$, msao.class$, ms.txt, ms.fmt, stem.PartOfSpeech, cn.txt from LexSense ls" + " left outer join MultiStr$ ms on ms.obj = ls.id and ms.flid = 5016005 and ms.ws = " + m_cache.DefaultAnalWs + " left outer join MoStemMsa stem on stem.id = ls.MorphoSyntaxAnalysis" + " left outer join CmPossibility_Name cn on stem.PartOfSpeech = cn.obj and cn.ws = " + m_cache.DefaultAnalWs + " left outer join CmObject msao on msao.id = ls.MorphoSyntaxAnalysis"; IVwOleDbDa dba = m_cache.VwOleDbDaAccessor; IDbColSpec dcs = DbColSpecClass.Create(); dcs.Push((int)DbColType.koctObjVec, 0, this.Tag, 0); dcs.Push((int)DbColType.koctObj, 1, (int)LexSense.LexSenseTags.kflidMorphoSyntaxAnalysis, 0); dcs.Push((int)DbColType.koctObj, 2, (int)CmObjectFields.kflidCmObject_Owner, 0); dcs.Push((int)DbColType.koctInt, 2, (int)CmObjectFields.kflidCmObject_Class, 0); dcs.Push((int)DbColType.koctMlsAlt, 1, (int)LexSense.LexSenseTags.kflidDefinition, m_cache.DefaultAnalWs); dcs.Push((int)DbColType.koctFmt, 1, (int)LexSense.LexSenseTags.kflidDefinition, m_cache.DefaultAnalWs); dcs.Push((int)DbColType.koctObj, 2, (int)MoStemMsa.MoStemMsaTags.kflidPartOfSpeech, 0); dcs.Push((int)DbColType.koctMltAlt, 7, (int)CmPossibility.CmPossibilityTags.kflidName, m_cache.DefaultAnalWs); dba.Load(sql, dcs, hvo, 0, null, false); }
/// ------------------------------------------------------------------------------------ /// <summary> /// fill in the columnSpec with the columns which contain the basic cable information, /// corresponding to a "classname_" SQL view /// </summary> /// <remarks> This is a static method because it is used outside of the context /// of an instance of CmObject. That is, it is used when we are trying to instantiate /// one or more CmObjects which do not exist yet. Although this is a static method, it /// is used something like a virtual method. /// That is, the corresponding method on the actual class of the object is first called, /// and that then calls the corresponding method on its base class. this continues until /// this method, on CmObject, is called.</remarks> /// <param name="cs">the columnSpec which will be added to</param> /// ------------------------------------------------------------------------------------ protected static void PopulateCsBasic(IDbColSpec cs) { cs.Push((int)DbColType.koctBaseId, 0, 0, 0); //id cs.Push((int)DbColType.koctGuid, 1, (int)CmObjectFields.kflidCmObject_Guid, 0); cs.Push((int)DbColType.koctInt, 1, (int)CmObjectFields.kflidCmObject_Class, 0); cs.Push((int)DbColType.koctObj, 1, (int)CmObjectFields.kflidCmObject_Owner, 0); cs.Push((int)DbColType.koctInt, 1, (int)CmObjectFields.kflidCmObject_OwnFlid, 0); cs.Push((int)DbColType.koctInt, 1, (int)CmObjectFields.kflidCmObject_OwnOrd, 0);//OwnOrd$ cs.Push((int)DbColType.koctTimeStamp, 1, 0, 0); //UpdStmp$ cs.Push((int)DbColType.koctTime, 1, 0, 0);// UpdDttm$ }
/// ------------------------------------------------------------------------------------ /// <summary> /// Add any custom fields to the columnSpec. /// </summary> /// <remarks> note that we should be able to use the code here to handle the entire CS /// creation, since all fields are listed in Field$. for now, I am just using this /// for custom fields in order to have the least impact on the code.</remarks> /// ------------------------------------------------------------------------------------ protected static void PopulateColumnSpecWithCustomFields(Type fdoClassType, FdoCache cache,IDbColSpec columnSpec) { //ToDo: This method kills InMemoryFdoCache if(cache.GetType() != typeof(FdoCache)) return; int iclassId =(int)GetStaticField(fdoClassType, "kClassId"); uint classId= (uint)iclassId; foreach(ClassAndPropInfo info in cache.GetFieldsOfClass(classId)) { if(!info.isCustom) continue; if(!info.isBasic) continue; switch(info.fieldType) { default: continue; case (int)FldType.kftString: columnSpec.Push((int)DbColType.koctString, 1, (int)info.flid, 0); columnSpec.Push((int)DbColType.koctFmt, 1, (int)info.flid, 0); break; } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Collect the information needed to load one or more members of the /// given class into the cache. /// </summary> /// <param name="csharpType">Class of objects that will be loaded.</param> /// <param name="dcs"> /// Column spec, which is assumed to already have the first column loaded. /// </param> /// <param name="sSelectClause">SQL select clause("select" not included)</param> /// <param name="sFromClause">SQL from clause ("From" not included)</param> /// ------------------------------------------------------------------------------------ private static void BuildOwningAtomicLoadSpec(Type csharpType, IDbColSpec dcs, ref string sSelectClause, ref string sFromClause) { // note: the "FlattenHierarchy" is needed here because the class we are giving it is "XXX" one, // but this property is on its superclass,"BaseXXXX" System.Reflection.FieldInfo fi = csharpType.GetField("OwningAtomicFlids", System.Reflection.BindingFlags.FlattenHierarchy | System.Reflection.BindingFlags.NonPublic | //these are marked "internal" System.Reflection.BindingFlags.Static); Debug.Assert(fi != null); int[] flids = (int[]) fi.GetValue(null); foreach(int flid in flids) { if(flid !=0) // 0 is an artifact of the xslt generator { dcs.Push((int)DbColType.koctObj, 1, (int)flid, 0); // (SteveMiller) This code originally built a query using // left outer joins. This is actually faster than using // subselects. However, The complexity of the query was // causing table spooling in the large English Websters // and Bible database, making it considerably slower. It // also was coming up with inexplicable "missing join // predicate" errors on the first five of the table spools. // (23 March 2007) sSelectClause += " (select Id from CmObject where Owner$ = obj.Id and OwnFlid$ = " + flid.ToString() + "), "; } } int commapos = sSelectClause.LastIndexOf(','); if (commapos >= 0) sSelectClause = sSelectClause.Remove(commapos, 1); }