Пример #1
0
		private Stream GetClearCommandStream()
		{
			if (type == CommandType.TableDirect)
				return new MemoryStream(Encoding.UTF8.GetBytes("select * from " + text)); // There is no parameter support on table direct.
			else if (type == CommandType.Text && parameters.Count == 0)
				return new MemoryStream(Encoding.UTF8.GetBytes(text));

			var ms = new MemoryStream();
			var sw = new StreamWriter(ms);
			if (type == CommandType.StoredProcedure)
			{
				if (Connector.SupportsPrepare)
					sw.Write("SELECT * FROM ");
				else
					sw.Write("SELECT ");
				sw.Write(text);
				if (!functionChecksDone)
				{
					functionNeedsColumnListDefinition = Parameters.Count != 0 && CheckFunctionNeedsColumnDefinitionList();

					// Check if just procedure name was passed. If so, does not replace parameter names and just pass parameter values in order they were added in parameters collection. Also check if command text finishes in a ";" which would make Npgsql incorrectly append a "()" when executing this command text.
					var end = text.TrimEnd();
					switch (end[end.Length - 1])
					{
						case ')':
						case ';':
							addProcedureParenthesis = false;
							break;
						default:
							addProcedureParenthesis = true;
							break;
					}
					functionChecksDone = true;
				}
			}
			else
			{
				sw.Write(text);
			}

			if (parameters.Count == 0)
			{
				if (addProcedureParenthesis)
					sw.Write("()");

				if (functionNeedsColumnListDefinition)
					AddFunctionColumnListSupport(sw);

				sw.Flush();
				return ms;
			}

			// Get parameters in query string to translate them to their actual values.

			// This regular expression gets all the parameters in format :param or @param
			// and everythingelse.
			// This is only needed if query string has parameters. Else, just append the
			// parameter values in order they were put in parameter collection.


			// If parenthesis don't need to be added, they were added by user with parameter names. Replace them.
			if (!addProcedureParenthesis)
			{
				var parameterIndex = new Dictionary<string, NpgsqlParameter>(parameters.Count, StringComparer.InvariantCultureIgnoreCase);
				foreach (NpgsqlParameter parameter in parameters)
					parameterIndex[parameter.CleanName] = parameter;

				ms = new MemoryStream();
				sw = new StreamWriter(ms);

				foreach (string s in parameterReplace.Split(text))
					//foreach (String s in parameterReplace.Split(result.ToString()))
					if (s.Length != 0)
					{
						NpgsqlParameter p = null;
						string parameterName = s;
						if ((parameterName[0] == ':') || (parameterName[0] == '@'))
						{
							parameterName = parameterName.Remove(0, 1);
							parameterIndex.TryGetValue(parameterName, out p);
						}

						if (p != null)
						{
							switch (p.Direction)
							{
								case ParameterDirection.Input:
								case ParameterDirection.InputOutput:
									//Wrap in probably-redundant parentheses. Queries should operate much as if they were in the a parameter or
									//variable in a postgres function. Generally this is the case without the parentheses (hence "probably redundant")
									//but there are exceptions to this rule. E.g. consider the postgres function:
									//
									//CREATE FUNCTION first_param(integer[])RETURNS int AS'select $1[1]'LANGUAGE 'sql' STABLE STRICT;
									//
									//The equivalent commandtext would be "select :param[1]", but this fails without the parentheses.

									sw.Write('(');
									PassParam(sw, p);
									sw.Write(')');
									break;
							}
						}
						else
						{
							sw.Write(s);
						}
					}
				//result = sb;
			}
			else
			{
				sw.Write('(');

				var len = parameters.Where(it => it.Direction == ParameterDirection.Input || it.Direction == ParameterDirection.InputOutput).Count();
				for (int i = 0; i < parameters.Count; i++)
				{
					switch (parameters[i].Direction)
					{
						case ParameterDirection.Input:
						case ParameterDirection.InputOutput:
							PassParam(sw, parameters[i]);
							len--;
							if (len > 1)
								sw.Write(',');
							break;
					}
				}

				sw.Write(')');
			}

			if (functionNeedsColumnListDefinition)
			{
				AddFunctionColumnListSupport(sw);
			}

			sw.Flush();
			return ms;
		}
Пример #2
0
		/// <summary>
		/// Creates a new <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see> that
		/// is a copy of the current instance.
		/// </summary>
		/// <returns>A new <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see> that is a copy of this instance.</returns>
		public NpgsqlParameter Clone()
		{
			// use fields instead of properties
			// to avoid auto-initializing something like type_info
			NpgsqlParameter clone = new NpgsqlParameter();
			clone.precision = precision;
			clone.scale = scale;
			clone.size = size;
			clone.type_info = type_info;
			clone.direction = direction;
			clone.is_nullable = is_nullable;
			clone.m_Name = m_Name;
			clone.source_column = source_column;
			clone.source_version = source_version;
			clone.value = value;
			clone.sourceColumnNullMapping = sourceColumnNullMapping;

			return clone;
		}
Пример #3
0
		private void PassParam(StreamWriter query, NpgsqlParameter p)
		{
			string serialised = p.TypeInfo.ConvertToBackend(p.Value, false);

			// Add parentheses wrapping parameter value before the type cast to avoid problems with Int16.MinValue, Int32.MinValue and Int64.MinValue
			// See bug #1010543
			// Check if this parenthesis can be collapsed with the previous one about the array support. This way, we could use
			// only one pair of parentheses for the two purposes instead of two pairs.
			query.Write('(');

			if (Connector.UseConformantStrings)
				switch (serialised[0])
				{
					case '\''://type passed as string or string with type.
						//We could test to see if \ is used anywhere, but then we could be doing quite an expensive check (if the value is large) for little gain.
						query.Write('E');
						query.Write(serialised);
						break;
					case 'a':
						if (POSTGRES_TEXT_ARRAY.IsMatch(serialised))
							PassEscapedArray(query, serialised);
						else
							query.Write(serialised);
						break;
					default:
						query.Write(serialised);
						break;
				}
			else
				query.Write(serialised);

			query.Write(')');


			if (p.UseCast)
			{
				query.Write("::");
				query.Write(p.TypeInfo.CastName);
				if (p.TypeInfo.UseSize && (p.Size > 0))
				{
					query.Write('(');
					query.Write(p.Size.ToString());
					query.Write(')');
				}
			}
		}