I'm trying to dump data from Firebird SQL 2.5 database with little or no success, because I'm trying to make a join between a table and stored procedure. The code representing the problematic query is following:
select
U.SYMBOL
, '0' AS FIRM_ID
, U.DATA_OD AS DATA
, IIF(EXTRACT(DAY FROM U.DATA_OD) = 1 AND EXTRACT(MONTH FROM U.DATA_OD) = 1, 'NR', 'ZW') AS PRZYCZYNA_ZMIANY_WYM
, PS.WYMIAR AS WYMIAR
, PS.ZALEGLY AS WYM_ZAL
, ' ' AS WYMIAR_INW
, ' ' AS WYMIAR_INW_ZAL
, ' ' AS NAZWA_ABSENCJI
from
P_PRA_WYM_URL U
left JOIN PS_WYK_URLOPOW(U.SYMBOL, U.DATA_OD, U.DATA_OD) ps ON 1=1
where
U.SYMBOL IN (SELECT SYMBOL FROM P_PRACOWNIK)
The PS_WYK_URLOPOW
stored procedure accepts three parameters: employee number, and two dates. All parameters are members of the P_PRA_WYM_URL
table, so the stored procedure needs to be executed once for every record in that table. The are more than 40 000 records in that table.
I'm executing this query using following C# code:
if (AreSettingsPopulated())
{
string sFilepath = dSettings[FILEPATHKEY];
string sUsername = dSettings[USERNAMEKEY];
string sPassword = Encoding.UTF8.GetString(System.Convert.FromBase64String(dSettings[DBPASSWORDKEY]));
string connectionString =
"User={0};" +
"Password={1};" +
"Database={2};" +
"DataSource=localhost;" +
"Port=3050;" +
"Dialect=1;" +
"Charset=NONE;" +
"Role=;" +
"Connection lifetime=15;" +
"Pooling=true;" +
"MinPoolSize=0;" +
"MaxPoolSize=50;" +
"Packet Size=8192;" +
"ServerType=0";
FbConnection fbConn = null;
try
{
string sSqlQuery = "";
using (FileStream fs = new FileStream(string.Format("{0}.sql", dSettings[TABLENAMEKEY]), FileMode.Open))
{
using (StreamReader sr = new StreamReader(fs, Encoding.UTF8))
{
if (!sr.EndOfStream)
sSqlQuery = sr.ReadToEnd();
sr.Close();
}
fs.Close();
}
if (sSqlQuery != "")
{
DataTable dtDumpResults = new DataTable(dSettings[TABLENAMEKEY]);
fbConn = new FbConnection(string.Format(connectionString, sUsername, sPassword, sFilepath));
FbCommand fbcDumpCommand = new FbCommand(sSqlQuery, fbConn);
fbcDumpCommand.CommandTimeout = 90000000;
if (fbConn.State != System.Data.ConnectionState.Open)
fbConn.Open();
using (FbDataAdapter fbdaDumpCommand = new FbDataAdapter(sSqlQuery, fbConn))
{
this.engine.WriteLine("Dumping the contents from database...");
fbdaDumpCommand.Fill(dtDumpResults);
this.engine.WriteLine("Dump complete!");
}
if (dtDumpResults.Rows.Count > 0)
{
GenerateExportXlsFile(dtDumpResults, dSettings[TABLENAMEKEY]);
}
else
throw new ArgumentNullException("The result set returned null!");
}
else
throw new ArgumentNullException("The SQL query is empty!");
}
catch (Exception ex)
{
return string.Format("Error while invoking plugin: {0}", ex.ToString());
}
finally
{
if (fbConn != null && fbConn.State == System.Data.ConnectionState.Open)
fbConn.Close();
}
}
else
return "Execution failed! The settings are not populated!";
return string.Format("Export of table {0} complete!", dSettings[TABLENAMEKEY]);
}
If I try to dump the data with query shown above with Flamerobin, the pre-fetching mechanism works and loading the data every 500 records I'm able to get the complete dump, while with C# application the execution stops on fbdaDumpCommand.Fill(dtDumpResults);
step.
The question is: how to optimize the query to make it work inside C# application?