mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-16 16:25:54 +01:00
211 lines
5.6 KiB
C++
211 lines
5.6 KiB
C++
|
/*
|
||
|
* PROGRAM: Object oriented API samples.
|
||
|
* MODULE: 02.update.cpp
|
||
|
* DESCRIPTION: Run once prepared statement with parameters
|
||
|
* a few times, committing transaction after each run.
|
||
|
* Learns how to prepare statement, manually define parameters
|
||
|
* for it, execute that statement with different parameters
|
||
|
* and perform non-default error processing.
|
||
|
*
|
||
|
* Example for the following interfaces:
|
||
|
* IAttachment - database attachment
|
||
|
* ITransaction - transaction
|
||
|
* IStatement - SQL statement execution
|
||
|
* IMessageMetadata - describe input and output data format
|
||
|
* IMetadataBuilder - tool to modify/create metadata
|
||
|
* IStatus - return state holder
|
||
|
*
|
||
|
* Note that all updates are rolled back in this version. (see *** later)
|
||
|
*
|
||
|
* The contents of this file are subject to the Interbase Public
|
||
|
* License Version 1.0 (the "License"); you may not use this file
|
||
|
* except in compliance with the License. You may obtain a copy
|
||
|
* of the License at http://www.Inprise.com/IPL.html
|
||
|
*
|
||
|
* Software distributed under the License is distributed on an
|
||
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||
|
* or implied. See the License for the specific language governing
|
||
|
* rights and limitations under the License.
|
||
|
*
|
||
|
* The Original Code was created by Inprise Corporation
|
||
|
* and its predecessors. Portions created by Inprise Corporation are
|
||
|
* Copyright (C) Inprise Corporation.
|
||
|
*
|
||
|
* All Rights Reserved.
|
||
|
* Contributor(s): ______________________________________.
|
||
|
* Alex Peshkov, 2013
|
||
|
*/
|
||
|
|
||
|
#include "ifaceExamples.h"
|
||
|
|
||
|
static IMaster* master = fb_get_master_interface();
|
||
|
|
||
|
int get_input(char*, double*);
|
||
|
static const char* Dept_data[] =
|
||
|
{"622", "100", "116", "900", 0};
|
||
|
static double Percent_data[] =
|
||
|
{0.05, 1.00, 0.075, 0.10, 0};
|
||
|
int Input_ptr = 0;
|
||
|
|
||
|
int main()
|
||
|
{
|
||
|
int rc = 0;
|
||
|
|
||
|
// set default password if none specified in environment
|
||
|
setenv("ISC_USER", "sysdba", 0);
|
||
|
setenv("ISC_PASSWORD", "masterkey", 0);
|
||
|
|
||
|
// status vector and main dispatcher
|
||
|
ThrowStatusWrapper status(master->getStatus());
|
||
|
IProvider* prov = master->getDispatcher();
|
||
|
|
||
|
// declare pointers to required interfaces
|
||
|
IAttachment* att = NULL;
|
||
|
ITransaction* tra = NULL;
|
||
|
|
||
|
// Interface executes prepared SQL statement
|
||
|
IStatement* stmt = NULL;
|
||
|
|
||
|
// Interfaces provides access to format of data in messages
|
||
|
IMessageMetadata* meta = NULL;
|
||
|
|
||
|
// Interface makes it possible to change format of data or define it yourself
|
||
|
IMetadataBuilder* builder = NULL;
|
||
|
|
||
|
const char* updstr =
|
||
|
"UPDATE department SET budget = ? * budget + budget WHERE dept_no = ?";
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// attach employee db
|
||
|
att = prov->attachDatabase(&status, "employee", 0, NULL);
|
||
|
|
||
|
// start transaction
|
||
|
tra = att->startTransaction(&status, 0, NULL);
|
||
|
|
||
|
// prepare statement
|
||
|
stmt = att->prepare(&status, tra, 0, updstr, SAMPLES_DIALECT, 0);
|
||
|
|
||
|
// build metadata
|
||
|
// IMaster creates empty new metadata in builder
|
||
|
builder = master->getMetadataBuilder(&status, 2);
|
||
|
// set required info on fields
|
||
|
builder->setType(&status, 0, SQL_DOUBLE + 1);
|
||
|
builder->setType(&status, 1, SQL_TEXT + 1);
|
||
|
builder->setLength(&status, 1, 3);
|
||
|
// IMetadata should be ready
|
||
|
meta = builder->getMetadata(&status);
|
||
|
// no need in builder any more
|
||
|
builder->release();
|
||
|
builder = NULL;
|
||
|
|
||
|
// allocate buffer on stack
|
||
|
char buffer[256];
|
||
|
unsigned len = meta->getMessageLength(&status);
|
||
|
if (len > sizeof(buffer))
|
||
|
{
|
||
|
throw "Input message length too big - can't continue";
|
||
|
}
|
||
|
|
||
|
// locations of parameters in input message
|
||
|
char* dept_no = &buffer[meta->getOffset(&status, 1)];
|
||
|
double* percent_inc = (double*) &buffer[meta->getOffset(&status, 0)];
|
||
|
|
||
|
// null IDs (set to NOT NULL)
|
||
|
short* flag = (short*)&buffer[meta->getNullOffset(&status, 0)];
|
||
|
*flag = 0;
|
||
|
flag = (short*) &buffer[meta->getNullOffset(&status, 1)];
|
||
|
*flag = 0;
|
||
|
|
||
|
// Get the next department-percent increase input pair.
|
||
|
while (get_input(dept_no, percent_inc))
|
||
|
{
|
||
|
printf("\nIncreasing budget for department: %s by %5.2lf percent.\n",
|
||
|
dept_no, *percent_inc);
|
||
|
|
||
|
// Update the budget.
|
||
|
try
|
||
|
{
|
||
|
stmt->execute(&status, tra, meta, buffer, NULL, NULL);
|
||
|
}
|
||
|
catch (const FbException& error)
|
||
|
{
|
||
|
// Handle exception raised during statement execution
|
||
|
if (error.getStatus()->getErrors()[1] == isc_not_valid)
|
||
|
{
|
||
|
// Don't save the update, if the new budget exceeds the limit.
|
||
|
printf("\tExceeded budget limit -- not updated.\n");
|
||
|
|
||
|
tra->rollbackRetaining(&status);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Another error - use default handler
|
||
|
throw;
|
||
|
}
|
||
|
|
||
|
// Save each department's update independently.
|
||
|
// *** Change to commitRetaining() to see changes
|
||
|
// *** tra->commitRetaining(&status);
|
||
|
tra->rollbackRetaining(&status);
|
||
|
}
|
||
|
|
||
|
// close interfaces
|
||
|
stmt->free(&status);
|
||
|
stmt = NULL;
|
||
|
|
||
|
meta->release();
|
||
|
meta = NULL;
|
||
|
|
||
|
tra->commit(&status);
|
||
|
tra = NULL;
|
||
|
|
||
|
att->detach(&status);
|
||
|
att = NULL;
|
||
|
}
|
||
|
catch (const FbException& error)
|
||
|
{
|
||
|
// handle error
|
||
|
rc = 1;
|
||
|
|
||
|
char buf[256];
|
||
|
master->getUtilInterface()->formatStatus(buf, sizeof(buf), error.getStatus());
|
||
|
fprintf(stderr, "%s\n", buf);
|
||
|
}
|
||
|
|
||
|
// release interfaces after error caught
|
||
|
if (builder)
|
||
|
builder->release();
|
||
|
if (meta)
|
||
|
meta->release();
|
||
|
if (stmt)
|
||
|
stmt->release();
|
||
|
if (tra)
|
||
|
tra->release();
|
||
|
if (att)
|
||
|
att->release();
|
||
|
|
||
|
prov->release();
|
||
|
status.dispose();
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Get the department and percent parameters for an example to run.
|
||
|
*/
|
||
|
|
||
|
int get_input (char *dept_no, double *percent)
|
||
|
{
|
||
|
if (Dept_data[Input_ptr] == 0)
|
||
|
return 0;
|
||
|
|
||
|
strcpy(dept_no, Dept_data[Input_ptr]);
|
||
|
|
||
|
if ((*percent = Percent_data[Input_ptr++]) == 0)
|
||
|
return 0;
|
||
|
|
||
|
return 1;
|
||
|
}
|