Contents 

AdeptSQL Diff Reference
Getting started
Connecting to databases
Scanning available servers
Saving and opening comparisons
Running from command line
Working with the schema
Viewing schema differences
Comparing objects side-by-side
Dragging and dropping schema items
Using schema filters
Configuring schema options
Comparing table data
DataDiff overview
Data comparison options
Column configuration file
Special situations comparing data
Executing the SQL
SQL errors and warnings
Keyboard shortcuts
Editing commands and keyboard shortcuts
Using keyboard templates
Choosing debugger's key mapping
Using COM Automation interface
Automating schema comparison
Automating data comparison
Licensing and contact info
Registration of AdeptSQL Diff
Contact information
Version history (last updated for ver. 1.90 [Build 58])

AdeptSQL Diff Online Help

Prev Page Next Page

AdeptSQL Diff Automation interface

Starting from version 1.50, AdeptSQL Diff provides limited programmatic control by external applications or scripts via a simple ActiveX Automation interface. Read the technical information below only if you are familiar with COM and plan to invoke AdeptSQL Diff from a programming language supporting ActiveX Automation. The Diff itself can't host automation scripts (yet), so if you are using an embeddable scripting language such as VBScript or JScript, you will have to put your scripts into a DHTML page or use Windows Scripting Host (WSH) to run the scripts  from command line.  Using VB, C++ or Delphi you can call AdeptSQL Diff from your own applications.

Multiprocess / unattended use limitations: Please note that in Diff versions 1.xx, the Automation support was added as an afterthought, on top of the GUI and all existing functionality.  This means that whether you run the Diff interactively or via its Automation interfaces, it always shows up with all its GUI windows. Multiple instances of comparison objects would all refer to the same  instance of Diff.  When you run a comparison from your script, the Diff will show the progress dialog; when you navigate the schema tree programmatically, it will move selection in the schema view panel accordingly, etc. In future versions the internal architecture is likely to change to separate the comparison engine into a separate layer accessible either from GUI or programmatically, but meanwhile you should avoid using Diff automation in any multi-process or server-like way.  

Trial mode limitations: Note that although the automation does work with Diff running in trial mode, it will not be convenient to use. Every time the Diff is programmatically started, you will have to switch to it and manually close the registration dialog. And another dialog will show up every time you start data comparison. Therefore it is strongly recommended that you purchase a license before starting to use the automation interface.

The Comparison object.

There isn't much of a "document object model" here: all you work with is a single automation object representing the program. Another object for DataDiff comparison can be produced by CompareData call. The DataDiff object is described on a separate page.

Class name: AdeptSQL_Diff.Comparison
Class GUID: {DD76F532-F4EA-416A-B099-142B14F825AF}

The primary IDispatch interface of the class is:

Interface name: IAdeptSQLDiff
IID: {B0D5F6EA-47CE-4351-A5B3-AFD68221CBB4}

Comparison methods of IAdeptSQLDiff:

function Ready: AppStates;

This is the function you must call after creating the object and later after starting a comparison. Poll the function in a loop (with a delay inside, like sleep(100) in Windows API or DoEvents in VB) until it returns a proper status code: apsEmpty (=2) after the Diff has started and then apsReady (=4) after the comparison is complete.  See the sample code below for details. Here is the complete list of the returned status codes:

  Constant name Indicates that...
0 apsStarting The program is still initializing itself, don't bother it in this state
1 apsModal The program has displayed some modal dialog, waiting for the user to close it. Nothing your script can do but wait.
2 apsEmpty The Diff is up and running, there is no comparison yet. Now this is time to call Compare/CompareDoc and begin the real work!
3 apsWorking The Diff is still comparing the databases, keep waiting...
4 apsReady Finally, everything is done and the program is ready to process your commands!

procedure LoadConfig(const FileName: WideString);

[Diff 1.90 or later]: This method attempts to load the entire set of AdeptSQL Diff settings (comparison, scripting, visual and all others) from the specified .INI file.  This method is optional. If you never call it,  the Diff will continue to use the settings it loaded on startup from either the registry or the default configuration file ASQLDIFF.INI.  Note that these application-level settings do not intersect with the project-level ones, which are kept in a comparison document.  By calling LoadConfig() first and then proceeding with CompareDoc(), you can ensure that the comparison and scripting are done in the completely controlled environment.  This may be important, because most of the automation methods described below are affected by various settings and there is currently no way to change those settings through the automation interfaces.

