Skip to content

Commit 912274e

Browse files
committed
Support for isc_info_sql_explain_plan (DNET-864).
1 parent 0c9d26e commit 912274e

File tree

4 files changed

+108
-36
lines changed

4 files changed

+108
-36
lines changed

Provider/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,35 @@ public void CommandCancellationTest()
738738
}
739739
}
740740

741+
[Test]
742+
public void CommandPlanTest()
743+
{
744+
using (var cmd = Connection.CreateCommand())
745+
{
746+
cmd.CommandText = "select * from test";
747+
cmd.Prepare();
748+
var plan = default(string);
749+
Assert.DoesNotThrow(() => { plan = cmd.CommandPlan; });
750+
Assert.IsNotEmpty(plan);
751+
}
752+
}
753+
754+
[Test]
755+
public void CommandExplainedPlanTest()
756+
{
757+
if (!EnsureVersion(new Version(3, 0, 0, 0)))
758+
return;
759+
760+
using (var cmd = Connection.CreateCommand())
761+
{
762+
cmd.CommandText = "select * from test";
763+
cmd.Prepare();
764+
var plan = default(string);
765+
Assert.DoesNotThrow(() => { plan = cmd.CommandExplainedPlan; });
766+
Assert.IsNotEmpty(plan);
767+
}
768+
}
769+
741770
[Test]
742771
public void NoCommandPlanTest()
743772
{
@@ -751,6 +780,22 @@ public void NoCommandPlanTest()
751780
}
752781
}
753782

783+
[Test]
784+
public void NoCommandExplainedPlanTest()
785+
{
786+
if (!EnsureVersion(new Version(3, 0, 0, 0)))
787+
return;
788+
789+
using (var cmd = Connection.CreateCommand())
790+
{
791+
cmd.CommandText = "recreate table NoCommandPlanTest (id int)";
792+
cmd.Prepare();
793+
var plan = default(string);
794+
Assert.DoesNotThrow(() => { plan = cmd.CommandExplainedPlan; });
795+
Assert.IsEmpty(plan);
796+
}
797+
}
798+
754799
[Test]
755800
public void ReadsTimeWithProperPrecision()
756801
{

Provider/src/FirebirdSql.Data.FirebirdClient/Common/IscCodes.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,8 @@ internal static class IscCodes
606606
public const int isc_info_sql_records = 23;
607607
public const int isc_info_sql_batch_fetch = 24;
608608
public const int isc_info_sql_relation_alias = 25;
609+
public const int isc_info_sql_explain_plan = 26;
610+
public const int isc_info_sql_stmt_flags = 27;
609611

610612
#endregion
611613

Provider/src/FirebirdSql.Data.FirebirdClient/Common/StatementBase.cs

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,21 @@ internal abstract class StatementBase : IDisposable
2626
{
2727
#region Protected Static Fields
2828

29-
// Plan information items
3029
protected static readonly byte[] DescribePlanInfoItems = new byte[]
3130
{
32-
IscCodes.isc_info_sql_get_plan
31+
IscCodes.isc_info_sql_get_plan,
32+
};
33+
34+
protected static readonly byte[] DescribeExplaindPlanInfoItems = new byte[]
35+
{
36+
IscCodes.isc_info_sql_explain_plan,
3337
};
3438

35-
// Records affected items
3639
protected static readonly byte[] RowsAffectedInfoItems = new byte[]
3740
{
38-
IscCodes.isc_info_sql_records
41+
IscCodes.isc_info_sql_records,
3942
};
4043

41-
// Describe information items
4244
protected static readonly byte[] DescribeInfoAndBindInfoItems = new byte[]
4345
{
4446
IscCodes.isc_info_sql_select,
@@ -65,12 +67,12 @@ internal abstract class StatementBase : IDisposable
6567
IscCodes.isc_info_sql_relation,
6668
// IscCodes.isc_info_sql_owner,
6769
IscCodes.isc_info_sql_alias,
68-
IscCodes.isc_info_sql_describe_end
70+
IscCodes.isc_info_sql_describe_end,
6971
};
7072

7173
protected static readonly byte[] StatementTypeInfoItems = new byte[]
7274
{
73-
IscCodes.isc_info_sql_stmt_type
75+
IscCodes.isc_info_sql_stmt_type,
7476
};
7577

7678
#endregion
@@ -107,36 +109,12 @@ public virtual void Dispose()
107109

108110
public string GetExecutionPlan()
109111
{
110-
var count = 0;
111-
var bufferSize = IscCodes.DEFAULT_MAX_BUFFER_SIZE;
112-
var buffer = GetSqlInfo(DescribePlanInfoItems, bufferSize);
113-
114-
if (buffer[0] == IscCodes.isc_info_end)
115-
{
116-
return string.Empty;
117-
}
118-
119-
while (buffer[0] == IscCodes.isc_info_truncated && count < 4)
120-
{
121-
bufferSize *= 2;
122-
buffer = GetSqlInfo(DescribePlanInfoItems, bufferSize);
123-
count++;
124-
}
125-
if (count > 3)
126-
{
127-
return null;
128-
}
112+
return GetPlanInfo(DescribePlanInfoItems);
113+
}
129114

130-
int len = buffer[1];
131-
len += buffer[2] << 8;
132-
if (len > 0)
133-
{
134-
return Database.Charset.GetString(buffer, 4, --len);
135-
}
136-
else
137-
{
138-
return string.Empty;
139-
}
115+
public string GetExecutionExplainedPlan()
116+
{
117+
return GetPlanInfo(DescribeExplaindPlanInfoItems);
140118
}
141119

142120
public virtual void Close()
@@ -328,6 +306,40 @@ protected void ClearArrayHandles()
328306
}
329307
}
330308

309+
protected string GetPlanInfo(byte[] planInfoItems)
310+
{
311+
var count = 0;
312+
var bufferSize = IscCodes.DEFAULT_MAX_BUFFER_SIZE;
313+
var buffer = GetSqlInfo(planInfoItems, bufferSize);
314+
315+
if (buffer[0] == IscCodes.isc_info_end)
316+
{
317+
return string.Empty;
318+
}
319+
320+
while (buffer[0] == IscCodes.isc_info_truncated && count < 4)
321+
{
322+
bufferSize *= 2;
323+
buffer = GetSqlInfo(planInfoItems, bufferSize);
324+
count++;
325+
}
326+
if (count > 3)
327+
{
328+
return null;
329+
}
330+
331+
int len = buffer[1];
332+
len += buffer[2] << 8;
333+
if (len > 0)
334+
{
335+
return Database.Charset.GetString(buffer, 4, --len);
336+
}
337+
else
338+
{
339+
return string.Empty;
340+
}
341+
}
342+
331343
#endregion
332344
}
333345
}

Provider/src/FirebirdSql.Data.FirebirdClient/FirebirdClient/FbCommand.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,19 @@ public string CommandPlan
110110
}
111111
}
112112

113+
[Browsable(false)]
114+
public string CommandExplainedPlan
115+
{
116+
get
117+
{
118+
if (_statement != null)
119+
{
120+
return _statement.GetExecutionExplainedPlan();
121+
}
122+
return null;
123+
}
124+
}
125+
113126
[Category("Behavior")]
114127
[DefaultValue(null)]
115128
public new FbConnection Connection

0 commit comments

Comments
 (0)