Update to 0.7beta3 release.
* NpgsqlBind.cs: Minor code cleanup.
* NpgsqlClosedState.cs: Code formatting.
* NpgsqlCommand.cs: Code cleanup and updating for new Plan and Portal name generation code.
* NpgsqlConnection.cs: Fixed contructor log message.
* NpgsqlConnectionString.cs: Code formatting.
* NpgsqlConnector.cs:
ReleasePlansPortals: Added method to release used plans and portals.
NextPortalName, NextPlanName: Added methods to handle name generation.
* NpgsqlConnectorPool.cs:
UngetPooledConnector: Added call to release plans and portals in connector.
* NpgsqlError.cs: New constructor which takes ProtocolVersion and String parameters.
* NpgsqlQuery.cs: Changed constructor to take an NpgsqlCommand instead of just the command string.
* NpgsqlReadyState.cs: Changed code to reflect NpgsqlQuery change.
* NpgsqlState.cs:
ProcessBackendResponses_Ver_(2,3): Fixed handling of invalid authentication methods. Thanks Magnus Hagander (mha at sollentuna dot net) for the heads up.
* NpgsqlState.resx: Fixed resource key typo.
* NpgsqlTransaction.cs: Fixed IDisposable pattern implementation of NpgsqlTransaction. Now it doesn't incorrectly raise InvalidOperation exceptions. Thanks Ivan Radovanovic ( rivan at sezampro dot yu ) for heads up.
* NpgsqlDbType.cs: Code cleanup.
* NpgsqlTypeConverters.cs : Removed method to handle string. String quoting is handled prevously as it depends in the type of query: simple or extended.
* NpgsqlTypes.cs: Code cleanup.
* NpgsqlTypesHelper.cs:
(CreateAndLoadInitialTypesMapping): Removed delegate handler of String types. It's not necessary anymore.
(ConvertToBackend): Refactorying. Fixed gborg 1035. Thanks Magnus Hagander (mha at sollentuna dot net) for the heads up.
svn path=/trunk/mcs/; revision=36553
private readonly Int16 READ_BUFFER_SIZE = 300; //[FIXME] Is this enough??
public NpgsqlAsciiRow(NpgsqlRowDescription rowDesc, ProtocolVersion protocolVersion)
- : base(rowDesc, protocolVersion)
+ : base(rowDesc, protocolVersion)
{
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME);
}
public override void ReadFromStream(Stream inputStream, Encoding encoding)
{
- switch (protocol_version) {
+ switch (protocol_version)
+ {
case ProtocolVersion.Version2 :
ReadFromStream_Ver_2(inputStream, encoding);
break;
Array.Clear(null_map_array, 0, null_map_array.Length);
-
+
// Decoders used to get decoded chars when using unicode like encodings which may have chars crossing the byte buffer bounds.
-
+
Decoder decoder = encoding.GetDecoder();
Char[] chars = null;
Int32 charCount;
-
-
+
+
// Read the null fields bitmap.
PGUtil.CheckedStreamRead(inputStream, null_map_array, 0, null_map_array.Length );
charCount = decoder.GetCharCount(input_buffer, 0, READ_BUFFER_SIZE);
chars = new Char[charCount];
-
+
decoder.GetChars(input_buffer, 0, READ_BUFFER_SIZE, chars, 0);
result.Append(new String(chars));
// Now, read just the field value.
PGUtil.CheckedStreamRead(inputStream, input_buffer, 0, bytes_left);
-
+
charCount = decoder.GetCharCount(input_buffer, 0, bytes_left);
chars = new Char[charCount];
decoder.GetChars(input_buffer, 0, bytes_left, chars, 0);
while (bytes_left > READ_BUFFER_SIZE)
{
-
+
// Now, read just the field value.
PGUtil.CheckedStreamRead(inputStream, input_buffer, 0, READ_BUFFER_SIZE);
charCount = decoder.GetCharCount(input_buffer, 0, READ_BUFFER_SIZE);
chars = new Char[charCount];
-
+
decoder.GetChars(input_buffer, 0, READ_BUFFER_SIZE, chars, 0);
result.Append(new String(chars));
// Add them to the AsciiRow data.
data.Add(NpgsqlTypesHelper.ConvertBackendStringToSystemType(field_descr.type_info, result.ToString(), field_descr.type_size, field_descr.type_modifier));
-
+
}
else
// FIXME: input_buffer isn't holding all the field value. This code isn't handling binary data correctly.
private static readonly String CLASSNAME = "NpgsqlBinaryRow";
public NpgsqlBinaryRow(NpgsqlRowDescription rowDesc)
- : base(rowDesc, ProtocolVersion.Version2)
+ : base(rowDesc, ProtocolVersion.Version2)
{
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME);
}
using System;
using System.IO;
using System.Text;
+using System.Data;
+
namespace Npgsql
{
}
else
{
- String parameterValue = (String)_parameterValues[i];
- if (parameterValue == null)
+ if ((_parameterValues[i] == null))
PGUtil.WriteInt32(outputStream, -1);
else
{
+ String parameterValue = (String)_parameterValues[i];
PGUtil.WriteInt32(outputStream, encoding.GetByteCount(parameterValue));
outputStream.Write(encoding.GetBytes(parameterValue), 0, encoding.GetByteCount(parameterValue));
}
private NpgsqlParse parse;
private NpgsqlBind bind;
+ private Boolean invalidTransactionDetected = false;
+
// Constructors
/// <summary>
text = cmdText;
this.connection = connection;
if (this.connection != null)
- this.connector = connection.Connector;
-
+ this.connector = connection.Connector;
+
parameters = new NpgsqlParameterCollection();
timeout = 20;
type = CommandType.Text;
set
{
+ if (this.Connection == value)
+ return;
+
if (this.transaction != null && this.transaction.Connection == null)
this.transaction = null;
if (this.connection != null && this.Connector.Transaction != null)
throw new InvalidOperationException(resman.GetString("Exception_SetConnectionInTransaction"));
+
+
this.connection = value;
if (this.connection != null)
- connector = this.connection.Connector;
-
+ connector = this.connection.Connector;
+
NpgsqlEventLog.LogPropertySet(LogLevel.Debug, CLASSNAME, "Connection", value);
}
}
{
if (connector == null && this.connection != null)
connector = this.connection.Connector;
-
+
return connector;
}
}
ExecuteCommand();
// If nothing is returned, just return -1.
- if(Connector.Mediator.CompletedResponses.Count == 0) {
+ if(Connector.Mediator.CompletedResponses.Count == 0)
+ {
return -1;
}
{
// Do not quote strings, or escape existing quotes - this will be handled by the backend.
// DBNull or null values are returned as null.
- // TODO: Would it be better to remove this null special handling out of ConvertToBackend??
+ // TODO: Would it be better to remove this null special handling out of ConvertToBackend??
parameterValues[i] = parameters[i].TypeInfo.ConvertToBackend(parameters[i].Value, true);
}
bind.ParameterValues = parameterValues;
// Check the connection state.
CheckConnectionState();
- if (! Connector.SupportsPrepare) {
+ if (! Connector.SupportsPrepare)
+ {
return; // Do nothing.
}
else
{
// Use the extended query parsing...
- planName = "NpgsqlPlan" + Connector.NextPlanIndex();
- String portalName = "NpgsqlPortal" + Connector.NextPortalIndex();
+ //planName = "NpgsqlPlan" + Connector.NextPlanIndex();
+ planName = Connector.NextPlanName();
+ String portalName = Connector.NextPortalName();
parse = new NpgsqlParse(planName, GetParseCommandText(), new Int32[] {});
-
+
Connector.Parse(parse);
Connector.Mediator.RequireReadyForQuery = false;
Connector.Flush();
-
+
// Check for errors and/or notifications and do the Right Thing.
connector.CheckErrorsAndNotifications();
-
+
bind = new NpgsqlBind(portalName, planName, new Int16[] {0}, null, new Int16[] {0});
}
}
private void CheckConnectionState()
{
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "CheckConnectionState");
-
+
+
// Check the connection state.
- if (Connector == null || Connector.State != ConnectionState.Open) {
+ if (Connector == null || Connector.State != ConnectionState.Open)
+ {
throw new InvalidOperationException(resman.GetString("Exception_ConnectionNotOpen"));
}
}
for (Int32 i = 0; i < parameters.Count; i++)
{
NpgsqlParameter Param = parameters[i];
-
+
// FIXME DEBUG ONLY
// adding the '::<datatype>' on the end of a parameter is a highly
// questionable practice, but it is great for debugging!
// Removed as this was going in infinite loop when the parameter name had the same name of parameter
// type name. i.e.: parameter name called :text of type text. It would conflict with the parameter type name ::text.
result = ReplaceParameterValue(
- result,
- Param.ParameterName,
- Param.TypeInfo.ConvertToBackend(Param.Value, false)
+ result,
+ Param.ParameterName,
+ Param.TypeInfo.ConvertToBackend(Param.Value, false)
);
}
- planName = "NpgsqlPlan" + Connector.NextPlanIndex();
+ planName = Connector.NextPlanName();
StringBuilder command = new StringBuilder("prepare " + planName);
for (i = 0; i < parameters.Count; i++)
{
-// command.Append(NpgsqlTypesHelper.GetDefaultTypeInfo(parameters[i].DbType));
+ // command.Append(NpgsqlTypesHelper.GetDefaultTypeInfo(parameters[i].DbType));
command.Append(parameters[i].TypeInfo.Name);
command.Append(',');
private String ReplaceParameterValue(String result, String parameterName, String paramVal)
{
- Int32 resLen = result.Length;
+ Int32 resLen = result.Length;
Int32 paramStart = result.IndexOf(parameterName);
Int32 paramLen = parameterName.Length;
Int32 paramEnd = paramStart + paramLen;
Boolean found = false;
-
+
while(paramStart > -1)
{
if(!found)
throw new IndexOutOfRangeException (String.Format(resman.GetString("Exception_ParamNotInQuery"), parameterName));
-
+
return result;
}//ReplaceParameterValue
{
// Check the connection state first.
CheckConnectionState();
-
+
// reset any responses just before getting new ones
connector.Mediator.ResetResponses();
- if (parse == null) {
+ if (parse == null)
+ {
Connector.Query(this);
// Check for errors and/or notifications and do the Right Thing.
connector.CheckErrorsAndNotifications();
- }
- else
+ }
+ else
{
try
{
-
- BindParameters();
- // Check for errors and/or notifications and do the Right Thing.
- connector.CheckErrorsAndNotifications();
+ BindParameters();
connector.Execute(new NpgsqlExecute(bind.PortalName, 0));
connector.Sync();
}
- }
+ }
}
}
}
/// <param name="ConnectionString">The connection used to open the PostgreSQL database.</param>
public NpgsqlConnection(String ConnectionString)
{
- NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME, ConnectionString);
-
+ NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME, "NpgsqlConnection()");
+
connection_string = NpgsqlConnectionString.ParseConnectionString(ConnectionString);
LogConnectionString();
{
connection_string = Other.connection_string;
connection_string_values = new ListDictionary(CaseInsensitiveComparer.Default);
- foreach (DictionaryEntry DE in Other.connection_string_values) {
+ foreach (DictionaryEntry DE in Other.connection_string_values)
+ {
connection_string_values.Add(DE.Key, DE.Value);
}
}
String[] pairs;
String[] keyvalue;
+ if (CS == null)
+ CS = String.Empty;
+
// Get the key-value pairs delimited by ;
pairs = CS.Split(';');
String Key = "", Value = "";
// Just ignore these.
- if (s == "") {
+ if (s == "")
+ {
continue;
}
Key = keyvalue[0].Trim().ToUpper();
// Make sure the key is even there...
- if (Key.Length == 0) {
+ if (Key.Length == 0)
+ {
throw new ArgumentException(resman.GetString("Exception_WrongKeyVal"), "<BLANK>");
}
// We don't expect keys this long, and it might be about to be put
// in an error message, so makes sure it is a sane length.
- if (Key.Length > 20) {
+ if (Key.Length > 20)
+ {
Key = Key.Substring(0, 20);
}
// Check if there is a key-value pair.
- if (keyvalue.Length != 2) {
+ if (keyvalue.Length != 2)
+ {
throw new ArgumentException(resman.GetString("Exception_WrongKeyVal"), Key);
}
// Substitute the real key name if this is an alias key (ODBC stuff for example)...
String AliasKey = (string)ConnectionStringKeys.Aliases[Key];
- if (AliasKey != null) {
+ if (AliasKey != null)
+ {
Key = AliasKey;
}
/// </summary>
public override String ToString()
{
- if (connection_string == null) {
+ if (connection_string == null)
+ {
StringBuilder S = new StringBuilder();
- foreach (DictionaryEntry DE in this) {
+ foreach (DictionaryEntry DE in this)
+ {
S.AppendFormat("{0}={1};", DE.Key, DE.Value);
}
/// </summary>
public String ToString(String Key, String Default)
{
- if (! connection_string_values.Contains(Key)) {
+ if (! connection_string_values.Contains(Key))
+ {
return Default;
}
/// </summary>
public Int32 ToInt32(String Key, Int32 Default)
{
- if (! connection_string_values.Contains(Key)) {
+ if (! connection_string_values.Contains(Key))
+ {
return Default;
}
- try {
+ try
+ {
return Convert.ToInt32(connection_string_values[Key]);
- } catch (Exception E) {
+ }
+ catch (Exception E)
+ {
throw new ArgumentException(String.Format(resman.GetString("Exception_InvalidIntegerKeyVal"), Key), Key, E);
}
}
V = ToInt32(Key, Default);
- if (V < Min) {
+ if (V < Min)
+ {
throw new ArgumentException(String.Format(resman.GetString("Exception_IntegerKeyValMin"), Key, Min), Key);
}
- if (V > Max) {
+ if (V > Max)
+ {
throw new ArgumentException(String.Format(resman.GetString("Exception_IntegerKeyValMax"), Key, Max), Key);
}
/// </summary>
public Boolean ToBool(String Key, Boolean Default)
{
- if (! connection_string_values.Contains(Key)) {
+ if (! connection_string_values.Contains(Key))
+ {
return Default;
}
- switch (connection_string_values[Key].ToString().ToLower()) {
+ switch (connection_string_values[Key].ToString().ToLower())
+ {
case "t" :
case "true" :
case "y" :
/// </summary>
public ProtocolVersion ToProtocolVersion(String Key)
{
- if (! connection_string_values.Contains(Key)) {
+ if (! connection_string_values.Contains(Key))
+ {
return ProtocolVersion.Version3;
}
- switch (ToInt32(Key)) {
+ switch (ToInt32(Key))
+ {
case 2 :
return ProtocolVersion.Version2;
private Boolean _shared;
private NpgsqlState _state;
-
-
+
+
private Int32 _planIndex;
private Int32 _portalIndex;
+ private const String _planNamePrefix = "NpgsqlPlan";
+ private const String _portalNamePrefix = "NpgsqlPortal";
+
/// <summary>
_oidToNameMapping = new NpgsqlBackendTypeMapping();
_planIndex = 0;
_portalIndex = 0;
-
+
}
/// This method checks if the connector is still ok.
/// We try to send a simple query text, select 1 as ConnectionTest;
/// </summary>
+
internal Boolean IsValid()
{
try
}
return true;
+ }
+ /// <summary>
+ /// This method is responsible to release all portals used by this Connector.
+ /// </summary>
+ internal void ReleasePlansPortals()
+ {
+ Int32 i = 0;
- }
+ if (_planIndex > 0)
+ {
+ for(i = 1; i <= _planIndex; i++)
+ Query(new NpgsqlCommand(String.Format("deallocate \"{0}\";", _planNamePrefix + i)));
+ }
+
+ _portalIndex = 0;
+ _planIndex = 0;
- /// <summary>
- /// Check for mediator errors (sent by backend) and throw the appropriate
- /// exception if errors found. This needs to be called after every interaction
- /// with the backend.
- /// </summary>
- internal void CheckErrors()
+ }
+
+
+
+ /// <summary>
+ /// Check for mediator errors (sent by backend) and throw the appropriate
+ /// exception if errors found. This needs to be called after every interaction
+ /// with the backend.
+ /// </summary>
+ internal void CheckErrors()
{
if (_mediator.Errors.Count > 0)
{
}
catch {}
}
-
-
- ///<summary>
- /// Returns next portal index.
- ///</summary>
- internal Int32 NextPortalIndex()
+
+
+ ///<summary>
+ /// Returns next portal index.
+ ///</summary>
+ internal String NextPortalName()
{
- return System.Threading.Interlocked.Increment(ref _portalIndex);
+ return _portalNamePrefix + System.Threading.Interlocked.Increment(ref _portalIndex);
}
-
-
+
+
///<summary>
/// Returns next plan index.
///</summary>
- internal Int32 NextPlanIndex()
+ internal String NextPlanName()
{
- return System.Threading.Interlocked.Increment(ref _planIndex);
+
+ return _planNamePrefix + System.Threading.Interlocked.Increment(ref _planIndex);
}
-
-
-
- }
+
+
+
+ }
}
if (Connector.State == System.Data.ConnectionState.Open)
{
+ // Release all plans and portals associated with this connector.
+ Connector.ReleasePlansPortals();
+
Queue.Enqueue(Connector);
}
}
// [TODO] Implement blob support.
- result.CopyTo(buffer, fieldOffset);
+ result.CopyTo(buffer, 0);
return result.Length;
{
protocol_version = protocolVersion;
}
+
+ internal NpgsqlError(ProtocolVersion protocolVersion, String errorMessage)
+ {
+ protocol_version = protocolVersion;
+ _message = errorMessage;
+ }
/// <summary>
/// Backend protocol version in use.
private static readonly String CLASSNAME = "NpgsqlException";
private static ResourceManager resman = new ResourceManager(typeof(NpgsqlException));
- // To allow deserialization.
- private NpgsqlException(SerializationInfo info, StreamingContext context) : base(info, context) {}
-
+ // To allow deserialization.
+ private NpgsqlException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {}
+
/// <summary>
/// Construct a backend error exception based on a list of one or more
/// backend errors. The basic Exception.Message will be built from the
{
NpgsqlEventLog.LogMsg(resman, "Log_ExceptionOccured", LogLevel.Normal, Message);
this.errors = errors;
-
+
}
/// <summary>
{
return (NpgsqlError)errors[Index];
}
- }
-
-
+ }
+
+
/// <summary>
/// Severity code. All versions.
/// </summary>
return this[0].Routine;
}
}
-
+
/// <summary>
/// Returns the entire list of errors provided by the PostgreSQL backend.
/// </summary>
S.WriteLine("{0}:", this.GetType().FullName);
- foreach (NpgsqlError PgError in Errors)
+ foreach (NpgsqlError PgError in Errors)
{
AppendString(S, "{0}", PgError.Message);
AppendString(S, "Severity: {0}", PgError.Severity);
S.Write(StackTrace);
return S.ToString();
-
+
}
/// <summary>
/// </summary>
private static void AppendString(StringWriter Stream, string Format, string Str)
{
- if (Str.Length > 0) {
+ if (Str.Length > 0)
+ {
Stream.WriteLine(Format, Str);
}
- }
+ }
}
this.value = DBNull.Value;
type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String));
return;
- } else {
+ }
+ else
+ {
type_info = NpgsqlTypesHelper.GetNativeTypeInfo(value.GetType());
- if (type_info == null) {
- throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), value.GetType()));
+ if (type_info == null)
+ {
+ throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), value.GetType()));
}
-
+
}
}
/// <param name="parameterType">One of the <see cref="System.Data.DbType">DbType</see> values.</param>
public NpgsqlParameter(String parameterName, NpgsqlDbType parameterType) : this(parameterName, parameterType, 0, String.Empty)
{}
-
-
+
+
public NpgsqlParameter(String parameterName, DbType parameterType) : this(parameterName, NpgsqlTypesHelper.GetNativeTypeInfo(parameterType).NpgsqlDbType, 0, String.Empty)
{}
public NpgsqlParameter(String parameterName, DbType parameterType, Int32 size) : this(parameterName, NpgsqlTypesHelper.GetNativeTypeInfo(parameterType).NpgsqlDbType, size, String.Empty)
{}
-
-
+
+
/// <summary>
/// Initializes a new instance of the <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see>
/// class with the parameter name, the <see cref="System.Data.DbType">DbType</see>, the size,
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME, parameterName, parameterType, size, source_column);
this.ParameterName = parameterName;
-
+
type_info = NpgsqlTypesHelper.GetNativeTypeInfo(parameterType);
if (type_info == null)
- throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), parameterType));
-
+ throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), parameterType));
+
this.size = size;
source_column = sourceColumn;
-
-
+
+
}
-
+
public NpgsqlParameter(String parameterName, DbType parameterType, Int32 size, String sourceColumn) : this(parameterName, NpgsqlTypesHelper.GetNativeTypeInfo(parameterType).NpgsqlDbType, size, sourceColumn)
- {}
-
-
+ {}
+
+
/// <summary>
/// Initializes a new instance of the <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see>
{
resman = new System.Resources.ResourceManager(this.GetType());
-
+
this.ParameterName = parameterName;
this.Size = size;
this.SourceColumn = sourceColumn;
this.SourceVersion = sourceVersion;
this.Value = value;
- if (this.value == null) {
+ if (this.value == null)
+ {
this.value = DBNull.Value;
type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String));
}
if (type_info == null)
throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), parameterType));
}
-
+
}
-
+
public NpgsqlParameter (String parameterName, DbType parameterType, Int32 size, String sourceColumn, ParameterDirection direction, bool isNullable, byte precision, byte scale, DataRowVersion sourceVersion, object value) : this(parameterName, NpgsqlTypesHelper.GetNativeTypeInfo(parameterType).NpgsqlDbType, size, sourceColumn, direction, isNullable, precision, scale, sourceVersion, value)
- {}
+ {}
// Implementation of IDbDataParameter
/// <summary>
{
NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "DbType", value);
type_info = NpgsqlTypesHelper.GetNativeTypeInfo(value);
- if (type_info == null)
+ if (type_info == null)
throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), value));
-
+
}
}
-
+
/// <summary>
/// Gets or sets the <see cref="System.Data.DbType">DbType</see> of the parameter.
/// </summary>
get
{
NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "DbType");
-
+
return TypeInfo.NpgsqlDbType;
}
type_info = NpgsqlTypesHelper.GetNativeTypeInfo(value);
if (type_info == null)
throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), value));
-
+
}
}
-
+
internal NpgsqlNativeTypeInfo TypeInfo
{
{
name = value;
if ( (name.Equals(String.Empty)) || ((name[0] != ':') && (name[0] != '@')) )
- name = ':' + name;
-
+ name = ':' + name;
+
NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "ParameterName", value);
}
}
set
{
NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "Value", value);
+
this.value = value;
- if (this.value == null) {
+ if ((this.value == null) || (this.value == DBNull.Value) )
+ {
+ // don't really know what to do - leave default and do further exploration
+ // Default type for null values is String.
this.value = DBNull.Value;
+ if (type_info == null)
+ type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String));
+
+ }
+ else
+ {
+ if (type_info == null)
+ {
+ type_info = NpgsqlTypesHelper.GetNativeTypeInfo(value.GetType());
+ if (type_info == null)
+ throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), value.GetType()));
+
+ }
+
}
}
}
/// </summary>
internal sealed class NpgsqlQuery
{
- private String _commandText;
+ private NpgsqlCommand _command;
private ProtocolVersion _protocolVersion;
- public NpgsqlQuery(String commandText, ProtocolVersion protocolVersion)
+ public NpgsqlQuery(NpgsqlCommand command, ProtocolVersion protocolVersion)
{
- _commandText = commandText;
+ _command = command;
_protocolVersion = protocolVersion;
}
//NpgsqlEventLog.LogMsg( this.ToString() + _commandText, LogLevel.Debug );
+ String commandText = _command.GetCommandText();
// Send the query to server.
// Write the byte 'Q' to identify a query message.
outputStream.WriteByte((Byte)'Q');
- if (_protocolVersion == ProtocolVersion.Version3) {
+ if (_protocolVersion == ProtocolVersion.Version3)
+ {
// Write message length. Int32 + string length + null terminator.
- PGUtil.WriteInt32(outputStream, 4 + encoding.GetByteCount(_commandText) + 1);
+ PGUtil.WriteInt32(outputStream, 4 + encoding.GetByteCount(commandText) + 1);
}
// Write the query. In this case it is the CommandText text.
// It is a string terminated by a C NULL character.
- PGUtil.WriteString(_commandText, outputStream, encoding);
+ PGUtil.WriteString(commandText, outputStream, encoding);
}
+
+
}
}
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Query");
- String commandText = command.GetCommandText();
- NpgsqlEventLog.LogMsg(resman, "Log_QuerySent", LogLevel.Debug, commandText);
+
+
+ //String commandText = command.GetCommandText();
+ //NpgsqlEventLog.LogMsg(resman, "Log_QuerySent", LogLevel.Debug, commandText);
// Send the query request to backend.
- NpgsqlQuery query = new NpgsqlQuery(commandText, context.BackendProtocolVersion);
+ NpgsqlQuery query = new NpgsqlQuery(command, context.BackendProtocolVersion);
+
BufferedStream stream = new BufferedStream(context.Stream);
query.WriteToStream(stream, context.Encoding);
stream.Flush();
public override void Close( NpgsqlConnector context )
{
- NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Close");
+ NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Close");
Stream stream = context.Stream;
stream.WriteByte((Byte)'X');
if (context.BackendProtocolVersion >= ProtocolVersion.Version3)
PGUtil.WriteInt32(stream, 4);
stream.Flush();
- try {
+ try
+ {
stream.Close();
- } catch {}
+ }
+ catch {}
context.Stream = null;
- ChangeState( context, NpgsqlClosedState.Instance );
+ ChangeState( context, NpgsqlClosedState.Instance )
+ ;
}
}
}
}
// Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now.
- NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationOK", LogLevel.Debug);
- mediator.Errors.Add(String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType));
+
+ mediator.Errors.Add(new NpgsqlError(context.BackendProtocolVersion, String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType)));
}
return;
}
// Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now.
- NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationOK", LogLevel.Debug);
- mediator.Errors.Add(String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType));
+ mediator.Errors.Add(new NpgsqlError(context.BackendProtocolVersion, String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType)));
}
return;
<data name="Log_NoticeResponse">
<value>NoticeResponse message from Server: {0}.</value>
</data>
- <data name="Log_AuthenticationOk">
- <value>AAuthenticationOK received.</value>
+ <data name="Log_AuthenticationOK">
+ <value>AuthenticationOK received.</value>
</data>
<data name="Log_AuthenticationClearTextRequest">
<value>Server requested cleartext password authentication.</value>
private NpgsqlConnection _conn = null;
private IsolationLevel _isolation = IsolationLevel.ReadCommitted;
- private bool _disposing = false;
+ private bool _disposed = false;
internal NpgsqlTransaction(NpgsqlConnection conn) : this(conn, IsolationLevel.ReadCommitted)
{}
{
get
{
- if (_conn == null) {
+ if (_conn == null)
+ {
throw new InvalidOperationException(resman.GetString("Exception_NoTransaction"));
}
/// </summary>
public void Dispose()
{
+ GC.SuppressFinalize(this);
+
this.Dispose(true);
}
- private void Dispose(bool disposing)
+ private void Dispose(Boolean disposing)
{
if(disposing && this._conn != null)
{
- this._disposing = true;
if (_conn.Connector.Transaction != null)
this.Rollback();
+
+ this._disposed = true;
}
}
/// </summary>
public void Commit()
{
- if (_conn == null) {
+ CheckDisposed();
+
+ if (_conn == null)
+ {
throw new InvalidOperationException(resman.GetString("Exception_NoTransaction"));
}
/// </summary>
public void Rollback()
{
- if (_conn == null) {
+ CheckDisposed();
+
+ if (_conn == null)
+ {
throw new InvalidOperationException(resman.GetString("Exception_NoTransaction"));
}
/// </summary>
internal void Cancel()
{
- if (_conn != null) {
+ CheckDisposed();
+
+ if (_conn != null)
+ {
_conn.Connector.Transaction = null;
_conn = null;
}
}
- internal bool Disposing{
+ internal bool Disposed{
get
{
- return _disposing;
+ return _disposed;
}
}
+
+
+ internal void CheckDisposed()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(CLASSNAME);
+
+ }
+
+ ~NpgsqlTransaction()
+ {
+ Dispose(false);
+ }
+
}
}
// NpgsqlTypes.NpgsqlDbType.cs
-//
+//
// Author:
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
-//
+//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
namespace NpgsqlTypes
{
- public enum NpgsqlDbType
- {
- Bigint,
- Boolean,
- Box,
- Bytea,
- Circle,
- Date,
- Double,
- Integer,
- Line,
- LSeg,
- Money,
- Numeric,
- Path,
- Point,
- Polygon,
- Real,
- Smallint,
- Text,
- Time,
- Timestamp
-
- }
-
+ public enum NpgsqlDbType
+ {
+ Bigint,
+ Boolean,
+ Box,
+ Bytea,
+ Circle,
+ Date,
+ Double,
+ Integer,
+ Interval,
+ Line,
+ LSeg,
+ Money,
+ Numeric,
+ Path,
+ Point,
+ Polygon,
+ Real,
+ Smallint,
+ Text,
+ Time,
+ Timestamp
+
+ }
+
}
/// </summary>
internal abstract class BasicNativeToBackendTypeConverter
{
- /// <summary>
- /// String data.
- /// </summary>
- internal static String ToString(NpgsqlNativeTypeInfo TypeInfo, Object NativeData)
- {
- return NativeData.ToString().Replace("'", "''").Replace("\\", "\\\\");
- }
-
/// <summary>
/// Binary data.
/// </summary>
namespace NpgsqlTypes
{
- /// <summary>
- /// Represents a PostgreSQL Point type
- /// </summary>
-
- public struct NpgsqlPoint
- {
- private Single _X;
- private Single _Y;
-
- public NpgsqlPoint(Single X, Single Y)
- {
- _X = X;
- _Y = Y;
- }
-
- public Single X
- {
- get
- {
- return _X;
- }
-
- set
- {
- _X = value;
- }
- }
-
-
- public Single Y
- {
- get
- {
- return _Y;
- }
-
- set
- {
- _Y = value;
- }
- }
- }
-
- public struct NpgsqlBox
- {
- private NpgsqlPoint _UpperRight;
- private NpgsqlPoint _LowerLeft;
-
- public NpgsqlBox(NpgsqlPoint UpperRight, NpgsqlPoint LowerLeft)
- {
- _UpperRight = UpperRight;
- _LowerLeft = LowerLeft;
- }
-
-
- public NpgsqlPoint UpperRight
- {
- get
- {
- return _UpperRight;
- }
- set
- {
- _UpperRight = value;
- }
- }
-
- public NpgsqlPoint LowerLeft
- {
- get
- {
- return _LowerLeft;
- }
- set
- {
- _LowerLeft = value;
- }
- }
-
- }
-
-
+ /// <summary>
+ /// Represents a PostgreSQL Point type
+ /// </summary>
+
+ public struct NpgsqlPoint
+ {
+ private Single _X;
+ private Single _Y;
+
+ public NpgsqlPoint(Single X, Single Y)
+ {
+ _X = X;
+ _Y = Y;
+ }
+
+ public Single X
+ {
+ get
+ {
+ return _X;
+ }
+
+ set
+ {
+ _X = value;
+ }
+ }
+
+
+ public Single Y
+ {
+ get
+ {
+ return _Y;
+ }
+
+ set
+ {
+ _Y = value;
+ }
+ }
+ }
+
+ public struct NpgsqlBox
+ {
+ private NpgsqlPoint _UpperRight;
+ private NpgsqlPoint _LowerLeft;
+
+ public NpgsqlBox(NpgsqlPoint UpperRight, NpgsqlPoint LowerLeft)
+ {
+ _UpperRight = UpperRight;
+ _LowerLeft = LowerLeft;
+ }
+
+
+ public NpgsqlPoint UpperRight
+ {
+ get
+ {
+ return _UpperRight;
+ }
+ set
+ {
+ _UpperRight = value;
+ }
+ }
+
+ public NpgsqlPoint LowerLeft
+ {
+ get
+ {
+ return _LowerLeft;
+ }
+ set
+ {
+ _LowerLeft = value;
+ }
+ }
+
+ }
+
+
/// <summary>
/// Represents a PostgreSQL Line Segment type.
/// </summary>
public struct NpgsqlPath
{
internal NpgsqlPoint[] Points;
-
- internal Boolean IsOpen;
+
+ internal Boolean IsOpen;
public NpgsqlPath(NpgsqlPoint[] Points)
{
}
public Int32 Count
- { get { return Points.Length; } }
+ { get
+ {
+ return Points.Length;
+ } }
public NpgsqlPoint this [Int32 Index]
- { get { return Points[Index]; } }
-
+ { get
+ {
+ return Points[Index];
+ } }
+
public Boolean Open
{
- get
- {
- return IsOpen;
- }
+ get
+ {
+ return IsOpen;
+ }
}
}
}
public Int32 Count
- { get { return Points.Length; } }
+ { get
+ {
+ return Points.Length;
+ } }
public NpgsqlPoint this [Int32 Index]
- { get { return Points[Index]; } }
+ { get
+ {
+ return Points[Index];
+ } }
}
/// <summary>
NativeTypeMapping = new NpgsqlNativeTypeMapping();
- NativeTypeMapping.AddType("text", NpgsqlDbType.Text, DbType.String, true,
- new ConvertNativeToBackendHandler(BasicNativeToBackendTypeConverter.ToString));
+ NativeTypeMapping.AddType("text", NpgsqlDbType.Text, DbType.String, true, null);
NativeTypeMapping.AddDbTypeAlias("text", DbType.StringFixedLength);
NativeTypeMapping.AddDbTypeAlias("text", DbType.AnsiString);
NativeTypeMapping.AddType("timestamp", NpgsqlDbType.Timestamp, DbType.DateTime, true,
new ConvertNativeToBackendHandler(BasicNativeToBackendTypeConverter.ToDateTime));
-
+
NativeTypeMapping.AddTypeAlias("timestamp", typeof(DateTime));
+
+ NativeTypeMapping.AddType("interval", NpgsqlDbType.Interval, DbType.DateTime, true,
+ new ConvertNativeToBackendHandler(BasicNativeToBackendTypeConverter.ToDateTime));
+
+ //NativeTypeMapping.AddTypeAlias("interval", typeof(DateTime));
NativeTypeMapping.AddType("point", NpgsqlDbType.Point, DbType.Object, true,
new ConvertNativeToBackendHandler(ExtendedNativeToBackendTypeConverter.ToPoint));
new NpgsqlBackendTypeInfo(0, "timestamp", NpgsqlDbType.Timestamp, DbType.DateTime, typeof(DateTime),
new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToDateTime)),
+
+ new NpgsqlBackendTypeInfo(0, "interval", NpgsqlDbType.Interval, DbType.DateTime, typeof(DateTime),
+ new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToDateTime)),
new NpgsqlBackendTypeInfo(0, "timestamptz", NpgsqlDbType.Timestamp, DbType.DateTime, typeof(DateTime),
new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToDateTime)),
/// plain queries or extended queries</param>
public String ConvertToBackend(Object NativeData, Boolean ForExtendedQuery)
{
+ if (ForExtendedQuery)
+ return ConvertToBackendExtendedQuery(NativeData);
+ else
+ return ConvertToBackendPlainQuery(NativeData);
+
+ }
+
+ private String ConvertToBackendPlainQuery(Object NativeData)
+ {
if ((NativeData == DBNull.Value) || (NativeData == null))
- if (ForExtendedQuery)
- return null; // Extended query expects null values be represented as null.
- else
- return "NULL"; // Plain queries exptects null values as string NULL.
-
- else if (_ConvertNativeToBackend != null) {
- return QuoteString(! ForExtendedQuery, _ConvertNativeToBackend(this, NativeData));
+ return "NULL"; // Plain queries exptects null values as string NULL.
+
+ if (_ConvertNativeToBackend != null)
+ return QuoteString(_ConvertNativeToBackend(this, NativeData));
+ else
+ {
+
+
+ if (NativeData is System.Enum)
+ {
+ // Do a special handling of Enum values.
+ // Translate enum value to its underlying type.
+ return QuoteString((String)Convert.ChangeType(Enum.Format(NativeData.GetType(), NativeData, "d"), typeof(String), CultureInfo.InvariantCulture));
+ }
+ else
+ // Do special handling of strings when in simple query. Escape quotes and backslashes.
+
+ return QuoteString(NativeData.ToString().Replace("'", "''").Replace("\\", "\\\\"));
- } else {
- // Do a special handling of Enum values.
- // Translate enum value to its underlying type.
- if (NativeData is System.Enum)
- return QuoteString(! ForExtendedQuery, (String)Convert.ChangeType(Enum.Format(NativeData.GetType(), NativeData, "d"), typeof(String), CultureInfo.InvariantCulture));
-
- return QuoteString(! ForExtendedQuery, (String)Convert.ChangeType(NativeData, typeof(String), CultureInfo.InvariantCulture));
}
+
}
-
- private static String QuoteString(Boolean Quote, String S)
+
+ private String ConvertToBackendExtendedQuery(Object NativeData)
{
- if (Quote) {
- return String.Format("'{0}'", S);
- } else {
- return S;
+ if ((NativeData == DBNull.Value) || (NativeData == null))
+ return null; // Extended query expects null values be represented as null.
+
+ if (_ConvertNativeToBackend != null)
+ return _ConvertNativeToBackend(this, NativeData);
+ else
+ {
+ if (NativeData is System.Enum)
+ {
+ // Do a special handling of Enum values.
+ // Translate enum value to its underlying type.
+ return (String)Convert.ChangeType(Enum.Format(NativeData.GetType(), NativeData, "d"), typeof(String), CultureInfo.InvariantCulture);
+ }
+ else
+ // Do special handling of strings when in simple query. Escape quotes and backslashes.
+ return NativeData.ToString();
+
}
+
+ }
+
+ private static String QuoteString(String S)
+ {
+ return String.Format("'{0}'", S);
+
}
}