Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
384 views

A5 SQL DB Application Architecture

The document discusses Alpha Five's architecture for supporting SQL databases. It aims to provide ease of use, portability across databases, and maintainability. The architecture uses connection strings to specify the database driver and syntax, and abstract classes that encapsulate differences between databases. Syntax handlers allow custom SQL dialects to be supported. Example scripts demonstrate common database operations like querying, updating, and importing/exporting data.

Uploaded by

mikcarh58
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
384 views

A5 SQL DB Application Architecture

The document discusses Alpha Five's architecture for supporting SQL databases. It aims to provide ease of use, portability across databases, and maintainability. The architecture uses connection strings to specify the database driver and syntax, and abstract classes that encapsulate differences between databases. Syntax handlers allow custom SQL dialects to be supported. Example scripts demonstrate common database operations like querying, updating, and importing/exporting data.

Uploaded by

mikcarh58
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 24

Alpha Five

SQL Database
Application Architecture

Alpha Five - SQL Database Application Architecture

Overview............................................................................................................................. 3
Design Goals....................................................................................................................... 3
Issues................................................................................................................................... 4
Architecture......................................................................................................................... 5
Connection Strings.......................................................................................................... 5
A Simple Connection String for a SQL Server Database ........................................... 6
A Simple Connection String for an Oracle Database ................................................. 6
Database APIs................................................................................................................. 7
Portable SQL................................................................................................................... 9
How These Examples Were Created ........................................................................ 11
Syntax Handlers ............................................................................................................ 12
Functionality ............................................................................................................. 12
User Defined Syntax Handlers.................................................................................. 12
Extracting a Schema Descriptions ............................................................................ 13
Generating Create Table Statements......................................................................... 14
The XBasic Object Model ................................................................................................ 16
About Namespaces........................................................................................................ 16
Objects that Manipulate Data........................................................................................ 16
Objects that Describe Database Objects ....................................................................... 16
Objects that Parse and Execute Portable SQL .............................................................. 16
Example Scripts ................................................................................................................ 18
Function Calls on SQL Objects .................................................................................... 18
Connecting To a SQL Database.................................................................................... 18
Fetching and Displaying Data....................................................................................... 18
Using Arguments in SQL Queries ................................................................................ 19
Working with SQL::ResultSet ...................................................................................... 20
Importing Data into a dBase Table ............................................................................... 20
Exporting Data from a dBase Table to a SQL Database .............................................. 21
Updating Rows in a SQL Database .............................................................................. 21
Inserting a Row into a SQL Database........................................................................... 22
Deleting Rows from a SQL Database........................................................................... 23
Conclusion ........................................................................................................................ 24

Page 2

2/8/2007

Alpha Five - SQL Database Application Architecture

Overview
Alpha Five is a business application development and run-time environment historically
targeted at the dBase market. Times have changed, and Alpha Software has been
retooling in recent years to support SQL databases with the same ease of use and power
that it brought to the dBase market so many years ago.
This article will discuss some of the goals, issues and architecture behind Alpha Fives
support for SQL databases. Example scripts, written in Alpha Fives Xbasic dialect of
BASIC will demonstrate how users experience the programming interface.
Note: This article assumes a basic knowledge of SQL Data Manipulation Language
(DML) and Data Definition Language (DDL) and the ability to read simple code
examples written in Xbasic.

Design Goals
Ease of use takes precedence in Alpha Five, so the first design priority is that features
work well in the simplest case and that it is possible to do complex tasks with a minimum
of code or keystrokes. It is frustrating for a new user to have functionality fail because of
something they are expected to know, but clearly dont.
Portability, in this context, is the ability to create an application that runs without code
changes when the user switches to another database vendor. It is one of those features
developers ignore until the time comes to port the application to another database server.
At the same time, when an application needs to make use of functionality unique to a
specific database, the tool should not stand in the way.
Performance is secondary, in importance, only to ease of use and portability. To get the
maximum overall balance, we want to invest an appropriate amount of attention to doing
time intensive tasks (such as importing or exporting data) quickly.
Maintainability is an indirect benefit to customers, but is a critical part of Alphas being
able to add features and database platforms in time to be useful to the marketplace. Since
Alpha Fives user interface must integrate the same architecture Xbasic programmers will
use, it is important to have dialogs and functions that do not need to be maintained when
new databases are added.

Page 3

2/8/2007

Alpha Five - SQL Database Application Architecture


