Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancisco Figueiredo Jr. <fxjr@mono-cvs.ximian.com>2005-08-27 17:58:09 +0400
committerFrancisco Figueiredo Jr. <fxjr@mono-cvs.ximian.com>2005-08-27 17:58:09 +0400
commita9d49d53003c1b18827cb8ac06fcb8a36f5851e6 (patch)
tree21cd98a396be26acca5f3bc92251bc3f530f9b98 /mcs/class/Npgsql
parent11e2e35c9a405dc17eb7f8a832076c33990420e6 (diff)
2005-08-27 Francisco Figueiredo Jr. <fxjrlists@yahoo.com.br>
* NpgsqlParameter.cs: Applied patch to fix a NullReferenceException when using Design Time support. Thanks Josh Cooley ( jbnpgsql at tuxinthebox dot net ) for patch. * NpgsqlDataReader.cs: Updated ProviderType metadata from NpgsqlDataReader.GetResultsetSchema to be the string for the type rather than the oid. Fixed ColumnSize, NumericPrecision, NumericScale, BaseColumnName, AllowDBNull, and IsAliased. Also integrated patch from (rlp at bamafolks dot com), gborg 751. Thanks Josh Cooley (jbnpgsql at tuxinthebox dot net) for patches! * NpgsqlConnection.cs, NpgsqlSchema.cs: Josh Cooley (jbnpgsql at tuxinthebox dot net) improved Metadata support in Npgsql. Added support for the following collections through NpgsqlConnection.GetSchema() methods: MetaDataCollections, Restrictions, Databases, Tables, Columns, Views and Users. Also added support for restrictions when getting info about these collections. * NpgsqlCommand.cs: Fixed problem with stored procedure command texts which finished with a ";". Npgsql was adding incorrectly a trailing "()" when calling this command text. * NpgsqlDbType.cs, NpgsqlTypesHelper.cs: Added refcursor parameter support. Now, refcursors can be passed as arguments for functions. Thanks Jon Asher for heads up and tests. * NpgsqlDataAdapter: Updated constructor documentation. * Npgsql.dll.sources: Added helper metadata class. Thanks Josh Cooley (jbnpgsql at tuxinthebox dot net). * NpgsqlConnectorPool: Fixed concurrent problem when using MinPoolSize > 1. Thanks Josh Cooley (jbnpgsql at tuxinthebox dot net) for patch. * NpgsqlParameterCollection.cs: Fixed problems with parameters with "@" prefix. They weren't correctly recognized. Thanks Pejvan Beigui ( pejvan at gmail dot com) for heads up. * NpgsqlCommandBuilder.cs: Updated documentation. svn path=/trunk/mcs/; revision=48966
Diffstat (limited to 'mcs/class/Npgsql')
-rw-r--r--mcs/class/Npgsql/ChangeLog15
-rw-r--r--mcs/class/Npgsql/Npgsql/NpgsqlCommand.cs4
-rw-r--r--mcs/class/Npgsql/Npgsql/NpgsqlCommandBuilder.cs3
-rw-r--r--mcs/class/Npgsql/Npgsql/NpgsqlConnection.cs106
-rw-r--r--mcs/class/Npgsql/Npgsql/NpgsqlConnectorPool.cs2
-rw-r--r--mcs/class/Npgsql/Npgsql/NpgsqlDataAdapter.cs3
-rw-r--r--mcs/class/Npgsql/Npgsql/NpgsqlDataReader.cs286
-rw-r--r--mcs/class/Npgsql/Npgsql/NpgsqlParameter.cs1
-rw-r--r--mcs/class/Npgsql/Npgsql/NpgsqlParameterCollection.cs2
-rw-r--r--mcs/class/Npgsql/Npgsql/NpgsqlSchema.cs279
-rw-r--r--mcs/class/Npgsql/NpgsqlTypes/NpgsqlDbType.cs7
-rw-r--r--mcs/class/Npgsql/NpgsqlTypes/NpgsqlTypesHelper.cs7
12 files changed, 605 insertions, 110 deletions
diff --git a/mcs/class/Npgsql/ChangeLog b/mcs/class/Npgsql/ChangeLog
index 662e9841ea5..b3251478d63 100644
--- a/mcs/class/Npgsql/ChangeLog
+++ b/mcs/class/Npgsql/ChangeLog
@@ -1,3 +1,18 @@
+
+2005-08-27 Francisco Figueiredo Jr. <fxjrlists@yahoo.com.br>
+ * NpgsqlParameter.cs: Applied patch to fix a NullReferenceException when using Design Time support. Thanks Josh Cooley ( jbnpgsql at tuxinthebox dot net ) for patch.
+ * NpgsqlDataReader.cs: Updated ProviderType metadata from NpgsqlDataReader.GetResultsetSchema to be the string for the type rather than the oid. Fixed ColumnSize, NumericPrecision, NumericScale, BaseColumnName, AllowDBNull, and IsAliased. Also integrated patch from (rlp at bamafolks dot com), gborg 751. Thanks Josh Cooley (jbnpgsql at tuxinthebox dot net) for patches!
+ * NpgsqlConnection.cs,
+ NpgsqlSchema.cs: Josh Cooley (jbnpgsql at tuxinthebox dot net) improved Metadata support in Npgsql. Added support for the following collections through NpgsqlConnection.GetSchema() methods: MetaDataCollections, Restrictions, Databases, Tables, Columns, Views and Users. Also added support for restrictions when getting info about these collections.
+ * NpgsqlCommand.cs: Fixed problem with stored procedure command texts which finished with a ";". Npgsql was adding incorrectly a trailing "()" when calling this command text.
+ * NpgsqlDbType.cs,
+ NpgsqlTypesHelper.cs: Added refcursor parameter support. Now, refcursors can be passed as arguments for functions. Thanks Jon Asher for heads up and tests.
+ * Npgsql.dll.sources: Added helper metadata class. Thanks Josh Cooley (jbnpgsql at tuxinthebox dot net).
+ * NpgsqlDataAdapter: Updated constructor documentation.
+ * NpgsqlConnectorPool: Fixed concurrent problem when using MinPoolSize > 1. Thanks Josh Cooley (jbnpgsql at tuxinthebox dot net) for patch.
+ * NpgsqlParameterCollection.cs: Fixed problems with parameters with "@" prefix. They weren't correctly recognized. Thanks Pejvan Beigui ( pejvan at gmail dot com) for heads up.
+ * NpgsqlCommandBuilder.cs: Updated documentation.
+
2005-08-21 Francisco Figueiredo Jr. <fxjrlists@yahoo.com.br>
* Makefile,
Npgsql.dll.resources: Removed references to design time support. This is not needed when compiling Npgsql with mono.
diff --git a/mcs/class/Npgsql/Npgsql/NpgsqlCommand.cs b/mcs/class/Npgsql/Npgsql/NpgsqlCommand.cs
index 5dadd0d38c7..285891d55a1 100644
--- a/mcs/class/Npgsql/Npgsql/NpgsqlCommand.cs
+++ b/mcs/class/Npgsql/Npgsql/NpgsqlCommand.cs
@@ -780,8 +780,8 @@ namespace Npgsql
functionReturnsRefcursor = CheckFunctionReturn("refcursor");
- // 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.
- if (!result.Trim().EndsWith(")"))
+ // 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.
+ if ((!result.Trim().EndsWith(")")) && (!result.Trim().EndsWith(";")))
{
addProcedureParenthesis = true;
result += "(";
diff --git a/mcs/class/Npgsql/Npgsql/NpgsqlCommandBuilder.cs b/mcs/class/Npgsql/Npgsql/NpgsqlCommandBuilder.cs
index 790f56878de..cab07a1b4f0 100644
--- a/mcs/class/Npgsql/Npgsql/NpgsqlCommandBuilder.cs
+++ b/mcs/class/Npgsql/Npgsql/NpgsqlCommandBuilder.cs
@@ -33,6 +33,9 @@ using System.ComponentModel;
namespace Npgsql
{
+ ///<summary>
+ /// This class is responsible to create database commands for automatic insert, update and delete operations.
+ ///</summary>
public sealed class NpgsqlCommandBuilder : Component
{
diff --git a/mcs/class/Npgsql/Npgsql/NpgsqlConnection.cs b/mcs/class/Npgsql/Npgsql/NpgsqlConnection.cs
index 90de7ef7429..df737229a84 100644
--- a/mcs/class/Npgsql/Npgsql/NpgsqlConnection.cs
+++ b/mcs/class/Npgsql/Npgsql/NpgsqlConnection.cs
@@ -725,81 +725,59 @@ namespace Npgsql
/// <summary>
- /// This method returns the collections we support.
+ /// Returns the supported collections
/// <summary>
public DataTable GetSchema()
{
-
-
- DataTable result = new DataTable("Schema");
-
- result.Columns.Add ("CollectionName", typeof (string));
- result.Columns.Add ("NumberOfRestrictions", typeof (int));
-
-
- DataRow row = result.NewRow();
- row["CollectionName"] = "Databases";
- row["NumberOfRestrictions"] = 0;
-
- result.Rows.Add(row);
-
- return result;
+ return NpgsqlSchema.GetMetaDataCollections();
}
-
- /// <summary>
- /// This method returns the collection data.
- ///
+
/// <summary>
- public DataTable GetSchema(String CollectionName)
+ /// Returns the schema collection specified by the collection name.
+ /// </summary>
+ /// <param name="collectionName">The collection name.</param>
+ /// <returns>The collection specified.</returns>
+ public DataTable GetSchema(string collectionName)
{
-
- if (CollectionName == "Databases")
- return GetSchemaDatabases();
-
- throw new NotSupportedException();
-
+ return GetSchema(collectionName, null);
}
-
- private DataTable GetSchemaDatabases()
+ /// <summary>
+ /// Returns the schema collection specified by the collection name filtered by the restrictions.
+ /// </summary>
+ /// <param name="collectionName">The collection name.</param>
+ /// <param name="restrictions">
+ /// The restriction values to filter the results. A description of the restrictions is contained
+ /// in the Restrictions collection.
+ /// </param>
+ /// <returns>The collection specified.</returns>
+ public DataTable GetSchema(string collectionName, string[] restrictions)
{
- NpgsqlConnection conn = new NpgsqlConnection(this.ConnectionString);
- conn.Open();
- NpgsqlCommand c = new NpgsqlCommand("SELECT d.datname as \"Name\", u.usename as \"Owner\", pg_catalog.pg_encoding_to_char(d.encoding) as \"Encoding\" FROM pg_catalog.pg_database d LEFT JOIN pg_catalog.pg_user u ON d.datdba = u.usesysid ORDER BY 1;", conn);
-
-
- DataTable result = new DataTable("Databases");
-
- result.Columns.Add ("Name", typeof (string));
- result.Columns.Add ("Owner", typeof (string));
- result.Columns.Add ("Encoding", typeof (string));
-
-
- NpgsqlDataReader dr = c.ExecuteReader();
-
- while (dr.Read())
- {
-
- DataRow row = result.NewRow();
- row["Name"] = dr["Name"];
- row["Owner"] = dr["Owner"];
- row["Encoding"] = dr["Encoding"];
-
- result.Rows.Add(row);
+ switch(collectionName)
+ {
+ case "MetaDataCollections":
+ return NpgsqlSchema.GetMetaDataCollections();
+ case "Restrictions":
+ return NpgsqlSchema.GetRestrictions();
+ case "DataSourceInformation":
+ case "DataTypes":
+ case "ReservedWords":
+ throw new NotSupportedException();
+ // custom collections for npgsql
+ case "Databases":
+ return new NpgsqlSchema(new NpgsqlConnection(ConnectionString)).GetDatabases(restrictions);
+ case "Tables":
+ return new NpgsqlSchema(new NpgsqlConnection(ConnectionString)).GetTables(restrictions);
+ case "Columns":
+ return new NpgsqlSchema(new NpgsqlConnection(ConnectionString)).GetColumns(restrictions);
+ case "Views":
+ return new NpgsqlSchema(new NpgsqlConnection(ConnectionString)).GetViews(restrictions);
+ case "Users":
+ return new NpgsqlSchema(new NpgsqlConnection(ConnectionString)).GetUsers(restrictions);
+ default:
+ throw new NotSupportedException();
}
-
-
- dr.Close();
-
- conn.Close();
-
-
- return result;
}
-
-
-
-
}
diff --git a/mcs/class/Npgsql/Npgsql/NpgsqlConnectorPool.cs b/mcs/class/Npgsql/Npgsql/NpgsqlConnectorPool.cs
index 0783e4a9a8c..91567f215bf 100644
--- a/mcs/class/Npgsql/Npgsql/NpgsqlConnectorPool.cs
+++ b/mcs/class/Npgsql/Npgsql/NpgsqlConnectorPool.cs
@@ -312,7 +312,7 @@ namespace Npgsql
Spare.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate;
Spare.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate;
- Queue.Enqueue(Connector);
+ Queue.Enqueue(Spare);
}
}
diff --git a/mcs/class/Npgsql/Npgsql/NpgsqlDataAdapter.cs b/mcs/class/Npgsql/Npgsql/NpgsqlDataAdapter.cs
index c5a7a111ab8..d41193edd0c 100644
--- a/mcs/class/Npgsql/Npgsql/NpgsqlDataAdapter.cs
+++ b/mcs/class/Npgsql/Npgsql/NpgsqlDataAdapter.cs
@@ -46,6 +46,9 @@ namespace Npgsql
public delegate void NpgsqlRowUpdatingEventHandler(Object sender, NpgsqlRowUpdatingEventArgs e);
+ /// <summary>
+ /// This class represents an adapter from many commands: select, update, insert and delete to fill <see cref="System.Data.DataSet">Datasets.</see>
+ /// </summary>
public sealed class NpgsqlDataAdapter : DbDataAdapter, IDbDataAdapter
{
diff --git a/mcs/class/Npgsql/Npgsql/NpgsqlDataReader.cs b/mcs/class/Npgsql/Npgsql/NpgsqlDataReader.cs
index eb1a27910c4..70fc86dc07c 100644
--- a/mcs/class/Npgsql/Npgsql/NpgsqlDataReader.cs
+++ b/mcs/class/Npgsql/Npgsql/NpgsqlDataReader.cs
@@ -26,6 +26,7 @@
using System;
using System.Data;
using System.Collections;
+using System.Text;
using NpgsqlTypes;
@@ -646,19 +647,11 @@ namespace Npgsql
private DataTable GetResultsetSchema()
{
-
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetResultsetSchema");
DataTable result = null;
-
NpgsqlRowDescription rd = _currentResultset.RowDescription;
-
- ArrayList list = null;
-
- list = GetPrimaryKeys(GetTableNameFromQuery());
-
-
Int16 numFields = rd.NumFields;
if(numFields > 0)
{
@@ -677,7 +670,7 @@ namespace Npgsql
result.Columns.Add ("BaseTableName", typeof (string));
result.Columns.Add ("DataType", typeof(Type));
result.Columns.Add ("AllowDBNull", typeof (bool));
- result.Columns.Add ("ProviderType", typeof (int));
+ result.Columns.Add ("ProviderType", typeof (string));
result.Columns.Add ("IsAliased", typeof (bool));
result.Columns.Add ("IsExpression", typeof (bool));
result.Columns.Add ("IsIdentity", typeof (bool));
@@ -687,50 +680,148 @@ namespace Npgsql
result.Columns.Add ("IsLong", typeof (bool));
result.Columns.Add ("IsReadOnly", typeof (bool));
- DataRow row;
+ if (_connection.Connector.BackendProtocolVersion == ProtocolVersion.Version2)
+ {
+ FillSchemaTable_v2(result);
+ }
+ else if (_connection.Connector.BackendProtocolVersion == ProtocolVersion.Version3)
+ {
+ FillSchemaTable_v3(result);
+ }
+ }
+ return result;
+ }
+ private void FillSchemaTable_v2(DataTable schema)
+ {
+ NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "FillSchemaTable_v2");
+ NpgsqlRowDescription rd = _currentResultset.RowDescription;
+ ArrayList keyList = GetPrimaryKeys(GetTableNameFromQuery());
+ DataRow row;
+ for (Int16 i = 0; i < rd.NumFields; i++)
+ {
+ row = schema.NewRow();
+
+ row["ColumnName"] = GetName(i);
+ row["ColumnOrdinal"] = i + 1;
+ if (rd[i].type_modifier != -1 && (rd[i].type_info.Name == "varchar" || rd[i].type_info.Name == "bpchar"))
+ row["ColumnSize"] = rd[i].type_modifier - 4;
+ else if (rd[i].type_modifier != -1 && (rd[i].type_info.Name == "bit" || rd[i].type_info.Name == "varbit"))
+ row["ColumnSize"] = rd[i].type_modifier;
+ else
+ row["ColumnSize"] = (int) rd[i].type_size;
+ if (rd[i].type_modifier != -1 && rd[i].type_info.Name == "numeric")
+ {
+ row["NumericPrecision"] = ((rd[i].type_modifier-4)>>16)&ushort.MaxValue;
+ row["NumericScale"] = (rd[i].type_modifier-4)&ushort.MaxValue;
+ }
+ else
+ {
+ row["NumericPrecision"] = 0;
+ row["NumericScale"] = 0;
+ }
+ row["IsUnique"] = false;
+ row["IsKey"] = IsKey(GetName(i), keyList);
+ row["BaseCatalogName"] = "";
+ row["BaseSchemaName"] = "";
+ row["BaseTableName"] = "";
+ row["BaseColumnName"] = GetName(i);
+ row["DataType"] = GetFieldType(i);
+ row["AllowDBNull"] = IsNullable(null, i);
+ row["ProviderType"] = rd[i].type_info.Name;
+ row["IsAliased"] = false;
+ row["IsExpression"] = false;
+ row["IsIdentity"] = false;
+ row["IsAutoIncrement"] = false;
+ row["IsRowVersion"] = false;
+ row["IsHidden"] = false;
+ row["IsLong"] = false;
+ row["IsReadOnly"] = false;
+
+ schema.Rows.Add(row);
+ }
+ }
+
+ private void FillSchemaTable_v3(DataTable schema)
+ {
+ NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "FillSchemaTable_v3");
+ NpgsqlRowDescription rd = _currentResultset.RowDescription;
+
+ ArrayList tableOids = new ArrayList();
+ for(short i=0; i<rd.NumFields; ++i)
+ {
+ if (rd[i].table_oid != 0 && !tableOids.Contains(rd[i].table_oid))
+ tableOids.Add(rd[i].table_oid);
+ }
+ Hashtable oidTableLookup = GetTablesFromOids(tableOids);
- for (Int16 i = 0; i < numFields; i++)
+ ArrayList keyList = null;
+ if (oidTableLookup != null && oidTableLookup.Count == 1)
+ {
+ // only 1, but we can't index into the Hashtable
+ foreach(DictionaryEntry entry in oidTableLookup)
{
- row = result.NewRow();
+ GetPrimaryKeys(((object[])entry.Value)[Tables.table_name].ToString());
+ }
+ }
+
+ Hashtable columnLookup = GetColumns();
- row["ColumnName"] = GetName(i);
- row["ColumnOrdinal"] = i + 1;
+ DataRow row;
+ for (Int16 i = 0; i < rd.NumFields; i++)
+ {
+ row = schema.NewRow();
+
+ row["ColumnName"] = GetName(i);
+ row["ColumnOrdinal"] = i + 1;
+ if (rd[i].type_modifier != -1 && (rd[i].type_info.Name == "varchar" || rd[i].type_info.Name == "bpchar"))
+ row["ColumnSize"] = rd[i].type_modifier - 4;
+ else if (rd[i].type_modifier != -1 && (rd[i].type_info.Name == "bit" || rd[i].type_info.Name == "varbit"))
+ row["ColumnSize"] = rd[i].type_modifier;
+ else
row["ColumnSize"] = (int) rd[i].type_size;
+ if (rd[i].type_modifier != -1 && rd[i].type_info.Name == "numeric")
+ {
+ row["NumericPrecision"] = ((rd[i].type_modifier-4)>>16)&ushort.MaxValue;
+ row["NumericScale"] = (rd[i].type_modifier-4)&ushort.MaxValue;
+ }
+ else
+ {
row["NumericPrecision"] = 0;
row["NumericScale"] = 0;
- row["IsUnique"] = false;
- row["IsKey"] = IsKey(GetName(i), list);
+ }
+ row["IsUnique"] = false;
+ row["IsKey"] = IsKey(GetName(i), keyList);
+ if (rd[i].table_oid != 0 && oidTableLookup != null)
+ {
+ row["BaseCatalogName"] = ((object[])oidTableLookup[rd[i].table_oid])[Tables.table_catalog];
+ row["BaseSchemaName"] = ((object[])oidTableLookup[rd[i].table_oid])[Tables.table_schema];
+ row["BaseTableName"] = ((object[])oidTableLookup[rd[i].table_oid])[Tables.table_name];
+ }
+ else
+ {
row["BaseCatalogName"] = "";
- row["BaseColumnName"] = GetName(i);
row["BaseSchemaName"] = "";
row["BaseTableName"] = "";
- row["DataType"] = GetFieldType(i);
- row["AllowDBNull"] = IsNullable(i);
- row["ProviderType"] = (int) rd[i].type_oid;
- row["IsAliased"] = false;
- row["IsExpression"] = false;
- row["IsIdentity"] = false;
- row["IsAutoIncrement"] = false;
- row["IsRowVersion"] = false;
- row["IsHidden"] = false;
- row["IsLong"] = false;
- row["IsReadOnly"] = false;
-
- result.Rows.Add(row);
}
-
-
-
-
-
+ row["BaseColumnName"] = GetBaseColumnName(columnLookup, i);
+ row["DataType"] = GetFieldType(i);
+ row["AllowDBNull"] = IsNullable(columnLookup, i);
+ row["ProviderType"] = rd[i].type_info.Name;
+ row["IsAliased"] = string.CompareOrdinal((string)row["ColumnName"], (string)row["BaseColumnName"]) != 0;
+ row["IsExpression"] = false;
+ row["IsIdentity"] = false;
+ row["IsAutoIncrement"] = false;
+ row["IsRowVersion"] = false;
+ row["IsHidden"] = false;
+ row["IsLong"] = false;
+ row["IsReadOnly"] = false;
+
+ schema.Rows.Add(row);
}
-
- return result;
-
}
@@ -779,9 +870,30 @@ namespace Npgsql
- private Boolean IsNullable(Int32 FieldIndex)
+ private Boolean IsNullable(Hashtable columnLookup, Int32 FieldIndex)
+ {
+ if (columnLookup == null || _currentResultset.RowDescription[FieldIndex].table_oid == 0)
+ return true;
+
+ string lookupKey = _currentResultset.RowDescription[FieldIndex].table_oid.ToString() + "," + _currentResultset.RowDescription[FieldIndex].column_attribute_number;
+ object[] row = (object[])columnLookup[lookupKey];
+ if (row != null)
+ return !(bool)row[Columns.column_notnull];
+ else
+ return true;
+ }
+
+ private string GetBaseColumnName(Hashtable columnLookup, Int32 FieldIndex)
{
- return true;
+ if (columnLookup == null || _currentResultset.RowDescription[FieldIndex].table_oid == 0)
+ return GetName(FieldIndex);
+
+ string lookupKey = _currentResultset.RowDescription[FieldIndex].table_oid.ToString() + "," + _currentResultset.RowDescription[FieldIndex].column_attribute_number;
+ object[] row = (object[])columnLookup[lookupKey];
+ if (row != null)
+ return (string)row[Columns.column_name];
+ else
+ return GetName(FieldIndex);
}
@@ -810,6 +922,100 @@ namespace Npgsql
}
+ private struct Tables
+ {
+ public const int table_catalog = 0;
+ public const int table_schema = 1;
+ public const int table_name = 2;
+ public const int table_id = 3;
+ }
+
+ private Hashtable GetTablesFromOids(ArrayList oids)
+ {
+ if (oids.Count == 0)
+ return null;
+
+ StringBuilder sb = new StringBuilder();
+
+ // the column index is used to find data.
+ // any changes to the order of the columns needs to be reflected in struct Tables
+ sb.Append("SELECT current_database() AS table_catalog, nc.nspname AS table_schema, c.relname AS table_name, c.oid as table_id");
+ sb.Append(" FROM pg_namespace nc, pg_class c WHERE c.relnamespace = nc.oid AND (c.relkind = 'r' OR c.relkind = 'v') AND c.oid IN (");
+ bool first = true;
+ foreach(int oid in oids)
+ {
+ if (!first)
+ sb.Append(',');
+ sb.Append(oid);
+ first = false;
+ }
+ sb.Append(')');
+
+ using (NpgsqlConnection connection = _connection.Clone())
+ using (NpgsqlCommand command = new NpgsqlCommand(sb.ToString(), connection))
+ using (NpgsqlDataReader reader = command.ExecuteReader())
+ {
+ Hashtable oidLookup = new Hashtable();
+ int columnCount = reader.FieldCount;
+ while (reader.Read())
+ {
+ object[] values = new object[columnCount];
+ reader.GetValues(values);
+ oidLookup[Convert.ToInt32(reader[Tables.table_id])] = values;
+ }
+ return oidLookup;
+ }
+ }
+
+ private struct Columns
+ {
+ public const int column_name = 0;
+ public const int column_notnull = 1;
+ public const int table_id = 2;
+ public const int column_num = 3;
+ }
+
+ private Hashtable GetColumns()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ // the column index is used to find data.
+ // any changes to the order of the columns needs to be reflected in struct Columns
+ sb.Append("SELECT a.attname AS column_name, a.attnotnull AS column_notnull, a.attrelid AS table_id, a.attnum AS column_num");
+ sb.Append(" from pg_attribute a WHERE a.attnum > 0 AND (");
+ bool first = true;
+ for(int i=0; i<_currentResultset.RowDescription.NumFields; ++i)
+ {
+ if (_currentResultset.RowDescription[i].table_oid != 0)
+ {
+ if (!first)
+ sb.Append(" OR ");
+ sb.AppendFormat("(a.attrelid={0} AND a.attnum={1})", _currentResultset.RowDescription[i].table_oid, _currentResultset.RowDescription[i].column_attribute_number);
+ first = false;
+ }
+ }
+ sb.Append(')');
+
+ // if the loop ended without setting first to false, then there will be no results from the query
+ if (first)
+ return null;
+
+ using (NpgsqlConnection connection = _connection.Clone())
+ using (NpgsqlCommand command = new NpgsqlCommand(sb.ToString(), connection))
+ using (NpgsqlDataReader reader = command.ExecuteReader())
+ {
+ Hashtable columnLookup = new Hashtable();
+ int columnCount = reader.FieldCount;
+ while(reader.Read())
+ {
+ object[] values = new object[columnCount];
+ reader.GetValues(values);
+ columnLookup[reader[Columns.table_id].ToString() + "," + reader[Columns.column_num].ToString()] = values;
+ }
+ return columnLookup;
+ }
+ }
+
IEnumerator IEnumerable.GetEnumerator ()
{
return new System.Data.Common.DbEnumerator (this);
diff --git a/mcs/class/Npgsql/Npgsql/NpgsqlParameter.cs b/mcs/class/Npgsql/Npgsql/NpgsqlParameter.cs
index 2c352b71aaf..cb0db918804 100644
--- a/mcs/class/Npgsql/Npgsql/NpgsqlParameter.cs
+++ b/mcs/class/Npgsql/Npgsql/NpgsqlParameter.cs
@@ -74,6 +74,7 @@ namespace Npgsql
{
resman = new System.Resources.ResourceManager(this.GetType());
NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME);
+ type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String));
}
/// <summary>
diff --git a/mcs/class/Npgsql/Npgsql/NpgsqlParameterCollection.cs b/mcs/class/Npgsql/Npgsql/NpgsqlParameterCollection.cs
index c361f0564c2..f6904614963 100644
--- a/mcs/class/Npgsql/Npgsql/NpgsqlParameterCollection.cs
+++ b/mcs/class/Npgsql/Npgsql/NpgsqlParameterCollection.cs
@@ -255,7 +255,7 @@ namespace Npgsql
foreach(NpgsqlParameter parameter in this)
{
- if (parameter.ParameterName == parameterName)
+ if (parameter.ParameterName.Remove(0, 1) == parameterName.Remove(0, 1))
return index;
index++;
}
diff --git a/mcs/class/Npgsql/Npgsql/NpgsqlSchema.cs b/mcs/class/Npgsql/Npgsql/NpgsqlSchema.cs
new file mode 100644
index 00000000000..d3fd36a8bcf
--- /dev/null
+++ b/mcs/class/Npgsql/Npgsql/NpgsqlSchema.cs
@@ -0,0 +1,279 @@
+// Npgsql.NpgsqlCommand.cs
+//
+// Author:
+// Josh Cooley <jbnpgsql@tuxinthebox.net>
+//
+// Copyright (C) 2002-2005 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
+// This library is free software; you can redistribute it and/or
+// 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
+
+
+using System;
+using System.Data;
+using System.Text;
+
+namespace Npgsql
+{
+ /// <summary>
+ /// Provides the underlying mechanism for reading schema information.
+ /// </summary>
+ internal sealed class NpgsqlSchema
+ {
+ private NpgsqlConnection _connection;
+
+ /// <summary>
+ /// Creates an NpgsqlSchema that can read schema information from the database.
+ /// </summary>
+ /// <param name="connection">An open database connection for reading metadata.</param>
+ internal NpgsqlSchema(NpgsqlConnection connection)
+ {
+ _connection = connection;
+ }
+
+ /// <summary>
+ /// Returns the MetaDataCollections that lists all possible collections.
+ /// </summary>
+ /// <returns>The MetaDataCollections</returns>
+ internal static DataTable GetMetaDataCollections()
+ {
+ DataTable metaDataCollections = new DataTable("MetaDataCollections");
+
+ metaDataCollections.Columns.AddRange(new DataColumn[] {
+ new DataColumn("CollectionName"),
+ new DataColumn("NumberOfRestrictions", typeof(int)),
+ new DataColumn("NumberOfIdentifierParts", typeof(int)) });
+
+ // Add(object[] { CollectionName, NumberOfRestrictions, NumberOfIdentifierParts })
+ metaDataCollections.Rows.Add(new object[]{"MetaDataCollections",0,0});
+ metaDataCollections.Rows.Add(new object[]{"Restrictions",0,0});
+ metaDataCollections.Rows.Add(new object[]{"Databases",1,1});
+ metaDataCollections.Rows.Add(new object[]{"Tables",4,3});
+ metaDataCollections.Rows.Add(new object[]{"Columns",4,4});
+ metaDataCollections.Rows.Add(new object[]{"Views",3,3});
+ metaDataCollections.Rows.Add(new object[]{"Users",1,1});
+
+ return metaDataCollections;
+ }
+
+ /// <summary>
+ /// Returns the Restrictions that contains the meaning and position of the values in the restrictions array.
+ /// </summary>
+ /// <returns>The Restrictions</returns>
+ internal static DataTable GetRestrictions()
+ {
+ DataTable restrictions = new DataTable("Restrictions");
+
+ restrictions.Columns.AddRange(new DataColumn[] {
+ new DataColumn("CollectionName"),
+ new DataColumn("RestrictionName"),
+ new DataColumn("RestrictionDefault"),
+ new DataColumn("RestrictionNumber", typeof(int)) });
+
+ restrictions.Rows.Add(new object[]{"Databases","Name","Name",1});
+ restrictions.Rows.Add(new object[]{"Tables","Catalog","table_catalog",1});
+ restrictions.Rows.Add(new object[]{"Tables","Schema","table_schema",2});
+ restrictions.Rows.Add(new object[]{"Tables","Table","table_name",3});
+ restrictions.Rows.Add(new object[]{"Tables","TableType","table_type",4});
+ restrictions.Rows.Add(new object[]{"Columns","Catalog","table_catalog",1});
+ restrictions.Rows.Add(new object[]{"Columns","Schema","table_schema",2});
+ restrictions.Rows.Add(new object[]{"Columns","Table","table_name",3});
+ restrictions.Rows.Add(new object[]{"Columns","Column","column_name",4});
+ restrictions.Rows.Add(new object[]{"Views","Catalog","table_catalog",1});
+ restrictions.Rows.Add(new object[]{"Views","Schema","table_schema",2});
+ restrictions.Rows.Add(new object[]{"Views","Table","table_name",3});
+
+ return restrictions;
+ }
+
+ private NpgsqlCommand BuildCommand(StringBuilder query, string[] restrictions, params string[] names)
+ {
+ NpgsqlCommand command = new NpgsqlCommand();
+
+ if (restrictions != null && names != null)
+ {
+ bool addWhere = true;
+ for(int i=0; i<restrictions.Length && i<names.Length; ++i)
+ {
+ if (restrictions[i] != null && restrictions[i].Length != 0)
+ {
+ if (addWhere)
+ query.Append(" WHERE ");
+ query.AppendFormat("{0} = :{0}", names[i]);
+
+ command.Parameters.Add(new NpgsqlParameter(names[i], restrictions[i]));
+ }
+ }
+ }
+ command.CommandText = query.ToString();
+ command.Connection = _connection;
+
+ return command;
+ }
+
+ /// <summary>
+ /// Returns the Databases that contains a list of all accessable databases.
+ /// </summary>
+ /// <param name="restrictions">The restrictions to filter the collection.</param>
+ /// <returns>The Databases</returns>
+ internal DataTable GetDatabases(string[] restrictions)
+ {
+ DataTable databases = new DataTable("Databases");
+
+ databases.Columns.AddRange(new DataColumn[] {
+ new DataColumn("database_name"),
+ new DataColumn("owner"),
+ new DataColumn("encoding") });
+
+ StringBuilder getDatabases = new StringBuilder();
+
+ getDatabases.Append("SELECT d.datname AS database_name, u.usename AS owner, pg_catalog.pg_encoding_to_char(d.encoding) AS encoding FROM pg_catalog.pg_database d LEFT JOIN pg_catalog.pg_user u ON d.datdba = u.usesysid");
+
+ using (NpgsqlCommand command = BuildCommand(getDatabases, restrictions, "datname"))
+ using (NpgsqlDataAdapter adapter = new NpgsqlDataAdapter(command))
+ {
+ adapter.Fill(databases);
+ }
+
+ return databases;
+ }
+
+ /// <summary>
+ /// Returns the Tables that contains table and view names and the database and schema they come from.
+ /// </summary>
+ /// <param name="restrictions">The restrictions to filter the collection.</param>
+ /// <returns>The Tables</returns>
+ internal DataTable GetTables(string[] restrictions)
+ {
+ DataTable tables = new DataTable("Tables");
+
+ tables.Columns.AddRange(new DataColumn[] {
+ new DataColumn("table_catalog"),
+ new DataColumn("table_schema"),
+ new DataColumn("table_name"),
+ new DataColumn("table_type") });
+
+ StringBuilder getTables = new StringBuilder();
+
+ getTables.Append("SELECT table_catalog, table_schema, table_name, table_type FROM information_schema.tables");
+
+ using (NpgsqlCommand command = BuildCommand(getTables, restrictions, "table_catalog", "table_schema", "table_name", "table_type"))
+ using (NpgsqlDataAdapter adapter = new NpgsqlDataAdapter(command))
+ {
+ adapter.Fill(tables);
+ }
+
+ return tables;
+ }
+
+ /// <summary>
+ /// Returns the Columns that contains information about columns in tables.
+ /// </summary>
+ /// <param name="restrictions">The restrictions to filter the collection.</param>
+ /// <returns>The Columns.</returns>
+ internal DataTable GetColumns(string[] restrictions)
+ {
+ DataTable columns = new DataTable("Columns");
+
+ columns.Columns.AddRange(new DataColumn[] {
+ new DataColumn("table_catalog"),
+ new DataColumn("table_schema"),
+ new DataColumn("table_name"),
+ new DataColumn("column_name"),
+ new DataColumn("ordinal_position", typeof(int)),
+ new DataColumn("column_default"),
+ new DataColumn("is_nullable"),
+ new DataColumn("data_type"),
+ new DataColumn("character_maximum_length", typeof(int)),
+ new DataColumn("character_octet_length", typeof(int)),
+ new DataColumn("numeric_precision", typeof(int)),
+ new DataColumn("numeric_precision_radix", typeof(int)),
+ new DataColumn("numeric_scale", typeof(int)),
+ new DataColumn("datetime_precision", typeof(int)),
+ new DataColumn("character_set_catalog"),
+ new DataColumn("character_set_schema"),
+ new DataColumn("character_set_name"),
+ new DataColumn("collation_catalog") });
+
+ StringBuilder getColumns = new StringBuilder();
+
+ getColumns.Append("SELECT table_catalog, table_schema, table_name, column_name, ordinal_position, column_default, is_nullable, udt_name AS data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_precision_radix, numeric_scale, datetime_precision, character_set_catalog, character_set_schema, character_set_name, collation_catalog FROM information_schema.columns");
+
+ using (NpgsqlCommand command = BuildCommand(getColumns, restrictions, "table_catalog", "table_schema", "table_name", "column_name"))
+ using (NpgsqlDataAdapter adapter = new NpgsqlDataAdapter(command))
+ {
+ adapter.Fill(columns);
+ }
+
+ return columns;
+ }
+
+ /// <summary>
+ /// Returns the Views that contains view names and the database and schema they come from.
+ /// </summary>
+ /// <param name="restrictions">The restrictions to filter the collection.</param>
+ /// <returns>The Views</returns>
+ internal DataTable GetViews(string[] restrictions)
+ {
+ DataTable views = new DataTable("Views");
+
+ views.Columns.AddRange(new DataColumn[] {
+ new DataColumn("table_catalog"),
+ new DataColumn("table_schema"),
+ new DataColumn("table_name"),
+ new DataColumn("check_option"),
+ new DataColumn("is_updatable") });
+
+ StringBuilder getViews = new StringBuilder();
+
+ getViews.Append("SELECT table_catalog, table_schema, table_name, check_option, is_updatable FROM information_schema.views");
+
+ using (NpgsqlCommand command = BuildCommand(getViews, restrictions, "table_catalog", "table_schema", "table_name"))
+ using (NpgsqlDataAdapter adapter = new NpgsqlDataAdapter(command))
+ {
+ adapter.Fill(views);
+ }
+
+ return views;
+ }
+
+ /// <summary>
+ /// Returns the Users containing user names and the sysid of those users.
+ /// </summary>
+ /// <param name="restrictions">The restrictions to filter the collection.</param>
+ /// <returns>The Users.</returns>
+ internal DataTable GetUsers(string[] restrictions)
+ {
+ DataTable users = new DataTable("Users");
+
+ users.Columns.AddRange(new DataColumn[] {
+ new DataColumn("user_name"),
+ new DataColumn("user_sysid", typeof(int)) });
+
+ StringBuilder getUsers = new StringBuilder();
+
+ getUsers.Append("SELECT usename as user_name, usesysid as user_sysid FROM pg_catalog.pg_user");
+
+ using (NpgsqlCommand command = BuildCommand(getUsers, restrictions, "usename"))
+ using (NpgsqlDataAdapter adapter = new NpgsqlDataAdapter(command))
+ {
+ adapter.Fill(users);
+ }
+
+ return users;
+ }
+ }
+}
diff --git a/mcs/class/Npgsql/NpgsqlTypes/NpgsqlDbType.cs b/mcs/class/Npgsql/NpgsqlTypes/NpgsqlDbType.cs
index 27d47a71681..5d101467215 100644
--- a/mcs/class/Npgsql/NpgsqlTypes/NpgsqlDbType.cs
+++ b/mcs/class/Npgsql/NpgsqlTypes/NpgsqlDbType.cs
@@ -28,6 +28,10 @@ namespace NpgsqlTypes
{
public enum NpgsqlDbType
{
+
+ // This list used to be ordered. But this ordering would break compiled applications
+ // as enum values would change after each insertion. Now, just append new types.
+
Bigint,
Boolean,
Box,
@@ -49,7 +53,8 @@ namespace NpgsqlTypes
Text,
Time,
Timestamp,
- Varchar
+ Varchar,
+ Refcursor
}
diff --git a/mcs/class/Npgsql/NpgsqlTypes/NpgsqlTypesHelper.cs b/mcs/class/Npgsql/NpgsqlTypes/NpgsqlTypesHelper.cs
index 39765e917d7..fe58fbeb526 100644
--- a/mcs/class/Npgsql/NpgsqlTypes/NpgsqlTypesHelper.cs
+++ b/mcs/class/Npgsql/NpgsqlTypes/NpgsqlTypesHelper.cs
@@ -167,7 +167,9 @@ namespace NpgsqlTypes
// to type mapping has the last entry, in this case, text, as the map value
// for DbType.String.
- NativeTypeMapping.AddType("char", NpgsqlDbType.Char, DbType.String, true, null);
+ NativeTypeMapping.AddType("refcursor", NpgsqlDbType.Refcursor, DbType.String, true, null);
+
+ NativeTypeMapping.AddType("char", NpgsqlDbType.Char, DbType.String, true, null);
NativeTypeMapping.AddType("varchar", NpgsqlDbType.Varchar, DbType.String, true, null);
@@ -302,6 +304,9 @@ namespace NpgsqlTypes
new NpgsqlBackendTypeInfo(0, "unknown", NpgsqlDbType.Text, DbType.String, typeof(String),
null),
+ new NpgsqlBackendTypeInfo(0, "refcursor", NpgsqlDbType.Refcursor, DbType.String, typeof(String),
+ null),
+
new NpgsqlBackendTypeInfo(0, "char", NpgsqlDbType.Char, DbType.String, typeof(String),
null),