To produce a customized configuration file, run the Diff interactively, specifying the "-wi filename.ini" command line parameter.  Configure any options as required and exit the program.  On exit, all modified options will be written to that configuration file.

procedure Compare(const ConnLeft: WideString; const ConnRight: WideString);

This method compares two databases specified by their ADO connection strings. Since all other methods deal with the results of the comparison, you have to call Compare and then poll Ready waiting for apsReady status before you do anything else. The program raises an exception if it can't connect to either of the databases.

The following example (in Delphi) shows you how to create an AdeptSQL Diff  interface object and start a comparison:

var
Diff: OleVariant;
procedure
TMyTestForm.btnCompareClick(Sender: TObject);
var
ws1, ws2: WideString;
n: Integer;
begin
Diff := CreateOleObject('AdeptSQL_Diff.Comparison');

n := 30;
while Diff.Ready <> apsEmpty do
begin
sleep(100); Dec(n);
if n = 0 then
raise Exception.Create('Timeout starting AdeptSQL Diff');
end;

ws1 := edConnStringLeft.Text;
ws2 := edConnStringRight.Text;
Diff.Compare(ws1, ws2);

n := 500; // Comparison time can be much longer!
while Diff.Ready <> apsReady do
begin
sleep(100);
Dec(n);
if n = 0 then
raise Exception.Create('Timeout comparing databases');
end;
end;

procedure CompareDoc(const FileName: WideString);

[Diff 1.90 or later]: This method runs the comparison using information from a previously saved comparison file.  The file determines both connection strings, DataDiff profiles for any previously compared tables and some other settings. Just as the Compare() method, CompareDoc() is asynchronous, so you must check the Ready status as shown above.

NOTE: There is currently no way to programmatically create (that is, configure and save) a comparison document using Diff's automation interface.  It is assumed that you first run the comparison manually, configure it as required, then save it into a file and later use that file to re-compare from script.  If you do need to generate a comparison file programmatically, you can do so in your own code, because comparisons (.ASQ files) are text files having rather simple INI-style format.

function CompareData(sKeys, sNormal, sIgnore, sFilter: WideString): DataDiff;

Invokes DataDiff to compare records of the selected table (matched pair of tables) and returns an object representing this data comparison. The schema comparison must be completed and the program be in apsReady state before data comparison can be attempted. The selection must be a single non-empty table (pair of matched tables), or the call would raise an exception. Call HasData() before to make sure the data comparison is possible.

When you start a data comparison programmatically, the column selection dialog is not displayed and all comparison parameters are taken from the parameters passed to CompareData:

  • sKeys, sNormal, sIgnore are each a comma-separated list with the names of columns (a) to be used as the key, (b) to be compared as normal columns and (c) to be ignored, respectively. All these parameters are optional. Each column not mentioned in one of the lists will retain its default status as described here. The only situation when you must specify sKeys is when there is no PK or UNIQUE constraint in the table to determine the default key. 
  • sFilter parameter is also optional. If specified, it must be a valid (for each of the tables in the matched pair) SQL condition for a WHERE clause or "*" (see below). It will be used to filter the records being compared. If a filter expression is not specified or is empty string, any filter stored in the comparison file will be applied (or the entire tables will be compared). 

    [Diff 1.90 or later]: If you need to specify different filter expressions for the two tables, separate them with "|" (for example: "Salary > 10000 | Salary > 10000 and Year = 2005").  You can use "*" to explicitly clear the filter, overriding any value from the loaded comparison document. The "*" works both as the whole sFilter value and with "|" (e.g. "Salary > 100 | *" - filtered records from the left-hand DB, all records from the right-hand one).

If the schema comparison is started with CompareDoc (and this particular pair of table has been compared before), the data comparison will use any filters, column settings and other details remembered from the last comparison. The above parameters will override these settings.

Note that, so far, the scripting modes, tolerances and other DataDiff comparison details are not accessible through the Automation. The only way to specify them is to put them into the project file.

The call is asynchronous: it returns a DataDiff object before the comparison is complete. Your script must poll the Ready() function of the newly created DataDiff object (not of the original schema comparison object!) until it returns apsReady and only then proceed exploring the data.

Selection methods.

All scripting and information functions described in the next sections work on one or more of selected objects. It is exactly as if you had selected the objects manually when running the program in interactive mode. In fact you can switch to the Diff window while it is being manipulated from a script and watch how the selection changes. The functions described below allow you to select the whole schema, or specific named items, or traverse the schema tree enumerating certain categories of objects. Please look at the sample scripts in SampleAutomation/ directory to see how this can be used to produce reports.