Issues
Legacy applications built using Alpha Five are written to access an indexed file
sequentially or directly (by record number) one record at a time. SQL databases perform
set based operations. This means that a SQL DML command may affect or retrieve
more than one row at a time. For new applications, using the new object model discussed
below, this is not a problem. One of the ongoing challenges for the Alpha Five
development team is making SQL data look like updateable random access files (dBase
tables).
Another challenge is to abstract out the differences in the many Application
Programming Interfaces (APIs) available. This problem is hardly new, and rather than
reinventing the wheel, as you will see, Alpha Five uses the connection string approach
and installable drivers.
SQL syntax is not standard. While at first glance, SQL appears to be a single language
(and standards do exist), database vendors have a habit of inventing their own dialects of
SQL, making a SQL statement written for one database vendor incompatible for use on
another database.
Data types are not standard. When moving data between two databases, it is important
to properly map each native type. The mapping of types between databases is a
combinatorial problem. The optimal approach, as we will see, is to create a common set
of types to translate to and from so that new syntaxes can be installed easily.
Not every syntax of SQL is going to be supported out of the box. Customers need to be
able to integrate a new syntax without waiting for Alpha Software to prioritize and
implement it. This can be done using XBasic.

Page 4

2/8/2007

Alpha Five - SQL Database Application Architecture


Architecture
SQL database support is implemented in Alpha Five as a set of abstract classes. The
object model is designed to hide the details of implementations from the programmer,
and as we will see, encapsulate the tasks that tend to differ by database vendor or API.
While there are already many abstraction layers introduced for accessing databases, and
they each have value, Alpha Five is aggressively focused on ease of use. The design
goals include simplicity as well as extensibility.

XBasic Object

Connection String

Connection and Event Management

Database Driver

SQL Syntax Handler

Before looking at the object model we will discuss database APIs and syntax handlers
and the connection strings that tell Alpha Five which ones to make use of. Because the
examples in this section use connection strings, we will discuss them first.

Connection Strings
Connecting to a database can be quite complicated. First you need to know what
API/driver you want to use. Then, in the case of generic drivers you need to decide what
syntax you want to use. All of the information required to connect to a specific database
is encoded in a single connection string as a set of name/value pairs.
A connection string can be encoded in either of two formats:
Format 1 A comma separated list enclosed in soft braces (most common usage).
{Name=Value[,Name=Value] }

Page 5

2/8/2007

Alpha Five - SQL Database Application Architecture


Note: Values that may contain commas should be enclosed in single quotes.
Format 2 Tab Separated Carriage Return Line Feed delimited
Name<TAB>Value<CRLF>
Name<TAB>Value<CRLF>

Connection strings generally have a named value specifying the driver or API being used
(A5API), and (for generic drivers) a syntax to use (A5Syntax). Other values will depend
on the API and syntax selected and the options needed.
In most cases, you do not need to hand code a connection string. There are dialogs and
help interfaces (even in the script editor) that will make it easy to create them.

A Simple Connection String for a SQL Server Database


{A5API='SQLServer',Server='(local)',Trusted_connection=yes,Database='DataModeling'}

A Simple Connection String for an Oracle Database


{A5API=Oracle,A5ProcedureLanguage=PLSQL,Server='localhost',Port=1521,Service='ORCL',U
serName='Fred',Password=''}
Note that the password in the Oracle connection is obscured. This is not encryption and is only as
safe as the location the string is stored in, but does prevent someone from seeing it looking over
your shoulder as you edit or display the connection string.

Page 6

2/8/2007

Alpha Five - SQL Database Application Architecture


Database APIs
Alpha Five currently runs on Intel based Microsoft Windows platforms. As a result,
access to databases is limited by the client-side interfaces provided by vendors. Alpha
Five includes loadable libraries (DLLs), called drivers or APIs, to make use of those
client-side interfaces. These drivers come in three basic types; native drivers, generic
drivers and extension drivers.
Native drivers make use of interfaces defined by vendors that know about the database
in very specific terms (data types, options, managing data). They also tend to retrieve
data faster because they can work directly against these lower level interfaces. At the
time of this writing, Alpha Five currently supports native drivers for Oracle, DB2 and
MySQL. In the case or Oracle and MySQL there is no need to install additional client
software from the vendor. Alpha Five automatically installs Oracles thin client software
and make configuration of TNS names optional. The drivers link to the database APIs
directly. This greatly simplifies distributing database applications.
There is a single generic driver in Alpha Five at the moment; ODBC. This driver
connects to Microsoft or other vendor supplied drivers written to the ODBC interface.
Extension drivers are an innovation in Alpha Five. They are built on generic drivers
(ODBC) to simplify connecting to a database that requires specific options. These
drivers also simplify configuration of databases. ODBC extension drivers eliminate the
need to create a named data source (DSN) on each client machine. For example: the
Microsoft Access extension driver in Alpha Five accepts a file name and handles the rest.
The table below lists the drivers/APIs currently implemented by Alpha Five.
Database APIs Supported in Alpha Five
Database

