//
-// System.Data.SqlClient.SqlCommand.cs
+// Mono.Data.PostgreSqlClient.PgSqlCommand.cs
//
// Author:
// Rodrigo Moya (rodrigo@ximian.com)
// Gonzalo Paniagua Javier <gonzalo@gnome-db.org>
//
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
// use #define DEBUG_SqlCommand if you want to spew debug messages
// #define DEBUG_SqlCommand
using System.Text;
using System.Xml;
-namespace System.Data.SqlClient {
+namespace Mono.Data.PostgreSqlClient {
/// <summary>
/// Represents a SQL statement that is executed
/// while connected to a SQL database.
/// </summary>
- // public sealed class SqlCommand : Component, IDbCommand, ICloneable
- public sealed class SqlCommand : IDbCommand {
+ // public sealed class PgSqlCommand : Component, IDbCommand, ICloneable
+ public sealed class PgSqlCommand : IDbCommand {
#region Fields
// default is 30 seconds
// for command execution
- private SqlConnection conn = null;
- private SqlTransaction trans = null;
+ private PgSqlConnection conn = null;
+ private PgSqlTransaction trans = null;
private CommandType cmdType = CommandType.Text;
private bool designTime = false;
- private SqlParameterCollection parmCollection = new
- SqlParameterCollection();
+ private PgSqlParameterCollection parmCollection = new
+ PgSqlParameterCollection();
- // SqlDataReader state data for ExecuteReader()
- private SqlDataReader dataReader = null;
+ // PgSqlDataReader state data for ExecuteReader()
+ private PgSqlDataReader dataReader = null;
private string[] queries = null;
private int currentQuery = -1;
private CommandBehavior cmdBehavior = CommandBehavior.Default;
#region Constructors
- public SqlCommand() {
+ public PgSqlCommand() {
sql = "";
}
- public SqlCommand (string cmdText) {
+ public PgSqlCommand (string cmdText) {
sql = cmdText;
}
- public SqlCommand (string cmdText, SqlConnection connection) {
+ public PgSqlCommand (string cmdText, PgSqlConnection connection) {
sql = cmdText;
conn = connection;
}
- public SqlCommand (string cmdText, SqlConnection connection,
- SqlTransaction transaction) {
+ public PgSqlCommand (string cmdText, PgSqlConnection connection,
+ PgSqlTransaction transaction) {
sql = cmdText;
conn = connection;
trans = transaction;
}
[MonoTODO]
- public SqlParameter CreateParameter () {
- return new SqlParameter ();
+ public PgSqlParameter CreateParameter () {
+ return new PgSqlParameter ();
+ }
+
+ public uint EscapeString (string to, string from, uint length) {
+ uint result = PostgresLibrary.PQescapeString (out to, from, length);
+ return result;
+ }
+
+ public byte[] EscapeByteArray (byte[] bintext, uint binlen,
+ uint bytealen) {
+
+ byte[] result;
+ result = PostgresLibrary.PQescapeBytea (bintext,
+ binlen, bytealen);
+
+ return result;
}
public int ExecuteNonQuery () {
PostgresLibrary.PQclear (pgResult);
pgResult = IntPtr.Zero;
\r
- throw new SqlException(0, 0,
+ throw new PgSqlException(0, 0,
errorMessage, 0, "",
conn.DataSource, "SqlCommand", 0);\r
}
}
[MonoTODO]
- public SqlDataReader ExecuteReader () {
+ public PgSqlDataReader ExecuteReader () {
return ExecuteReader(CommandBehavior.Default);
}
}
[MonoTODO]
- public SqlDataReader ExecuteReader (CommandBehavior behavior)
+ public PgSqlDataReader ExecuteReader (CommandBehavior behavior)
{
if(conn.State != ConnectionState.Open)
throw new InvalidOperationException(
queries = null;
currentQuery = -1;
- dataReader = new SqlDataReader(this);
+ dataReader = new PgSqlDataReader(this);
queries = sql.Split(new Char[] {';'});
return dataReader;
}
- internal SqlResult NextResult()
+ internal PgSqlResult NextResult()
{
- SqlResult res = new SqlResult();
+ PgSqlResult res = new PgSqlResult();
res.Connection = this.Connection;
res.Behavior = cmdBehavior;
string statement;
private string TweakQuery(string query, CommandType commandType) {
string statement = "";
- StringBuilder td;
-
-#if DEBUG_SqlCommand
- Console.WriteLine("---------[][] TweakQuery() [][]--------");
- Console.WriteLine("CommandType: " + commandType + " CommandBehavior: " + cmdBehavior);
- Console.WriteLine("SQL before command type: " + query);
-#endif
+
// finish building SQL based on CommandType
switch(commandType) {
case CommandType.Text:
- statement = query;
+ // TODO: this parameters utility
+ // currently only support input variables
+ // need todo output, input/output, and return.
+ parmUtil = new ParmUtil(query, parmCollection);
+ statement = parmUtil.ReplaceWithParms();
break;
case CommandType.StoredProcedure:
- statement =
- "SELECT " + query + "()";
+ string sParmList = GetStoredProcParmList ();
+ statement = "SELECT " + query + "(" + sParmList + ")";
break;
- case CommandType.TableDirect:
- // NOTE: this is for the PostgreSQL provider
- // and for OleDb, according to the docs,
- // an exception is thrown if you try to use
- // this with SqlCommand
- string[] directTables = query.Split(
- new Char[] {','});
-
- td = new StringBuilder("SELECT * FROM ");
-
- for(int tab = 0; tab < directTables.Length; tab++) {
- if(tab > 0)
- td.Append(',');
- td.Append(directTables[tab]);
- // FIXME: if multipe tables, how do we
- // join? based on Primary/Foreign Keys?
- // Otherwise, a Cartesian Product happens
- }
- statement = td.ToString();
- break;
- default:
- // FIXME: throw an exception?
- statement = query;
+ case CommandType.TableDirect:
+ statement = "SELECT * FROM " + query;
break;
}
-#if DEBUG_SqlCommand
- Console.WriteLine("SQL after command type: " + statement);
-#endif
- // TODO: this parameters utility
- // currently only support input variables
- // need todo output, input/output, and return.
-#if DEBUG_SqlCommand
- Console.WriteLine("using ParmUtil in TweakQuery()...");
-#endif
- parmUtil = new ParmUtil(statement, parmCollection);
-#if DEBUG_SqlCommand
- Console.WriteLine("ReplaceWithParms...");
-#endif
-
- statement = parmUtil.ReplaceWithParms();
-#if DEBUG_SqlCommand
- Console.WriteLine("SQL after ParmUtil: " + statement);
-#endif
return statement;
}
- private void ExecuteQuery (string query, SqlResult res)
+ string GetStoredProcParmList () {
+ StringBuilder s = new StringBuilder();
+
+ int addedCount = 0;
+ for(int p = 0; p < parmCollection.Count; p++) {
+ PgSqlParameter prm = parmCollection[p];
+ if(prm.Direction == ParameterDirection.Input) {\r
+ string strObj = PostgresHelper.\r
+ ObjectToString(prm.DbType, \r
+ prm.Value);\r
+ if(addedCount > 0)\r
+ s.Append(",");\r
+ s.Append(strObj);\r
+ addedCount++;\r
+ }
+ }
+ return s.ToString();
+ }
+
+ private void ExecuteQuery (string query, PgSqlResult res)
{
IntPtr pgResult;
PostgresLibrary.PQclear (pgResult);
pgResult = IntPtr.Zero;
\r
- throw new SqlException(0, 0,
+ throw new PgSqlException(0, 0,
errorMessage, 0, "",
conn.DataSource, "SqlCommand", 0);\r
}
// only meant to be used between SqlConnectioin,
// SqlCommand, and SqlDataReader
- internal void OpenReader(SqlDataReader reader) {
+ internal void OpenReader(PgSqlDataReader reader) {
conn.OpenReader(reader);
}
PostgresLibrary.PQclear (pgResult);
pgResult = IntPtr.Zero;
\r
- throw new SqlException(0, 0,
+ throw new PgSqlException(0, 0,
errorMessage, 0, "",
conn.DataSource, "SqlCommand", 0);\r
}
}
[MonoTODO]
- public SqlCommand Clone () {
+ public PgSqlCommand Clone () {
throw new NotImplementedException ();
}
// transaction in progress
// csc
- Connection = (SqlConnection) value;
+ Connection = (PgSqlConnection) value;
// mcs
// Connection = value;
}
}
- public SqlConnection Connection {
+ public PgSqlConnection Connection {
get {
// conn defaults to null
return conn;
}
}
- public SqlParameterCollection Parameters {
+ public PgSqlParameterCollection Parameters {
get {
return parmCollection;
}
// has already begun
// csc
- Transaction = (SqlTransaction) value;
+ Transaction = (PgSqlTransaction) value;
// mcs
// Transaction = value;
}
}
- public SqlTransaction Transaction {
+ public PgSqlTransaction Transaction {
get {
return trans;
}
}
[MonoTODO]
- ~SqlCommand() {
+ ~PgSqlCommand() {
// FIXME: need proper way to release resources
// Dispose(false);
}
// SqlResult is used for passing Result Set data
// from SqlCommand to SqlDataReader
- internal class SqlResult {
+ internal class PgSqlResult {
private DataTable dataTableSchema = null; // only will contain the schema
private IntPtr pg_result = IntPtr.Zero; // native PostgreSQL PGresult
private int fieldCount = 0;
private string[] pgtypes = null; // PostgreSQL types (typname)
private bool resultReturned = false;
- private SqlConnection con = null;
+ private PgSqlConnection con = null;
private int rowsAffected = -1;
private ExecStatusType execStatus = ExecStatusType.PGRES_FATAL_ERROR;
private int currentQuery = -1;
}
- internal SqlConnection Connection {
+ internal PgSqlConnection Connection {
get {
return con;
}
dataTableSchema.Columns.Add ("BaseColumnName", typeof (string));
dataTableSchema.Columns.Add ("BaseSchemaName", typeof (string));
dataTableSchema.Columns.Add ("BaseTableName", typeof (string));
- dataTableSchema.Columns.Add ("DataType", typeof(string));
+ dataTableSchema.Columns.Add ("DataType", typeof(Type));
dataTableSchema.Columns.Add ("AllowDBNull", typeof (bool));
dataTableSchema.Columns.Add ("ProviderType", typeof (int));
dataTableSchema.Columns.Add ("IsAliased", typeof (bool));
schemaRow["ColumnSize"] = PostgresLibrary.PQfsize (pgResult, i);
schemaRow["NumericPrecision"] = 0;
schemaRow["NumericScale"] = 0;
- if((cmdBehavior & CommandBehavior.SingleResult) == CommandBehavior.KeyInfo) {
+ // TODO: need to get KeyInfo
+ if((cmdBehavior & CommandBehavior.KeyInfo) == CommandBehavior.KeyInfo) {
bool IsUnique, IsKey;
GetKeyInfo(columnName, out IsUnique, out IsKey);
}
\r
typ = PostgresHelper.DbTypeToSystemType (dbType);\r
string st = typ.ToString();\r
- schemaRow["DataType"] = st;\r
+ schemaRow["DataType"] = typ;\r
schemaRow["AllowDBNull"] = false;
schemaRow["ProviderType"] = oid;
private void GetKeyInfo(string columnName, out bool isUnique, out bool isKey) {
isUnique = false;
isKey = false;
-
+/*
string sql;
sql =
"FROM pg_class c, pg_class c2, pg_index i " +
"WHERE c.relname = ':tableName' AND c.oid = i.indrelid " +
"AND i.indexrelid = c2.oid ";
+*/
}
}
}