I have managed to knock up an initial draft. You will see straight away that it is very limited in what it does. I have managed to run the select statement as shown in the code and it does return 10000 records although I have not checked for any boundary conditions. Although I expect there are a few of them lurking due to the way the driver has been written but we can ignore the driver bugs for now ;-) or at least until Dan finds them.
.pcc_sub _MAIN prototyped
.param pmc argv
.include "/home/parrot/dbdi/lib/dbdi/dbdi_header.imc"
.sym string dbstring
.sym PerlHash dbh
dbstring = "host=lhost dbname=name user=user password=pass"
.pcc_begin prototyped
.arg dbstring
.pcc_call connect
retconnect:
.result dbh
.pcc_end
print "New $dbh successful????\n"
# Now that we have a $dbh we can pass it into
# the prepare funtion with the SQL statement
.sym Sub sth
.sym string sql
sql = "select * from parrot"
.pcc_begin prototyped
.arg dbh
.arg sql
.pcc_call prepare
retprepare:
.result sth
.pcc_end
print "SQL statement prepared????\n"
# We need to access the execute function
# before we call it.
.sym int rows
.pcc_begin prototyped
.arg sth
.pcc_call execute
retexecute:
.result rows
.pcc_end
.PRINT("Execution Successful ", rows, " Affected\n" )
.sym PerlArray rowarray
.sym int rowcount
.sym PerlString field0
.sym PerlString field1
.sym PerlString field2
.sym PerlString field3
.sym PerlString field4
fetchnext:
.pcc_begin prototyped
.pcc_call fetch
retfetch:
.result rowarray
.result rowcount
.pcc_end
if rowcount == 0 goto finish
field0 = rowarray[0]
field1 = rowarray[1]
field2 = rowarray[2]
field3 = rowarray[3]
field4 = rowarray[4]
.PRINT("", field0, "")
.PRINT(" ", field1, "")
.PRINT(" ", field2, "")
.PRINT(" ", field3, "")
.PRINT(" ", field4, "")
.PRINT(" ROWCOUNT = ", rowcount , "\n" )
branch fetchnext
finish:
end
.end
.include "/home/parrot/dbdi/lib/dbdi/dbdi_functions.imc"
#######################################################
=head1 NAME
DBDI Example usage
=head1 SYNOPSIS
.pcc_sub _MAIN prototyped
.param pmc argv
.include "/home/parrot/dbdi/lib/dbdi/dbdi_header.imc"
.sym string dbstring
dbstring = "host=lhost dbname=name user=user password=pass"
.pcc_begin prototyped
.arg dbstring
.pcc_call connect
retconnect:
.pcc_end
print "New $dbh successful\n"
.sym string sql
sql = "select * from parrot"
.pcc_begin prototyped
.arg sql
.pcc_call prepare
retprepare:
.pcc_end
print "SQL statement prepared\n"
end
.end
include "/home/parrot/dbdi/lib/dbdi/dbdi_functions.imc"
=head1 DESCRIPTION
I am hoping that this file gives some indication
on how the first draft of the DBDI can be used to
connect to and access a database. For the time
being please assume that the driver we are using
is the universal babel fish driver. It is actually
a roughly hacked Postgres Driver I knocked up
purpose built to facilitate working on the DBDI.
It is not the actual Postgres driver and very
little development is being carried out on it at
this time. I will work on it B<if> we need a
feature added to help with the DBDI otherwise
please ignore it an do not use it as a good
example to base further drivers on.
You will also notice that I have not shown how to
execute or fetch results. There is also no error
handling in this at the moment. I have a very good
reason for this, one of the best, I have not
written it yet ;-). I am working on this at the
moment.
=head1 Gettin Started.
We are allowed to use B<POD> in IMCC source files.
The pod can go at the top or the bottom of the
source. I have had some odd results mixing pod in
with the source. Unfortunately this means that we
have no excuse not to do documentation ;-)
I am going to walk you through what I have done
step by step so that we can see what is required
to use IMCC to access a database using the DBDI.
This is not an IMCC tutorial just some pointers as
to what is involved using IMCC.
=over 4
=item Program Entry
PLEASE NOTE. THE WALKTHROUGH IS NOW OUT OF DATE.
The first line of our program is our entry point
and those familiar with C will notice the C<_MAIN>
declaration. This indicates where Parrot is going
to start execution from.
1 .pcc_sub _MAIN prototyped
The second line is an optional parameter that we
can pass in to our program. We are not going to be
using it, so for now we can ignore it.
2 .param pmc argv
Line 3 is a very important line. To use the Parrot
DBDI we first need to make sure that we have
access to its data structures and any necessary
funtions that we need. The C<.include> directive
loads the contents of the following header files
directly into our program during pre-processing.
This is not a runtime load. There are also some
nasty affect associated with this but this which
will become apparetn if you dive deeper into the
Parrot DBDI.
3 .include "/home/parrot/dbdi/lib/dbdi/dbdi_header.imc"
Line five demonstrates how we declare datatyes in
IMCC. C<.sym> can be used interchangeably with
C<.local> but it involves less typing so I have
been using it throughout. C<string> is the
B<type>. In this case we are declaring a string
constant which is what our driver requres as a
connect string.
5 .sym string dbstring
Line six is the connect string required by the
driver.
6 dbstring = "host=lhost dbname=db user=user password=pass"
Now for a more interesting part. IMCC allows us to
use various methods to make funtions calls. The
one we are using is C<prototyped> which basically
tells IMCC that we know what we are doing and are
going to pass in any arguments (C<.arg>) that are
required by the funtion. In this case we are
passing in the constant string declared earlier.
7 .pcc_begin prototyped
8 .arg dbstring
The next two line are the actual call and return
point. In our case we are calling the C<connect>
function. Control will be passed to the line
immediatley after the call where we have declared
a return continuation C<retconnect>. There is
noting special about the name of the label we used
for the return but we did have to declare the
C<connect> function before use. This was done in
the DBDI header file.
9 .pcc_call connect
10 retconnect:
11 .pcc_end
The rest is pretty self explanatory.
12 print "New $dbh successful\n"
13
14 .sym string sql
15 sql = "select * from parrot"
16 .pcc_begin prototyped
17 .arg sql
18 .pcc_call prepare
19 retprepare:
20 .pcc_end
21 print "SQL statement prepared\n"
These two lines are required at the end of every
program.
22 end
23 .end
All of this will be changing as we add more
features and change the design. In fact it
could be you who makes the change or suggests a
feature that changes this interface so post your
thoughts to the DBDI list.
For a detailed description of IMCC please see
the IMCC faq at http://www.parrotcode.org/faq/imcc
=head1 DIAGNOSTICS
If you encounter an error please submit......??
=head1 BUGS
Of that, I am absolutely sure.
=head1 TODO
=over 4
=item Returning objects from functions
I want to return some object like structures back
from the functions above rather than hiding
everything in the background. This will make it
easier to see and know what is going on between
calls.
=item We need objects
The current method above is a stop gap until they
arrive. Objects give us much needed privacy
amongst other things.
=item We need runtime loading
This will be required when we have multiple
drivers and do not know which one we want until we
run the program.
=item1 execute()
Write the C<execute> function.
=item fetch()
Write the C<fetch> function.
=item Error Handling
There is a multitude of error handling functions
and data structures that need to be written to
make the above code remotely robust or even
useful.
=item Tests
Tests are going to have to be written once we have
agreed an acceptable test suite.
=back
=head1 AUTHOR
Harry Jackson
=head1 COPYRIGHT
Copyright (c) 2004, Harry Jackson. All Rights
Reserved. This is free software. It may be used,
redistributed and/or modified under the same terms
as Parrot itself.
=cut
