/*
 *	PROGRAM:		Firebird interface.
 *	MODULE:			firebird/Interface.idl
 *	DESCRIPTION:	Collection of interfaces used by FB to talk with outer world.
 *
 *  The contents of this file are subject to the Initial
 *  Developer's Public License Version 1.0 (the "License");
 *  you may not use this file except in compliance with the
 *  License. You may obtain a copy of the License at
 *  http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
 *
 *  Software distributed under the License is distributed AS IS,
 *  WITHOUT WARRANTY OF ANY KIND, either express or implied.
 *  See the License for the specific language governing rights
 *  and limitations under the License.
 *
 *  The Original Code was created by Alex Peshkov
 *  for the Firebird Open Source RDBMS project.
 *
 *  Copyright (c) 2010 Alex Peshkov <peshkoff at mail.ru>
 *  and all contributors signed below.
 *
 *  All Rights Reserved.
 *  Contributor(s): ______________________________________.
 *
 *
 */

typedef ISC_DATE;
typedef ISC_QUAD;
typedef ISC_TIME;
typedef ISC_TIMESTAMP;
typedef ISC_TIME_TZ;
typedef ISC_TIMESTAMP_TZ;
typedef ISC_TIME_TZ_EX;
typedef ISC_TIMESTAMP_TZ_EX;
typedef FB_DEC16;
typedef FB_DEC34;
typedef FB_I128;

boolean FB_UsedInYValve;

// Versioned interface - base for all FB interfaces
interface Versioned
{
}

// Reference counted interface - base for refCounted FB interfaces
interface ReferenceCounted : Versioned
{
	void addRef();
	int release();
}

// Disposable interface - base for disposable FB interfaces
interface Disposable : Versioned
{
	void dispose();
}

// Interface to work with status vector
[exception]
interface Status : Disposable
{
	// flags in value returned by getState()
	const uint STATE_WARNINGS	= 0x01;
	const uint STATE_ERRORS 	= 0x02;

	// completion codes - not used in Status, but I must have them somewhere
	const int RESULT_ERROR = -1;
	const int RESULT_OK = 0;
	const int RESULT_NO_DATA = 1;
	const int RESULT_SEGMENT = 2;

	void init();
	uint getState() const;

	void setErrors2(uint length, const intptr* value);
	void setWarnings2(uint length, const intptr* value);
	void setErrors(const intptr* value);
	void setWarnings(const intptr* value);

	[onError stubError]
	const intptr* getErrors() const;
	[onError stubError]
	const intptr* getWarnings() const;

	Status clone() const;
}

// Master interface is used to access almost all other interfaces.
interface Master : Versioned
{
	Status getStatus();
	Provider getDispatcher();
	PluginManager getPluginManager();
	TimerControl getTimerControl();
	Dtc getDtc();
	Attachment registerAttachment(Provider provider, Attachment attachment);
	Transaction registerTransaction(Attachment attachment, Transaction transaction);

	MetadataBuilder getMetadataBuilder(Status status, uint fieldCount);
	int serverMode(int mode);
	Util getUtilInterface();
	ConfigManager getConfigManager();
	boolean getProcessExiting();
}


/*
 * Firebird plugins are accessed using methods of PluginLoader interface.
 * For each plugin_module tag found, it constructs a Plugin object, reads the corresponding
 * plugin_config tag and inserts all config information in the object.
 *
 * When requested, the engine gets the attribute value of plugin_module/filename, load it as a
 * dynamic (shared) library and calls the exported function firebirdPlugin (FB_PLUGIN_ENTRY_POINT
 * definition, PluginEntrypoint prototype) passing the Plugin object as parameter.
 *
 * The plugin library may save the plugin object and call they methods later. The object and all
 * pointers returned by it are valid until the plugin is unloaded (done through OS unload of the
 * dynamic library) when Firebird is shutting down.
 *
 * Inside the plugin entry point (firebirdPlugin), the plugin may register extra functionality that
 * may be obtained by Firebird when required. Currently only External Engines may be registered
 * through Plugin::setExternalEngineFactory.
 *
 * Example plugin configuration file:
 *
 * <external_engine UDR>
 *     plugin_module UDR_engine
 * </external_engine>
 *
 * <plugin_module UDR_engine>
 *     filename $(this)/udr_engine
 *     plugin_config UDR_config
 * </plugin_module>
 *
 * <plugin_config UDR_config>
 *     path $(this)/udr
 * </plugin_config>
 *
 * Note that the external_engine tag is ignored at this stage. Only plugin_module and plugin_config
 * are read. The dynamic library extension may be ommitted, and $(this) expands to the directory of
 * the .conf file.
 *
 * Plugins may access Firebird API through the fbclient library.
 */

// IPluginBase interface - base for master plugin interfaces (factories are registered for them)
interface PluginBase : ReferenceCounted
{
	// Additional (compared with Interface) functions getOwner() and setOwner()
	// are needed to release() owner of the plugin. This is done in releasePlugin()
	// function in PluginManager. Such method is needed to make sure that owner is released
	// after plugin itself, and therefore module is unloaded after release of last plugin from it.
	// Releasing owner from release() of plugin will unload module and after returning control
	// to missing code segfault is unavoidable.
	void setOwner(ReferenceCounted r);
	ReferenceCounted getOwner();
}

// PluginSet - low level tool to access plugins according to parameter from firebird.conf
interface PluginSet : ReferenceCounted
{
	const string getName() const;
	const string getModuleName() const;
	PluginBase getPlugin(Status status);
	void next(Status status);
	void set(Status status, const string s);
}

// Entry in configuration file
interface ConfigEntry : ReferenceCounted
{
	const string getName();
	const string getValue();
	int64 getIntValue();
	boolean getBoolValue();
	Config getSubConfig(Status status);
}

// Generic form of access to configuration file - find specific entry in it
interface Config : ReferenceCounted
{
	ConfigEntry find(Status status, const string name);
	ConfigEntry findValue(Status status, const string name, const string value);
	ConfigEntry findPos(Status status, const string name, uint pos);
}

// Used to access config values from firebird.conf (may be DB specific)
interface FirebirdConf : ReferenceCounted
{
	// Get integer key by it's name
	// Value ~0 means name is invalid
	// Keys are stable: one can use once obtained key in other instances of this interface
	// provided they have same minor version (upper 16 bits match with getVersion())
	uint getKey(const string name);
	// Use to access integer values
	int64 asInteger(uint key);
	// Use to access string values
	const string asString(uint key);
	// Use to access boolean values
	boolean asBoolean(uint key);
version:		// 3.0 => 4.0
	// Use to access version of configuration manager serving this interface
	// Format: major byte, minor byte, buildno 2-byte
	uint getVersion(Status status);
}

// This interface is passed to plugin's factory as it's single parameter
// and contains methods to access specific plugin's configuration data
interface PluginConfig : ReferenceCounted
{
	const string getConfigFileName();
	Config getDefaultConfig(Status status);
	FirebirdConf getFirebirdConf(Status status);
	void setReleaseDelay(Status status, uint64 microSeconds);
}

// Required to creat instances of given plugin
interface PluginFactory : Versioned
{
	PluginBase createPlugin(Status status, PluginConfig factoryParameter);
}

// Required to let plugins manager invoke module's cleanup routine before unloading it.
// For some OS/compiler this may be done in dtor of global variable in module itself.
// Others (Windows/VC) fail to create some very useful resources (threads) when module is unloading.
interface PluginModule : Versioned
{
	void doClean();

version:		// 3.0.3 => 3.0.4
	// Used to release resources allocated per-thread
	void threadDetach();
}