Type of Driver

Access
DB2
Excel
MySQL
ODBC
Oracle
OracleLite
Paradox
QuickBooks
QuickBooksOnline
SQLServer

Extension (ODBC)
Native
Extension (ODBC)
Native
Generic
Native
Extension (ODBC)
Extension (ODBC)
Extension (ODBC)
Extension (ODBC)
Extension (ODBC)

Page 7

2/8/2007

Alpha Five - SQL Database Application Architecture


Each driver in Alpha Fives includes its own embeddable or standalone dialog that is used
throughout Alpha Five to help users define connections. The dialog is dynamically
constructed using Alpha Fives XDialog engine and returns a connection string
appropriate for the driver.
Here are some examples of the dialogs that help build connection strings. We show
dialogs for Access, ODBC, SQLServer and QuickBooksOnline drivers.

Page 8

2/8/2007

Alpha Five - SQL Database Application Architecture


Portable SQL
Alpha Five has a SQL parser built in that understands SQL INSERT, UPDATE,
DELETE and SELECT statements. The SQL objects execute portable SQL by parsing
and then automatically reconstructing database specific implementations of SQL you
create by hand, or with a user interface.
Before launching into the details, some of you may be worrying that Alpha Five requires
you to use Portable SQL. This is not the case. Unless you are working specifically with
portable syntax objects, you have the option of executing each command as either
Portable SQL or native syntax. Alpha Five also extends native syntaxes by supporting
named arguments in queries. This makes calling stored procedures very easy to do. We
will show examples of named arguments later.

Portable
SQL Statement

Query Parser

Syntax Handler

Native
SQL Statement

Alpha Five Portable SQL must contend with such issues as formatting names properly
when they contain spaces and special characters, formats for literals and subtle
differences in join syntax. The examples below show how SQL literals and names are
translated for some of the different syntaxes:
Formatting Literals
Portable SQL

SELECT 'Test', 12.4, true,


{2006-12-14},
{2006-12-15 10:00:00.123},
{11:00:00.456} from customers

Oracle

SELECT 'Test', 12.4, 1,


DATE '2006-12-14',
TIMESTAMP '2006-12-15 10:00:00.123000',

Page 9

2/8/2007

Alpha Five - SQL Database Application Architecture


TIME '11:00:00.456000' FROM customers
MySQL

SELECT 'Test', 12.4, true,


DATE('2006-12-14'),
TIMESTAMP('2006-12-15 10:00:00.123000'),
TIME('11:00:00.456000') FROM customers

SQLServer

SELECT 'Test', 12.4, true,


{d '2006-12-14'},
{ts '2006-12-15 10:00:00.123'},
{t '11:00:00.456'} FROM customers

Formatting Column Names


Portable SQL

SELECT [My Special Column Name] from customers

Oracle
MySQL
SQLServer

SELECT "My Special Column Name" FROM customers


SELECT `My Special Column Name` FROM customers
SELECT [My Special Column Name] FROM customers

Portable SQL also supports more than fifty functions for use in SQL expressions to do
things from extracting a substring to computing a standard deviation. In generating the
SQL, Alpha Five will use the native implementation where one is available. In other
cases, Alpha Five will construct SQL to generate the result using more basic functions as
building blocks. In one extreme case, for example, standard deviations are implemented
by combining SUM and COUNT functions in the appropriate expressions. The examples
below show how SQL functions are translated for some of the different syntaxes:
Formatting Functions
Portable SQL

SELECT CurrentDate(), StringLength('Hello') from customers

Oracle
MySQL
SQLServer

SELECT SYSDATE, Length('Hello') FROM customers


SELECT CurDate(), Char_Length('Hello') FROM customers
SELECT getDate() , len('Hello') FROM customers

Portable SQL also adds special syntax to handle limiting the number of rows return from
a query by using the FIRST keyword. This operation is not standard in SQL. It is
supported natively by some databases, such as Microsoft SQL Server and MySQL. In
other cases, special SQL must be generated to accomplish the desired result. The
example below shows how portable SQL using the FIRST keyword is translated by some
of the different syntax handlers:
Using the FIRST Keyword
Portable SQL

SELECT FIRST 10 * from Customers

Oracle
MySQL

SELECT * FROM (SELECT * FROM customers ) where ROWNUM <= 10


