/// <summary> /// Run this Database query. /// If FReportingQueryCancelFlag is set, this returns immediately with an empty table. /// The query can be cancelled WHILE IT IS RUNNING. In this case the returned table may be partially filled. /// </summary> /// <returns>DataTable. May be empty (even with no fields defined!) if cancellation happens or has happened.</returns> public DataTable RunQuery(String Query, String TableName, TDBTransaction Trans) { var ResultDT = new DataTable(TableName); if (!FCancelFlag) { try { FRunningQuery = true; FPrivateDatabaseObj.SelectUsingDataAdapter(Query, Trans, ref ResultDT, out FDataAdapterCanceller); } catch (NpgsqlException Exp) { if (Exp.Code == "57014") // Exception with Code 57014 is what Npgsql raises as a response to a Cancel request of a Command { TLogging.LogAtLevel(7, this.GetType().FullName + ".RunQuery: Query got cancelled; proper reply from Npgsql!"); } else if (Exp.Code == "25P02") // Exception with Code 25P02 is what Npgsql raises as a response to a cancellation of a request of a Command when that happens in another code path (eg. on a different Thread [e.g. Partner Find { // screen: Cancel got pressed while Report Query ran, for instance]) TLogging.LogAtLevel(1, this.GetType().FullName + ".RunQuery: Query got cancelled (likely trought another code path [likely on another Thread]); proper reply from Npgsql!"); } else { TLogging.Log(this.GetType().FullName + ".RunQuery: Query got cancelled; general NpgsqlException occured: " + Exp.ToString()); } FCancelFlag = true; return(null); } catch (Exception Exc) { TLogging.Log("ReportingQueryWithCancelOption: Query Raised exception: " + Exc.ToString() + "\nQuery: " + Query); FRunQueryException = Exc; FCancelFlag = true; /* * WE MUST 'SWALLOW' ANY EXCEPTION HERE, OTHERWISE THE WHOLE * PETRASERVER WILL GO DOWN!!! (THIS BEHAVIOUR IS NEW WITH .NET 2.0.) * * --> ANY EXCEPTION THAT WOULD LEAVE THIS METHOD WOULD BE SEEN AS AN <-- * --> UNHANDLED EXCEPTION IN A THREAD, AND THE .NET/MONO RUNTIME <-- * --> WOULD BRING DOWN THE WHOLE PETRASERVER PROCESS AS A CONSEQUENCE. <-- * */ } finally { FRunningQuery = false; } } return(ResultDT); }