void ContainerQueryCommand::execute(Args &args, Environment &env) { if(args.size() != 2) { throw CommandException("Wrong number of arguments"); } env.testContainer(); env.deleteResults(); std::string fullQuery = "collection('" + env.container()->getName() + "')/(" + args[1] + ")"; u_int32_t flags = DBXML_LAZY_DOCS; if(env.documentProjection()) flags |= DBXML_DOCUMENT_PROJECTION; if(env.txn()) { XmlQueryExpression expr = env.db().prepare(*env.txn(), fullQuery, env.context()); env.results() = new XmlResults(expr.execute(*env.txn(), env.context(), flags)); } else { XmlQueryExpression expr = env.db().prepare(fullQuery, env.context()); env.results() = new XmlResults(expr.execute(env.context(), flags)); } if(env.context().getEvaluationType() == XmlQueryContext::Eager) { if(env.verbose()) cout << (unsigned int) env.results()->size() << " objects returned for eager expression '" << args[1] << "'" << endl << endl; } else { if(env.verbose()) cout << "Lazy expression '" << args[1] << "' completed" << endl << endl; } }
BdRetVal bdbXMLInterface::insert_new_node(container_index container_type, const string& docname, const string &node_path, const string &node_name, vector<string>* attr_list, const string& element) { if (m_manager == NULL) { throw XmlException(XmlException::NULL_POINTER, "m_manager", __FILE__, __LINE__); // return xml_exception; } if (container_type >= CONT_IDX_NUM) { throw XmlException(XmlException::INVALID_VALUE, "contianer_type", __FILE__, __LINE__); // return para_error; } string query_string = "insert nodes "; query_string += "\n<" + node_name; if (attr_list != NULL) { for (int i=0; i < attr_list->size(); i++) { query_string += "\n"; query_string += (*attr_list)[i]; } } query_string += ">\n" + element; query_string += "\n</" + node_name + ">\n"; query_string += " into "; query_string += "doc(\"dbxml:/" + container_names[container_type] + ".dbxml/" + docname + "\")" + node_path; XmlQueryContext context = m_manager->createQueryContext(); XmlQueryExpression qe; XmlResults results; try { qe = m_manager->prepare(query_string, context); results = qe.execute(context); } catch (XmlException &xe) { debugOut() << "insert operation: " << query_string << endl; debugOut() << "insert exception: " << xe.what() << endl; throw xe; } return no_error; }
void ContextItemQueryCommand::execute(Args &args, Environment &env) { if(args.size() != 2) { throw CommandException("Wrong number of arguments"); } env.testResults(); XmlResults newResults = env.db().createResults(); env.results()->reset(); u_int32_t flags = DBXML_LAZY_DOCS; if(env.documentProjection()) flags |= DBXML_DOCUMENT_PROJECTION; if(env.txn()) { XmlQueryExpression expr = env.db().prepare(*env.txn(), args[1], env.context()); XmlValue value; while(env.results()->next(value)) { XmlResults tmpResults = expr.execute(*env.txn(), value, env.context(), flags); XmlValue tmpValue; while(tmpResults.next(tmpValue)) { newResults.add(tmpValue); } } } else { XmlQueryExpression expr = env.db().prepare(args[1], env.context()); XmlValue value; while(env.results()->next(value)) { XmlResults tmpResults = expr.execute(value, env.context(), flags); XmlValue tmpValue; while(tmpResults.next(tmpValue)) { newResults.add(tmpValue); } } } env.deleteResults(); env.results() = new XmlResults(newResults); if(env.verbose()) cout << (unsigned int)env.results()->size() << " objects returned for expression '" << args[1] << "'\n" << endl; }
int main(int argc, char **argv) { // This program uses a named container, which will apear // on disk std::string containerName = "people.dbxml"; std::string content = "<people><person><name>joe</name></person><person><name>mary</name></person></people>"; std::string docName = "people"; // Note that the query uses a variable, which must be set // in the query context std::string queryString = "collection('people.dbxml')/people/person[name=$name]"; std::string environmentDir = "."; // Berkeley DB environment flags u_int32_t envFlags = DB_RECOVER|DB_CREATE|DB_INIT_MPOOL| DB_INIT_LOCK|DB_INIT_TXN|DB_INIT_LOG; // Berkeley DB cache size (25 MB). The default is quite small u_int32_t envCacheSize = 25*1024*1024; // argument parsing should really use getopt(), but // avoid it for platform-independence if (argc == 3) { if (std::string(argv[1]) != std::string("-h")) usage(argv[0]); environmentDir = argv[2]; } else if (argc != 1) usage(argv[0]); // Create and open a Berkeley DB Transactional Environment. int dberr; DB_ENV *dbEnv = 0; dberr = db_env_create(&dbEnv, 0); if (dberr == 0) { dbEnv->set_cachesize(dbEnv, 0, envCacheSize, 1); dbEnv->set_errcall(dbEnv, errcall); // set error callback dbEnv->set_lk_detect(dbEnv, DB_LOCK_DEFAULT); // handle deadlocks dberr = dbEnv->open(dbEnv, environmentDir.c_str(), envFlags, 0); } if (dberr) { std::cout << "Unable to create environment handle due to the following error: " << db_strerror(dberr) << std::endl; if (dbEnv) dbEnv->close(dbEnv, 0); return -1; } try { // All BDB XML programs require an XmlManager instance. // Create it from the DbEnv XmlManager mgr(dbEnv, DBXML_ADOPT_DBENV); // Because the container will exist on disk, remove it // first if it exists if (mgr.existsContainer(containerName)) mgr.removeContainer(containerName); /* Create a container that is transactional. The container * type is NodeContainer, which is the default container type, * and the index is on nodes, which is the default for a * NodeContainer container. XmlContainerConfig can be used * to set the container type and index type. */ XmlContainerConfig config; config.setTransactional(true); XmlContainer cont = mgr.createContainer( containerName, config); // All Container modification operations need XmlUpdateContext XmlUpdateContext uc = mgr.createUpdateContext(); // The following putDocument call will auto-transact // and will abort/cleanup if the operation deadlocks or // otherwise fails cont.putDocument(docName, content, uc); // Querying requires an XmlQueryContext XmlQueryContext qc = mgr.createQueryContext(); // Add a variable to the query context, used by the query qc.setVariableValue("name", "mary"); // Use try/catch and while to handle deadlock/retry int retry = 0; while (retry < 5) { // hard-code 5 retries // Create a new transaction for the query XmlTransaction txn = mgr.createTransaction(); try { // o Note the passing of txn to both methods // o Often the XmlQueryExpression object will be created and // saved for reuse in order to amortize the cost of parsing a query XmlQueryExpression expr = mgr.prepare(txn, queryString, qc); XmlResults res = expr.execute(txn, qc); // Note use of XmlQueryExpression::getQuery() and // XmlResults::size() std::cout << "The query, '" << expr.getQuery() << "' returned " << (unsigned int)res.size() << " result(s)" << std::endl; // Process results -- just print them XmlValue value; std::cout << "Result: " << std::endl; while (res.next(value)) { std::cout << "\t" << value.asString() << std::endl; } // done with the transaction txn.commit(); break; } catch (XmlException &x) { txn.abort(); // unconditional if ((x.getExceptionCode() == XmlException::DATABASE_ERROR) && (x.getDbErrno() == DB_LOCK_DEADLOCK)) { ++retry; continue; // try again } throw; // re-throw -- not deadlock } } // In C++, resources are released as objects go out // of scope. } catch (XmlException &xe) { std::cout << "XmlException: " << xe.what() << std::endl; } return 0; }
/** * @breif * Get the number of nodes in a xml file * * @Param container_type * should be value defined in container_index enum * @Param doc * the document name of xml file * @Param node_path * the xpath path of node to be search * * @Returns * the node number */ int bdbXMLInterface::get_node_element_num (container_index container_type, const string *doc, const string *node_path) { string query_string; int res = 0; if (m_manager == NULL) { throw XmlException(XmlException::NULL_POINTER, "m_manager", __FILE__, __LINE__); // return xml_exception; } if (container_type >= CONT_IDX_NUM) { throw XmlException(XmlException::INVALID_VALUE, "contianer_type", __FILE__, __LINE__); // return para_error; } if (doc == NULL) { query_string += "count(collection('" + container_names[container_type] + ".dbxml')"; } else { query_string += "count(doc(\"dbxml:/" + container_names[container_type] + ".dbxml/" + *doc + "\")"; } if (node_path != NULL) query_string += *node_path; query_string += ")"; XmlQueryContext context = m_manager->createQueryContext(); XmlQueryExpression qe; XmlResults results; try { qe = m_manager->prepare(query_string, context); results = qe.execute(context); } catch (XmlException &xe) { debugOut() << "get_node_element_num: " << query_string << endl; debugOut() << "get_node_element_num exception: " << xe.what() << endl; throw xe; } XmlValue value; results.next(value); if (value.isNumber()) res = (int)value.asNumber(); else res = 0; return res; }
/** * @breif * get the node content of a document as a string * * @Param container_type * should be value defined in container_index enum * @Param doc * the document name of xml file * @Param node_path * the xpath path of node to be search * @Param res * output parameter, return the string value of results * * @Returns * return no_error for success * otherwise an XmlException was throwed */ BdRetVal bdbXMLInterface::get_node(container_index container_type, const string *doc, const string *node_path, string &res) { string query_string; if (m_manager == NULL) { throw XmlException(XmlException::NULL_POINTER, "m_manager null", __FILE__, __LINE__); } if (container_type >= CONT_IDX_NUM) { throw XmlException(XmlException::INVALID_VALUE, "contianer_type", __FILE__, __LINE__); } if (doc == NULL) { query_string += "collection('" + container_names[container_type] + ".dbxml')"; } else { query_string += "doc(\"dbxml:/" + container_names[container_type] + ".dbxml/" + *doc + "\")"; } if (node_path != NULL) query_string += *node_path; XmlQueryContext context = m_manager->createQueryContext(); XmlQueryExpression qe; XmlResults results; try { qe = m_manager->prepare(query_string, context); results = qe.execute(context); } catch (XmlException &xe) { debugOut() << "get node query string: " << query_string << endl; debugOut() << "get_node in prepare xml exception: " << xe.what() << endl; throw xe; } res.clear(); XmlValue value; while (results.next(value)) { res = value.asString(); } return no_error; }