procedure SelectRoot;

Selects the root node of the compared schema (so that subsequent calls to MakeSQL/SaveSQL would script the whole schema). This method is equivalent to Select("",""), it was also known as SelectAll() (which is still supported but not recommended).

function Select(const Category: WideString; const Items: WideString): Integer;

Selects one, several or all schema objects in the specified category and returns the number of selected items. In the Category parameter you can specify "Tables", "Views", or a title of any other first-level collection node, exactly as it appears in the schema tree.

The Items parameter may be empty, which means selecting the category node itself, or it may contain one or more comma-separated names.  The names must be specified exactly as they are displayed in the schema tree, including any  square brackets "[]" and owner names. E.g. if you have configured the Diff to display table names with owner prefix, the owner must also be specified for each name in Items,  but if there is no owner prefixes in the displayed schema, there shouldn't be any in Items either.

The return value will be 0 if none of the specified item(s) are found in the schema, 1 if a single node has been selected (even if it is a category node). The result of Select may be >1 only when Items parameter contains a comma-separated list. If any (or even all) of the schema entities in the Items are not found, this will be reflected in the returned selection count.

Note that Select() can not be used to access summary collection nodes. For that, you must use a combination of SelectRoot() / SelectNext() / SelectChild() functions, as described below.

function SelectChild(const ChildName: WideString = ''): Boolean;

Selects a child node of the currently selected node. The optional ChildName parameter specifies the name of the child node (exactly as displayed in the schema tree). If ChildName is not specified or is an empty string, the first child node will be selected. The function returns FALSE if the selected node has no child nodes or if none of them match the specified name. Before calling this function you must make sure that exactly one node is selected. If no nodes or more than one node are selected, the function raises exception.

function SelectNext(bExtend: Boolean): Boolean;

Selects the next sibling node after the currently selected one. If bExtend=True, the previous node remains selected as well, which gives you one more way (besides Select()) to select multiple items. If bExtend=False, the function deselects the currently selected node (or the last of selected nodes, if several have been already selected). The function returns False if there is no more sibling nodes. Before calling this function, you must make sure at least one node is selected, otherwise the function raises exception. Having a multiple selection before SelectNext() is OK, the function will start at the last of the selected items.

function SelectParent(): Boolean;

Moves selection from the currently selected node(s) to its parent node. Returns False if there is no parent, which only happens when we are already at the root node. Before calling this function, you must make sure at least one node is selected, otherwise the function raises exception. Multiple selection is OK, since the selected nodes are always siblings and finding their common parent node is not a problem.

One example of using these schema-traversing functions is getting to the 'Summary' collections, e.g. when we intend to script all triggers:

diff.SelectRoot(); // we are at the 'Schema' node
diff.SelectNext(false); // we are at the 'Summary collections'
diff.SelectChild("Triggers");
s = diff.MakeSQL(sqlCREATE, 0);

function SelectFirstDifference(const Category: WideString): Boolean;

Selects the first changed node in the specified category (e.g. "Tables") or in the whole schema (if no category is specified). Returns TRUE if such a node is found.  The effect is similar to calling Select(Category, ""), followed by SelectNextDifference, except that it also sets the scope: subsequent calls to SelectNextDifference would only locate changes within the specified category.

function SelectNextDifference: Boolean;

Selects the next changed schema object (starting after the current selection). If there is no such object, the function returns FALSE and the selection remains unchanged. If the last call to SelectFirstDifference has specified a category (e.g. "Tables"), the search stops at the last changed item in this category, otherwise it traverses the whole schema.  SelectNextDifference (as well as SelectFirstDifference) always selects a particular schema object (e.g. a "Customers" table), not a category itself ("Tables") and not a subitem (e.g. not a particular changed column in "Customers").

Information functions

The following functions allow to obtain information about the currently selected item(s), including its type, name and comparison status.

function SelItemName: WideString;

Returns name of a selected item, as displayed in the schema view. Exactly one node must be selected, otherwise this method raises an exception. This method works on a node of any kind: root, category or schema item.

function SelItemType: WideString;

Returns a string describing what kind of node(s) is currently selected. At least one node must be selected, otherwise this method raises an exception. Multiple selection is acceptable, because only sibling items can be multi-selected and those are guaranteed to be of the same type. If the selected node is a schema entity (e.g. a specific table), the function will return the caption of its parent category (e.g. 'Tables'). If the node is a category, the function will return string 'Collection'. For the root node it will return 'Root'.