// Interface to deal with plugins here and there, returned by master interface
interface PluginManager : Versioned
{
	// Plugin types
	const uint TYPE_PROVIDER = 1;
	const uint TYPE_FIRST_NON_LIB = 2;
	const uint TYPE_AUTH_SERVER = 3;
	const uint TYPE_AUTH_CLIENT = 4;
	const uint TYPE_AUTH_USER_MANAGEMENT = 5;
	const uint TYPE_EXTERNAL_ENGINE = 6;
	const uint TYPE_TRACE = 7;
	const uint TYPE_WIRE_CRYPT = 8;
	const uint TYPE_DB_CRYPT = 9;
	const uint TYPE_KEY_HOLDER = 10;
	const uint TYPE_REPLICATOR = 11;
	const uint TYPE_PROFILER = 12;
	const uint TYPE_COUNT = 13;	// keep in sync
	//// TYPE_COUNT is not count. And these constants starts from 1, different than DIR_* ones.

	// Main function called by plugin modules in firebird_plugin()
	void registerPluginFactory(uint pluginType, const string defaultName, PluginFactory factory);
	// Sets cleanup for plugin module
	// Pay attention - this should be called at plugin-register time!
	// Only at this moment manager knows, which module sets his cleanup
	void registerModule(PluginModule cleanup);
	// Remove registered module before cleanup routine.
	// This method must be called by module which detects that it's unloaded,
	// but not notified prior to it by PluginManager via PluginModule.
	void unregisterModule(PluginModule cleanup);
	// Main function called to access plugins registered in plugins manager
	// Has front-end in GetPlugins.h - template GetPlugins
	// In namesList parameter comma or space separated list of names of configured plugins is passed
	// in case when plugin's version is less than desired
	// If caller already has an interface for firebird.conf, it may be passed here
	// If parameter is missing, plugins will get access to default (non database specific) config
	PluginSet getPlugins(Status status, uint pluginType,
						const string namesList, FirebirdConf firebirdConf);
	// Get generic config interface for given file
	Config getConfig(Status status, const string filename);
	// Plugins must be released using this function - use of plugin's release()
	// will cause resources leak
	void releasePlugin(PluginBase plugin);
}


// Helper interface to pass wire crypt key from authentication to crypt plugin
interface CryptKey : Versioned
{
	// In 2 following methods NULL type means auth plugin's name is used as key type
	void setSymmetric(Status status, const string type, uint keyLength, const void* key);
	void setAsymmetric(Status status, const string type, uint encryptKeyLength,
		const void* encryptKey, uint decryptKeyLength, const void* decryptKey);

	const void* getEncryptKey(uint* length);
	const void* getDecryptKey(uint* length);
}


// Generic access to all config interfaces
interface ConfigManager : Versioned
{
	// Codes for ConfigManager::getDirectory()
	const uint DIR_BIN = 0;
	const uint DIR_SBIN = 1;
	const uint DIR_CONF = 2;
	const uint DIR_LIB = 3;
	const uint DIR_INC = 4;
	const uint DIR_DOC = 5;
	const uint DIR_UDF = 6;
	const uint DIR_SAMPLE = 7;
	const uint DIR_SAMPLEDB = 8;
	const uint DIR_HELP = 9;
	const uint DIR_INTL = 10;
	const uint DIR_MISC = 11;
	const uint DIR_SECDB = 12;
	const uint DIR_MSG = 13;
	const uint DIR_LOG = 14;
	const uint DIR_GUARD = 15;
	const uint DIR_PLUGINS = 16;
	const uint DIR_TZDATA = 17;
	const uint DIR_COUNT = 18;	// keep in sync

	const string getDirectory(uint code);
	FirebirdConf getFirebirdConf();
	FirebirdConf getDatabaseConf(const string dbName);
	Config getPluginConfig(const string configuredPlugin);
	const string getInstallDirectory();
	const string getRootDirectory();

version:		// 3.0 => 4.0
	const string getDefaultSecurityDb();
}


// Provider interface - how we talk to databases
// This interfaces are implemented by yvalve code and by each of providers.

interface EventCallback : ReferenceCounted
{
	// eventCallbackFunction is missing error status cause it's always called from places
	// where an ability to report an error to the user is missing
	void eventCallbackFunction(uint length, const uchar* events);
}

interface Blob : ReferenceCounted
{
	void getInfo(Status status,
						 uint itemsLength, const uchar* items,
						 uint bufferLength, uchar* buffer);

	[notImplemented(Status::RESULT_ERROR)]
	int getSegment(Status status, uint bufferLength, void* buffer, uint* segmentLength);

	void putSegment(Status status, uint length,
									const void* buffer);
	void deprecatedCancel(Status status);
	void deprecatedClose(Status status);
	int seek(Status status, int mode, int offset);			// returns position

version:	// 3.0.7 => 3.0.8, 4.0.0 => 4.0.1
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedCancel(status) endif]
	void cancel(Status status);
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedClose(status) endif]
	void close(Status status);
}

interface Transaction : ReferenceCounted
{
	void getInfo(Status status,
						 uint itemsLength, const uchar* items,
						 uint bufferLength, uchar* buffer);
	void prepare(Status status,
						 uint msgLength, const uchar* message);
	void deprecatedCommit(Status status);
	void commitRetaining(Status status);
	void deprecatedRollback(Status status);
	void rollbackRetaining(Status status);
	void deprecatedDisconnect(Status status);
	Transaction join(Status status, Transaction transaction);
	Transaction validate(Status status, Attachment attachment);
	Transaction enterDtc(Status status);

version:	// 3.0.7 => 3.0.8, 4.0.0 => 4.0.1
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedCommit(status) endif]
	void commit(Status status);
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedRollback(status) endif]
	void rollback(Status status);
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedDisconnect(status) endif]
	void disconnect(Status status);
}

interface MessageMetadata : ReferenceCounted
{
	uint getCount(Status status);
	const string getField(Status status, uint index);
	const string getRelation(Status status, uint index);
	const string getOwner(Status status, uint index);
	const string getAlias(Status status, uint index);
	uint getType(Status status, uint index);
	boolean isNullable(Status status, uint index);
	int getSubType(Status status, uint index);
	uint getLength(Status status, uint index);
	int getScale(Status status, uint index);
	uint getCharSet(Status status, uint index);
	uint getOffset(Status status, uint index);
	uint getNullOffset(Status status, uint index);

	MetadataBuilder getBuilder(Status status);
	uint getMessageLength(Status status);

version:	// 3.0 => 4.0
	uint getAlignment(Status status);
	uint getAlignedLength(Status status);
}

interface MetadataBuilder : ReferenceCounted
{
	void setType(Status status, uint index, uint type);
	void setSubType(Status status, uint index, int subType);
	void setLength(Status status, uint index, uint length);
	void setCharSet(Status status, uint index, uint charSet);
	void setScale(Status status, uint index, int scale);

	void truncate(Status status, uint count);
	void moveNameToIndex(Status status, const string name, uint index);
	void remove(Status status, uint index);
	uint addField(Status status);

	MessageMetadata getMetadata(Status status);

version:	// 3.0 => 4.0
	void setField(Status status, uint index, const string field);
	void setRelation(Status status, uint index, const string relation);
	void setOwner(Status status, uint index, const string owner);
	void setAlias(Status status, uint index, const string alias);
}

interface ResultSet : ReferenceCounted
{
	// Info items
	const uchar INF_RECORD_COUNT = 10;		// Number of records in the result set

	[notImplemented(Status::RESULT_ERROR)] int fetchNext(Status status, void* message);
	[notImplemented(Status::RESULT_ERROR)] int fetchPrior(Status status, void* message);
	[notImplemented(Status::RESULT_ERROR)] int fetchFirst(Status status, void* message);
	[notImplemented(Status::RESULT_ERROR)] int fetchLast(Status status, void* message);
	[notImplemented(Status::RESULT_ERROR)] int fetchAbsolute(Status status, int position, void* message);
	[notImplemented(Status::RESULT_ERROR)] int fetchRelative(Status status, int offset, void* message);
	boolean isEof(Status status);
	boolean isBof(Status status);
	MessageMetadata getMetadata(Status status);
	void deprecatedClose(Status status);

	// This item is for ISC API emulation only
	// It may be gone in future versions
	// Please do not use it!
	void setDelayedOutputFormat(Status status, MessageMetadata format);

version:	// 3.0.7 => 3.0.8, 4.0.0 => 4.0.1
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedClose(status) endif]
	void close(Status status);

