a5 sql db application architecture

Upload: miltoncarhuas

Post on 04-Nov-2015

37 views

Category:

Documents


2 download

DESCRIPTION

Alpha Five SQL

TRANSCRIPT

  • Alpha Five

    SQL Database Application Architecture

  • Alpha Five - SQL Database Application Architecture

    Page 2 2/8/2007

    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

  • Alpha Five - SQL Database Application Architecture

    Page 3 2/8/2007

    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.

  • Alpha Five - SQL Database Application Architecture

    Page 4 2/8/2007

    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.

  • Alpha Five - SQL Database Application Architecture

    Page 5 2/8/2007

    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.

    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] }

    Connection and Event Management

    Database Driver

    SQL Syntax Handler

    XBasic Object

    Connection String

  • Alpha Five - SQL Database Application Architecture

    Page 6 2/8/2007

    Note: Values that may contain commas should be enclosed in single quotes. Format 2 Tab Separated Carriage Return Line Feed delimited

    NameValue NameValue

    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',UserName='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.

  • Alpha Five - SQL Database Application Architecture

    Page 7 2/8/2007

    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 Extension (ODBC)DB2 Native Excel Extension (ODBC)MySQL Native ODBC Generic Oracle Native OracleLite Extension (ODBC)Paradox Extension (ODBC)QuickBooks Extension (ODBC)QuickBooksOnline Extension (ODBC)SQLServer Extension (ODBC)

  • Alpha Five - SQL Database Application Architecture

    Page 8 2/8/2007

    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.

  • Alpha Five - SQL Database Application Architecture

    Page 9 2/8/2007

    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.

    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',

    Query Parser

    Portable SQL Statement

    Syntax Handler

    Native SQL Statement

  • Alpha Five - SQL Database Application Architecture

    Page 10 2/8/2007

    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 SELECT "My Special Column Name" FROM customers MySQL SELECT `My Special Column Name` FROM customers SQLServer 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 SELECT SYSDATE, Length('Hello') FROM customers MySQL SELECT CurDate(), Char_Length('Hello') FROM customers SQLServer 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 SELECT * FROM (SELECT * FROM customers ) where ROWNUM

  • Alpha Five - SQL Database Application Architecture

    Page 11 2/8/2007

    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}")

  • Alpha Five - SQL Database Application Architecture

    Page 12 2/8/2007

    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()

  • Alpha Five - SQL Database Application Architecture

    Page 13 2/8/2007

    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.

  • Alpha Five - SQL Database Application Architecture

    Page 14 2/8/2007

    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

  • Alpha Five - SQL Database Application Architecture

    Page 15 2/8/2007

    ( 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)

  • Alpha Five - SQL Database Application Architecture

    Page 16 2/8/2007

    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::. 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.

  • Alpha Five - SQL Database Application Architecture

    Page 17 2/8/2007

  • Alpha Five - SQL Database Application Architecture

    Page 18 2/8/2007

    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

  • Alpha Five - SQL Database Application Architecture

    Page 19 2/8/2007

    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

  • Alpha Five - SQL Database Application Architecture

    Page 20 2/8/2007

    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

  • Alpha Five - SQL Database Application Architecture

    Page 21 2/8/2007

    TableName = "Project" LocalTableName = "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.

  • Alpha Five - SQL Database Application Architecture

    Page 22 2/8/2007

    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 =

  • Alpha Five - SQL Database Application Architecture

    Page 23 2/8/2007

    %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

  • Alpha Five - SQL Database Application Architecture

    Page 24 2/8/2007

    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