SELECT * FROM customers LIMIT 10

Page 10

2/8/2007

Alpha Five - SQL Database Application Architecture


SQLServer

SELECT TOP 10 * FROM customers

How These Examples Were Created


The SQL statements above were all generated using the XBasic code shown below. The
code was executed in Alpha Fives interactive window. Only the SQL strings themselves
were different. We will discuss the objects used in more detail further on.
dim q as sql::query
?q.parse("select first 10 * from customers")
?q.generatenativesyntax("{A5Syntax=Oracle}")
?q.generatenativesyntax("{A5Syntax=MySQL}")
?q.generatenativesyntax("{A5Syntax=SQLServer}")

Page 11

2/8/2007

Alpha Five - SQL Database Application Architecture


Syntax Handlers
Functionality
Syntax handlers are responsible for generating vendor specific SQL, mapping types,
extracting schema information. Although native drivers and extension drivers generally
each have a specific syntax, treating syntax handling as a separate set of functionality
makes it possible to share a syntax handler between native, generic, and extension
drivers.
Syntax handlers generate SQL SELECT, INSERT, UPDATE and DELETE statements
from parsed Portable SQL as described above. This includes handling literals, functions,
special naming syntax and extensions such as the FIRST keyword.
Definitional storage and the functions used to retrieve schema information vary widely in
database implementations. Alpha Five includes XBasic objects (discussed below) to
manage that information. Each syntax handler is responsible for generating and
executing SQL to extract a definition of schemas, tables, indexes and columns from the
database and returning a complex object that can be used directly in XBasic or passed to
other functions.
Syntax handlers also generate executable native SQL for such functions as creating or
dropping a table or adding a user. It requires only a few lines of XBasic code to extract a
schema definition from one database and then generate tables in another database (even
from a different vendor).
Lastly, syntax handlers map type information from database definitions to Alpha Five
data types. Although Alpha Five supports a few basic types, the objects used to do the
translation recognize over seventy different types used by a variety of databases. Not all
types are supported, but this is a pretty good list. As a result, it is possible to move
definitions to and from a database without losing information and across databases with a
minimum of loss of type information (for example, NVARCHAR remains
NVARCHAR).

User Defined Syntax Handlers


Alpha Five syntax handlers are coded in C++ for maximum performance. In cases where
you want to either override specific behavior or implement an entirely new syntax, you
can do so with Xbasic.
Note: Developers can get a list of currently available syntaxes and APIs by executing the
connection function ListAPIs() or ListSyntaxes(). In the interactive window of Alpha
Five, execute the following statements:
dim Connection as SQL::Connection
?Connection.ListAPIs()
?Connection.ListSyntaxes()

Page 12

2/8/2007

Alpha Five - SQL Database Application Architecture


Extracting a Schema Descriptions
As we have said, syntax handlers are responsible for extracting the information from the
database needed to describe the tables and views in the database. In most cases, you
dont see this activity directly, you call functions that then delegate the work to the
appropriate syntax handler.
In the code example below, we connect to a database (in this case Microsoft Access
Northwind.mdb) and extract the definition of the table Categories into an object of type
SQL::TableInfo. Again, the script is being executed in Alpha Fives interactive window.
We wont go into the details of the schema description objects, but from the example
below, you can see that Alpha Five keeps track of three kinds of data types for each
column in a TableInfo object; the Alpha type, the intermediate type and the native type.
You can access each of them as a number or a name.
dim c as sql::connection
dim ti as sql::tableinfo
c.open("{A5API=Access,FileName=Northwind.mdb}")
c.GetTableInfo(ti, "categories")
?ti.column[1].AlphaType
= "N"
?ti.column[1].AlphaTypeName
= "Numeric"
?ti.column[1].NativeType
=3
?ti.column[1].NativeTypeName
= "Integer"
?ti.column[1].ItermediateType
= 10
?ti.column[1].IntermediateTypeName
= "Integer32"

If you want to extract whole sets of table descriptions, the SQL::Schema object is
probably the best choice. It contains a set of SQL::TableInfos and can perform
operations on them as a group, including presenting them in order using the referential
constraints linking them together. This feature makes it easy to create or delete sets of
tables that depend on each other in the right order.
dim c as sql::connection
dim Sc as sql::Schema
c.open("{A5API='SQLServer',Server='(local)',Trusted_connection=yes,Database='DataModeling'}")
c.GetSchema(Sc,)
Note: Optional parameters for GetSchema can be used to include or exclude specific table types.

Page 13

2/8/2007

Alpha Five - SQL Database Application Architecture


