From: Michael D. <mik...@us...> - 2004-05-20 21:06:14
|
Update of /cvsroot/nhibernate/nhibernate/src/NHibernate/Hql In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7116/NHibernate/Hql Modified Files: QueryTranslator.cs Log Message: Methods to convert Hql's sql string into an IDbCommand moved into QueryTranslator. It now works with both "?" and named parameters. Index: QueryTranslator.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Hql/QueryTranslator.cs,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -d -r1.27 -r1.28 *** QueryTranslator.cs 30 Apr 2004 14:06:46 -0000 1.27 --- QueryTranslator.cs 20 May 2004 21:05:29 -0000 1.28 *************** *** 460,464 **** if (superQuery != null) superQuery.AddNamedParameter(name); ! int loc = ++parameterCount; object o = namedParameters[name]; if (o == null) --- 460,466 ---- if (superQuery != null) superQuery.AddNamedParameter(name); ! // want the param index to start at 0 instead of 1 ! //int loc = ++parameterCount; ! int loc = parameterCount++; object o = namedParameters[name]; if (o == null) *************** *** 902,906 **** { // Hack: parametercollection starts at 0 ! typedval.Type.NullSafeSet(ps, typedval.Value, Impl.AdoHack.ParameterPos(locs[i] + start), session); // end-of Hack } --- 904,909 ---- { // Hack: parametercollection starts at 0 ! //typedval.Type.NullSafeSet(ps, typedval.Value, Impl.AdoHack.ParameterPos(locs[i] + start), session); ! typedval.Type.NullSafeSet(ps, typedval.Value, (locs[i] + start), session); // end-of Hack } *************** *** 1228,1231 **** --- 1231,1343 ---- } } + + /// <summary> + /// Obtain an <see cref="IDbCommand"/> and bind the parameters. + /// </summary> + /// <param name="sql">A string containing the Sql statement</param> + /// <param name="values">The values to put in the Parameters.</param> + /// <param name="types">The IType to use to put the values in the Parameters.</param> + /// <param name="selection"></param> + /// <param name="scroll"></param> + /// <param name="session">The ISession currently in.</param> + /// <returns>An IDbCommand that is ready for execution.</returns> + /// <remarks> + /// <para> + /// This is used to convert an Hql sql string into a SqlString and then finally into an IDbCommand + /// that has been prepared. + /// </para> + /// <para> + /// This should not be considered a permanent solution because it is not very smart - it splits on + /// a <c>?</c> as long as the previous token ends with <c>"="</c> or <c>"= "</c>. + /// </para> + /// <para> + /// This used to be in the Loader, but since the only use of this right now is in the QueryTranslator + /// I moved it into here. + /// </para> + /// </remarks> + protected override IDbCommand PrepareQueryStatement(string sql, object[] values, IType[] types, IDictionary namedParams, RowSelection selection, bool scroll, ISessionImplementor session) + { + IType[] paramTypes = null; + object[] paramValues = null; + + if(namedParams==null) + { + paramTypes = types; + paramValues = values; + } + else + { + // convert the named parameters to an array of values and types + ArrayList paramTypeList = new ArrayList(namedParams.Keys.Count); + ArrayList paramValueList = new ArrayList(namedParams.Keys.Count); + + // assumes that types are all of span 1 + foreach (DictionaryEntry e in namedParams) + { + int lastInsertedIndex = paramTypeList.Count; + + string name = (string) e.Key; + TypedValue typedval = (TypedValue) e.Value; + int[] locs = GetNamedParameterLocs(name); + + for (int i = 0; i < locs.Length; i++) + { + int insertAt = locs[i]; + + // need to make sure that the ArrayList is populated with null objects + // up to the index we are about to add the values into. An Index Out + // of Range exception will be thrown if we add an element at an index + // that is greater than the Count. + if(insertAt >= lastInsertedIndex) + { + for(int j = lastInsertedIndex; j <= insertAt; j++) + { + paramTypeList.Add(null); + paramValueList.Add(null); + } + } + + paramTypeList[insertAt] = typedval.Type; + paramValueList[insertAt] = typedval.Value; + } + + } + paramTypes = (IType[]) paramTypeList.ToArray( typeof(IType) ); + paramValues = (object[]) paramValueList.ToArray( typeof(object) ); + } + + + StringTokenizer tokenizer = new StringTokenizer(sql, StringHelper.SqlParameter, true); + string[] tokens = sql.Split(StringHelper.SqlParameter[0]); + + SqlStringBuilder hqlToSqlBuilder = new SqlStringBuilder(types.Length * 2); + + IEnumerator tokenEnum = tokenizer.GetEnumerator(); + string previousToken = String.Empty; + string token = String.Empty; + int paramIndex = 0; + + while(tokenEnum.MoveNext()) + { + token = (string)tokenEnum.Current; + + if(token.Equals(StringHelper.SqlParameter) + && ( previousToken.EndsWith("=") || previousToken.EndsWith("= ") ) ) + { + Parameter param = Parameter.GenerateParameters(session.Factory, new string[]{paramIndex.ToString()}, paramTypes[paramIndex])[0]; + hqlToSqlBuilder.Add(param); + paramIndex++; + } + else + { + hqlToSqlBuilder.Add(token); + } + + previousToken = token; + } + + return PrepareCommand(hqlToSqlBuilder.ToSqlString(), paramValues, paramTypes, null, selection, scroll, session); + + } } } \ No newline at end of file |