version:	// 4.0.1 => 5.0
	void getInfo(Status status,
				 uint itemsLength, const uchar* items,
				 uint bufferLength, uchar* buffer);
}

interface Statement : ReferenceCounted
{
	// Prepare flags.
	const uint PREPARE_PREFETCH_NONE 				= 0x00;
	const uint PREPARE_PREFETCH_TYPE 				= 0x01;
	const uint PREPARE_PREFETCH_INPUT_PARAMETERS 	= 0x02;
	const uint PREPARE_PREFETCH_OUTPUT_PARAMETERS	= 0x04;
	const uint PREPARE_PREFETCH_LEGACY_PLAN			= 0x08;
	const uint PREPARE_PREFETCH_DETAILED_PLAN		= 0x10;
	const uint PREPARE_PREFETCH_AFFECTED_RECORDS	= 0x20;	// not used yet
	const uint PREPARE_PREFETCH_FLAGS				= 0x40;
	const uint PREPARE_PREFETCH_METADATA =
		PREPARE_PREFETCH_TYPE | PREPARE_PREFETCH_FLAGS |
		PREPARE_PREFETCH_INPUT_PARAMETERS | PREPARE_PREFETCH_OUTPUT_PARAMETERS;
	const uint PREPARE_PREFETCH_ALL =
		PREPARE_PREFETCH_METADATA | PREPARE_PREFETCH_LEGACY_PLAN | PREPARE_PREFETCH_DETAILED_PLAN |
		PREPARE_PREFETCH_AFFECTED_RECORDS;

	// Statement flags.
	const uint FLAG_HAS_CURSOR	 					= 0x01;
	const uint FLAG_REPEAT_EXECUTE				 	= 0x02;

	// Cursor flags.
	const uint CURSOR_TYPE_SCROLLABLE 				= 0x01;

	void getInfo(Status status,
								 uint itemsLength, const uchar* items,
								 uint bufferLength, uchar* buffer);
	uint getType(Status status);
	const string getPlan(Status status, boolean detailed);
	uint64 getAffectedRecords(Status status);
	MessageMetadata getInputMetadata(Status status);
	MessageMetadata getOutputMetadata(Status status);
	Transaction execute(Status status, Transaction transaction,
		MessageMetadata inMetadata, void* inBuffer, MessageMetadata outMetadata, void* outBuffer);
	ResultSet openCursor(Status status, Transaction transaction,
		MessageMetadata inMetadata, void* inBuffer, MessageMetadata outMetadata, uint flags);
	void setCursorName(Status status, const string name);
	void deprecatedFree(Status status);
	uint getFlags(Status status);

version:	// 3.0 => 4.0
	// Statement execution timeout, milliseconds
	uint getTimeout(Status status);
	void setTimeout(Status status, uint timeOut);

	// Batch API
	Batch createBatch(Status status, MessageMetadata inMetadata, uint parLength, const uchar* par);

	/*
	Pipe createPipe(Status status, Transaction transaction, MessageMetadata inMetadata,
		void* inBuffer, MessageMetadata outMetadata, uint parLength, const uchar* par);
	*/

version:	// 3.0.7 => 3.0.8, 4.0.0 => 4.0.1
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedFree(status) endif]
	void free(Status status);

version:	// 5.0.3, 6.0
	// Inline blob transfer
	uint getMaxInlineBlobSize(Status status);
	void setMaxInlineBlobSize(Status status, uint size);
}

interface Batch : ReferenceCounted
{
	const uchar VERSION1 = 1;				// Tag for parameters block
	const uchar CURRENT_VERSION = VERSION1;

	// Tags for parameters
	const uchar TAG_MULTIERROR = 1;			// Can have >1 buffers with errors
	const uchar TAG_RECORD_COUNTS = 2;		// Per-record modified records accountung
	const uchar TAG_BUFFER_BYTES_SIZE = 3;	// Maximum possible buffer size
	const uchar TAG_BLOB_POLICY = 4;		// What policy is used to store blobs
	const uchar TAG_DETAILED_ERRORS = 5;	// How many vectors with detailed error info are stored

	// Info items
	const uchar INF_BUFFER_BYTES_SIZE = 10;	// Maximum possible buffer size
	const uchar INF_DATA_BYTES_SIZE = 11;	// Already added messages size
	const uchar INF_BLOBS_BYTES_SIZE = 12;	// Already added blobs size
	const uchar INF_BLOB_ALIGNMENT = 13;	// Duplicate getBlobAlignment
	const uchar INF_BLOB_HEADER = 14;		// Blob header size

	// How should batch work with blobs
	const uchar BLOB_NONE = 0;				// Blobs can't be used
	const uchar BLOB_ID_ENGINE = 1;			// Blobs are added one by one, IDs are generated by firebird
	const uchar BLOB_ID_USER = 2;			// Blobs are added one by one, IDs are generated by user
	const uchar BLOB_STREAM = 3;			// Blobs are added in a stream, IDs are generated by user

	// Blob stream
	const uint BLOB_SEGHDR_ALIGN = 2;		// Alignment of segment header in the blob stream

	void add(Status status, uint count, const void* inBuffer);
	void addBlob(Status status, uint length, const void* inBuffer, ISC_QUAD* blobId, uint parLength, const uchar* par);
	void appendBlobData(Status status, uint length, const void* inBuffer);
	void addBlobStream(Status status, uint length, const void* inBuffer);
	void registerBlob(Status status, const ISC_QUAD* existingBlob, ISC_QUAD* blobId);
	BatchCompletionState execute(Status status, Transaction transaction);
	void cancel(Status status);
	uint getBlobAlignment(Status status);
	MessageMetadata getMetadata(Status status);
	void setDefaultBpb(Status status, uint parLength, const uchar* par);
	void deprecatedClose(Status status);

version:	// 4.0.0 => 4.0.1
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedClose(status) endif]
	void close(Status status);
	void getInfo(Status status,
				 uint itemsLength, const uchar* items,
				 uint bufferLength, uchar* buffer);
}

interface BatchCompletionState : Disposable
{
	const int EXECUTE_FAILED = -1;				// Error happened when processing record
	const int SUCCESS_NO_INFO = -2;				// Record update info was not collected
	const uint NO_MORE_ERRORS = 0xFFFFFFFF;		// Special value returned by findError()

	uint getSize(Status status);
	int getState(Status status, uint pos);
	uint findError(Status status, uint pos);
	void getStatus(Status status, Status to, uint pos);
}

/*
interface Pipe : ReferenceCounted
{
	uint add(Status status, uint count, void* inBuffer);
	uint fetch(Status status, uint count, void* outBuffer);
	void close(Status status);
}
*/
/*
interface ReplicationBatch : Versioned
{
	void process(Status status, ReplicationSession replicator);
	const string getDatabaseID();
	uint64 getTransactionID();
	ISC_TIMESTAMP getTimestamp();
}
*/
interface Replicator : ReferenceCounted
{
/*
	void process(Status status, ReplicationBatch batch);
*/
	void process(Status status, uint length, const uchar* data);
	void deprecatedClose(Status status);

version:	// 4.0.0 => 4.0.1
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedClose(status) endif]
	void close(Status status);
}

interface Request : ReferenceCounted
{
	void receive(Status status, int level, uint msgType,
						 uint length, void* message);
	void send(Status status, int level, uint msgType,
					  uint length, const void* message);
	void getInfo(Status status, int level,
						 uint itemsLength, const uchar* items,
						 uint bufferLength, uchar* buffer);
	void start(Status status, Transaction tra, int level);
	void startAndSend(Status status, Transaction tra, int level, uint msgType,
							  uint length, const void* message);
	void unwind(Status status, int level);
	void deprecatedFree(Status status);

version:	// 3.0.7 => 3.0.8, 4.0.0 => 4.0.1
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedFree(status) endif]
	void free(Status status);
}

interface Events : ReferenceCounted
{
	void deprecatedCancel(Status status);

version:	// 3.0.7 => 3.0.8, 4.0.0 => 4.0.1
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedCancel(status) endif]
	void cancel(Status status);
}

