Going Cross-Platform Again Using Visual FoxPro To Connect To A MySQL Database On Linux
Going Cross-Platform Again Using Visual FoxPro To Connect To A MySQL Database On Linux
Remember when one of FoxPro's claims to fame was "cross-platform capability"? You
could write an application and, with a bit of forethought and planning, make that single
code base run on DOS, Windows, Unix, and Mac platforms. Then some marketing genius
subverted the term "cross-platform" to mean Windows 3.1, Windows 95, and Windows NT,
and the capability of Fox to run on other platforms gradually disappeared. But happy
days are here again. In this article, Bob Lee shows you how to use Visual FoxPro desktop
applications to access data residing on another platform, specifically addressing the
issues involved in connecting to a MySQL database running on a Linux server.
I have to come clean. I initially wrote this article to show VFP developers that creating a
client/server application doesn't need to be a daunting task anymore. There are still
perceived roadblocks of technology, time and learning curves, and substantial software
costsbut these can all be overcome. I wanted to move from a pure desktop VFP
application into client/server systems, but I kept running into roadblocks. The online Help
took me deep into the quagmire of possibilities and unfamiliar syntax, none of which made
any sense and would take hours of testing to see what the right fit was for power and
simplicity to use. Microsoft SQL Server, while less expensive than Oracle, is still costly;
and its little brother, MSDE, with its five-user maximum, has been crippled so that it's
unusable for anything but learning practice and trivial applications.
But this article has turned out to be a good tutorial for learning how to connect to
non-Windows-based databases as well. I've managed to kill two birds with one stone.
Why MySQL?
When I started to look into taking the next step from a VFP Web application to a true
client/server desktop application, I was noticing MySQL over and over again. It seemed to
be everywhere. Other databases were available, and I assume they'd work equally well, but
the sheer number of installations of MySQL at ISPs and ASPs impressed me. Good
documentation, many after-market books, and a healthy following of dedicated users eager
to help were other factors that pushed me toward MySQL. Like anything, MySQL isn't
the right solution for every database application or VFP-connected application, but it's a
worthy contender. Before you spend hours with it, you should be aware of MySQL's
limitations. For example, subqueries and stored procedures aren't yet supported on the
MySQL server.
Getting started
Okay, it's time to get started. How about a big-picture view first? Your VFP application
will send a SQL statement to MySQL via an ODBC driver, and that gets carried over your
network (whether that network is a local area network or the Internet doesn't really
matter) via TCP/IP to the machine running MySQL. The MySQL database processes the
SQL statement and returns the results to VFP as a read-write cursor. You manipulate that
cursor, and then commit your changes back to the server.
Let's look at each step individually.
Access to MySQL
The first thing you'll need is access to a MySQL database. I'm going to assume that you've
got access to a Linux server running MySQL with a known IP address. Unlike SQL
Server, where you have to depend on the operating system to know where the database is
(how many of you have had a SQL Server "disappear" from the combo box without
warning?), you just use the IP address of the Linux box to identify the MySQL server.
ODBC connections
The next thing you'll need is a means to connect VFP to MySQL. This is done through the
MySQL ODBC driver. ODBC is a set of protocols that all database servers have mutually
agreed upon and provide a common interface. Microsoft is now moving away from ODBC
to a new interface called OLEDB, but the most mature databases in the market haven't
converted to OLEDB, so stick with the tried-and-true ODBC for the time being. You can
download the latest version from the MySQL Web site for free.
A read-write cursor
Yes, a read-write cursor! When you finish making changes to the data, you post the
changes back to the server using standard SQL all the time. You're working with
something you know and understandthe VFP cursor. SKIP and REPLACE to your
heart's content on your read-write cursor. At the end, write one line of code to post your
changes to the server. Done. That's it.
Reports are just as simple. Get a cursor with the data you're interested in. REPORT
FORM YOUR REPORT TO PRINT. Close the cursor. That's it. Adding a record is just as
simple. Get a blank record cursor, do your REPLACE statements on the cursor, and then
insert your new records to the server.
Once you have it in mind that you're always working with cursors (and not the table
itself, or a VFP view), remembering to put back your changes becomes as simple as a SQL
version of tableupdate(.t.).
Pointers
In actuality, you do have to write your own wrappers for the connection statements (or
use a commercial framework). But once you've done so, they become part of your library,
and you simply use them over and over.
The second tip is to stay away from Remote Views. While they appear to be easier to
set up, you're no longer in control of the actual SQL statements or the VFP buffering when
Remote Views are used. Reliability and speed both suffer when you employ Remote
Views.
Since SQL Servers don't have the concept of a deleted record, you might want to
change the structure of your tables on the server to duplicate the "deleted" functionality of
the DBF by adding a field to each table that represents the deleted flag in DBFs. I use a
one-char field (like a tiny INT-type field) and fill it with a 1 or a 0 to indicate whether the
record is considered deleted(). My sample code uses a field name DLD as the deleted
record field for each table.
A Primary Key field is required on all MySQL tables. This is because the concept of a
record number isn't native to a SQL table. Make use of the auto_inc feature of MySQL.
You can define a field as an INT-type field and make it auto_inc. This much-wanted field
type in VFP is native to MySQL and instantly gives you a unique record ID and PK if you
need one.
MySQL on Linux is case-sensitive when it comes to table namesbecause Linux, like
other variants of Unix, is case-sensitive. Be aware that when you write your SQL
statements you must make sure you match the case for the names of the tables you're
attempting to query. If you're running MySQL on Windows, the table names aren't case-
sensitive
Don't go overboard with the use of the MySQL permissions functions. While they
appear at first reading to be able to do everything that your application could need, I
found it's much better to set up only three classes of users. SQL Table permissions can be
made rather complex, but details are beyond the scope of this article. Suffice it to say that
I'd suggest that you create these three: The first is you or the database administrator, the
second is the regular users who can read and write to tables, and the third is the casual
user who can only read, but not write. The MySQL permissions don't restrict the types of
SQL statements you can issue, and thus you'd need to code separate statements to allow
for different groups of users. Thus, most of that security needs to be written into your
application. So don't get too hung up on using the permissions.
Since most of us started out with DBF files in a directory, it may be comforting to
understand what the file structure of a MySQL database looks like. A MySQL database
essentially maps to a disk directory, and the tables are files in that directory. There's one
special database called "mysql" that holds the users and permissions to tables for the
server that's being used. The structure of MySQL is a server applicationon Windows, it's
running as a service while in Linux it's called a Daemon process like an HTTP server. The
service is usually started on boot-up, runs 24x7, and is only really active and takes
resources when a SQL request is sent to it.
There's a command line interface to the server itself, but I for one haven't used it past
getting the first user on. Then I prefer using MySQLFront or VFP to do all communication
with the server. MySQL is configured like most Linux applications by modifying one text
file (my.cnf), which is in a similar syntax to a Windows INI file. So, essentially, you start it
up, let it run, and manage it with MySQLFront.
has to be surrounded by curly brackets because it has a space embedded in the name.
SERVER=216.XXX.XXX.13X;
This identifies the location of the MySQL server machine. The syntax can be a name
instead of an IP address, but doing so is a little slower with a name because every time it
has to communicate with the server, it has to do a name resolution.
PORT=3306;
The port is optional. It's usually set up by the server at port 3306. My server is running
MySQL on port 1433, so leave it out of your connection string if you're communicating
with a normal MySQL server.
UID=bob; PWD=XXXXXX;
It's a good idea to pass in the DATABASE namethat way, the default database is set
up, and you don't have to specify on each SQL statement you make what database you're
communicating with. This setting is optional.
option=131609
This option parameter number is a value consisting of multiple binary flags, much like
the parameters for Visual FoxPro's MessageBox function. More specifically, it's
constructed like so: Go to your ODBC control panel, and open up a MySQL DSN as
shown in Figure 1. The options I'm referring to are the ones at the bottom (a bunch of
check boxes). They're numbered top to bottom starting with the first column. The first
option is 1, the second is 2, the third is 4, then 8, 16, 32... To set multiple options, you add
their values together and pass that number. So if you want options 1, 2, and 3, you'd pass
7 (1 + 2 + 4).
Figure 1. The MySQL ODBC driver configuration.
The options I selected, to add up to 131,609, include "Pad char to full length," "Don't
optimize column width," and "Safety (check this if you have problems)"without padding
char to full length, the trim (value) of the data is returned from the server. That looks like
it's a really big number, but it's simply five options that equate to the binary values of the
first, fourth, fifth, tenth, and eighteenth options.
Function Description
MySQL Wrapper to get a VFP cursor from a MySQL table (but doesn't disconnect).
MySQLP Wrapper to get a VFP cursor from a MySQL table (and disconnects).
DtoSQL Converts VFP data to standard data that's understood by MySQL.
FixSQL Called from FixSQL.
MySave Saves data from a cursor to the MySQL table. It builds the SQL statement
on the fly based on the structure of the current cursor, and sends to the
MySQL server a SQL commandto save any changes made to the cursor.
MyBlank Creates an empty one-record VFP cursor, ready to for you to populate with
data.
MyNew Appends the currently selected cursor to the matching MySQL table
record. This first passes in the MySQL procedure, stays connected, gets a
new PK (auto-increment), updates the record, and then disconnects from
the server.
MyError A basic error-trapping script to write a text file with error information.
The only difference between MySQL and MySQLP is that MySQL doesn't disconnect.
This is used so you can append a record and let the MySQL server create an automatic PK
for you in the table.
Rough versions of each of these functions are included in MY.PRG in the Download
file for this article.
Conclusion
Put together these concepts, procedures, and functions, and you're ready to take the next
logical step into the client/server world. Make use of the Internet and your skills using
VFP as a client to MySQL, and then it's a short jump to any other SQL database. You can
make great desktop applications served with data from the Internetand you're able to
connect to SQL databases on platforms other than Windows.
MySQL and the MySQL ODBC driver are available now for freetogether, you end
up with fewer lines of VFP code, faster applications than you'd have programming the
same functions using native VFP tables, and, I've found, enhanced features and speed that
could only come from working in a true client/server environment.
My love of the Fox over the years is partly due to Fox giving us the ability to
distribute free runtimes for our applications. With MySQL, you can develop true, robust
client/server applications without having to pay the hefty license fees that SQL Server
requires. This solutioncost-free VFP runtimes and license-free MySQLis a truly cost-
effective cross-platform solution for my clients, and possibly yours as well.
Download 03LEESC.ZIP
Bob Lee is the IT manager at Wolf-Gordon. He's written Xbase solutions since 1987 using dBASE
III+/dBman on DOS and Xenix/FoxPro. He's created Web-connected database applications since 1998
and MySQL applications since 2001. He's currently working on a replacement for Adobe Acrobat to
create PDF files and migrate data and reports from legacy systems to more modern interfaces and
electronic document storage. bob@1amsoftware.com.