Generating Create Table Statements
Once we have a table definition (TableInfo), we can ask the appropriate syntax handler to
generate a DDL CREATE TABLE statement based on the information in the object.
There are many functions in Alpha Five to maintain schema objects and, in many cases,
generate the SQL syntax to do it.
When creating a table from a TableInfo, types are generated based on an intermediate
type stored in the definition of each column. This intermediate type gives very fine
grained definition for types; which vary widely between database vendors. If the syntax
handler sees that the source syntax is its own (the NativeSyntax property below), it is free
to use the native type to get an exact match.
?ti.NativeSyntax
= "db2"

In the following examples, we are using the connection object to generate syntax by
assigning a connection string with only a syntax name. The connection object finds the
matching syntax handler and asks it to generate the appropriate code.
dim c as SQL::Connection
c.setconnectionstring("{a5syntax=oracle}")
?c.generateCreateTableStatement(ti)
= CREATE TABLE categories
(
CategoryID
integer NOT NULL,
CategoryName nvarchar2(15) NOT NULL,
Description
nclob NULL,
Picture long raw
NULL,
PRIMARY KEY (CategoryID))\
CREATE SEQUENCE A5AI_CATEGORIES START WITH 9 INCREMENT BY 1
NOMAXVALUE\
CREATE OR REPLACE TRIGGER A5TI_CATEGORIES BEFORE INSERT ON
CATEGORIES REFERENCING NEW AS new FOR EACH ROW WHEN (new.CategoryID IS
NULL) BEGIN SELECT A5AI_CATEGORIES.nextval into :new.CategoryID from dual; END
A5TI_CATEGORIES;
c.setconnectionstring("{a5syntax=mysql}")
?c.generateCreateTableStatement(ti)
= CREATE TABLE categories
(
CategoryID
int(10) NOT NULL,
CategoryName varchar(15)
NOT NULL,
Description
longtext NULL,
Picture longblob
NULL,
PRIMARY KEY (CategoryID))
c.setconnectionstring("{a5syntax=access}")
?c.generateCreateTableStatement(ti)
= CREATE TABLE categories

Page 14

2/8/2007

Alpha Five - SQL Database Application Architecture


(
CategoryID
long
NOT NULL,
CategoryName national char varying(15) WITH COMPRESSION NOT NULL,
Description
national char varying(134217728) WITH COMPRESSION NULL,
Picture image NULL,
PRIMARY KEY (CategoryID))
c.setconnectionstring("{a5syntax=SQLServer}")
?c.generateCreateTableStatement(ti)
= CREATE TABLE categories
(
CategoryID
integer(10)
NOT NULL,
CategoryName nvarchar(15)
NOT NULL,
Description
ntext
NULL,
Picture image NULL,
PRIMARY KEY (CategoryID))

You would not typically use the functions we have shown here in most of your code. We
show them to explain the architecture. They are used in some of the Alpha Five user
interface and are available to any developer needing a more sophisticated interface. More
often, a table would be created using a script like the one below. Normally the
GenerateCreateTableStatement function would be invoked internally.
dim SourceConnection as sql::connection
dim TargetConnection as sql::connection
dim TableDefinition as sql::tableinfo
SourceConnection.open("{A5API=Oracle,A5ProcedureLanguage=PLSQL,Server='localhost',Port
=1521,Service='ORCL',UserName='Fred',Password=''}")
SourceConnection.GetTableInfo(ti, "categories")
TargetConnection.open({a5api=excel,filename=c:\northwind.xls})
TargetConnection.CreateTable(TableDefinition)

Page 15

2/8/2007

Alpha Five - SQL Database Application Architecture


The XBasic Object Model
While there isnt room here to go into great detail, we will take a quick look at the objects
that Xbasic programmers use to interact with SQL databases. The examples that follow
should make it clearer how the objects can be used in scripts. See the Alpha Five online
documentation for more detailed descriptions of the object properties and methods.

About Namespaces
Alpha Five classes of objects and enumerations are grouped into collections called
namespaces. The namespace SQL has been added in order to group the new object
classes that implement support for SQL databases. To dimension a variable for one of
these objects, use the syntax SQL::<object class>. To help get you used to this syntax, all
of the types are named referring to their fully qualified names. The list below includes
some of the more commonly used objects.

Objects that Manipulate Data


SQL::Connection A session with a database server.
SQL::ResultSet - A collection of rows returned from the execution of a query.
SQL::Row - A single row from a result set.

Objects that Describe Database Objects