interface Attachment : ReferenceCounted
{
	void getInfo(Status status,
						 uint itemsLength, const uchar* items,
						 uint bufferLength, uchar* buffer);
	Transaction startTransaction(Status status,
		uint tpbLength, const uchar* tpb);
	Transaction reconnectTransaction(Status status,
		uint length, const uchar* id);
	Request compileRequest(Status status,
		uint blrLength, const uchar* blr);
	void transactRequest(Status status, Transaction transaction,
								 uint blrLength, const uchar* blr,
								 uint inMsgLength, const uchar* inMsg,
								 uint outMsgLength, uchar* outMsg);
	Blob createBlob(Status status, Transaction transaction, ISC_QUAD* id,
							 uint bpbLength, const uchar* bpb);
	Blob openBlob(Status status, Transaction transaction, ISC_QUAD* id,
						   uint bpbLength, const uchar* bpb);
	int getSlice(Status status, Transaction transaction, ISC_QUAD* id,
						 uint sdlLength, const uchar* sdl,
						 uint paramLength, const uchar* param,
						 int sliceLength, uchar* slice);
	void putSlice(Status status, Transaction transaction, ISC_QUAD* id,
						  uint sdlLength, const uchar* sdl,
						  uint paramLength, const uchar* param,
						  int sliceLength, uchar* slice);
	void executeDyn(Status status, Transaction transaction, uint length,
		const uchar* dyn);
	Statement prepare(Status status, Transaction tra,
		uint stmtLength, const string sqlStmt, uint dialect, uint flags);
	Transaction execute(Status status, Transaction transaction,
		uint stmtLength, const string sqlStmt, uint dialect,
		MessageMetadata inMetadata, void* inBuffer, MessageMetadata outMetadata, void* outBuffer);
	ResultSet openCursor(Status status, Transaction transaction,
		uint stmtLength, const string sqlStmt, uint dialect,
		MessageMetadata inMetadata, void* inBuffer, MessageMetadata outMetadata,
		const string cursorName, uint cursorFlags);
	Events queEvents(Status status, EventCallback callback,
						   uint length, const uchar* events);
	void cancelOperation(Status status, int option);
	void ping(Status status);
	void deprecatedDetach(Status status);
	void deprecatedDropDatabase(Status status);

version:	// 3.0 => 4.0
	// Idle attachment timeout, seconds
	uint getIdleTimeout(Status status);
	void setIdleTimeout(Status status, uint timeOut);

	// Statement execution timeout, milliseconds
	uint getStatementTimeout(Status status);
	void setStatementTimeout(Status status, uint timeOut);

	// Batch API
	Batch createBatch(Status status, Transaction transaction, uint stmtLength, const string sqlStmt,
		uint dialect, MessageMetadata inMetadata, uint parLength, const uchar* par);

	/*
	Pipe createPipe(Status status, uint stmtLength, const string sqlStmt, uint dialect,
		Transaction transaction, MessageMetadata inMetadata, void* inBuffer,
		MessageMetadata outMetadata, uint parLength, const uchar* par);
	*/

	Replicator createReplicator(Status status);

version:	// 3.0.7 => 3.0.8, 4.0.0 => 4.0.1
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedDetach(status) endif]
	void detach(Status status);
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedDropDatabase(status) endif]
	void dropDatabase(Status status);

version:	// 5.0.3, 6.0
	// Blob caching by client
	uint getMaxBlobCacheSize(Status status);
	void setMaxBlobCacheSize(Status status, uint size);

	// Inline blob transfer
	uint getMaxInlineBlobSize(Status status);
	void setMaxInlineBlobSize(Status status, uint size);
}

interface Service : ReferenceCounted
{
	void deprecatedDetach(Status status);
	void query(Status status,
					   uint sendLength, const uchar* sendItems,
					   uint receiveLength, const uchar* receiveItems,
					   uint bufferLength, uchar* buffer);
	void start(Status status,
					   uint spbLength, const uchar* spb);

version:	// 3.0.7 => 3.0.8, 4.0.0 => 4.0.1
	[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedDetach(status) endif]
	void detach(Status status);

version:	// 3.0.9 => 3.0.10, 4.0.1 => 4.0.2
	void cancel(Status status);
}

interface Provider : PluginBase
{
	Attachment attachDatabase(Status status, const string fileName,
		uint dpbLength, const uchar* dpb);
	Attachment createDatabase(Status status, const string fileName,
		uint dpbLength, const uchar* dpb);
	Service attachServiceManager(Status status, const string service,
		 uint spbLength, const uchar* spb);
	void shutdown(Status status, uint timeout, const int reason);
	void setDbCryptCallback(Status status, CryptKeyCallback cryptCallback);
}

// Helper to start transaction over >1 attachments (former TEB)
interface DtcStart : Disposable
{
	void addAttachment(Status status, Attachment att);
	void addWithTpb(Status status, Attachment att, uint length, const uchar* tpb);
	Transaction start(Status status);	// successfull call disposes interfaces
}

// Distributed transactions coordinator
interface Dtc : Versioned
{
	Transaction join(Status status, Transaction one, Transaction two);
	DtcStart startBuilder(Status status);
}


// Interfaces, used by authentication plugins

interface Auth : PluginBase
{
	const int AUTH_FAILED = -1;
	const int AUTH_SUCCESS = 0;
	const int AUTH_MORE_DATA = 1;
	const int AUTH_CONTINUE = 2;
	const int AUTH_SUCCESS_WITH_DATA = 3;
}

interface Writer : Versioned
{
	void reset();
	void add(Status status, const string name);
	void setType(Status status, const string value);
	void setDb(Status status, const string value);
}

// Representation of auth-related data, passed to/from server auth plugin
interface ServerBlock : Versioned
{
	const string getLogin();
	const uchar* getData(uint* length);
	void putData(Status status, uint length, const void* data);
	CryptKey newKey(Status status);
}

// Representation of auth-related data, passed to/from client auth plugin
interface ClientBlock : ReferenceCounted
{
	const string getLogin();
	const string getPassword();
	const uchar* getData(uint* length);
	void putData(Status status, uint length, const void* data);
	CryptKey newKey(Status status);
version:	// 3.0 => 4.0
	AuthBlock getAuthBlock(Status status);
}

// server part of authentication plugin
interface Server : Auth
{
	[notImplemented(Auth::AUTH_FAILED)]
	int authenticate(Status status, ServerBlock sBlock, Writer writerInterface);

version:		// 3.0.1 => 4.0
	void setDbCryptCallback(Status status, CryptKeyCallback cryptCallback);
}

// .. and corresponding client
interface Client : Auth
{
	[notImplemented(Auth::AUTH_FAILED)]
	int authenticate(Status status, ClientBlock cBlock);
}

interface UserField : Versioned
{
	int entered();
	int specified();
	void setEntered(Status status, int newValue);
}

interface CharUserField : UserField
{
	const string get();
	void set(Status status, const string newValue);
}

interface IntUserField : UserField
{
	int get();
	void set(Status status, int newValue);
}

interface User : Versioned
{
	uint operation();

	CharUserField userName();
	CharUserField password();

	CharUserField firstName();
	CharUserField lastName();
	CharUserField middleName();

	CharUserField comment();
	CharUserField attributes();
	IntUserField active();

	IntUserField admin();

	void clear(Status status);

	// code of operation()
	const uint OP_USER_ADD = 1;
	const uint OP_USER_MODIFY = 2;
	const uint OP_USER_DELETE = 3;
	const uint OP_USER_DISPLAY = 4;
	const uint OP_USER_SET_MAP = 5;
	const uint OP_USER_DROP_MAP = 6;
}

interface ListUsers : Versioned
{
	void list(Status status, User user);
}

interface LogonInfo : Versioned
{
	const string name();
	const string role();
	const string networkProtocol();
	const string remoteAddress();
	const uchar* authBlock(uint* length);

version:
	Attachment attachment(Status status);
	Transaction transaction(Status status);
}

