1 // created on 21/5/2002 at 20:03
3 // Npgsql.NpgsqlCommand.cs
6 // Francisco Jr. (fxjrlists@yahoo.com.br)
8 // Copyright (C) 2002 The Npgsql Development Team
9 // npgsql-general@gborg.postgresql.org
10 // http://gborg.postgresql.org/project/npgsql/projdisplay.php
12 // This library is free software; you can redistribute it and/or
13 // modify it under the terms of the GNU Lesser General Public
14 // License as published by the Free Software Foundation; either
15 // version 2.1 of the License, or (at your option) any later version.
17 // This library is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 // Lesser General Public License for more details.
22 // You should have received a copy of the GNU Lesser General Public
23 // License along with this library; if not, write to the Free Software
24 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 using System.Net.Sockets;
33 using System.ComponentModel;
34 using System.Collections;
40 /// Represents a SQL statement or function (stored procedure) to execute against a PostgreSQL database. This class cannot be inherited.
42 [System.Drawing.ToolboxBitmapAttribute(typeof(NpgsqlCommand)), ToolboxItem(true)]
43 public sealed class NpgsqlCommand : Component, IDbCommand, IDisposable {
45 private NpgsqlConnection connection;
46 private NpgsqlTransaction transaction;
48 private Int32 timeout;
49 private CommandType type;
50 private NpgsqlParameterCollection parameters;
51 private String planName;
52 private static Int32 planIndex = 0;
53 private static Int32 portalIndex = 0;
55 private NpgsqlParse parse;
56 private NpgsqlBind bind;
58 // Logging related values
59 private static readonly String CLASSNAME = "NpgsqlCommand";
60 private System.Resources.ResourceManager resman;
65 /// Initializes a new instance of the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see> class.
67 public NpgsqlCommand() : this(String.Empty, null, null){}
69 /// Initializes a new instance of the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see> class with the text of the query.
71 /// <param name="cmdText">The text of the query.</param>
72 public NpgsqlCommand(String cmdText) : this(cmdText, null, null){}
74 /// Initializes a new instance of the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see> class with the text of the query and a <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see>.
76 /// <param name="cmdText">The text of the query.</param>
77 /// <param name="connection">A <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see> that represents the connection to a PostgreSQL server.</param>
78 public NpgsqlCommand(String cmdText, NpgsqlConnection connection) : this(cmdText, connection, null){}
80 /// Initializes a new instance of the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see> class with the text of the query, a <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see>, and the <see cref="Npgsql.NpgsqlTransaction">NpgsqlTransaction</see>.
82 /// <param name="cmdText">The text of the query.</param>
83 /// <param name="connection">A <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see> that represents the connection to a PostgreSQL server.</param>
84 /// <param name="transaction">The <see cref="Npgsql.NpgsqlTransaction">NpgsqlTransaction</see> in which the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see> executes.</param>
85 public NpgsqlCommand(String cmdText, NpgsqlConnection connection, NpgsqlTransaction transaction) {
86 resman = new System.Resources.ResourceManager(this.GetType());
87 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME);
89 planName = String.Empty;
91 this.connection = connection;
92 parameters = new NpgsqlParameterCollection();
94 type = CommandType.Text;
95 this.Transaction = transaction;
100 /// Gets or sets the SQL statement or function (stored procedure) to execute at the data source.
102 /// <value>The Transact-SQL statement or stored procedure to execute. The default is an empty string.</value>
103 [Category("Data"), DefaultValue("")]
104 public String CommandText {
110 // [TODO] Validate commandtext.
111 NpgsqlEventLog.LogPropertySet(LogLevel.Debug, CLASSNAME, "CommandText", value);
113 planName = String.Empty;
120 /// Gets or sets the wait time before terminating the attempt
121 /// to execute a command and generating an error.
123 /// <value>The time (in seconds) to wait for the command to execute.
124 /// The default is 20 seconds.</value>
126 public Int32 CommandTimeout {
133 throw new ArgumentException(resman.GetString("Exception_CommandTimeoutLessZero"));
136 NpgsqlEventLog.LogPropertySet(LogLevel.Debug, CLASSNAME, "CommandTimeout", value);
141 /// Gets or sets a value indicating how the
142 /// <see cref="Npgsql.NpgsqlCommand.CommandText">CommandText</see> property is to be interpreted.
144 /// <value>One of the <see cref="System.Data.CommandType">CommandType</see> values. The default is <see cref="System.Data.CommandType">CommandType.Text</see>.</value>
145 [Category("Data"), DefaultValue(CommandType.Text)]
146 public CommandType CommandType {
153 NpgsqlEventLog.LogPropertySet(LogLevel.Debug, CLASSNAME, "CommandType", value);
158 IDbConnection IDbCommand.Connection {
164 connection = (NpgsqlConnection) value;
165 NpgsqlEventLog.LogPropertySet(LogLevel.Debug, CLASSNAME, "IDbCommand.Connection", value);
170 /// Gets or sets the <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see>
171 /// used by this instance of the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see>.
173 /// <value>The connection to a data source. The default value is a null reference.</value>
174 [Category("Behavior"), DefaultValue(null)]
175 public NpgsqlConnection Connection {
177 NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "Connection");
182 if (this.transaction != null && this.transaction.Connection == null)
183 this.transaction = null;
184 if (this.connection != null && this.connection.InTransaction == true)
185 throw new NpgsqlException(resman.GetString("Exception_SetConnectionInTransaction"));
186 this.connection = value;
187 NpgsqlEventLog.LogPropertySet(LogLevel.Debug, CLASSNAME, "Connection", value);
191 IDataParameterCollection IDbCommand.Parameters {
198 /// Gets the <see cref="Npgsql.NpgsqlParameterCollection">NpgsqlParameterCollection</see>.
200 /// <value>The parameters of the SQL statement or function (stored procedure). The default is an empty collection.</value>
201 [Category("Data"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
202 public NpgsqlParameterCollection Parameters {
204 NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "Parameters");
210 /// Gets or sets the <see cref="Npgsql.NpgsqlTransaction">NpgsqlTransaction</see>
211 /// within which the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see> executes.
213 /// <value>The <see cref="Npgsql.NpgsqlTransaction">NpgsqlTransaction</see>.
214 /// The default value is a null reference.</value>
215 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
216 public IDbTransaction Transaction {
218 NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "Transaction");
219 //throw new NotImplementedException();
220 if (this.transaction != null && this.transaction.Connection == null){
221 this.transaction = null;
223 return this.transaction;
227 NpgsqlEventLog.LogPropertySet(LogLevel.Debug, CLASSNAME, "Transaction" ,value);
228 //throw new NotImplementedException();
229 /*if (this.connection != null && this.connection.InTransaction == true){
230 throw new NpgsqlException(resman.GetString("Exception_SetTransactionInTransaction"));
232 this.transaction = (NpgsqlTransaction) value;
237 /// Gets or sets how command results are applied to the <see cref="System.Data.DataRow">DataRow</see>
238 /// when used by the <see cref="System.Data.Common.DbDataAdapter.Update">Update</see>
239 /// method of the <see cref="System.Data.Common.DbDataAdapter">DbDataAdapter</see>.
241 /// <value>One of the <see cref="System.Data.UpdateRowSource">UpdateRowSource</see> values.</value>
242 [Category("Behavior"), DefaultValue(UpdateRowSource.Both)]
243 public UpdateRowSource UpdatedRowSource {
246 NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "UpdatedRowSource");
247 // [FIXME] Strange, the line below doesn't appears in the stack trace.
249 //throw new NotImplementedException();
250 return UpdateRowSource.Both;
254 throw new NotImplementedException();
258 private void CheckNotification() {
259 if (connection.Mediator.Notifications.Count > 0)
260 for (int i=0; i < connection.Mediator.Notifications.Count; i++)
261 connection.Notify((NpgsqlNotificationEventArgs) connection.Mediator.Notifications[i]);
266 /// Attempts to cancel the execution of a <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see>.
268 /// <remarks>This Method isn't implemented yet.</remarks>
269 public void Cancel() {
270 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Cancel");
272 // [TODO] Finish method implementation.
273 throw new NotImplementedException();
277 /// Creates a new instance of an <see cref="System.Data.IDbDataParameter">IDbDataParameter</see> object.
279 /// <returns>An <see cref="System.Data.IDbDataParameter">IDbDataParameter</see> object.</returns>
280 IDbDataParameter IDbCommand.CreateParameter() {
281 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "IDbCommand.CreateParameter");
283 return (NpgsqlParameter) CreateParameter();
287 /// Creates a new instance of a <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see> object.
289 /// <returns>A <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see> object.</returns>
290 public NpgsqlParameter CreateParameter() {
291 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "CreateParameter");
293 return new NpgsqlParameter();
297 /// Executes a SQL statement against the connection and returns the number of rows affected.
299 /// <returns>The number of rows affected.</returns>
300 public Int32 ExecuteNonQuery() {
301 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ExecuteNonQuery");
303 // Check the connection state.
304 CheckConnectionState();
306 /*if ((type == CommandType.Text) || (type == CommandType.StoredProcedure))
308 connection.Query(this);
312 connection.Execute(new NpgsqlExecute(bind.PortalName, 0));
315 throw new NotImplementedException(resman.GetString("Exception_CommandTypeTableDirect"));
320 // Check if there were any errors.
321 if (connection.Mediator.Errors.Count > 0) {
322 StringWriter sw = new StringWriter();
323 sw.WriteLine(String.Format(resman.GetString("Exception_MediatorErrors"), "ExecuteNonQuery"));
325 foreach(string error in connection.Mediator.Errors){
326 sw.WriteLine("{0}. {1}", i++, error);
328 throw new NpgsqlException(sw.ToString());
335 // The only expected result is the CompletedResponse result.
336 // If nothing is returned, just return -1.
338 if(connection.Mediator.GetCompletedResponses().Count == 0)
341 String[] ret_string_tokens = ((String)connection.Mediator.GetCompletedResponses()[0]).Split(null); // whitespace separator.
343 // Check if the command was insert, delete or update.
344 // Only theses commands return rows affected.
345 // [FIXME] Is there a better way to check this??
346 if ((String.Compare(ret_string_tokens[0], "INSERT", true) == 0) ||
347 (String.Compare(ret_string_tokens[0], "UPDATE", true) == 0) ||
348 (String.Compare(ret_string_tokens[0], "DELETE", true) == 0))
350 // The number of rows affected is in the third token for insert queries
351 // and in the second token for update and delete queries.
352 // In other words, it is the last token in the 0-based array.
354 return Int32.Parse(ret_string_tokens[ret_string_tokens.Length - 1]);
361 /// Sends the <see cref="Npgsql.NpgsqlCommand.CommandText">CommandText</see> to
362 /// the <see cref="Npgsql.NpgsqlConnection">Connection</see> and builds a
363 /// <see cref="Npgsql.NpgsqlDataReader">NpgsqlDataReader</see>.
365 /// <returns>A <see cref="Npgsql.NpgsqlDataReader">NpgsqlDataReader</see> object.</returns>
366 IDataReader IDbCommand.ExecuteReader() {
367 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "IDbCommand.ExecuteReader");
369 return (NpgsqlDataReader) ExecuteReader();
373 /// Sends the <see cref="Npgsql.NpgsqlCommand.CommandText">CommandText</see> to
374 /// the <see cref="Npgsql.NpgsqlConnection">Connection</see> and builds a
375 /// <see cref="Npgsql.NpgsqlDataReader">NpgsqlDataReader</see>
376 /// using one of the <see cref="System.Data.CommandBehavior">CommandBehavior</see> values.
378 /// <param name="cb">One of the <see cref="System.Data.CommandBehavior">CommandBehavior</see> values.</param>
379 /// <returns>A <see cref="Npgsql.NpgsqlDataReader">NpgsqlDataReader</see> object.</returns>
380 IDataReader IDbCommand.ExecuteReader(CommandBehavior cb) {
381 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "IDbCommand.ExecuteReader", cb);
383 return (NpgsqlDataReader) ExecuteReader(cb);
388 /// Sends the <see cref="Npgsql.NpgsqlCommand.CommandText">CommandText</see> to
389 /// the <see cref="Npgsql.NpgsqlConnection">Connection</see> and builds a
390 /// <see cref="Npgsql.NpgsqlDataReader">NpgsqlDataReader</see>.
392 /// <returns>A <see cref="Npgsql.NpgsqlDataReader">NpgsqlDataReader</see> object.</returns>
393 public NpgsqlDataReader ExecuteReader() {
394 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ExecuteReader");
397 return ExecuteReader(CommandBehavior.Default);
402 /// Sends the <see cref="Npgsql.NpgsqlCommand.CommandText">CommandText</see> to
403 /// the <see cref="Npgsql.NpgsqlConnection">Connection</see> and builds a
404 /// <see cref="Npgsql.NpgsqlDataReader">NpgsqlDataReader</see>
405 /// using one of the <see cref="System.Data.CommandBehavior">CommandBehavior</see> values.
407 /// <param name="cb">One of the <see cref="System.Data.CommandBehavior">CommandBehavior</see> values.</param>
408 /// <returns>A <see cref="Npgsql.NpgsqlDataReader">NpgsqlDataReader</see> object.</returns>
409 /// <remarks>Currently the CommandBehavior parameter is ignored.</remarks>
410 public NpgsqlDataReader ExecuteReader(CommandBehavior cb) {
411 // [FIXME] No command behavior handling.
413 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ExecuteReader", cb);
415 // Check the connection state.
416 CheckConnectionState();
418 /*if ((type == CommandType.Text) || (type == CommandType.StoredProcedure))
420 connection.Query(this);
424 connection.Execute(new NpgsqlExecute(bind.PortalName, 0));
427 throw new NotImplementedException(resman.GetString("Exception_CommandTypeTableDirect"));
432 // Check if there were any errors.
433 if (connection.Mediator.Errors.Count > 0) {
434 StringWriter sw = new StringWriter();
435 sw.WriteLine(String.Format(resman.GetString("Exception_MediatorErrors_1P"), "ExecuteReader", cb));
437 foreach(string error in connection.Mediator.Errors){
438 sw.WriteLine("{0}. {1}", i++, error);
440 throw new NpgsqlException(sw.ToString());
446 // Get the resultsets and create a Datareader with them.
447 return new NpgsqlDataReader(connection.Mediator.GetResultSets(), connection.Mediator.GetCompletedResponses(), connection);
452 /// This method binds the parameters from parameters collection to the bind
455 private void BindParameters()
458 if (parameters.Count != 0)
460 Object[] parameterValues = new Object[parameters.Count];
461 for (Int32 i = 0; i < parameters.Count; i++)
463 parameterValues[i] = NpgsqlTypesHelper.ConvertNpgsqlParameterToBackendStringValue(parameters[i]);
465 bind.ParameterValues = parameterValues;
468 connection.Bind(bind);
475 /// Executes the query, and returns the first column of the first row
476 /// in the result set returned by the query. Extra columns or rows are ignored.
478 /// <returns>The first column of the first row in the result set,
479 /// or a null reference if the result set is empty.</returns>
480 public Object ExecuteScalar() {
481 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ExecuteScalar");
484 // Check the connection state.
485 CheckConnectionState();
487 /*if ((type == CommandType.Text) || (type == CommandType.StoredProcedure))
489 connection.Query(this);
493 connection.Execute(new NpgsqlExecute(bind.PortalName, 0));
496 throw new NotImplementedException(resman.GetString("Exception_CommandTypeTableDirect"));
501 // Check if there were any errors.
502 // [FIXME] Just check the first error.
503 if (connection.Mediator.Errors.Count > 0) {
504 StringWriter sw = new StringWriter();
505 sw.WriteLine(String.Format(resman.GetString("Exception_MediatorErrors"), "ExecuteScalar"));
507 foreach(string error in connection.Mediator.Errors){
508 sw.WriteLine("{0}. {1}", i++, error);
510 throw new NpgsqlException(sw.ToString());
515 //ArrayList results = connection.Mediator.Data;
517 //Object result = null; // Result of the ExecuteScalar().
520 // Now get the results.
521 // Only the first column of the first row must be returned.
524 ArrayList resultSets = connection.Mediator.GetResultSets();
527 // First data is the RowDescription object.
528 //NpgsqlRowDescription rd = (NpgsqlRowDescription)results[0];
530 NpgsqlResultSet firstResultSet = (NpgsqlResultSet)resultSets[0];
532 NpgsqlRowDescription rd = firstResultSet.RowDescription;
534 NpgsqlAsciiRow ascii_row = (NpgsqlAsciiRow)firstResultSet[0];
542 /// Creates a prepared version of the command on a PostgreSQL server.
544 public void Prepare() {
545 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Prepare");
547 // Check the connection state.
548 CheckConnectionState();
550 if (!connection.SupportsPrepare)
551 return; // Do nothing.
555 // [TODO] Finish method implementation.
556 //throw new NotImplementedException();
558 //NpgsqlCommand command = new NpgsqlCommand("prepare plan1 as " + GetCommandText(), connection );
560 if (connection.BackendProtocolVersion == ProtocolVersion.Version2)
562 NpgsqlCommand command = new NpgsqlCommand(GetPrepareCommandText(), connection );
563 command.ExecuteNonQuery();
567 // Use the extended query parsing...
568 planName = "NpgsqlPlan" + System.Threading.Interlocked.Increment(ref planIndex);
569 String portalName = "NpgsqlPortal" + System.Threading.Interlocked.Increment(ref portalIndex);
571 parse = new NpgsqlParse(planName, GetParseCommandText(), new Int32[] {});
573 connection.Parse(parse);
576 bind = new NpgsqlBind(portalName, planName, new Int16[] {0}, null, new Int16[] {0});
582 /// Releases the resources used by the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see>.
584 public new void Dispose() {
585 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Dispose");
589 /// This method checks the connection state to see if the connection
590 /// is set or it is open. If one of this conditions is not met, throws
591 /// an InvalidOperationException
593 private void CheckConnectionState() {
594 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "CheckConnectionState");
596 // Check the connection state.
597 if (connection == null)
598 throw new InvalidOperationException(resman.GetString("Exception_ConnectionNull"));
599 if (connection.State != ConnectionState.Open)
600 throw new InvalidOperationException(resman.GetString("Exception_ConnectionNotOpen"));
605 /// This method substitutes the <see cref="Npgsql.NpgsqlCommand.Parameters">Parameters</see>, if exist, in the command
606 /// to their actual values.
607 /// The parameter name format is <b>:ParameterName</b>.
609 /// <returns>A version of <see cref="Npgsql.NpgsqlCommand.CommandText">CommandText</see> with the <see cref="Npgsql.NpgsqlCommand.Parameters">Parameters</see> inserted.</returns>
610 internal String GetCommandText() {
611 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetCommandText");
613 if (planName == String.Empty)
614 return GetClearCommandText();
616 return GetPreparedCommandText();
622 private String GetClearCommandText() {
623 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetClearCommandText");
626 String result = text;
628 if (type == CommandType.StoredProcedure)
629 if (connection.SupportsPrepare)
630 result = "select * from " + result; // This syntax is only available in 7.3+ as well SupportsPrepare.
632 result = "select " + result; // Only a single result return supported. 7.2 and earlier.
633 else if (type == CommandType.TableDirect)
634 return "select * from " + result; // There is no parameter support on table direct.
636 if (parameters.Count == 0)
642 String parameterName;
644 for (Int32 i = 0; i < parameters.Count; i++) {
645 parameterName = parameters[i].ParameterName;
647 result = ReplaceParameterValue(result, parameterName, NpgsqlTypesHelper.ConvertNpgsqlParameterToBackendStringValue(parameters[i]));
657 private String GetPreparedCommandText() {
658 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetPreparedCommandText");
660 if (parameters.Count == 0)
661 return "execute " + planName;
664 StringBuilder result = new StringBuilder("execute " + planName + '(');
667 for (Int32 i = 0; i < parameters.Count; i++) {
668 result.Append(NpgsqlTypesHelper.ConvertNpgsqlParameterToBackendStringValue(parameters[i]) + ',');
671 result = result.Remove(result.Length - 1, 1);
674 return result.ToString();
680 private String GetParseCommandText()
682 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetParseCommandText");
684 String parseCommand = text;
686 if (type == CommandType.StoredProcedure)
687 parseCommand = "select * from " + parseCommand; // This syntax is only available in 7.3+ as well SupportsPrepare.
688 else if (type == CommandType.TableDirect)
689 return "select * from " + parseCommand; // There is no parameter support on TableDirect.
691 if (parameters.Count > 0)
693 // The ReplaceParameterValue below, also checks if the parameter is present.
695 String parameterName;
698 for (i = 0; i < parameters.Count; i++)
700 //result = result.Replace(":" + parameterName, parameters[i].Value.ToString());
701 parameterName = parameters[i].ParameterName;
702 //textCommand = textCommand.Replace(':' + parameterName, "$" + (i+1));
703 parseCommand = ReplaceParameterValue(parseCommand, parameterName, "$" + (i+1));
713 private String GetPrepareCommandText() {
714 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetPrepareCommandText");
718 planName = "NpgsqlPlan" + System.Threading.Interlocked.Increment(ref planIndex);
720 StringBuilder command = new StringBuilder("prepare " + planName);
722 String textCommand = text;
724 if (type == CommandType.StoredProcedure)
725 textCommand = "select * from " + textCommand;
726 else if (type == CommandType.TableDirect)
727 return "select * from " + textCommand; // There is no parameter support on TableDirect.
730 if (parameters.Count > 0) {
731 // The ReplaceParameterValue below, also checks if the parameter is present.
733 String parameterName;
736 for (i = 0; i < parameters.Count; i++) {
737 //result = result.Replace(":" + parameterName, parameters[i].Value.ToString());
738 parameterName = parameters[i].ParameterName;
739 //textCommand = textCommand.Replace(':' + parameterName, "$" + (i+1));
740 textCommand = ReplaceParameterValue(textCommand, parameterName, "$" + (i+1));
744 //[TODO] Check if there is any missing parameters in the query.
745 // For while, an error is thrown saying about the ':' char.
749 for (i = 0; i < parameters.Count; i++) {
750 command.Append(NpgsqlTypesHelper.GetBackendTypeNameFromDbType(parameters[i].DbType));
755 command = command.Remove(command.Length - 1, 1);
760 command.Append(" as ");
761 command.Append(textCommand);
764 return command.ToString();
769 private String ReplaceParameterValue(String result, String parameterName, String paramVal) {
770 Int32 resLen = result.Length;
771 Int32 paramStart = result.IndexOf(parameterName);
772 Int32 paramLen = parameterName.Length;
773 Int32 paramEnd = paramStart + paramLen;
774 Boolean found = false;
776 while(paramStart > -1) {
777 if((resLen > paramEnd) &&
778 (result[paramEnd] == ' ' ||
779 result[paramEnd] == ',' ||
780 result[paramEnd] == ')' ||
781 result[paramEnd] == ';')) {
782 result = result.Substring(0, paramStart) + paramVal + result.Substring(paramEnd);
785 else if(resLen == paramEnd) {
786 result = result.Substring(0, paramStart)+ paramVal;
791 resLen = result.Length;
792 paramStart = result.IndexOf(parameterName, paramStart);
793 paramEnd = paramStart + paramLen;
797 throw new NpgsqlException(String.Format(resman.GetString("Exception_ParamNotInQuery"), parameterName));
800 }//ReplaceParameterValue
803 private void ExecuteCommand()
805 //if ((type == CommandType.Text) || (type == CommandType.StoredProcedure))
807 connection.Query(this);
811 connection.Execute(new NpgsqlExecute(bind.PortalName, 0));
814 throw new NotImplementedException(resman.GetString("Exception_CommandTypeTableDirect"));*/