function GetDiffInfo: Variant;

This function returns an array containing 6 integer values - various difference counters for the currently selected item(s). If more than one item is selected, the counters for each of them add up. If a category node or the whole schema is selected, the counters represent the number of changes in all schema items under this category or across the whole schema.

Element Description
a[0]

Selection count: the number of items actually selected. The same result can be obtained from SelCount() function described below. Note that (unlike the next 4 counters) for a category node or the root node this counter will be 1, not the number of subnodes. If you need the total number of items in the stats, just sum up the next 4 elements of this array.

a[1]

Unchanged count: the number of items which are identical between the two databases. Same as SameCount() function below.

a[2]

Changed count: the number of items which are present in each of the databases but have some differences. Same as DiffCount() function below.

a[3]

Left-only count: the number of items which are only present in the left-hand database. Same as LeftCount() function below.

a[4]

Right-only count: the number of items which are only present in the right-hand database. Same as RightCount() function below.

a[5]

Difference flags: a bit mask indicating that at least one schema item in the selection has a specified kind of difference. In other words, there is a bit for each of the 4 counters above and this bit is set if the counter is not zero. The bits are:

dfSame = 1;
dfChanged = 2;
dfLeftOnly = 4;
dfRightOnly = 8;

The same bitmask is returned by DiffState() function described below.

JScript note: arrays in JScript are completely different and incompatible with the array variant type returned by GetDiffInfo. So if you need to call it in JScript, use the following code to convert the results into the format recognized by its scripting engine:

 var va = new VBArray(diff.GetDiffInfo());
var a = va.toArray();
var selCount = a[0];
...

function SameCount: Integer;
function DiffCount: Integer;
function LeftCount: Integer;
function RightCount: Integer;
function DiffState: WORD;

Each of these functions calls an internal version of GetDiffInfo and returns just one of the computed statistics. See description of GetDiffInfo for more information. Getting the integer counters returned from these functions might be more convenient than accessing the array returned by GetDiffInfo (especially in JScript), but if you need several of these counters it would be much more efficient to call GetDiffInfo once.

function SelCount: Integer;

This function returns the number of selected items, which is the same information GetDiffInfo returns in the 0-th element of the info array. But unlike the 5 counter functions described above, SelCount does not rely on GetDiffInfo to calculate its vaue (in fact, it is the other way around), so there is no overhead in calling SelCount directly.

function HasData: Bool;

Returns TRUE if data comparison can be successfully run on the currently selected schema item (see CompareData). This means that the current selection must be a single schema item, the item must represent a table (or a pair of matched tables) and this table must contain some data records. Returns FALSE if any other kind of schema item is selected (or several items, or none) or if the selected table is empty.

Scripting functions

function MakeSQL(SQLKind: SQLKinds; TargetDB: Integer): WideString;

Produces one of the 3 possible kinds of SQL:  CREATE, DROP or ALTER (SQLKind = 0, 1, or 2 accordingly) for all previously selected schema items.  The resulting SQL is returned as a Unicode string.  TargetDB determines which of the compared schemas is used to produce the SQL or which database the SQL should be applied to (except for CREATE scripts, which usually can't be applied to either DB). The following table explains the possible combinations:

  SQLKinds: TargetDB = 0 TargetDB = 1
0 sqlCREATE CREATEs are produced from the left-hand schema (and can be applied to an empty database, but probably not to either one of those compared) CREATEs are produced from the right-hand schema (and can be applied to an empty database, but probably not to either one of those compared)
1 sqlDROP DROPs are produced from the left-hand schema (and can be applied to the same database, if you need to delete the selected objects) DROPs are produced from the right-hand schema (and can be applied to the same database)
2 sqlALTER Update script is produced from the right-hand schema to be applied to the left-hand one Update script is produced from the left-hand schema to be applied to the right-hand one

procedure SaveSQL(SQLKind: SQLKinds; TargetDB: Integer; const FileName: WideString);

Same as MakeSQL method described above, except that the resulting SQL is not returned as a string, but immediately saved to the specified text file (as ANSI, not Unicode).

procedure SaveReport(const FileName: WideString);

Supposed to write a template-driven difference report into the specified HTML file. Not currently implemented, parameters are subject to change.

   
The CHM file was converted to HTML by chm2web software.