interface Management : PluginBase
{
	void start(Status status, LogonInfo logonInfo);
	int execute(Status status, User user, ListUsers callback);
	void commit(Status status);
	void rollback(Status status);
}

interface AuthBlock : Versioned
{
	const string getType();
	const string getName();
	const string getPlugin();
	const string getSecurityDb();
	const string getOriginalPlugin();
	boolean next(Status status);
	boolean first(Status status);
}


// Encryption

// Part 1. Network crypt.

// Plugins of this type are used to crypt data, sent over the wire
// Plugin must support encrypt and decrypt operations.
// Interface of plugin is the same for both client and server,
// and it may have different or same implementations for client and server.
interface WireCryptPlugin : PluginBase
{
	// getKnownTypes() function must return list of acceptable keys' types
	// special type 'builtin' means that crypt plugin knows itself where to get the key from
	const string getKnownTypes(Status status);
	void setKey(Status status, CryptKey key);
	void encrypt(Status status, uint length, const void* from, void* to);
	void decrypt(Status status, uint length, const void* from, void* to);

version:
	const uchar* getSpecificData(Status status, const string keyType, uint* length);
	void setSpecificData(Status status, const string keyType, uint length, const uchar* data);
}


// Part 2. Database crypt.

// This interface is used to transfer some data (related to crypt keys)
// between different components of firebird.
interface CryptKeyCallback : Versioned
{
	// First two parameters can be used by calling side to identify
	// itself for callback object.
	// Buffer must be big enough to hold a key.
	// It may be NULL, in this case just a key size will be returned
	// (not recommended because callback may cause network roundtrip).
	// Returning value is a real size of the key.
	// Returning of zero means error, but there is no way to provide
	// any further details.
	uint callback(uint dataLength, const void* data,
		uint bufferLength, void* buffer);

version:		// 6.0, 5.0.2, 4.0.6

	// NULL in attStatus means attach was successful.
	// DO_RETRY return will be ignored in this case, but plugin has a chance
	// to reflect internally success.
	[stub defaultAction]
	void dummy1(Status status);

	// interface not needed any more
	[stub defaultAction]
	void dummy2();

	// Produce something to be compared with other interface instance
	[notImplemented(-1)]
	int getHashLength(Status status);
	void getHashData(Status status, void* hash);
}


// Key holder accepts key(s) from attachment at database attach time
// (or gets them it some other arbitrary way)
// and sends it to database crypt plugin on request.
interface KeyHolderPlugin : PluginBase
{
	// keyCallback() signals that a new attachment will need a key.
	// Key holder can call callback to send upstairs a request for
	// some additional information (if needed). For example, RSA key
	// holder can send request to end user application for passphrase.
	// Return value is 1 if key is ready.
	int keyCallback(Status status, CryptKeyCallback callback);
	// Crypt plugin calls keyHandle() when it needs a key with a given name, stored in key holder.
	// Key is not returned directly - instead of it callback interface is returned.
	// Missing key with given name is not an error condition for keyHandle().
	// It should just return NULL in this case
	CryptKeyCallback keyHandle(Status status, const string keyName);

version:		// 3.0.1 => 4.0
	// With returning true here KeyHolder attachment can use only keys, provided by this KeyHolder.
	// Use of keys, got by database crypt plugin from other attachments, is prohibited.
	boolean useOnlyOwnKeys(Status status);
	// Communication in a chain of key holders - get callback interface for chaining holders
	CryptKeyCallback chainHandle(Status status);
}


// Information calls available for crypt plugin
interface DbCryptInfo : ReferenceCounted
{
	const string getDatabaseFullPath(Status status);
}


interface DbCryptPlugin : PluginBase
{
	// When database crypt plugin is loaded, setKey() is called to provide information
	// about key holders, available for a given database and key name for database.
	// It's supposed that crypt plugin will invoke keyHandle() function from them
	// to access callback interface for getting actual crypt key.
	// If crypt plugin fails to find appropriate key in sources, it should raise error.
	void setKey(Status status, uint length, KeyHolderPlugin* sources, const string keyName);
	void encrypt(Status status, uint length, const void* from, void* to);
	void decrypt(Status status, uint length, const void* from, void* to);

version:		// 3.0.1 => 4.0
	// Crypto manager may pass some additional info to plugin
	void setInfo(Status status, DbCryptInfo info);
}



// External procedures, functions & triggers


// Connection to current database in external engine.
// Context passed to ExternalEngine has SYSDBA privileges.
// Context passed to ExternalFunction, ExternalProcedure and ExternalTrigger
// has user privileges.
// There is one IExternalContext per attachment. The privileges and character
// set properties are changed during the calls.
interface ExternalContext : Versioned
{
	// Gets the Master associated with this context.
	Master getMaster();

	// Gets the ExternalEngine associated with this context.
	ExternalEngine getEngine(Status status);

	// Gets the Attachment associated with this context.
	Attachment getAttachment(Status status);

	// Obtained transaction is valid only before control is returned to the engine
	// or in ExternalResultSet::fetch calls of correspondent ExternalProcedure::open.
	Transaction getTransaction(Status status);

	const string getUserName();
	const string getDatabaseName();

	// Get user attachment character set.
	const string getClientCharSet();

	// Misc info associated with a context. The pointers are never accessed or freed by Firebird.

	// Obtains an unique (across all contexts) code to associate plugin and/or user information.
	int obtainInfoCode();
	// Gets a value associated with this code or FB_NULL if no value was set.
	void* getInfo(int code);
	// Sets a value associated with this code and returns the last value.
	void* setInfo(int code, void* value);
}


// To return set of rows in selectable procedures.
interface ExternalResultSet : Disposable
{
	boolean fetch(Status status);
}



interface ExternalFunction : Disposable
{
	// This method is called just before execute and informs the engine our requested character
	// set for data exchange inside that method.
	// During this call, the context uses the character set obtained from ExternalEngine::getCharSet.
	void getCharSet(Status status, ExternalContext context,
		string name, uint nameSize);

	void execute(Status status, ExternalContext context,
		void* inMsg, void* outMsg);
}



interface ExternalProcedure : Disposable
{
	// This method is called just before open and informs the engine our requested character
	// set for data exchange inside that method and ExternalResultSet::fetch.
	// During this call, the context uses the character set obtained from ExternalEngine::getCharSet.
	void getCharSet(Status status, ExternalContext context,
		string name, uint nameSize);

	// Returns a ExternalResultSet for selectable procedures.
	// Returning NULL results in a result set of one record.
	// Procedures without output parameters should return NULL.
	ExternalResultSet open(Status status, ExternalContext context,
		void* inMsg, void* outMsg);
}



interface ExternalTrigger : Disposable
{
	// types
	const uint TYPE_BEFORE = 1;
	const uint TYPE_AFTER = 2;
	const uint TYPE_DATABASE = 3;

	// actions
	const uint ACTION_INSERT = 1;
	const uint ACTION_UPDATE = 2;
	const uint ACTION_DELETE = 3;
	const uint ACTION_CONNECT = 4;
	const uint ACTION_DISCONNECT = 5;
	const uint ACTION_TRANS_START = 6;
	const uint ACTION_TRANS_COMMIT = 7;
	const uint ACTION_TRANS_ROLLBACK = 8;
	const uint ACTION_DDL = 9;

	// This method is called just before execute and informs the engine our requested character
	// set for data exchange inside that method.
	// During this call, the context uses the character set obtained from ExternalEngine::getCharSet.
	void getCharSet(Status status, ExternalContext context,
		string name, uint nameSize);

	void execute(Status status, ExternalContext context,
		uint action, void* oldMsg, void* newMsg);
}



interface RoutineMetadata : Versioned
{
	const string getPackage(Status status) const;
	const string getName(Status status) const;
	const string getEntryPoint(Status status) const;
	const string getBody(Status status) const;
	MessageMetadata getInputMetadata(Status status) const;
	MessageMetadata getOutputMetadata(Status status) const;
	MessageMetadata getTriggerMetadata(Status status) const;
	const string getTriggerTable(Status status) const;
	uint getTriggerType(Status status) const;
}