SQL::Schema A collection of SQL table definitions.
SQL::TableInfo - A fairly complete description of a SQL table, its columns, and its
indexes.
SQL::DataTypeInfo - A single column in a table or result set.
SQL::IndexInfo - A description of an index on a SQL table.
SQL::IndexColumnInfo - A description of one of the columns in an index.
SQL::IntermediateType - An enumeration used to precisely define a column type
independent of any specific database vendor.

Objects that Parse and Execute Portable SQL


SQL::Query Parses, translates and executes Portable SQL SELECT statements
SQL::InsertStatement Parses, translates and executes Portable SQL INSERT
statements.
SQL::UpdateStatement Parses, translates and executes Portable SQL UPDATE
statements.
SQL::Delete Statement Parses, translates and executes Portable SQL DELETE
statements.
SQL::Statement A generic object that can parse, translate and execute Portable
SQL SELECT, INSERT, UPDATE and DELETE statements. As new statements are
parsed, SQL::Statement takes on the appearance (properties and behaviors) of the
specific object that normally parses the statement.

Page 16

2/8/2007

Alpha Five - SQL Database Application Architecture

Page 17

2/8/2007

Alpha Five - SQL Database Application Architecture


Example Scripts
Function Calls on SQL Objects
Many SQL object functions returns a logical (.t. or .f.) and have a property named
CallResult that is of type SQL::CallResult; which contains more detailed information.
The result of the most recent call is stored in that object. For example, we can display the
text for the error by referencing the objects CallResult.Text if there is an error.

Connecting To a SQL Database


The object SQL::Connection is the basic building block of Alpha Fives SQL namespace.
This object represents a connection. Calling the Open function on the Connection causes
the appropriate driver to be loaded and attempts to connect to the database.
' Declare the connection variable
dim MyConnection as SQL::Connection
' Initialize the connection string
ConnectionString = "{A5API='SQLServer',Server='(local)',Trusted_connection=yes,Database='DataModeling'}"
' Open the connection
if MyConnection.Open(ConnectionString)
' Do something
else
ui_msg_box("Error connecting to database", MyConnection.CallResult.text)
end if

Fetching and Displaying Data


The object SQL::ResultSet is available (as the ResultSet property of a Connection) after
successfully calling the Execute function on the SQL::Connection object to invoke a
SELECT statement or a stored procedure that returns one of more result sets.
In this example, after a successful call to Execute, we call the function
SQL_ResultSet_Preview to display a limited number of rows of data in the ResultSet.
' Declare the connection variable
dim MyConnection as SQL::Connection
' Initialize the connection string
ConnectionString
= "{A5API='SQLServer',Server='(local)',Trusted_connection=yes,Database='DataModeling'}"
Query
= "select * from project"
' Open the connection
if MyConnection.Open(ConnectionString)
' Execute the query
if MyConnection.Execute(Query) then
SQL_ResultSet_Preview(MyConnection.ResultSet)
else
ui_msg_box("Error retrieving data from database", MyConnection.CallResult.text)
end if

Page 18

2/8/2007

Alpha Five - SQL Database Application Architecture


else
ui_msg_box("Error connecting to database", MyConnection.CallResult.text)
end if

Using Arguments in SQL Queries


It is more efficient (and safer when executing SQL on web pages) to use arguments in
queries than to construct them with literal values. Alpha Five makes this easy in two
ways.
First, any SQL statement (including native syntax) can contain variable names beginning
with a : character. You can use the same name in multiple places in the statement.
Alpha Five will replace the variable with the appropriate database marker at execution
time.
Secondly, the SQL::Arguments collection can be used to easily construct a list of named
values. The Add function adds or sets a value into the argument list using any supported
XBasic type. This implementation is greatly simplified when compared to APIs such as
ADO.
Note that the arguments collection is passed as a parameter to the connections Execute
function.
' Declare the connection variable
dim MyConnection as SQL::Connection
dim MyArguments as SQL::Arguments
' Initialize the connection string
ConnectionString
= "{A5API='SQLServer',Server='(local)',Trusted_connection=yes,Database='DataModeling'}"
' Initialize the query. Note: The argument RequestedId is preceded by the ':' character.
Query
= "select * from project where FeatureID = :RequestedId"
' Assign the RequestedId argument referenced in the Query
MyArguments.Add("RequestedId", 12)
' Open the connection
if MyConnection.Open(ConnectionString)
' Execute the query
if MyConnection.Execute(Query, MyArguments) then
SQL_ResultSet_Preview(MyConnection.ResultSet)
else
ui_msg_box("Error retrieving data from database", MyConnection.CallResult.text)
end if
else
ui_msg_box("Error connecting to database", MyConnection.CallResult.text)
end if

