Skip to content
pb-diff Help

PowerBuilder object types

pb-diff does not compare a PowerBuilder export as lines of text. It reads each object into the parts PowerBuilder itself keeps apart - a window's controls and scripts, a DataWindow's columns, a query's clauses - and compares part with part, so a change is named by what changed. This page says what those parts are for each kind of object. Every example is one of the Order Desk files installed beside pb-diff, in docs/examples/order-desk: release 1.4 under old, release 1.5 under new.

Object Export What pb-diff compares
Window .srw Variables, functions, events, controls with their properties and scripts
User object .sru As a window; a visual one has controls too
Menu .srm Each menu item, with its properties and scripts
Function .srf The function, with its signature and its script
Structure .srs Each member
Query .srq Each table, column, join, condition, sort key and argument
Data pipeline .srp Each setting, each column of the source and destination tables, and the retrieve query
Project .srj Each entry, and each library on its own
DataWindow .srd Each band, control, property, database column, and the retrieve SQL
Application .sra As a window, with the global variables

The files that hold an application together beside its objects - workspaces, targets, Solutions and their projects, resource files and PowerGen projects - have a page of their own: Project and build files.

The same reading applies whichever way an object arrives: an export file, an entry of a .pbl, or a source of a PowerBuilder 2025 Solution. pb-diff-cli parse <file> --format json prints the parts of any of them.

Windows

A window is read into its declarations, its variables (instance, shared and global), its external functions, each function and event script, and each control. A control is a node holding its own property block and its own scripts, so a button whose text changed and a button whose clicked script changed are two different findings. A function is identified by its name: when its signature changes, the old and the new function are paired as one modified function rather than one deleted and one added.

Your first comparison walks through w_order_entry, where release 1.5 changed four functions, deleted one and added two.

User objects

A user object is read as a window is. A non-visual one, n_order_service in Order Desk, is its variables, functions and events; a visual one has controls as well. The signature of of_price changed in release 1.5, and pb-diff shows one modified function with both signatures under the panes: see A changed signature.

Each item of a menu is a node, with its properties and its scripts, wherever it sits in the menu. In m_order_desk, release 1.5 replaced Print preview with Export invoices: the tree shows one item deleted and one new, and the new item's clicked script reads on its own. See A menu.

Functions

A global function is one function: its signature, its variables and its script. A change of parameters is a modified function, as it is inside a window; the signature strip under the panes shows both. f_round_money is the Order Desk example, and is the same in both releases.

Structures

Each member of a structure is a node, named by its name and then its type - unit_price (decimal{2})

pb-diff comparing two versions of the structure s_order_line. The tree shows the structure's definition with the member discount (decimal{2}) marked new; the definition is selected, and the added discount line is shown in green in the New pane.
In the s_order_line structure, release 1.5 adds a discount member. Each member is a node of its own, named by its name and its type, and the structure's definition shows the whole change in place. Select the image to view it at full size.
pb-diff-cli compare old/s_order_line.srs new/s_order_line.srs --format json

(result)

Queries

PowerBuilder writes a query as one PBSELECT statement on one line, often some hundreds of characters long. pb-diff shows the statement as Query, and beneath it each part of it, grouped: Tables, Columns, Joins, Where, Group By, Having, Order By and Arguments. Each part is named by what it is - orders.order_no, orders.status = 'O' - and shows its exact text.

In release 1.5, q_open_orders also selects the order total and lists the newest orders first. The tree says exactly that: orders.total_amount new under Columns, and orders.order_date modified under Order By.

pb-diff comparing two versions of the query q_open_orders. The tree shows the Query node with its Columns group, where orders.total_amount is marked new and selected, and a collapsed Order By group marked modified; the New pane shows the added COLUMN clause in green and the Old pane has nothing in its place.
The q_open_orders query in release 1.5 also selects the order total and lists the newest orders first. Each table, column, condition and sort key of the query is a node of its own, so the added column is named in the tree. Select the image to view it at full size.
pb-diff-cli compare old/q_open_orders.srq new/q_open_orders.srq --format json

(result)

A query is only meaningful whole, so the Query node is what a merge takes or leaves: select it to take the old or the new query. Two people who each changed the same query meet in a conflict, which is decided on the query as a whole. A query written as plain SQL rather than PBSELECT is one statement with nothing beneath it.

Data pipelines

A data pipeline is four statements, each a node:

In release 1.5, dp_archive_orders copies the customer too, and commits every 500 rows instead of 100. The tree shows commit modified under Pipeline, and customer_id new in the source table, in the retrieve query and in the destination table.

pb-diff comparing two versions of the data pipeline dp_archive_orders. The tree shows the Pipeline node with its commit setting modified, the source table orders and the destination table orders_archive each with a new customer_id column, and the Retrieve node with its Columns group; the new customer_id column of the destination is selected, and its COLUMN definition is shown in green in the New pane.
The dp_archive_orders pipeline in release 1.5 copies the customer too, and commits every 500 rows. Each setting of the pipeline and each column of its tables and of its retrieve query is a node of its own. Select the image to view it at full size.
pb-diff-cli compare old/dp_archive_orders.srp new/dp_archive_orders.srp --format json

(result)

A merge takes or leaves each statement whole. One person who changed the commit interval and another who renamed the destination table changed two statements, and the two changes merge.

Projects

A project is a list of entries, one per line, each a node named for what it holds: Executable (EXE), Compiler options (CMP), Product version (PVS) and so on. A project has one library entry for each library of the application, and each is named and paired by its library - Library orders.pbl (PBD) - so a library added, removed or built differently is that library. The objects a project lists are paired the same way, by the object and its type - Object w_main (OBJ) - and not by the path of their library, which is wherever the project was last saved.

Within a line, pb-diff marks only the field that changed: when the executable is built against another PowerBuilder runtime, the runtime version at the end of the Executable line is what is highlighted, not the whole line. In release 1.5, p_order_desk moves to the PowerBuilder 2025 runtime, gains a copyright and carries version 1.5.

pb-diff comparing two versions of the project p_order_desk. The tree lists the changed entries by name - Executable (EXE), Copyright (CPY) and the product and file versions - all marked modified; the Executable entry is selected, and the strip under the panes shows its old and new line, which differ only in the runtime version at the end, 22.2.0.3397 against 25.0.0.6430.
The p_order_desk project in release 1.5 builds against the PowerBuilder 2025 runtime and carries version 1.5. Each entry of a project is a node named for what it holds, and within a line only the field that changed is marked. Select the image to view it at full size.
pb-diff-cli compare old/p_order_desk.srj new/p_order_desk.srj --format json

(result)

A merge takes or leaves each entry.

DataWindows

A DataWindow is read into its bands, the controls in each band, every property of every control, the table definition with each database column, and the retrieve SQL. Each property is a node of its own and their order is not a difference, so a changed display format is that format and nothing else. The DataWindow Overview at the top summarises it: its processing style, its columns, its bands, how many controls it has, its update table and its retrieve SQL. See A DataWindow, where release 1.5 filters out cancelled lines and shows negative amounts in red.

The application

The application object is read as a window is: its global variables, its events and its create and destroy scripts, each a node. In order_desk.sra the open event opens w_order_entry; the application is the same in both releases.

In every comparison

Whatever the type, the same tree, the same navigation and the same five reports apply, and a library compare lists each object with its type. A part beneath a statement - a column of a query or of a pipeline, a property of a DataWindow control - is marked and can be selected and read, but the counts, the change navigation and a merge work on the statement that holds it. How a merge decides is in How merging works.