/// <summary>
        ///
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="iter"></param>
        private void AppendTokens(SqlStringBuilder builder, ICollection iter)
        {
            bool lastSpaceable = true;
            bool lastQuoted    = false;

            int debugIndex = 0;

            foreach (object token in iter)
            {
                string    tokenString    = token as string;
                SqlString tokenSqlString = token as SqlString;

                bool spaceable = !dontSpace.Contains(token);
                bool quoted    = false;

                //TODO: seems HACKish to cast between String and SqlString
                if (tokenString != null)
                {
                    quoted = tokenString.StartsWith("'");
                }
                else
                {
                    quoted = tokenSqlString.StartsWith("'");
                }

                if (spaceable && lastSpaceable)
                {
                    if (!quoted || !lastQuoted)
                    {
                        builder.Add(" ");
                    }
                }

                lastSpaceable = spaceable;

                if (token.Equals(StringHelper.SqlParameter))
                {
                    Parameter param = new Parameter("placeholder");
                    builder.Add(param);
                }
                else
                {
                    // not sure if we have a string or a SqlString here and token is a
                    // reference to an object - so let the builder figure out what the
                    // actual object is
                    builder.AddObject(token);
                }
                debugIndex++;

                if (tokenString != null)
                {
                    lastQuoted = tokenString.EndsWith("'");
                }
                else
                {
                    lastQuoted = tokenSqlString.EndsWith("'");
                }
            }
        }
		public override SqlString ApplyLocksToSql(SqlString sql, IDictionary<string, LockMode> aliasedLockModes, IDictionary<string, string[]> keyColumnNames)
		{
			// TODO:  merge additional lockoptions support in Dialect.applyLocksToSql

			var buffer = new StringBuilder(sql.ToString());
			int correction = 0;
			
			foreach (KeyValuePair<string, LockMode> entry in aliasedLockModes)
			{
				LockMode mode = entry.Value;
				
				if (mode.GreaterThan(LockMode.Read))
				{
					string alias = entry.Key;
					int start = -1;
					int end = -1;
					
					if (sql.EndsWith(" " + alias))
					{
						start = (sql.Length - alias.Length) + correction;
						end = start + alias.Length;
					}
					else
					{
						int position = sql.IndexOfCaseInsensitive(" " + alias + " ");
						
						if (position <= -1)
							position = sql.IndexOfCaseInsensitive(" " + alias + ",");
						
						if (position > -1)
						{
							start = position + correction + 1;
							end = start + alias.Length;
						}
					}
					
					if (start > -1)
					{
						string lockHint = AppendLockHint(mode, alias);
						buffer.Remove(start, end - start + 1);
						buffer.Insert(start, lockHint);
						correction += (lockHint.Length - alias.Length);
					}
				}
			}
			return new SqlString(buffer.ToString());
		}
		public void EndsWithParameter()
		{
			SqlString sql = new SqlString(new object[] { "", "select", " from table where id = ", Parameter.Placeholder });
			Assert.IsFalse(sql.EndsWith("'"));
			Assert.IsFalse(sql.EndsWith(""));
		}
		public void EndsWithEmptyString()
		{
			SqlString sql = new SqlString(new string[] { "", "select", " from table", "" });
			Assert.IsTrue(sql.EndsWith("ble"));
			Assert.IsFalse(sql.EndsWith("'"));
		}