// In SuperServer, shared by all attachments to one database and disposed when last (non-external)
// user attachment to the database is closed.
interface ExternalEngine : PluginBase
{
	// This method is called once (per ExternalEngine instance) before any following methods.
	// The requested character set for data exchange inside methods of this interface should
	// be copied to charSet parameter.
	// During this call, the context uses the UTF-8 character set.
	void open(Status status, ExternalContext context,
		string charSet, uint charSetSize);

	// Attachment is being opened.
	void openAttachment(Status status, ExternalContext context);

	// Attachment is being closed.
	void closeAttachment(Status status, ExternalContext context);

	// Called when engine wants to load object in the cache. Objects are disposed when
	// going out of the cache.
	ExternalFunction makeFunction(Status status, ExternalContext context,
		RoutineMetadata metadata,
		MetadataBuilder inBuilder, MetadataBuilder outBuilder);
	ExternalProcedure makeProcedure(Status status, ExternalContext context,
		RoutineMetadata metadata,
		MetadataBuilder inBuilder, MetadataBuilder outBuilder);
	ExternalTrigger makeTrigger(Status status, ExternalContext context,
		RoutineMetadata metadata, MetadataBuilder fieldsBuilder);
}


// Identifies particular timer.
// Callback handler is invoked when timer fires.
interface Timer : ReferenceCounted
{
	void handler();
}

// Interface to set timer for particular time
interface TimerControl : Versioned
{
	// Set timer
	void start(Status status, Timer timer, uint64 microSeconds);
	// Stop timer
	void stop(Status status, Timer timer);
}


// Misc calls

interface VersionCallback : Versioned
{
	void callback(Status status, const string text);
}

interface Util : Versioned
{
	void getFbVersion(Status status, Attachment att, VersionCallback callback);
	void loadBlob(Status status, ISC_QUAD* blobId,
		Attachment att, Transaction tra, const string file, boolean txt);
	void dumpBlob(Status status, ISC_QUAD* blobId,
		Attachment att, Transaction tra, const string file, boolean txt);
	void getPerfCounters(Status status, Attachment att,
		const string countersSet, int64* counters);
	Attachment executeCreateDatabase(Status status,
		uint stmtLength, const string creatDBstatement, uint dialect,
		boolean* stmtIsCreateDb);
	void decodeDate(ISC_DATE date, uint* year, uint* month, uint* day);
	void decodeTime(ISC_TIME time, uint* hours, uint* minutes, uint* seconds, uint* fractions);
	ISC_DATE encodeDate(uint year, uint month, uint day);
	ISC_TIME encodeTime(uint hours, uint minutes, uint seconds, uint fractions);
	uint formatStatus(string buffer, uint bufferSize, Status status);
	uint getClientVersion();	// Returns major * 256 + minor
	XpbBuilder getXpbBuilder(Status status, uint kind, const uchar* buf, uint len);
	uint setOffsets(Status status, MessageMetadata metadata, OffsetsCallback callback);

version:	// 3.0 => 4.0 Alpha1
	DecFloat16 getDecFloat16(Status status);
	DecFloat34 getDecFloat34(Status status);
	void decodeTimeTz(Status status, const ISC_TIME_TZ* timeTz, uint* hours, uint* minutes, uint* seconds,
		uint* fractions, uint timeZoneBufferLength, string timeZoneBuffer);
	void decodeTimeStampTz(Status status, const ISC_TIMESTAMP_TZ* timeStampTz, uint* year, uint* month, uint* day,
		uint* hours, uint* minutes, uint* seconds, uint* fractions, uint timeZoneBufferLength, string timeZoneBuffer);
	void encodeTimeTz(Status status, ISC_TIME_TZ* timeTz, uint hours, uint minutes, uint seconds,
		uint fractions, const string timeZone);
	void encodeTimeStampTz(Status status, ISC_TIMESTAMP_TZ* timeStampTz, uint year, uint month, uint day,
		uint hours, uint minutes, uint seconds, uint fractions, const string timeZone);

version:	// 4.0 Beta1 => 4.0 Beta2
	Int128 getInt128(Status status);
	void decodeTimeTzEx(Status status, const ISC_TIME_TZ_EX* timeTz, uint* hours, uint* minutes, uint* seconds,
		uint* fractions, uint timeZoneBufferLength, string timeZoneBuffer);
	void decodeTimeStampTzEx(Status status, const ISC_TIMESTAMP_TZ_EX* timeStampTz, uint* year, uint* month, uint* day,
		uint* hours, uint* minutes, uint* seconds, uint* fractions, uint timeZoneBufferLength, string timeZoneBuffer);
}

interface OffsetsCallback : Versioned
{
	void setOffset(Status status, uint index, uint offset, uint nullOffset);
}

interface XpbBuilder : Disposable
{
	const uint DPB = 1;
	const uint SPB_ATTACH = 2;
	const uint SPB_START = 3;
	const uint TPB = 4;
	const uint BATCH = 5;
	const uint BPB = 6;
	const uint SPB_SEND = 7;
	const uint SPB_RECEIVE = 8;
	const uint SPB_RESPONSE = 9;
	const uint INFO_SEND = 10;
	const uint INFO_RESPONSE = 11;

	// removing data
	void clear(Status status);
	void removeCurrent(Status status);

	// adding data
	void insertInt(Status status, uchar tag, int value);
	void insertBigInt(Status status, uchar tag, int64 value);
	void insertBytes(Status status, uchar tag, const void* bytes, uint length);
	void insertString(Status status, uchar tag, const string str);
	void insertTag(Status status, uchar tag);

	// navigation
	boolean isEof(Status status);
	void moveNext(Status status);
	void rewind(Status status);
	boolean findFirst(Status status, uchar tag);
	boolean findNext(Status status);

	// Methods which work with current selection
	uchar getTag(Status status);
	uint getLength(Status status);
	int getInt(Status status);
	int64 getBigInt(Status status);
	const string getString(Status status);
	const uchar* getBytes(Status status);

	// Methods which work with resulting buffer
	uint getBufferLength(Status status);
	const uchar* getBuffer(Status status);
}

// Database trace objects

struct PerformanceInfo;
struct dsc;

interface TraceConnection : Versioned
{
	const uint KIND_DATABASE = 1;
	const uint KIND_SERVICE = 2;

	uint getKind();

	int getProcessID();
	const string getUserName();
	const string getRoleName();
	const string getCharSet();
	const string getRemoteProtocol();
	const string getRemoteAddress();
	int getRemoteProcessID();
	const string getRemoteProcessName();
}

interface TraceDatabaseConnection : TraceConnection
{
	int64 getConnectionID();
	const string getDatabaseName();
}

interface TraceTransaction : Versioned
{
	const uint ISOLATION_CONSISTENCY = 1;
	const uint ISOLATION_CONCURRENCY = 2;
	const uint ISOLATION_READ_COMMITTED_RECVER = 3;
	const uint ISOLATION_READ_COMMITTED_NORECVER = 4;
	const uint ISOLATION_READ_COMMITTED_READ_CONSISTENCY = 5;

	int64 getTransactionID();
	boolean getReadOnly();
	int getWait();
	uint getIsolation();
	PerformanceInfo* getPerf();

version: // 3.0.4 -> 3.0.5
	int64 getInitialID();
	int64 getPreviousID();
}

interface TraceParams : Versioned
{
	uint getCount();
	const dsc* getParam(uint idx);

version:
	const string getTextUTF8(Status status, uint idx);
}

interface TraceStatement : Versioned
{
	int64 getStmtID();
	PerformanceInfo* getPerf();
}

interface TraceSQLStatement : TraceStatement
{
	const string getText();
	const string getPlan();
	TraceParams getInputs();
	const string getTextUTF8();
	const string getExplainedPlan();
}

interface TraceBLRStatement : TraceStatement
{
	const uchar* getData();
	uint getDataLength();
	const string getText();
}

interface TraceDYNRequest : Versioned
{
	const uchar* getData();
	uint getDataLength();
	const string getText();
}

