internal DataTable[] ExecuteSql(
			InstanceInfo                    instance,
			QueryItemInfo                   sql,
			IEnumerable<QueryParameterInfo> parameters = null,
			IEnumerable<ParameterValue>     parameterValues = null
		)
		{
			bool shouldExecute = true;

			if (sql == null)
			{
				throw new Exception("There is no sql statement to execute (QueryItemInfo == null).");
			}

			// Log.InfoFormat("instance:'{0}';sql.Text:'{1}'",
			// 	instance,
			// 	sql.Text
			// );

			if (sql.ExecuteIfSqlText != null)
			{
				var clone = sql.Clone();

				clone.ExecuteIfSqlText = null;
				clone.Text             = sql.ExecuteIfSqlText;

				DataTable[] tt = ExecuteSql(
					instance,
					clone,
					parameters,
					parameterValues
				);

				if (tt.Length > 0 && tt[0].Rows.Count > 0)
				{
					shouldExecute = (int)(tt[0].Rows[0][0]) == 1;
				}
			}

			if (shouldExecute)
			{
				return this.CurrentStorage.ExecuteSql(
					sql.Text,
					parameters,
					parameterValues,
					instance
				);
			}

			return new DataTable[0];
		}
		internal DataTable[] ExecuteSql(
			InstanceInfo                    instance,
			QueryItemInfo                   sql,
			string                          database = null,
			IEnumerable<QueryParameterInfo> parameters = null,
			IEnumerable<ParameterValue>     parameterValues = null,
			ProgressItem                    progress = null,
			bool                            fromGroupSelect = false
		)
		{
			Exception       gotException    = null;
			List<DataTable> tables          = new List<DataTable>();

			this._cancellationToken.ThrowIfCancellationRequested();

			try
			{
				if (sql == null)
				{
					throw new Exception("There is no sql statement to execute (QueryItemInfo == null).");
				}

				List<Tuple<int, string>> parametersQueueForODBC;

				using (IQueryConnection connection = _queryConnectionFactory.CreateQueryConnection(sql.ParentQuery.Source, instance))
				{
					using (IQueryCommand sqlCommand = connection.GetCommand(sql.Text, this._model.Settings.SqlTimeout, parameters, out parametersQueueForODBC))
					{
						using (new TryFinally(connection.Open, connection.Close))
						{
							connection.ChangeDatabase(database);

							var shouldExecute = true;

							if (sql.ExecuteIfSqlText != null)
							{
								var clone = sql.Clone();

								clone.ExecuteIfSqlText = null;
								clone.Text             = sql.ExecuteIfSqlText;

								DataTable[] tt = ExecuteSql(
									instance,
									clone,
									database,
									parameters,
									parameterValues,
									progress,
									fromGroupSelect
								);

								if (tt.Length > 0 && tt[0].Rows.Count > 0)
								{
									shouldExecute = (int)(tt[0].Rows[0][0]) == 1;
								}
							}

							if (shouldExecute)
							{
								var executionFinishedEvent = new AutoResetEvent(false);

								IQueryCommand command = null;

								Action<IAsyncResult> handleCallback = result =>
								{
									command = (IQueryCommand)result.AsyncState;

									try
									{
										using (var reader = command.EndExecuteReader(result))
										{
											while (!reader.IsClosed)
											{
												DataTable table = new DataTable();

												table.Load(reader, LoadOption.OverwriteChanges, ExecuteSqlFillErrorHandler);
												tables.Add(table);
											}
										}
									}
									catch (Exception ex)
									{
										log.Error(ex);

										gotException = ex;

										if (fromGroupSelect)
										{
											log.ErrorFormat(
												"Instance:'{0}';Authentication:'{1}';SQL:'{2}';Exception:'{3}'",
												instance.Instance,
												instance.Authentication,
												sql,
												ex
											);
										}
									}
									finally
									{
										if (command != null)
										{
											command.Cancel();
										}

										executionFinishedEvent.Set();
									}
								};

								sqlCommand.AssignParameters(parameters, parameterValues, parametersQueueForODBC);
								var callback = new AsyncCallback(handleCallback);
								var asyncResult = sqlCommand.BeginExecuteReader(callback);

								if (WaitHandle.WaitAny(new[] { asyncResult.AsyncWaitHandle, this._cancellationToken.WaitHandle }) == 1)
								{
									if (command != null)
									{
										command.Cancel();
									}

									this._cancellationToken.ThrowIfCancellationRequested();
								}

								executionFinishedEvent.WaitOne();
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				log.Error(ex);

				if (gotException == null)
				{
					gotException = ex;

					if (fromGroupSelect)
					{
						log.ErrorFormat(
							"Instance:'{0}';Authentication:'{1}';Exception:'{2}'",
							instance.Instance,
							instance.Authentication,
							ex
						);
					}
				}
			}
			finally
			{
				if (progress != null)
				{
					progress.SetProgressDone();
				}
			}

			if (gotException != null)
			{
				if (!fromGroupSelect)
				{
					gotException.Data.Add("IgnoreLog", true);
				}

				throw gotException;
			}

			return tables.ToArray();
		}