Page 19

2/8/2007

Alpha Five - SQL Database Application Architecture


Working with SQL::ResultSet
SQL::ResultSet objects have a number of functions that describe and format data. In this
example, we execute a query and then get the syntax from the ResultSet that Alpha Five
uses to create a dBase table.
Next, we call the ResultSets ToXML function to format the data retrieved into XML.
' Declare the connection variable
dim MyConnection as SQL::Connection
dim MyArguments as SQL::Arguments
dim MyResults as SQL::ResultSet
dim DisplayOutput as C
' Initialize the connection string
ConnectionString
= "{A5API='SQLServer',Server='(local)',Trusted_connection=yes,Database='DataModeling'}"
' Initialize the query. Note: The argument RequestedId is preceded by the ':' character.
Query
= "select * from project where FeatureID = :RequestedId"
' Assign the RequestedId argument referenced in the Query
MyArguments.Add("RequestedId", 12)
' Open the connection
if MyConnection.Open(ConnectionString)
' Execute the query
if MyConnection.Execute(Query, MyArguments) then
MyResults = MyConnection.ResultSet
DisplayOutput = "Row Syntax to Create a dBase Table: " + crlf(2)
DisplayOutput = DisplayOutput + MyResults.DBFRowSyntax + crlf(2)
DisplayOutput = DisplayOutput + "XML formatted Data:" + crlf(2)
DisplayOutput = DisplayOutput + MyResults.ToXML()
showvar(DisplayOutput)
else
ui_msg_box("Error retrieving data from database", MyConnection.CallResult.text)
end if
else
ui_msg_box("Error connecting to database", MyConnection.CallResult.text)
end if

Importing Data into a dBase Table


The SQL_TableImport function can be used to automatically create a dBase table and
populate it from a SQL table. The implementation of this function calls many of the
syntax handling functions we have talked about to get the definition of the table and then
construct a dBase table. It then constructs and executes a SQL SELECT and imports the
data into the local table.
' Declare the connection variable
dim MyConnection as SQL::Connection
' Initialize the connection string
ConnectionString = "{A5API='SQLServer',Server='(local)',Trusted_connection=yes,Database='DataModeling'}"
' Initialize the table Names

Page 20

2/8/2007

Alpha Five - SQL Database Application Architecture


TableName
LocalTableName

= "Project"
= "c:\test\Project.dbf"

' Open the connection


if MyConnection.Open(ConnectionString)
' Import the table
ImportResult = SQL_TableImport(MyConnection,"", TableName,LocalTableName, .t., .t., .t.)
if ImportResult.HasError
ui_msg_box("Error importing table '" + TableName + "'", ImportResult.ErrorText)
else if .not. ImportResult.UserCancelled
ui_msg_box("Import table '" + TableName + "'", "Succeeded")
end if
else
ui_msg_box("Error connecting to database", MyConnection.CallResult.text)
end if

Exporting Data from a dBase Table to a SQL Database


The SQL_TableExport function can be used to automatically create a SQL table and
populate it from a local dBase table. The implementation of this function calls many of
the syntax handling functions we have talked about to get the definition of the local table
and then construct a Create Table SQL statement. It then constructs and executes a SQL
INSERT statement to export the rows of the local table to the SQL table.
' Declare the connection variable
dim MyConnection as SQL::Connection
dim ResultMessage as C
' Initialize the connection string
ConnectionString = "{A5API='SQLServer',Server='(local)',Trusted_connection=yes,Database='DataModeling'}"
' Initialize the table Name
TableName
= "ProjectExported"
LocalTableName
= "c:\test\Project.dbf"
' Open the connection
if MyConnection.Open(ConnectionString)
' Drop the table if it exists (ignore errors)
dim ti as SQL::TableInfo
ti.name = TableName
MyConnection.DropTable(ti)
' Export the table
if .not. SQL_TableExport(MyConnection,.t., LocalTableName,"", TableName, ResultMessage)
ui_msg_box("Error exporting table '" + TableName + "'", ResultMessage)
else
ui_msg_box("Export table '" + TableName + "'", "Succeeded")
end if
else
ui_msg_box("Error connecting to database", MyConnection.CallResult.text)
end if

Updating Rows in a SQL Database


This example executes a SQL UPDATE statement, passing in a SQL::Arguments
collection that contains the values for both the SET clause and the WHERE clause.

Page 21

2/8/2007

Alpha Five - SQL Database Application Architecture


