gw_logo_08.gif (1982 bytes)  
Last edit: 2008-07-11 Graham Wideman

ModelRight

Introduction to ModelRight scripting and automation

Document Status
Date (reverse) Who Description
     
2008-07-10 GW Original

This document provides my draft suggestions regarding the scope, sequence and structure of content for introducing the programmability area of ModelRight.

Contents

Outline of sections below

Introduction

As delivered, ModelRight provides a comprehensive environment for forward and reverse engineering databases. In addition, the environment provides a great deal of control over the graphical appearance of the model views, including the capability to add annotations and control style features.

To this foundation, ModelRight adds programmability features which provide opportunities to access and manipulate the database model and the diagram graphic appearance in powerful ways.  Many of ModelRight's built-in capabilities use this programmability: during the forward-and reverse engineering processes, when ModelRight generates SQL to read or manipulate the database, it uses scripts to compose the SQL statements.  You can modify these SQL-generating scripts to suit your own special purposes, different dialects of SQL and so on.

But that is just one use for ModelRight's programmability; here are some other scenarios that position ModelRight as a key component in a larger application development and maintenance process.

Orientation to ModelRight programmability

What there is to know

To gain traction on ModelRight programmability, there are two main themes to master:

These topics are described in more detail below.

Choice of two programmability approaches

ModelRight provides two main programmability approaches:

1. Built-in VBScript scripting environment 

ModelRight includes Microsoft's Visual Basic Scripting (VBS) environment, which is at version 5.6 at this writing. Scripts can be created, edited and run within ModelRight, and are generally used to manipulate the current database model, or to inspect the database model and produce some kind of output, often SQL statements.

Scripts defined by the user are associated with a particular model and stored in the currently-open ModelRight model file (".wer" file).

As I understand it, VBS does not have "include" capability, right? So the only "shared" function capability would be in the GlobalNamespace.  Or is it possible for users to add additional scripts to, for example, the MySQL folder -- or are these all named in a pre-defined way?

You may already be familiar with the Visual Basic for Applications (VBA) environment found in Microsoft products like Access, Excel and Word.  The VBS environment is similar in concept:

However, there are significant differences between VBA and VBS.  In general VBS is suited to smaller-scaled functionality for less-demanding tasks. For example, variables in VBS are all "variant" -- they don't need to be declared as a particular data type. This is good for small tasks, but less suited to large and complicated bodies of code.

There are a variety of ways that the integration of VBS into ModelRight has been made specific to the needs of ModelRight. However the language itself, its general functions and features (not specific to ModelRight) are as documented here at Microsoft Developer Network: VBScript.

2. Automation using external programs

In addition to the built-in VBS programmability, ModelRight also provides an API through which to manipulate ModelRight models/diagrams from an external program, and this API is accessed via COM Automation. Consequently, such external programs can be written in your choice of language, including VBA from Access or Excel; VB, C# or C++ from .NET; Delphi, Python, PHP or any language which can create an Automation client.

This approach is especially powerful where ModelRight modeling activities are part of a larger database application workflow, as suggested in the introduction.  For example:

In other scenarios, automation using an external program may simply be a better choice for accomplishing tasks that are beyond the complexity readily handled within the VBS environment.

What ModelRight features can be programmed?

ModelRight provides your code with the capability to read and manipulate its model of the database itself (tables, columns, relationships etc), and its model of the diagrams of the database (particular layouts of table graphics and relationship graphics on a page; annotations; and formatting of these).

Programmability not currently available:

Accessing and navigating ModelRight's objects

To write useful code for ModelRight, you will need to become familiar with ModelRight's object model -- that is to say the objects that ModelRight exposes for your code to interact with. The general strategy is very similar to working with VBA to manipulate objects in Word or Excel, and in ModelRight goes something like this:

Exact details (or how to find out the exact details) are described in sections below. But first, a look at the user interface for programming, so that you can use it to explore ModelRight's objects.

ModelRight's programming UI ("Hello world")

Script Explorer

In the ModelRight application, you can browse, create or select scripts in the Script Explorer panel. If this is not visible, you can summon it from the main menu: Window > Script Explorer.

Script Explorer shows three or more top-level folders, which entail three different kinds of scripts:

Script Editor

As you select (or create) scripts in the Script Explorer, the text of the script appears in an editor in the Property Browser panel. (To open: Window > Property Browser).

Main points:

To manually run a script (ie: cause it to load), click on the leftmost button (hint says: "Execute the script").

