string valueToString(IAttachment* attachment, ITransaction* transaction, MessageImpl& message, Offset<void*>& field) { if (message.isNull(field)) return ""; void* p = message[field]; switch (field.getType()) { //// TODO: scale for SQL_SHORT, SQL_LONG and SQL_INT64 case SQL_SHORT: return lexical_cast<string>(*static_cast<ISC_SHORT*>(p)); case SQL_LONG: return lexical_cast<string>(*static_cast<ISC_LONG*>(p)); case SQL_INT64: return lexical_cast<string>(*static_cast<ISC_INT64*>(p)); case SQL_FLOAT: return lexical_cast<string>(*static_cast<float*>(p)); case SQL_DOUBLE: return lexical_cast<string>(*static_cast<double*>(p)); case SQL_BLOB: { IStatus* status = master->getStatus(); IBlob* blob = attachment->openBlob(status, transaction, static_cast<ISC_QUAD*>(p), 0, NULL); BOOST_VERIFY(status->isSuccess()); string str; char blobBuffer[1024]; unsigned blobLen; while ((blobLen = blob->getSegment(status, sizeof(blobBuffer), blobBuffer)) != 0) str.append(blobBuffer, blobLen); blob->close(status); BOOST_VERIFY(status->isSuccess()); status->dispose(); return str; } case SQL_TEXT: case SQL_VARYING: return string(static_cast<char*>(p) + sizeof(ISC_USHORT), *static_cast<ISC_USHORT*>(p)); default: BOOST_VERIFY(false); return ""; } }
void getEngineVersion(Firebird::IAttachment* attachment, unsigned* major, unsigned* minor, unsigned* revision) { static const UCHAR ITEMS[] = {isc_info_firebird_version}; UCHAR buffer[512]; IStatus* status = master->getStatus(); attachment->getInfo(status, sizeof(ITEMS), ITEMS, sizeof(buffer), buffer); BOOST_VERIFY(status->isSuccess()); if (buffer[0] == isc_info_firebird_version) { const UCHAR* p = buffer + 5; if (major) *major = p[4] - '0'; if (minor) *minor = p[6] - '0'; if (revision) *revision = p[8] - '0'; } else { if (major) *major = 0; if (minor) *minor = 0; if (revision) *revision = 0; } status->dispose(); }
int main() { int rc = 0; // set default password if none specified in environment setenv("ISC_USER", "sysdba", 0); setenv("ISC_PASSWORD", "masterkey", 0); // declare pointers to required interfaces IStatus* st = NULL; IProvider* prov = NULL; IAttachment* att = NULL; ITransaction* tra = NULL; IStatement* stmt = NULL; IResultSet* curs = NULL; IMessageMetadata* meta = NULL; IMetadataBuilder* builder = NULL; try { // status vector and main dispatcher st = master->getStatus(); prov = master->getDispatcher(); // attach employee db att = prov->attachDatabase(st, "localhost:employee", 0, NULL); check(st, "attachDatabase"); // start default transaction tra = att->startTransaction(st, 0, NULL); check(st, "startTransaction"); // prepare statement stmt = att->prepare(st, tra, 0, "select * from country", 3, IStatement::PREPARE_PREFETCH_METADATA); check(st, "prepare"); // get list of columns meta = stmt->getOutputMetadata(st); check(st, "getOutputMetadata"); builder = meta->getBuilder(st); check(st, "getBuilder"); unsigned cols = meta->getCount(st); check(st, "getCount"); // 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(st, j); check(st, "getType"); if (t == SQL_VARYING || t == SQL_TEXT) { builder->setType(st, j, SQL_TEXT); check(st, "setType"); fields[j].name = meta->getField(st, j); check(st, "getField"); } } meta->release(); meta = builder->getMetadata(st); check(st, "getMetadata"); // now we may also get offsets info for (unsigned j = 0; j < cols; ++j) { if (fields[j].name) { fields[j].length = meta->getLength(st, j); check(st, "getLength"); fields[j].offset = meta->getOffset(st, j); check(st, "getOffset"); } } builder->release(); builder = NULL; // open cursor curs = stmt->openCursor(st, tra, NULL, NULL, meta); check(st, "openCursor"); // allocate output buffer unsigned l = meta->getMessageLength(st); check(st, "getMessageLength"); unsigned char* buffer = new unsigned char[l]; // fetch records from cursor and print them while (curs->fetch(st, buffer)) { for (unsigned j = 0; j < cols; ++j) { if (fields[j].name) { printf("%s: %*.*s\n", fields[j].name, fields[j].length, fields[j].length, buffer + fields[j].offset); } } printf("\n"); } check(st, "fetch"); // close interfaces curs->close(st); check(st, "close"); curs = NULL; stmt->free(st); check(st, "free"); stmt = NULL; meta->release(); meta = NULL; tra->commit(st); check(st, "commit"); tra = NULL; att->detach(st); check(st, "detach"); att = NULL; } catch(const char* text) { // handle error rc = 1; fprintf(stderr, "%s:\n", text); if (st) isc_print_status(st->get()); } // 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 (prov) prov->release(); if (st) st->dispose(); return rc; }
int main() { int rc = 0; // set default password if none specified in environment setenv("ISC_USER", "sysdba", 0); setenv("ISC_PASSWORD", "masterkey", 0); // Declare pointers to required interfaces // IStatus is used to return wide error description to user IStatus* st = NULL; // IProvider is needed to start to work with database (or service) IProvider* prov = NULL; // IAttachment and ITransaction contain methods to work with database attachment // and transactions IAttachment* att = NULL; ITransaction* tra = NULL; try { // status vector and main dispatcher are returned by calls to IMaster functions // no error return may happen - these functions always succeed st = master->getStatus(); prov = master->getDispatcher(); // status wrapper - will be used later in all calls where status interface is needed // With ThrowStatusWrapper passed as status interface FbException will be thrown on error ThrowStatusWrapper status(st); // create DPB (to be replaced with IPBWriter) unsigned char dpbBuf[32]; unsigned char *dpb = dpbBuf; *dpb++ = isc_dpb_version1; *dpb++ = isc_dpb_page_size; *dpb++ = 2; *dpb++ = (8 * 1024) & 0xFF; *dpb++ = (8 * 1024) >> 8; // create empty database att = prov->createDatabase(&status, "fbtests.fdb", dpb - dpbBuf, dpbBuf); printf("Database fbtests.fdb created\n"); // detach from database att->detach(&status); att = NULL; // attach it once again att = prov->attachDatabase(&status, "fbtests.fdb", 0, NULL); printf("Re-attached database fbtests.fdb\n"); // start transaction tra = att->startTransaction(&status, 0, NULL); // create table att->execute(&status, tra, 0, "create table dates_table (d1 date)", 3, NULL, NULL, NULL, NULL); // Input parameters and output data not used // commit transaction retaining tra->commitRetaining(&status); printf("Table dates_table created\n"); // insert a record into dates_table att->execute(&status, tra, 0, "insert into dates_table values (CURRENT_DATE)", 3, NULL, NULL, NULL, NULL); // Input parameters and output data not used // commit transaction (will close interface) tra->commit(&status); tra = NULL; printf("Record inserted into dates_table\n"); // detach from database (will close interface) att->detach(&status); att = NULL; } catch (const FbException& error) { // handle error rc = 1; isc_print_status(error.getStatus()->getErrors()); } // release interfaces after error caught if (tra) tra->release(); if (att) att->release(); if (prov) prov->release(); if (st) st->dispose(); return rc; }
int main() { int rc = 0; // set default password if none specified in environment setenv("ISC_USER", "sysdba", 0); setenv("ISC_PASSWORD", "masterkey", 0); // declare pointers to required interfaces IStatus* st = NULL; IProvider* prov = NULL; 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 { // status vector and main dispatcher st = master->getStatus(); prov = master->getDispatcher(); // attach employee db att = prov->attachDatabase(st, "employee", 0, NULL); check(st, "attachDatabase"); // start transaction tra = att->startTransaction(st, 0, NULL); check(st, "startTransaction"); // prepare statement stmt = att->prepare(st, tra, 0, updstr, 3, 0); check(st, "prepare"); // build metadata // IMaster creates empty new metadata in builder builder = master->getMetadataBuilder(st, 2); check(st, "getMetadataBuilder"); // set required info on fields builder->setType(st, 0, SQL_DOUBLE + 1); check(st, "setType"); builder->setType(st, 1, SQL_TEXT + 1); check(st, "setType"); builder->setLength(st, 1, 3); check(st, "setLength"); // IMetadata should be ready meta = builder->getMetadata(st); check(st, "getMetadata"); // no need in builder any more builder->release(); builder = NULL; // allocate buffer char buffer[256]; unsigned len = meta->getMessageLength(st); check(st, "getMessageLength"); if (len > 256) { throw "Input message length too big - can't continue"; } // locations of parameters in input message char* dept_no = &buffer[meta->getOffset(st, 1)]; check(st, "getOffset"); double* percent_inc = (double*) &buffer[meta->getOffset(st, 0)]; check(st, "getOffset"); // null IDs (set to NOT NULL) short* flag = (short*)&buffer[meta->getNullOffset(st, 0)]; check(st, "getNullOffset"); *flag = 0; flag = (short*) &buffer[meta->getNullOffset(st, 1)]; check(st, "getNullOffset"); *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. stmt->execute(st, tra, meta, buffer, NULL, NULL); if (st->getStatus() & IStatus::FB_HAS_ERRORS) { int sqlcode = isc_sqlcode(st->getErrors()); // Don't save the update, if the new budget exceeds the limit. if (sqlcode == -625) { printf("\tExceeded budget limit -- not updated.\n"); tra->rollbackRetaining(st); check(st, "rollback"); continue; } // use default handler check(st, "execute"); } // Save each department's update independently. // *** Change to commitRetaining() to see changes // *** tra->commitRetaining(st); tra->rollbackRetaining(st); check(st, "rollback"); } // close interfaces stmt->free(st); check(st, "free"); stmt = NULL; meta->release(); meta = NULL; tra->commit(st); check(st, "commit"); tra = NULL; att->detach(st); check(st, "detach"); att = NULL; } catch (const char* text) { // handle error rc = 1; fprintf(stderr, "%s:\n", text); if (st) isc_print_status(st->getErrors()); } // 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(); if (prov) prov->release(); if (st) st->dispose(); return rc; }