Note that after a successful call, the Connection objects CallResult.RowsAffected
property contains the number of rows that matched the WHERE clause and were updated.
' Declare the connection variable
dim MyConnection as SQL::Connection
dim MyArguments as SQL::Arguments
' Initialize the connection string
ConnectionString
= "{A5API='SQLServer',Server='(local)',Trusted_connection=yes,Database='DataModeling'}"
' Initialize the query.
Query = <<%str%
UPDATE Project SET ProjectDescription = :ProjectDescription
WHERE ProjectID = :ProjectID
%str%
' Assign the arguments referenced in the Query
MyArguments.Add("ProjectID", 12)
MyArguments.Add("ProjectDescription", "My most favorite project")
' Open the connection
if MyConnection.Open(ConnectionString)
' Execute the query
if MyConnection.Execute(Query, MyArguments) then
Rows = MyConnection.CallResult.RowsAffected
ui_msg_box("Update Data", Rows + " row" + if(Rows = 1, " was", "s were") + " added.")
else
ui_msg_box("Error updating data in database", MyConnection.CallResult.text)
end if
else
ui_msg_box("Error connecting to database", MyConnection.CallResult.text)
end if

Inserting a Row into a SQL Database


This example executes a SQL INSERT statement, passing in a SQL::Arguments
collection that contains the values for the new row.
Note that after a successful call, the Connection objects CallResult.LastInsertedIdentity
contains the value created by the database for the tables key column (ProjectID is
omitted from the INSERT statement) which is defined as AUTOINCREMENT.
' Declare the connection variable
dim MyConnection as SQL::Connection
dim MyArguments as SQL::Arguments
dim SaveIdentity as N
' Initialize the connection string
ConnectionString
= "{A5API='SQLServer',Server='(local)',Trusted_connection=yes,Database='DataModeling'}"
' Initialize the query.
Query = <<%str%
INSERT INTO Project (
ProjectName,
ProjectDescription,
FeatureID) VALUES (
:ProjectName,
:ProjectDescription,
:FeatureID)

Page 22

2/8/2007

Alpha Five - SQL Database Application Architecture


%str%
' Assign the arguments referenced in the Query
MyArguments.Add("ProjectName", "Baseball")
MyArguments.Add("ProjectDescription", "My favorite project")
MyArguments.Add("FeatureID", 12)
' Open the connection
if MyConnection.Open(ConnectionString)
' Execute the query
if MyConnection.Execute(Query, MyArguments) then
Rows = MyConnection.CallResult.RowsAffected
SaveIdentity = MyConnetion.CallResult.LastInsertedIdentity
ui_msg_box("Insert Row", Rows + " row" + if(Rows = 1, " was", "s were") + " added.")
else
ui_msg_box("Error inserting row into database", MyConnection.CallResult.text)
end if
else
ui_msg_box("Error connecting to database", MyConnection.CallResult.text)
end if

Deleting Rows from a SQL Database


This example executes a SQL DELETE statement, passing in a SQL::Arguments
collection that contains the value for the WHERE clause.
Note that after a successful call, the Connection objects CallResult.RowsAffected
property contains the number of rows that matched the WHERE clause and were deleted.
' Declare the connection variable
dim MyConnection as SQL::Connection
dim MyArguments as SQL::Arguments
' Initialize the connection string
ConnectionString
= "{A5API='SQLServer',Server='(local)',Trusted_connection=yes,Database='DataModeling'}"
' Initialize the query.
Query = "DELETE from Project WHERE FeatureID = :RequestedId"
' Assign the argument referenced in the Query
MyArguments.Add("RequestedId", 12)
' Open the connection
if MyConnection.Open(ConnectionString)
' Execute the query
if MyConnection.Execute(Query, MyArguments) then
Rows = MyConnection.CallResult.RowsAffected
ui_msg_box("Delete Rows", Rows + " row" + if(Rows = 1, " was", "s were") + " deleted.")
else
ui_msg_box("Error deleting rows from database", MyConnection.CallResult.text)
end if
else
ui_msg_box("Error connecting to database", MyConnection.CallResult.text)
end if

Page 23

2/8/2007

Alpha Five - SQL Database Application Architecture


Conclusion
Alpha Software is committed to creating world class development tools to make creating
business applications for the web and for the desktop easy, fast, and cost effective. The
architecture we have discussed is part of a rich set of tools that will continue to evolve by
pushing the level of functionality to higher and higher levels of abstraction.
Example functions like SQL_ImportTable and SQL_ExportTable make it possible to
replicate tables with only a few lines of code.
Moving forward, we will push toward managing complex sets of data in updateable
collections.
This is just the beginning

Page 24

2/8/2007

You might also like