mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 18:43:02 +01:00
Added sample of changing returned by engine metadata and using changed metadata in Statement::execute()
This commit is contained in:
parent
71286edffe
commit
4dffa04237
153
examples/interfaces/13.null_pk.cpp
Normal file
153
examples/interfaces/13.null_pk.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* PROGRAM: Object oriented API samples.
|
||||
* MODULE: 13.null_pk.cpp
|
||||
* DESCRIPTION: Changing metadata, passed from DB engine, and using modified
|
||||
* copy later. Useful for changing nullability or coercing datatype.
|
||||
*
|
||||
* Example for the following interfaces:
|
||||
* IMessageMetadata - describe input and output data format
|
||||
* IMetadataBuilder - tool to modify/create metadata
|
||||
*
|
||||
* 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, 2020
|
||||
*/
|
||||
|
||||
#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();
|
||||
|
||||
// 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* sqlStr =
|
||||
"Insert into COUNTRY values(?, ?)";
|
||||
|
||||
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, sqlStr, SAMPLES_DIALECT, 0);
|
||||
|
||||
// build metadata
|
||||
meta = stmt->getInputMetadata(&status);
|
||||
builder = meta->getBuilder(&status);
|
||||
|
||||
// set nullability on fields
|
||||
for (unsigned n = 0; n < meta->getCount(&status); ++n)
|
||||
{
|
||||
unsigned t = meta->getType(&status, n);
|
||||
builder->setType(&status, n, t | 1);
|
||||
}
|
||||
|
||||
// IMetadata should be ready
|
||||
meta->release();
|
||||
meta = NULL;
|
||||
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";
|
||||
}
|
||||
|
||||
// all null
|
||||
for (unsigned n = 0; n < meta->getCount(&status); ++n)
|
||||
{
|
||||
short* flag = (short*)&buffer[meta->getNullOffset(&status, n)];
|
||||
*flag = -1;
|
||||
// setting value for NULL field makes no sense - skip it
|
||||
}
|
||||
|
||||
// this should throw - passing NULLs to not-NULL columns
|
||||
// can work only with something like before insert trigger
|
||||
stmt->execute(&status, tra, meta, buffer, NULL, NULL);
|
||||
|
||||
// close interfaces
|
||||
stmt->free(&status);
|
||||
stmt = NULL;
|
||||
|
||||
meta->release();
|
||||
meta = NULL;
|
||||
|
||||
tra->rollback(&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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user