May 30, 2008
Using the new database functionality in the iPhone
WebKit, and therefor Safari and the UIWebView, allows a programmer to access its’ built in SQLite database via JavaScript. Using the PhoneDataAccessObject from QuickConnectiPhone makes this very easy.
As a quick example, if you use the PhoneDataAccessObject from the QuickConnectiPhone framework, creation of a database is as simple as
//this line will create the table if it doesn't exist. If it already exists a database error is thrown that is ignored.
var database = new PhoneDataAccessObject("WelcomeExample", "1.0", "Welcome example", 20);
//this line will create the states table.
database.setData("CREATE TABLE states (id INTEGER UNIQUE, state TEXT)");
Since the QuickConnectiPhone framework supplies you with a client side session object you can just as easily store your applications current state assuming you have kept the client side session object up to date by modifying it every time the application state changed.
//serialize the client side session that stores the current state of the application
var params = [JSON.stringify(aClientSideSession)];
//insert the generated string into the states table the current state as the first record
database.setData('INSERT OR REPLACE INTO states (id, state) values( 1, ?)', params);
At startup of the application or at any time you choose you can easily retrieve the state data to reset the application’s current state to the stored state.
database.getData('SELECT state FROM states WHERE id=1');
Notice that there is no return value from the getData method. That is because all calls to the underlying SQLite database are asynchronous. The QuickConnectiPhone framework will pass the data that is the result of the query to any View Control Function you have defined where you can use the JSON library to de-serialize the stored session and use it.
See the previous post on the QuickConnectiPhone framework for more information. If you wish to see the source code for the PhoneDataAccessObject download the QuickConnectiPhone framework and open the PhoneDataAccessObject.js file. Download it here..
May 29, 2008
iPhone hybrid UIWebView applications can now use the SQLite database
It works! The latest beta (6) of the iPhone OS includes the ability to use the SQLite database from JavaScript. This is the last step required to begin to create standalone applications on the iPhone written completely in HTML, CSS, and JavaScript. These are not web applications. These are fully fledged applications in their own right. You no longer need to know how to write Objective-C in order to create standalone applications.
You can now store the current state of you application on exiting and restore it when the application is started up again. This will allow you to use the links that start the Calendar, Contacts, music, videos, etc. When such a link is selected you app is exited and the other one started. You then exit that app and start yours again. Prior to this database fix your application could not restore its’ state at startup.
The source code for the library that does this is to large to place here as an example but a followup posting will include an example of how to easily access and use the database functionality built into WebKit. If you go to the QuickConnectiPhone download you can get an Xcode and Dashcode project that includes sample code. They show how to interact with the database easily without knowing the unique requirements of SQLite.
for an explanation of these projects and what the QuickConnectiPhone framework is see my previous post.
May 28, 2008
QuickConnect iPhone: an iPhone UIWebView hybrid framework
Having seen the interest in the UIWebView post I made a while back, a followup posting on the framework that includes the class discussed in that posting seems to be needed. I created this framework so that you don’t have to reinvent the wheel when you start creating iPhone hybrid applications. An Objective-C version of this framework is also in the works. I look forward to receiving feedback from you.
A new version of QuickConnectiPhone is now available. To see the new functionality that is in the current shipping versions look here. For a QuickStart on how to use QuickConnect look here.This posting is just a brief overview of the framework to give you an idea of how you can use it. The download of the framework, select the iPhone download out of the family, includes a simple example application. The framework is open source and is licensed under lgpl so you can use it in your free application or one you decide to charge for.
The QuickConnect iPhone framework is designed to make iPHone hybrid applications easy to create and yet use as little processing power and memory as possible. The framework is distributed as Xcode and Dashcode projects that you can drop into each of those applications. When you do they become available in the gallery of project types.
These two new project types allow you to create and test your application from within Dashcode and then move it into Xcode, compile it, run it, and install it directly onto your device. No internet connection is then required to use your application.
The framework includes a javascript wrapper to the SQLite database that is embedded in WebKit, the engine used by the UIWebView class. This wrapper, called a Data Access Object (DAO), allows you to make calls to the database using two simple methods, getData and setData. You use getData to do queries and setData to do updates, insertions, and other modifications to the database. The result of a query is returned to you as a standard JavaScript array and other information is stored in the DAO such as any error numbers, error messages, the field names and their indices, etc. If you have inserted a record into a table and the table has an auto incrementing primary key field the DAO also stores the newly created key value. All of this is done without you needing to know the peculiarities of interacting with SQLite. For example,in WebKit all of the actual API calls to the database are asynchronous. You don’t need to worry about this since the framework and the DAO take care of this for you.
It must be noted that beta 5 of the iPhone OS 2.0 does not yet have the capability to interact with the SQL database from within JavaScript. It does work from within the simulators accessible from Xcode and Dashcode. A defect has been reported to Apple and I am hoping the functionality will be included in an upcoming beta release.
If you choose to retrieve remote data from a web server the QuickConnect iPhone framework supplies you with a Server Access Object (SAO). This SAO behaves like the DAO but wraps AJAX calls instead of database calls. You use it the same way as the DAO. It has a getData function that uses a GET type of request and a setData that is a POST type of request.
Since your application is running as a hybrid application you can use the SAO to make calls to any number of servers in any number of locations in your application. This is different than if you were making an AJAX call from within a browser. In that case you can only request data from the server that the current page originated from. Since you can now request data from any server you wish you will need to make sure the data you received is secure. The framework supplies you with security functions to make this easy for you.
The QuickConnect iPhone framework allows you to create what are called control functions. The types of these control functions are:
- Validation Control Functions (ValCF’s) – You use these to validate user input. You can have zero, one or more ValCF’s for each user interaction with your application.
- Business Control Functions(BCF’s) – This is where you make a call the Data Access Objects’ (DAO) methods to query or modify the database. There is one of these per user interaction.
- View Control Functions (VCF’s) – These are where the screen is updated for the user and other ‘view’ type functionality is defined. For example you may want to update some number of global variables or the client-side Session object supplied by the framework. You can have one or more VCF’s per user interaction.
- Error Control Functions(ECF’s) – Zero, one, or more of these functions can be applied to a command. This is where error handling is done. These errors may be due to user interaction or, if you choose to retrieve data from a web server, from a web server.
- Security Control Functions(SCF’s) – Zero, one, or more of these functions can be applied to a request to a web server to ensure that the data received has not been interfered with via something like a man-in-the-middle attack. The example application doesn’t access a remote server so there are none created or mapped.
The framework uses a Command/Behavior paradigm. This allows you to create each of these type of functions in the provided functions.js file, or any other file you wish, and then place a call to the mapping function that will map your command to the control function. Below are the example mappings and control functions from the example application included in the QuickConnect iPhone download. This is just a partial example. To see the full example please download the framework.
/*
*
* This file is organized by the command being handled.
*/
mapCommandToValidation("setName",validateNameInputValCF);
mapCommandToBCF('setName', setNameBCF);
mapCommandToView('setName', displayNameVCF);
mapErrorToControl('setName', dbError);
mapCommandToBCF('getName', getNameBCF);
mapCommandToView('getName', displayNameVCF);
mapErrorToControl('getName', dbError);
mapCommandToBCF('clearName', dropTableBCF);
mapCommandToView('clearName', displayPromptVCF);
mapErrorToControl('clearName', dbError);
/*
* This validation function ensures that the name field is not empty
*/
function validateNameInputValCF(){
if(document.getElementById('nameInput') != null){
//retrieve the name and remove any white space
//from the beginning and end of the field values if any
var name = trim(document.getElementById('nameInput').value);
if(name != ''){
return true;
}
}
return false;
}
/*
*
*
* Business Control Functions
*
*
*/
function setNameBCF(){
//retrieve the welcome name and remove any white space
//from the beginning and end of the fields' values
var userName = trim(document.getElementById('nameInput').value);
var params = [userName];
//insert the name into the database
database.setData('INSERT OR REPLACE INTO names (id, name) values( 1, ?)', params);
}
function getNameBCF(){
//document.getElementById('displayName').innerHTML = database.getData;
//document.getElementById('nameDisplay').innerHTML = 'getting Name '+window['openDatabase'];
database.getData('SELECT name FROM names WHERE id=1');
//return nothing since database query results are handled asynchronously
}
function dropTableBCF(){
database.setData("DROP TABLE names");
}
/*
*
*
* View Control Functions
*
*
*/
/*
* This function displays a name if one was found in the database or
* if a name was just inserted into the database.
*/
function displayNameVCF(result){
var aName = "";
var data = result.getData();
//if the result has data then this data must have been retrieved from the database
if(data){
if(data.length > 0){
aName = data[0][0];
}
//no name was found in the database
else{
displayPromptVCF(data);
return;
}
}
//there must have been an update done
else{
aName = trim(document.getElementById('nameInput').value);
}
document.getElementById('nameDisplay').innerHTML = aName;
document.getElementById('nameInput').value = "";
}
/*
* This function displays to the user that they need to enter a name for display since no
* stored value could be found.
*/
function displayPromptVCF(data){
aName = "Please enter a name to be displayed.";
document.getElementById('nameDisplay').innerHTML = aName;
document.getElementById('nameInput').value = "";
}
/*
*
*
* Security Control Functions
*
*
*/
//Since no there is no accessing of data from servers there are no security control functions in this example
/*
*
*
* Error Control Functions
*
*/
function dbError(){
displayPromptVCF();
}
To see the full example and how the framework is embedded in an Objective-C application and what the other parts of the framework are please download the framework.
May 24, 2008
Handling very large integers in Erlang
As mentioned in a previous post, Erlang appears to handle very large integers whose limit is RAM and other hardware limitations of the machine. In fact I have calculated 50,000! several times on my machine.
Multiplication, subtraction, and addition all work with these numbers without any programmer interference in Erlang. Division and other functionality uses the underlying OS functionality and so do not work with these large numbers.
I have written some code that allows division to work with these large numbers as well as a few other items such as m_choose_n, factorial, and floor. I have not spent time to evaluate speed optimizations for the code other than to use bit shifting to handle the actual division.
The division functions are:
- big_rem – similar to mod. It returns only the remainder of the division
- big_div_with_rem – returns both an integer quotient and remainder
- big_divide – returns a floating point value if it is possible to calculate it or an integer quotient and remainder if it is not possible
The code below is part of my simulation engine written in Erlang and is used in conjunction with the sim_dist library that contains random number distribution streams such as normal, binomial, negative binomial, and other types of streams the code for which will become available on sourceforge when I have finished testing it.
%% Copyright 2008 Lee S. Barney
%% This file is part of erl_sim.
%% erl_sim is free software: you can redistribute it and/or modify
%% it under the terms of the GNU Lesser General Public License as published by
%% the Free Software Foundation, either version 3 of the License, or
%% (at your option) any later version.
%%
%% erl_sim is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%% GNU Lesser General Public License for more details.
%%
%% You should have received a copy of the GNU Lesser General Public License
%% along with QuickConnectiPhoneHybrid. If not, see http://www.gnu.org/licenses/.
%% Description: This file contains functions for doing division with very large numbers as well as some other
%% useful functions
-module(sim_math).
%%
%% Include files
%%
%%
%% Exported Functions
%%
-export([big_divide/2, big_div_with_rem/2, big_rem/2, floor/1,
factorial/1, m_choose_n/2]).
%%
%% API Functions
%%
%%
%% TODO: Add description of div_with_rem/function_arity
%%
big_div_with_rem(Dividend, Divisor) ->
if
Divisor /= 0 ->
{ok,New_divisor,Cnt} = count_div_shifts(abs(Dividend), abs(Divisor), 0),
case big_div_with_rem_helper(abs(Dividend), abs(New_divisor),Cnt,0) of
{ok, Quotient, Remainder} when (Dividend < 0) xor (Divisor
{ok,-Quotient,-Remainder};
{ok, Quotient, Remainder} ->
{ok, Quotient, Remainder};
{error,Why} ->
{error,Why};
true ->
{error,"Unknown error"}
end;
true ->
{error,"Division by Zero error"}
end.
%%
%% TODO: Add description of big_divide/function_arity
%%
big_divide(Dividend, Divisor)->
%double limit. Erlang uses underlying system algorithms for floating point mathematics
Limit = math:pow(2,1023),
case big_div_with_rem(Dividend, Divisor) of
{ok,Quotient,Remainder} ->
if
Remainder == 0 ->
{ok, Quotient};
%the quotient must be less than the limit or else and error will happen
%when the result floating point value is added to it
%the remainder and the divisor must be less than the limit or else the
%division will fail.
Remainder < Limit andalso Divisor < Limit andalso Quotient
Result = Remainder/abs(Divisor),
io:format("Remainder/Divisor:~p Quotient:~p~n",[Result,Quotient]),
{ok, Quotient+Result};
true ->
{ok, Quotient,Remainder}
end;
{error,Why} ->
{error,Why}
end.
%%
%% TODO: Add description of big_rem/function_arity
%%
big_rem(A, B) ->
if
B /= 0 ->
{ok,New_divisor,Cnt} = count_div_shifts(abs(A), abs(B), 0),
case big_div_with_rem_helper(abs(A), abs(New_divisor),Cnt,0) of
{ok, Quotient, Remainder} when (A < 0) xor (B
{ok,-Remainder};
{ok, Quotient, Remainder} ->
{ok, Remainder};
{error,Why} ->
{error,Why};
true ->
{error,"Unknown error"}
end;
true ->
{error,"Division by Zero error"}
end.
%%
%% TODO: Add description of floor/function_arity
%%
floor(X) ->
T = trunc(X),
case X - T T - 1;
false -> T
end.
%factorial of N
factorial(N) ->
fact_helper(N, 1).
fact_helper(0, Product) ->
Product;
fact_helper(1, Product) ->
Product;
fact_helper(N, Product) ->
%io:format("N: ~p Product: ~p~n",[N, Product]),
fact_helper(N - 1, Product * N).
m_choose_n(M,N) ->
if
N > M orelse N < 0 orelse M 0;
true ->
factorial(M)/(factorial(N)*factorial(M-N))
end.
%%
%% Local Functions
%%
big_div_with_rem_helper(Dividend, Divisor, Count, Quotient) ->
%io:format("Dividend:~p Divisor:~p Count:~p~n",[Dividend, Divisor, Count, Quotient]),
if
Count
{ok, Quotient, Dividend};
true ->
if
Divisor =
big_div_with_rem_helper(Dividend-Divisor, Divisor bsr 1, Count-1, (Quotient bsl 1) +1);
true ->
big_div_with_rem_helper(Dividend, Divisor bsr 1, Count -1, Quotient bsl 1)
end
end.
count_div_shifts(Dividend, Divisor, Cnt) ->
if
Divisor =
count_div_shifts(Dividend, Divisor bsl 1, Cnt+1);
true ->
{ok,Divisor bsr 1, Cnt -1}
end.
May 23, 2008
UIWebView Example Code
The information in this posting is old and has been superseded by the information in a new post.
The information and source code covered in this posting has been expanded on and is included in a downloadable framework called QuickConnectiPhone. Take a look at this posting about version 1.5 to learn more more.
There is also a development roadmap
It appears that a great need exists for a straight forward example of how to use the UIWebView class. The purpose of this example is to show how to use it from within a class that can be initialized by an application delegate class. I have included both the header and source file code so that you can see how this can be done. The complete source for these files as well as additional code and helps can be found at the QuickConnect site. Go to the downloads section and grab the QuickConnectiPhone framework.
If you wish to have your view scale in response to pinch gestures you will need to uncomment the
//aWebView.scalesPageToFit = YES;
line.
This class also is listening to acceleration events and making a call to a javascript function which you would need to write when an acceleration event occurs. I hope this is helpful. I am working on some QuickConnectiPhone documentation right now and hope to have an introduction video available soon.
To see a quick discription of the QuickConnectiPhone framework see this post.
The header file:
/*
Copyright 2007 Lee S. Barney
This file is part of QuickConnectiPhoneHybrid.
QuickConnectiPhoneHybrid is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QuickConnectiPhoneHybrid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with QuickConnectiPhoneHybrid. If not, see .
*/
#import
#define kAccelerometerFrequency .001 //Hz
@interface BrowserViewController : UIViewController {
UIWebView *webView;
}
@property (nonatomic, retain) UIWebView *webView;
@end
The class file:
/*
Copyright 2007 Lee S. Barney
This file is part of QuickConnectiPhoneHybrid.
QuickConnectiPhoneHybrid is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QuickConnectiPhoneHybrid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with QuickConnectiPhoneHybrid. If not, see .
*/
#import "BrowserViewController.h"
@implementation BrowserViewController
@synthesize webView;
– (id)init
{
/*
if (self = [super init]) {
}
*/
return self;
}
– (void)loadView
{
NSLog(@”loading view”);
// the base view for this view controller
UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
contentView.backgroundColor = [UIColor blueColor];
// important for view orientation rotation
contentView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
self.view = contentView;
self.view.autoresizesSubviews = YES;
//create a frame that will be used to size and place the web view
CGRect webFrame = [[UIScreen mainScreen] applicationFrame];
webFrame.origin.y -= 20.0; // shift the display up so that it covers the default open space from the content view
UIWebView *aWebView = [[UIWebView alloc] initWithFrame:webFrame];
self.webView = aWebView;
//aWebView.scalesPageToFit = YES;
aWebView.autoresizesSubviews = YES;
aWebView.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
//set the web view and acceleration delagates for the web view to be itself
[aWebView setDelegate:self];
//determine the path the to the index.html file in the Resources directory
NSString *filePathString = [[NSBundle mainBundle] pathForResource:@”index” ofType:@”html”];
//build the URL and the request for the index.html file
NSURL *aURL = [NSURL fileURLWithPath:filePathString];
NSURLRequest *aRequest = [NSURLRequest requestWithURL:aURL];
//load the index.html file into the web view.
[aWebView loadRequest:aRequest];
//add the web view to the content view
[contentView addSubview:webView];
[aWebView release];
[contentView release];
}
– (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations.
return YES;
}
– (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if(fromInterfaceOrientation == UIInterfaceOrientationPortrait){
NSString* result = [webView stringByEvaluatingJavaScriptFromString:@”rotate(0)”];
//NSString a = *result;
NSLog(result);
}
else{
[webView stringByEvaluatingJavaScriptFromString:@”rotate(1)”];
}
//[self.webView sizeToFit];
//CGRect curBounds = [[UIScreen mainScreen] bounds];
//[self.webView setBounds:self.origViewRectangle];
//[[UIScreen mainScreen] bounds]]
//NSLog(@”orienting”);
}
– (void) accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
{
NSString* javaScriptCall = [NSString stringWithFormat:@”accelerate(%f, %f, %f)”, acceleration.x, acceleration.y, acceleration.z];
[webView stringByEvaluatingJavaScriptFromString:javaScriptCall];
//Use a basic low-pass filter to only keep the gravity in the accelerometer values
//_accelerometer[0] = acceleration.x * kFilteringFactor + _accelerometer[0] * (1.0 – kFilteringFactor);
//_accelerometer[1] = acceleration.y * kFilteringFactor + _accelerometer[1] * (1.0 – kFilteringFactor);
//_accelerometer[2] = acceleration.z * kFilteringFactor + _accelerometer[2] * (1.0 – kFilteringFactor);
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning]; // Releases the view if it doesn’t have a superview.
// Release anything that’s not essential, such as cached data.
}
– (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
NSLog(@”An error happened during load”);
}
– (void)webViewDidStartLoad:(UIWebView *)webView{
NSLog(@”loading started”);
}
– (void)webViewDidFinishLoad:(UIWebView *)webView{
NSLog(@”finished loading”);
}
– (void)dealloc
{
[super dealloc];
}
@end
May 22, 2008
Numeric Limitations in Erlang
The debugging process for the erlang distribution code continues. While debugging the binomial distribution last night I wrote a naive factorial calculator the code for which is common.
%factorial of N
factorial(N) ->
fact_helper(N, 1).
fact_helper(0, Product) ->
Product;
fact_helper(1, Product) ->
Product;
fact_helper(N, Product) ->
fact_helper(N - 1, Product * N).
Out of curiosity I started plugging in large numbers. The largest I have tried is 50,000! It took about 1.5 seconds to calculate and the result is much to large to post here. In fact, I was going to post it here but the number is too large to fit in the clipboard on my machine. Even if the sequence of digits was divided into 6 segments the segments still don’t fit in the clipboard.
This seems to indicate that for integer addition, subtraction, and multiplication the upper numerical bound is limited only by your hardware.
Division is different. It appears to use standard floating point type algorithms. Floating point numbers appear to have a limit similar to other languages and causes an error if the numbers are too large.
For example
sim_dist:factorial(20)/sim_dist:factorial(19).
yeilds 20 as expected.
sim_dist:factorial(200)/sim_dist:factorial(199).
** exception error: bad argument in an arithmetic expression
in operator '/'/2
throws a bad argument exception for the division operator. Floating point numbers therefor must have a maximum size that is less than 199!
An amazing language.
May 20, 2008
iPhone Exchange Server Client
I connected my iPhone up to my works’ exchange server today. My iPhone is running the version 2 beta 5 OS. It connected right up without a problem. Best of all, when I started looking at my email I could view Word and Excel files directly within the mail application. I tried both 2003 and 2007 formats and both worked really well.
I am very pleased. Now if the client would insert meetings into my Calendar when the meeting file is selected just like mail does on my mac it would be super.
May 19, 2008
Erlang Simulation Testing Times
The Erlang simulation engine, which I now call erlSim, is running. I have some test results that show the concurrency capabilities of the Erlang language and the erlSim simulator.
Num Processes | Events per Process | Total Events | Seconds per Event | Total Time |
---|---|---|---|---|
1 | 1 | 10 | 0.000079900000 | 0.000799 |
5 | 1 | 50 | 0.000009260000 | 0.000463 |
1 | 10 | 100 | 0.000016520000 | 0.001652 |
25 | 25 | 6250 | 0.000014700640 | 0.091879 |
100 | 100 | 100000 | 0.000014360140 | 1.436014 |
200 | 200 | 400000 | 0.000015691415 | 6.276566 |
50 | 1000 | 500000 | 0.000015591182 | 7.795591 |
This information indicates that as the number of concurrent processes increases there is not a significant increase in the speed each process requires.
This data was generated on :
2.4 Ghz Intel Core 2 Duo
2 GB RAM
OS X MacBook
Erlang (BEAM) emulator version 5.6.1
This is looking very promising as a basis for discreet event simulations. I am working on a series of random number streams (triangular, normal, beta, etc.) to go with this basic engine. It is nearing completion for eight different random number stream types.
May 16, 2008
PHP modular framework
QuickConnectPHP is a modular framework for the server side of PHP applications. It can be downloaded from QuickConnectPHP on sourceforge. The idea behind it, as with most frameworks, is to make it easy for developers to create applications that are scalable, flexible, and secure.
Currently I am working on a database access object to include in the frame work that interacts with Oracle. The existing database access object works with MySQL. Both of these classes have a straight forward API that hides much of the complexity of interacting with a database. The main methods are getData for doing queries and setData for all other calls. Prepared statements are handled as well as BLOBs, CLOBS, transactions, and stored procedures.
When the DAO is used to interact with a database it stores and makes available such information as error codes and messages, the id of any new records inserted into tables that use auto-incrementing keys, the field names retrieved in select statemets, etc. If the getData method is used the result of the query is returned to the programmer making the call as a standard PHP 2D array.
The Oracle version is now moving into the testing phase. The getData and setData methods allow the programmer to follow a prepared statement pattern that uses a ? as the place holder in the SQL. They then replace these question marks with bindings to variables. This frees the programmer from needing to know how to interact with OCI8 and doing variable bindings.
I hope to have this Oracle version in a beta state soon so a working version can replace the place holder in the QuickConnectPHP package available from sourceForge.
Erlang Simulator
Erlang is an interesting language. It appears to be hugely concurrent without threads in the language. It has its’ own strangeness such as the lack of variables, loops, etc. but overall very interesting.
I have created a modular discreet event simulation engine that takes advantage of the languages possibilities. It has allowed me to make full use of both cores on my machine and have thousands of concurrent simulation events executing. I have not noticed much of a per event execution penalty either. Very interesting.
I am looking forward to creating a factory scheduling simulation package based on this work.
There are now testing times available in this follow up entry
Erlang Simulation Testing Times.