interface TraceContextVariable : Versioned
{
	const string getNameSpace();
	const string getVarName();
	const string getVarValue();
}

interface TraceProcedure : Versioned
{
	const string getProcName();
	TraceParams getInputs();
	PerformanceInfo* getPerf();

version: // 4.0 -> 5.0
	int64 getStmtID();
	const string getPlan();
	const string getExplainedPlan();
}

interface TraceFunction : Versioned
{
	const string getFuncName();
	TraceParams getInputs();
	TraceParams getResult();
	PerformanceInfo* getPerf();

version: // 4.0 -> 5.0
	int64 getStmtID();
	const string getPlan();
	const string getExplainedPlan();
}

interface TraceTrigger : Versioned
{
	//// TODO: TYPE or WHICH? ExternalTrigger has similar constants.
	const uint TYPE_ALL = 0;
	const uint TYPE_BEFORE = 1;
	const uint TYPE_AFTER = 2;
	//// TODO: What about database triggers?

	//// TODO: Action constants?

	const string getTriggerName();
	const string getRelationName();
	int getAction();
	int getWhich();
	PerformanceInfo* getPerf();

version: // 4.0 -> 5.0
	int64 getStmtID();
	const string getPlan();
	const string getExplainedPlan();
}

interface TraceServiceConnection : TraceConnection
{
	void* getServiceID();
	const string getServiceMgr();
	const string getServiceName();
}

interface TraceStatusVector : Versioned
{
	boolean hasError();
	boolean hasWarning();
	Status getStatus();
	const string getText();
}

interface TraceSweepInfo : Versioned
{
	int64 getOIT();
	int64 getOST();
	int64 getOAT();
	int64 getNext();
	PerformanceInfo* getPerf();
}

interface TraceLogWriter : ReferenceCounted
{
	uint write(const void* buf, uint size);
version: // 3.0.4 -> 3.0.5
	uint write_s(Status status, const void* buf, uint size);
}

interface TraceInitInfo : Versioned
{
	const string getConfigText();
	int getTraceSessionID();
	const string getTraceSessionName();
	const string getFirebirdRootDirectory();
	const string getDatabaseName();
	TraceDatabaseConnection getConnection();
	TraceLogWriter getLogWriter();
}

// API of trace plugin. Used to deliver notifications for each database
interface TracePlugin : ReferenceCounted
{
	const uint RESULT_SUCCESS = 0;
	const uint RESULT_FAILED = 1;
	const uint RESULT_UNAUTHORIZED = 2;

	// Function to return error string for hook failure
	const string trace_get_error();

	// Events supported:

	// Create/close attachment

	[notImplemented(true)]
	boolean trace_attach(TraceDatabaseConnection connection, boolean create_db, uint att_result);

	[notImplemented(true)]
	boolean trace_detach(TraceDatabaseConnection connection, boolean drop_db);

	// Start/end transaction

	[notImplemented(true)]
	boolean trace_transaction_start(TraceDatabaseConnection connection, TraceTransaction transaction,
			uint tpb_length, const uchar* tpb, uint tra_result);

	[notImplemented(true)]
	boolean trace_transaction_end(TraceDatabaseConnection connection, TraceTransaction transaction,
			boolean commit, boolean retain_context, uint tra_result);

	// Stored procedures and triggers execution

	[notImplemented(true)]
	boolean trace_proc_execute (TraceDatabaseConnection connection, TraceTransaction transaction, TraceProcedure procedure,
			boolean started, uint proc_result);

	[notImplemented(true)]
	boolean trace_trigger_execute(TraceDatabaseConnection connection, TraceTransaction transaction, TraceTrigger trigger,
			boolean started, uint trig_result);

	// Assignment to context variables

	[notImplemented(true)]
	boolean trace_set_context(TraceDatabaseConnection connection, TraceTransaction transaction, TraceContextVariable variable);

	// DSQL statement lifecycle

	[notImplemented(true)]
	boolean trace_dsql_prepare(TraceDatabaseConnection connection, TraceTransaction transaction,
			TraceSQLStatement statement, int64 time_millis, uint req_result);

	[notImplemented(true)]
	boolean trace_dsql_free(TraceDatabaseConnection connection, TraceSQLStatement statement, uint option);

	[notImplemented(true)]
	boolean trace_dsql_execute(TraceDatabaseConnection connection, TraceTransaction transaction, TraceSQLStatement statement,
			boolean started, uint req_result);

	// BLR requests

	[notImplemented(true)]
	boolean trace_blr_compile(TraceDatabaseConnection connection, TraceTransaction transaction,
			TraceBLRStatement statement, int64 time_millis, uint req_result);

	[notImplemented(true)]
	boolean trace_blr_execute(TraceDatabaseConnection connection, TraceTransaction transaction,
			TraceBLRStatement statement, uint req_result);

	// DYN requests

	[notImplemented(true)]
	boolean trace_dyn_execute(TraceDatabaseConnection connection, TraceTransaction transaction,
			TraceDYNRequest request, int64 time_millis, uint req_result);

	// Using the services

	[notImplemented(true)]
	boolean trace_service_attach(TraceServiceConnection service, uint att_result);

	[notImplemented(true)]
	boolean trace_service_start(TraceServiceConnection service, uint switches_length, const string switches,
			uint start_result);

	[notImplemented(true)]
	boolean trace_service_query(TraceServiceConnection service, uint send_item_length,
			const uchar* send_items, uint recv_item_length,
			const uchar* recv_items, uint query_result);

	[notImplemented(true)]
	boolean trace_service_detach(TraceServiceConnection service, uint detach_result);

	// Errors happened

	[notImplemented(true)]
	boolean trace_event_error(TraceConnection connection, TraceStatusVector status, const string function);

	// Sweep activity

	const uint SWEEP_STATE_STARTED = 1;
	const uint SWEEP_STATE_FINISHED = 2;
	const uint SWEEP_STATE_FAILED = 3;
	const uint SWEEP_STATE_PROGRESS = 4;

	[notImplemented(true)]
	boolean trace_event_sweep(TraceDatabaseConnection connection, TraceSweepInfo sweep,
			uint sweep_state);

	// Stored functions execution

	[notImplemented(true)]
	boolean trace_func_execute(TraceDatabaseConnection connection, TraceTransaction transaction,
		TraceFunction function,	boolean started, uint func_result);

version:	// 4.0.1 -> 4.0.2
	[notImplemented(true)]
	boolean trace_dsql_restart(TraceDatabaseConnection connection, TraceTransaction transaction,
		TraceSQLStatement statement, uint number);

version:	// 4.0 -> 5.0

	// Compilation of stored procedures, functions, triggers

	[notImplemented(true)]
	boolean trace_proc_compile(TraceDatabaseConnection connection, TraceProcedure procedure,
		int64 time_millis, uint proc_result);

	[notImplemented(true)]
	boolean trace_func_compile(TraceDatabaseConnection connection, TraceFunction function,
		int64 time_millis, uint func_result);

	[notImplemented(true)]
	boolean trace_trigger_compile(TraceDatabaseConnection connection, TraceTrigger trigger,
		int64 time_millis, uint trig_result);
}

// Trace plugin second level factory (this is what is known to PluginManager as "trace plugin")
interface TraceFactory : PluginBase
{
	// Known notifications
	const uint TRACE_EVENT_ATTACH = 0;
	const uint TRACE_EVENT_DETACH = 1;
	const uint TRACE_EVENT_TRANSACTION_START = 2;
	const uint TRACE_EVENT_TRANSACTION_END = 3;
	const uint TRACE_EVENT_SET_CONTEXT = 4;
	const uint TRACE_EVENT_PROC_EXECUTE = 5;
	const uint TRACE_EVENT_TRIGGER_EXECUTE = 6;
	const uint TRACE_EVENT_DSQL_PREPARE = 7;
	const uint TRACE_EVENT_DSQL_FREE = 8;
	const uint TRACE_EVENT_DSQL_EXECUTE = 9;
	const uint TRACE_EVENT_BLR_COMPILE = 10;
	const uint TRACE_EVENT_BLR_EXECUTE = 11;
	const uint TRACE_EVENT_DYN_EXECUTE = 12;
	const uint TRACE_EVENT_SERVICE_ATTACH = 13;
	const uint TRACE_EVENT_SERVICE_START = 14;
	const uint TRACE_EVENT_SERVICE_QUERY = 15;
	const uint TRACE_EVENT_SERVICE_DETACH = 16;
	const uint TRACE_EVENT_ERROR = 17;
	const uint TRACE_EVENT_SWEEP = 18;
	const uint TRACE_EVENT_FUNC_EXECUTE = 19;
	const uint TRACE_EVENT_PROC_COMPILE = 20;
	const uint TRACE_EVENT_FUNC_COMPILE = 21;
	const uint TRACE_EVENT_TRIGGER_COMPILE = 22;
	const uint TRACE_EVENT_MAX = 23;	// keep it last

