mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-16 08:15:53 +01:00
210 lines
5.3 KiB
C++
210 lines
5.3 KiB
C++
/*
|
|
* PROGRAM: Object oriented API samples.
|
|
* MODULE: 03.select.cpp
|
|
* DESCRIPTION: A sample of running SELECT statement without parameters.
|
|
* Prints string fields in a table, coercing VARCHAR to CHAR.
|
|
* Learns how to coerce output data in prepared statement
|
|
* and execute it.
|
|
*
|
|
* Example for the following interfaces:
|
|
*
|
|
* IStatement - SQL statement execution
|
|
* IMessageMetadata - describe input and output data format
|
|
* IResultSet - fetch data returned by statement after execution
|
|
*
|
|
* The contents of this file are subject to the Initial
|
|
* Developer's 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.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
|
*
|
|
* Software distributed under the License is distributed AS IS,
|
|
* 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 Alexander Peshkoff
|
|
* for the Firebird Open Source RDBMS project.
|
|
*
|
|
* Copyright (c) 2013 Alexander Peshkoff <peshkoff@mail.ru>
|
|
* and all contributors signed below.
|
|
*
|
|
* All Rights Reserved.
|
|
* Contributor(s): ______________________________________.
|
|
*/
|
|
|
|
#include "ifaceExamples.h"
|
|
|
|
static IMaster* master = fb_get_master_interface();
|
|
|
|
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();
|
|
IUtil* utl = master->getUtilInterface();
|
|
|
|
// declare pointers to required interfaces
|
|
IAttachment* att = NULL;
|
|
ITransaction* tra = NULL;
|
|
IStatement* stmt = NULL;
|
|
IMessageMetadata* meta = NULL;
|
|
IMetadataBuilder* builder = NULL;
|
|
IXpbBuilder* tpb = NULL;
|
|
|
|
// Interface provides access to data returned by SELECT statement
|
|
IResultSet* curs = NULL;
|
|
|
|
try
|
|
{
|
|
// attach employee db
|
|
att = prov->attachDatabase(&status, "employee", 0, NULL);
|
|
|
|
// start read only transaction
|
|
tpb = utl->getXpbBuilder(&status, IXpbBuilder::TPB, NULL, 0);
|
|
tpb->insertTag(&status, isc_tpb_read_committed);
|
|
tpb->insertTag(&status, isc_tpb_no_rec_version);
|
|
tpb->insertTag(&status, isc_tpb_wait);
|
|
tpb->insertTag(&status, isc_tpb_read);
|
|
tra = att->startTransaction(&status, tpb->getBufferLength(&status), tpb->getBuffer(&status));
|
|
|
|
// prepare statement
|
|
stmt = att->prepare(&status, tra, 0, "select last_name, first_name, phone_ext from phone_list "
|
|
"where location = 'Monterey' order by last_name, first_name",
|
|
SAMPLES_DIALECT, IStatement::PREPARE_PREFETCH_METADATA);
|
|
|
|
// get list of columns
|
|
meta = stmt->getOutputMetadata(&status);
|
|
builder = meta->getBuilder(&status);
|
|
unsigned cols = meta->getCount(&status);
|
|
|
|
// struct to cache received metadata
|
|
struct MyField
|
|
{
|
|
const char* name;
|
|
unsigned length, offset;
|
|
};
|
|
MyField* fields = new MyField[cols];
|
|
memset(fields, 0, sizeof(MyField) * cols);
|
|
|
|
// parse columns list & coerce datatype(s)
|
|
for (unsigned j = 0; j < cols; ++j)
|
|
{
|
|
unsigned t = meta->getType(&status, j);
|
|
|
|
if (t == SQL_VARYING || t == SQL_TEXT)
|
|
{
|
|
builder->setType(&status, j, SQL_TEXT);
|
|
fields[j].name = meta->getField(&status, j);
|
|
}
|
|
}
|
|
|
|
// release automatically created metadata
|
|
// metadata is not database object, therefore no specific call to close it
|
|
meta->release();
|
|
|
|
// get metadata with coerced datatypes
|
|
meta = builder->getMetadata(&status);
|
|
|
|
// builder not needed any more
|
|
builder->release();
|
|
builder = NULL;
|
|
|
|
// now we may also get offsets info
|
|
for (unsigned j = 0; j < cols; ++j)
|
|
{
|
|
if (fields[j].name)
|
|
{
|
|
fields[j].length = meta->getLength(&status, j);
|
|
fields[j].offset = meta->getOffset(&status, j);
|
|
}
|
|
}
|
|
|
|
// open cursor
|
|
curs = stmt->openCursor(&status, tra, NULL, NULL, meta, 0);
|
|
|
|
// allocate output buffer
|
|
unsigned l = meta->getMessageLength(&status);
|
|
unsigned char* buffer = new unsigned char[l];
|
|
|
|
// fetch records from cursor and print them
|
|
for (int line = 0; curs->fetchNext(&status, buffer) == IStatus::RESULT_OK; ++line)
|
|
{
|
|
if (line % 10 == 0)
|
|
{
|
|
printf("\n");
|
|
for (unsigned j = 0; j < cols; ++j)
|
|
{
|
|
if (fields[j].name)
|
|
{
|
|
printf("%-*.*s ", fields[j].length, fields[j].length, fields[j].name);
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
for (unsigned j = 0; j < cols; ++j)
|
|
{
|
|
if (fields[j].name)
|
|
{
|
|
printf("%*.*s ", fields[j].length, fields[j].length, buffer + fields[j].offset);
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
printf("\n");
|
|
|
|
// close interfaces
|
|
curs->close(&status);
|
|
curs = NULL;
|
|
|
|
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 (meta)
|
|
meta->release();
|
|
if (builder)
|
|
builder->release();
|
|
if (curs)
|
|
curs->release();
|
|
if (stmt)
|
|
stmt->release();
|
|
if (tra)
|
|
tra->release();
|
|
if (att)
|
|
att->release();
|
|
if (tpb)
|
|
tpb->dispose();
|
|
|
|
prov->release();
|
|
status.dispose();
|
|
|
|
return rc;
|
|
}
|