Note: this works for User Defined scripts, but for database-manipulation scripts this generally results in an error, so there must be some more preparation required for those, for example when troubleshooting them.

Pressing the "Execute the script" button also causes the display to change like this:

Here you see:

(Side note: Obviously with features to handle scripts in two languages -- VBS and SQL -- there's some room for ambiguity and confusion.)

ModelRight Object Model

Having covered some basic skills in operating ModelRight's programming environment, we can proceed to discuss the objects that are available for your scripts to interact with: ModelRight's object model.  To learn what to expect in ModelRight's data structure, we will first look at various browsers. After that we will make the jump to ModelRight's actual programming object model.

Orientation from Model Explorer

You no doubt already expect to find ModelRight's data to be organized like you see in the Model Explorer, pictured here, and as you see in the properties that display in the Property Browser as you select each item in the Model Explorer (or on the diagram).

The branches shown in the "Model Objects" panel are obviously of great interest, as these describe the database objects themselves: Tables, columns etc.

Of interest in other scenarios are the diagrams, appearing in the upper panel. Here the structure is Model > Model Subsets > Diagrams.  Again, related properties appear in the Properties Browser as you select them in Model Explorer.

Less obvious is the fact that "drilling down" into a diagram brings you to the graphics for tables, views and so on that appear on the actual diagram page. You can make these appear in the Model Explorer by setting Tools > Options > Model Explorer > Diagrams: Display Graphics Objects. Whether you select graphics objects in the Model Explorer or on the diagram page, their properties again appear in the Property Browser.

We can follow tree branches like:

Model > Model Subsets > Diagrams > Table Graphics > Column Graphics.

So, the Model Objects branches correspond recognizably to our knowledge of databases and their parts, and the Diagrams branches correspond to the visual diagrams and graphics we see in ModelRight.

So far so good, but the Model Explorer, the diagrams themselves and the Property Browser are all intended for the end user (ie: database designer/analyst), and hide the technical details of the actual script-accessible objects.  More investigation is needed.

Problem: In Model Explorer there is an issue that hampers several explorers/browsers in ModelRight.  Collections are captioned with a singular noun: For example the collection of Tables is captioned "Table".  This is especially misleading when a collection has no members, and thus shows no expand button to hint that it's a collection.  This I think is an impediment to discoverability.

Model Browser

The Model Browser (Model > Model Browser, and not to be confused with Model Explorer) displays the entire tree of objects and properties that constitute a ModelRight model, and shows it in a single tree view.  Here in one view we can dig into all the collections, objects and properties that we previously saw in the two panes of the Model Explorer, and on the diagram, and in many panes-worth of Property Browser. 

You may want to dig into the "Model > Table" branch, and the "Model > Model Subset...Diagram...etc" branches of an example model to reassure yourself that it's all there to be found, and to be manipulated by your scripts, if only you knew how to navigate to the data you want.

The ModelRight object model uses generic objects

Given all the build-up above, you might have expected that objects that ModelRight exposes to your script would work something like:

'--- NOT how it works! ---
  Set AModel = ModelRight.GiveMeTheDarnModel
  Set ATable = AModel.Tables("SomeTable")
  Set AColumn = ATable.Columns("SpecialColumn")
  AColumn.DataType = Integer
  ... and so on...

But this is not how ModelRight works. ModelRight has instead implemented the model using multi-purpose "MRObjects" from which to assemble a tree, and on which to hang names and database properties.  An MRObject could hold data for a table, or for a column, or an index etc. In short it's a general purpose object that holds a collection of properties and a collection of children (themselves MRObjects), and can itself be a child of some other MRObject.

This allows ModelRight to make the tree adapt to different vendors' databases (and versions thereof) -- where different database may have different complements of features and properties. This adaptability is defined by ModelRight in a separate structure called the MetaModel, which guides what ModelRight may or may not assemble into an MRModel for a particular database, and helps define what operations it can perform.

In more detail, most of the database model structure is built from five (VBS) classes of objects:

MRObject Contains properties and collections of child MRObjects. Used for Table, View, Index, Column etc
MRObjectCollection Attached to an MRObject, this Implements the collections of child MRObjects. So an MRObject holding Table data, would have an attached MRObjectCollection which contains MRObjects describing columns, indexes etc.
MRPropertyCollection Attached to an MRObject, this contains the set of properties of whatever it is that the MRObject represents
MRProperty Contains a single property -- ie: a single member item in an MRPropertyCollection
MRPropertyValue  Within an MRProperty, the value itself is contained within an MRPropertyValue object. (A property could be a vector, in which case MRVectorPropertyValue gets involved)

In practice, the Collections objects aren't accessed directly by your script statements, as MRObject includes methods to retrieve child MRObjects and MRProperties from the collections it owns.

In the Script Language API Reference it looks to me like there's some confusion over type names.  There's a type description whose caption is "Object", which I think is really MRObject aka ISCFObject. Meanwhile, "Object" is shown as the return type of a bunch of methods and properties -- there I think Object means generic VBS Object, ie: IUnknown or IDispatch.

Typical ModelRight model

Combining the above-described classes with a couple of additional classes gives us the following sketch of a typical database model, as contained in ModelRight objects:

Things to note:

Sample VBScript code to navigate the model

To consolidate this knowledge, here is a sample procedure which navigates a ModelRight model, picking out some basic info:

Sub Evaluate_OnLoad
  Set Context = CreateObject("SCF.ScriptContext")
  Set Document = Context.ScriptDocument
  Set ThisScript = Context.Object
  Set Model = ThisScript.Model
  Set ModelObject = Model.AsObject
  Set Tables = ModelObject.Children("Table")
  Document.Write("------ Tables and columns -------" & vbCRLF)
  For Each Table In Tables
    Set TableNameProp = Table.Property("Name")
    TableName = TableNameProp.AsString
    Document.Write(Table.TypeName & ": " & Table.Name & vbCRLF)
    Set Columns = Table.Children("Column")
    For Each Column in Columns
      Document.Write(" " & TableName & "." & Column.Property("Name").AsString _
                   & " : " & Column.Property("Datatype").AsString & vbNewLine)
    Next
  Next
end sub

The lines involving Context and Model are often-used preliminary steps to gain initial access to the ModelRight programming interface.  For more details on this see the ScriptContext and MRModel sections in the ModelRight Objects Reference

Interpreting the browser info for scripting purposes

Now that the concept of multi-purpose MRObjects has been covered, we can see how to use the MRXxx object model to navigate the database model, but since MRObjects are so general all we know so far is that MRObjects have generic properties and generic children, and we don't know precisely what properties and what kind of children.

For that purpose we need to return to the ModelRight environment and its browsers/explorers. 

Model Browser revisited

If you open the Model Browser (Model > Model Browser) for a typical database, you can readily follow the tree to familiar looking features and attributes, but how do these relate to the objects that your script has to work with? The basic relationships are as follows:

Item in Model Browser: What it is Example of how to access it
Has no icon. Example:
Model
    Character Set : latin1
MRProperty

Model.AsObject.Property("Character Set").AsString

Has icon; If it has children it shows an expand box.
Example:
Model
    Table
        Table: MyTable (418)
MRObject
(In this case,
for a table)

Set Tables = Model.AsObject.Children("Table")
For Each Table In Tables

MetaModel browser

What if you want to know the structure of parts of the ModelRight model that you don't happen to have an example for, and so can't view in Model Browser?  This is one of the purposes of the MetaModel Browser (Tools > MetaModel Browser).  In addition, in MetaModel Browser the tree of objects and properties is captioned in a manner somewhat closer to what you need to know as a programmer.

One minor issue with the MetaModel Browser is that both it and the Model Browser pop up in modal dialogs, so you can only open one of them at a time, when it would be useful to compare them side-by-side.  You can work around this problem by opening a second instance of ModelRight  (File > New)  and opening MetaModel Browser from there.

Here are some examples comparing what you see in Model Browser vs the same branch of the tree in MetaModel Browser.

Model Browser MetaModel Browser
Model
    Character Set 1: latin1
Model
    Properties
        Character Set
            Name: Character Set
            Definition: a set of symbols...
            Property Class: 8
            MySQL 5.0: True
Model
    Table
        Table: MyTable (418)
            [...properties...]
            Column
                Column: MyKey (420)
                    [...properties...]
                    Check Constraint
Model
    Children
        Table
            [...metamodel items...]
            Properties
                [...many...]
                Name
            Children
                Column
                    [...metamodel items]
                    Properties
                        [...many...]
                        Datatype
                            [...details...]
                        Name
                            [...etc...]
                    Children
                        Check Constraint
                            [...etc...]

The MetaModel browser makes the Children and Properties collections explicit.  Like the Model Explorer and Model Browser, it shares the idiosyncrasy of captioning collections with singular nouns rather than plural.

Suggestion for amplifying the value of the MetaModel Browser and Model Browser:

It would be a great help to script programmers if the Browsers could provide an "example code" feature:

When clicking on an item in the browser tree, have the browser show a sample statement to access that item, perhaps in a text box at the bottom of the browser dialog.

When clicking on a column in Model Browser, that aid would show something like:
Model.AsObject.AllChildren("MyTable").AllChildren("MyColumn")

When clicking on the corresponding node in MetaModel browser, a similar statement would appear, but with fake names filled in. 

If the user clicks on a collection, perhaps the example code would show how to set up a For Each for this collection.

To-dos

Below are a number of additional topics, many of which touched on in ModelRight Evangelist's basic tutorial of 2008-07-09

Automation from VBA

Automation from other environments

Debugging strategies

MetaModel discussion

IDs

How are IDs useful?

Properties

Local, vs inherited, vs calculated

This is an issue that non-programmer power-users also work with within the UI, so presumably it's discussed somewhere on that level? At any rate, probably does need a programmer-perspective discussion too.

Property terminology

modelright evangelist wrote:

Any object and any property have a type. For instance, we have objects of type “Table”, “View” or “Column”; we have properties of type “Name”, “Datatype”, etc.

I agree on MRObject, however I don't see how MRProperty has a "type" of Name, Datatype.  Looks to me like MRProperty has:
type: integer
Name: String

Transactions

Required

Scripts for generating DDL

 

ModelRight Objects (Classes) Reference

Note: As of 2008-07-11, in a number of cases I'm just guessing on the descriptions.

Classes are described in approximate order  of top-to-bottom of the overall model tree, starting with the two possible gateways to the ModelRight data:  ScriptFramework and ScriptContext.

ScriptFramework

Category Member Args Return
Type
Description
Utility        
  Initialize     In automation clients, must be called right after obtaining a ScriptFramework object.
  Evaluate Property as String String Calculate a property formula?
MetaModel        
  MetaModel   IDispatch  
Model        
  LoadModel ModelPath as String IDispatch Load model from file (xxx\xxx.wer)
  SaveModel ModelPath as String,
Model as IDispatch
  Save model to file
  Model ModelId as String IDispatch  
  ActiveModels   IUnknown  
  CreateModel   IDispatch  
  CurrentModel   IDispatch  
UI selection?        
  CurrentSelection   IUnknown  
  CurrentDrawableSelection   IUnknown  
(MR?)Object        
  CreateObject type as String,
Owner as IDispatch
IDispatch  
  DeleteObject Object as IDispatch Boolean  
  CreateObjectById type as Integer,
Owner as IDispatch
IDispatch  
Property        
  CreatePropertyValue ObjType as String,
PropType as String
IDispatch Use MetaModel to create a MRPropertyValue of the appropriate datatype.
  CreatePropertyValueById ObjType as Integer,
PropType as Integer
IDispatch  

ScriptContext

Category Member Args Return
Type
Description
Gateway to other objects        
  Object   IDispatch For ModelRight's database-manipulation scripts, ScriptContext.Object returns the "target" object, that is the object that ModelRight wants the script to operate upon.  For example, for the Column/Alter Script, ScriptContext.Object provides an MRObject of type Column, that pertains to a particular column.
For User Defined scripts, ScriptContext.Object provides an MRObject pertaining to the script itself. 
In either case, the returned MRObject can be used to get to the Model, etc.
  ScriptDocument   IDispatch Returns a ScriptDocument object to which to write
  Options   IDispatch Returns an MRObject, I think mostly as a convenient container for Properties, used by ModelRight to pass options to the script.
Database        
  CurrentDatabase   String  
  PrevDatabase   String  
Model Subset        
  SelectedModelSubset   IDispatch  
  HasSelectedModelSubset   Boolean  
  ContainedInSelectedModelSubset Obj as IDispatch Boolean  
Migration        
  MigratingRelation   IDispatch  
  MigratingColumn   IDispatch  

ScriptDocument

Category Member Args Return
Type
Description
  Write Val as String   Writes a string to the script's "output document".  Does NOT add a final line break. If linebreak is needed add it to the end of the string -- in VB using "& vbCRLF".
  WriteLine Val as String   Conspicuously missing procedure to write a string to the script's output document, including a terminating linebreak.

MRModel

Note that an MRModel also includes the features of an MRObject. See the MRModel.AsObject method.

Category Member Args Return
Type
Description
Identity, Structure Name   String  
  Id   String ???
  AsObject   IDispatch An MRModel object also includes the features of an MRModel (properties and children etc). The AsObject member gives access to that part of MRModel.
  MetaModel   IDispatch Returns a reference to a (the?) MRMetaModel that describes the allowable structure of a ModelRight database model.
         
Action management BeginTransaction pVal as String    
  EndTransaction      
  RollbackTransaction      
  Undo      
  Redo      

MRObject

Category Member (Args) Return
Type
Description
Identity, Type        
  Id   Long  
  Name   String  
  type   Long Type within the ModelRight world: Table, View, Column etc.
  TypeName   String  
  SetDatatype Datatype as String    
  IsValid   Boolean When is an MRObject invalid?
  Equals Obj: IDispatch Boolean Does this calculate object identity or value equality?
Children-related        
  Children type as String IUnknown Returns MRObjectCollection of Children that match type Type
  AllChildren   IUnknown Returns MRObjectCollection of all children?
  OriginalChildren type as String IUnknown Don't know
  ChildrenById type as Long IUnknown Presumably returns an MRObjectCollection of child objects, matching a type number.
  ChildByOrder type as String,
Order: Long
IDispatch Access children of a particular type, in order. Returns single child object?
  ChildOrder Child as IDispatch Long Tells order number of a child object within the children collection of the current object
  ModifiedChildrenPosition   IUnknown Don't know
Properties-related        
  Property type as String IDispatch Return the Property named by string type
  Properties - IUnknown returns collection of all properties on this MRObject
  PropertyById type as Long IDispatch Return the property selected by integer type
  OriginalProperty type as String IDispatch Don't know
  ModifiedProperties   IUnknown Don't know
  HasProperty PropType as WideString Boolean Tell whether property exists
  HasPropertyById PropType as Long Boolean Tell whether property exists
  SetProperty type as String,
Prop: IDispatch)
Boolean Not sure
  SetPropertyById type as Long;