	// What notifications does plugin need
	uint64 trace_needs();

	// Create plugin
	TracePlugin trace_create(Status status, TraceInitInfo init_info);
}

// UDR Factory interfaces. They should be singletons instances created by user's modules and
// registered. When UDR engine is going to load a routine, it calls newItem.

interface UdrFunctionFactory : Disposable
{
	void setup(Status status, ExternalContext context, RoutineMetadata metadata,
		MetadataBuilder inBuilder, MetadataBuilder outBuilder);
	ExternalFunction newItem(Status status, ExternalContext context, RoutineMetadata metadata);
}

interface UdrProcedureFactory : Disposable
{
	void setup(Status status, ExternalContext context, RoutineMetadata metadata,
		MetadataBuilder inBuilder, MetadataBuilder outBuilder);
	ExternalProcedure newItem(Status status, ExternalContext context, RoutineMetadata metadata);
}

interface UdrTriggerFactory : Disposable
{
	void setup(Status status, ExternalContext context, RoutineMetadata metadata,
		MetadataBuilder fieldsBuilder);
	ExternalTrigger newItem(Status status, ExternalContext context, RoutineMetadata metadata);
}

interface UdrPlugin : Versioned
{
	Master getMaster();

	void registerFunction(Status status, const string name, UdrFunctionFactory factory);
	void registerProcedure(Status status, const string name, UdrProcedureFactory factory);
	void registerTrigger(Status status, const string name, UdrTriggerFactory factory);
}

interface DecFloat16 : Versioned
{
	const uint BCD_SIZE = 16;
	const uint STRING_SIZE = 24;	// includes terminating \0
	void toBcd(const FB_DEC16* from, int* sign, uchar* bcd, int* exp);
	void toString(Status status, const FB_DEC16* from, uint bufferLength, string buffer);
	void fromBcd(int sign, const uchar* bcd, int exp, FB_DEC16* to);
	void fromString(Status status, const string from, FB_DEC16* to);
}

interface DecFloat34 : Versioned
{
	const uint BCD_SIZE = 34;
	const uint STRING_SIZE = 43;	// includes terminating \0
	void toBcd(const FB_DEC34* from, int* sign, uchar* bcd, int* exp);
	void toString(Status status, const FB_DEC34* from, uint bufferLength, string buffer);
	void fromBcd(int sign, const uchar* bcd, int exp, FB_DEC34* to);
	void fromString(Status status, const string from, FB_DEC34* to);
}

interface Int128 : Versioned
{
	// - 170141183460469231731687303715884105728 e - 128 \0
	// 1 + 39 +							1 + 1 + 3 + 1 = 46
	const uint STRING_SIZE = 46;	// includes terminating \0
	void toString(Status status, const FB_I128* from, int scale, uint bufferLength, string buffer);
	void fromString(Status status, int scale, const string from, FB_I128* to);
}

// Replication interfaces

interface ReplicatedField : Versioned
{
	// Return field name (or nullptr on error)
	const string getName();
	// Return field type (or zero if the field does not exist)
	uint getType();
	// Return field subtype, if applicable
	int getSubType();
	// Return field scale (behavior is undefined for non-numeric fields)
	int getScale();
	// Return maximum length of the field data in bytes
	uint getLength();
	// Return character set without collation part for text or CLOB fields
	uint getCharSet();
	// Return pointer to data (or nullptr for NULL values)
	const void* getData();
}

interface ReplicatedRecord : Versioned
{
	// Return count of fields
	uint getCount();
	// Return ReplicatedField with given index (or nullptr if index is invalid).
	// Returned reference is valid until next call of getField() or end of the record life.
	ReplicatedField getField(uint index);

	// Return size of raw data
	uint getRawLength();
	// Dirty method to return record buffer in internal format
	const uchar* getRawData();
}

interface ReplicatedTransaction : Disposable
{
	// Last chance to return an error and make commit to be aborted.
	// The transaction still can be rolled back on error happened after this call.
	void prepare(Status status);
	// An error returned from these methods may be logged but do not abort process.
	void commit(Status status);
	void rollback(Status status);

	void startSavepoint(Status status);
	void releaseSavepoint(Status status);
	void rollbackSavepoint(Status status);

	// ReplicatedRecords parameters point to local objects, do not ever store the pointer.
	void insertRecord(Status status, const string name,
					  ReplicatedRecord record);
	void updateRecord(Status status, const string name,
					  ReplicatedRecord orgRecord,
					  ReplicatedRecord newRecord);
	void deleteRecord(Status status, const string name,
					  ReplicatedRecord record);

	void executeSql(Status status, const string sql);
	void executeSqlIntl(Status status, uint charset, const string sql);
}

interface ReplicatedSession : PluginBase
{
	// Parameter don't need to be released if not used.
	boolean init(Status status, Attachment attachment);

	ReplicatedTransaction startTransaction(Status status, Transaction transaction, int64 number);
	void cleanupTransaction(Status status, int64 number);
	void setSequence(Status status, const string name, int64 value);
}

// Profiler interfaces

interface ProfilerPlugin : PluginBase
{
	void init(Status status, Attachment attachment, uint64 ticksFrequency);

	ProfilerSession startSession(Status status, const string description,
		const string options, ISC_TIMESTAMP_TZ timestamp);

	void flush(Status status);
}

interface ProfilerSession : Disposable
{
	const uint FLAG_BEFORE_EVENTS = 0x1;
	const uint FLAG_AFTER_EVENTS = 0x2;

	int64 getId();
	uint getFlags();

	// When closing an attachment, the engine is free to dispose the ProfilerPlugin without call this method in advance.
	void cancel(Status status);

	void finish(Status status, ISC_TIMESTAMP_TZ timestamp);

	void defineStatement(Status status, int64 statementId, int64 parentStatementId,
		const string type, const string packageName, const string routineName, const string sqlText);

	void defineCursor(int64 statementId, uint cursorId, const string name, uint line, uint column);

	void defineRecordSource(int64 statementId, uint cursorId, uint recSourceId,
		uint level, const string accessPath, uint parentRecSourceId);

	void onRequestStart(Status status, int64 statementId, int64 requestId,
		int64 callerStatementId, int64 callerRequestId, ISC_TIMESTAMP_TZ timestamp);

	void onRequestFinish(Status status, int64 statementId, int64 requestId,
		ISC_TIMESTAMP_TZ timestamp, ProfilerStats stats);

	void beforePsqlLineColumn(int64 statementId, int64 requestId, uint line, uint column);
	void afterPsqlLineColumn(int64 statementId, int64 requestId, uint line, uint column, ProfilerStats stats);

	void beforeRecordSourceOpen(int64 statementId, int64 requestId, uint cursorId, uint recSourceId);
	void afterRecordSourceOpen(int64 statementId, int64 requestId, uint cursorId, uint recSourceId,
		ProfilerStats stats);

	void beforeRecordSourceGetRecord(int64 statementId, int64 requestId, uint cursorId, uint recSourceId);
	void afterRecordSourceGetRecord(int64 statementId, int64 requestId, uint cursorId, uint recSourceId,
		ProfilerStats stats);
}

interface ProfilerStats : Versioned
{
	uint64 getElapsedTicks();
}
