mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 00:43:02 +01:00
155 lines
3.9 KiB
C++
155 lines
3.9 KiB
C++
/*
|
|
* 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.
|
|
* In this sample we insert NULLs in all columns.
|
|
*
|
|
* 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;
|
|
}
|
|
|