const Prop as IDispatch
Boolean  
  DeleteProperty type as String Boolean  
  DeletePropertyById type as Long Boolean  
Inheritance        
  InheritsFrom   IUnknown  
  HasLocalProperty PropType as string Boolean  
  HasLocalPropertyById PropType as Long Boolean  
         
Ancestors-related        
  Owner   IDispatch  
  OldOwner   IDispatch  
  Model   IDispatch  
SQL-related        
  CreateStatement   String  
  AlterStatement   String  
  DropStatement   String  
         
Misc Evaluate Property as string String  

MRObjectCollection

In general it's not necessary to interact with an MRObjectCollection directly, as the MRObject that owns it provides methods for accessing the collection's items.

Category Member Args Return
Type
Description
All Item Index as Long Variant Returns an item. This is the default property of this object, so that code for accessing collections:
MyTable.AllChildren.Item(3)    can be compressed to:
MyTable.AllChildren(3)  
  Count   Long  
  _NewEnum   IUnknown Used by VB "for each... in..." statements

MRProperty

Category Member Args Return
Type
Description
All type   Long Is this the data type of the property, or a code for the property name?
  Name   String  
  Value   IDispatch  

MRPropertyCollection

In general it's not necessary to interact with an MRPropertyCollection directly, as the MRObject that owns it provides methods for accessing the collection's items.

Category Member Args Return
Type
Description
All Item Index as Long Variant Returns an MRProperty object
(default member of MRPropertyCollection)
  Count   Long  
  _NewEnum   IUnknown Used by VB "for each... in..." statements

MRPropertyValue

Category Member Args Return
Type
Description
Set FromString Val as String    
  FromBoolean Val as Boolean    
  FromInteger Val as Long    
  FromDouble Val as Double    
  FromObject Val as IDispatch    
         
Get AsString   String  
  AsBoolean   Boolean  
  AsInteger   Long  
  AsDouble   Double  
  AsObject   IDispatch  
  AsVector   IUnknown  
         
Test IsStringProperty   Boolean  
  IsBooleanProperty   Boolean  
  IsIntegerProperty   Boolean  
  IsDoubleProperty   Boolean  
  IsObjectProperty   Boolean  
  IsVectorProperty   Boolean  
  IsNull   Boolean  

MRVectorPropertyValue

Category Member Args Return
Type
Description
All Item Index as long Variant Returns an MRPropertyValue?
(Default property of this VBS object)
  Count   Long  
  _NewEnum   IUnknown Used by VB "for each... in.." statements
  AddValue Val: IDispatch    

 

Other References

Active Call Center programmability: Integrating COM Applications