for (PKC kp = Klist; kp; kp = kp->Next) if (kp->Incolp)
kp->Incolp->Destroy();
} // end of Destroy
/* -------------------------- Class CMgoConn ------------------------- */
/***********************************************************************/ /* Implementation of the CMgoConn class. */ /***********************************************************************/
CMgoConn::CMgoConn(PGLOBAL g, PCPARM pcg)
{
Pcg = pcg;
Uri = NULL; //Pool = NULL;
Client = NULL;
Database = NULL;
Collection = NULL;
Cursor = NULL;
Document = NULL;
Query = NULL;
Opts = NULL;
Fpc = NULL;
fp = NULL;
m_Connected = false;
} // end of CMgoConn standard constructor
/***********************************************************************/ /* Required to initialize libmongoc's internals. */ /***********************************************************************/ void CMgoConn::mongo_init(bool init)
{ if (init)
mongoc_init(); elseif (IsInit)
mongoc_cleanup();
IsInit = init;
} // end of mongo_init
/***********************************************************************/ /* Connect to the MongoDB server and get the collection. */ /***********************************************************************/ bool CMgoConn::Connect(PGLOBAL g)
{ if (!Pcg->Db_name || !Pcg->Coll_name) { // This would crash in mongoc_client_get_collection
snprintf(g->Message, sizeof(g->Message), "Missing DB or collection name"); returntrue;
} // endif name
if (!IsInit) #ifdefined(_WIN32)
__try {
mongo_init(true);
} __except (EXCEPTION_EXECUTE_HANDLER) {
snprintf(g->Message, sizeof(g->Message), "Cannot load MongoDB C driver"); returntrue;
} // end try/except #else// !_WIN32
mongo_init(true); #endif// !_WIN32
Uri = mongoc_uri_new_with_error(Pcg->Uristr, &Error);
if (!Uri) {
snprintf(g->Message, sizeof(g->Message), "Failed to parse URI: \"%s\" Msg: %s",
Pcg->Uristr, Error.message); returntrue;
} // endif Uri
#if0 // Create a new client pool instance
Pool = mongoc_client_pool_new(Uri);
mongoc_client_pool_set_error_api(Pool, 2);
// Register the application name so we can track it in the profile logs // on the server. This can also be done from the URI.
mongoc_client_pool_set_appname(Pool, "Connect");
// Create a new client instance
Client = mongoc_client_pool_pop(Pool); #else // Create a new client instance
Client = mongoc_client_new_from_uri (Uri);
if (!Client) {
snprintf(g->Message, sizeof(g->Message), "Failed to get Client"); returntrue;
} // endif Client
// Register the application name so we can track it in the profile logs // on the server. This can also be done from the URI (see other examples).
mongoc_client_set_appname (Client, "Connect");
// Get a handle on the database // Database = mongoc_client_get_database (Client, Pcg->Db_name); #endif// 0
// Get a handle on the collection
Collection = mongoc_client_get_collection(Client, Pcg->Db_name, Pcg->Coll_name);
if (!Collection) {
snprintf(g->Message, sizeof(g->Message), "Failed to get Collection %s.%s",
Pcg->Db_name, Pcg->Coll_name); returntrue;
} // endif Collection
/*********************************************************************/ /* Link a Fblock. This make possible to automatically close it */ /* in case of error (throw). */ /*********************************************************************/
PDBUSER dbuserp = (PDBUSER)g->Activityp->Aptr;
m_Connected = true; returnfalse;
} // end of Connect
/***********************************************************************/ /* CollSize: returns the number of documents in the collection. */ /***********************************************************************/ int CMgoConn::CollSize(PGLOBAL g)
{ int cnt;
bson_t* query; constchar* jf = NULL;
if (Pcg->Pipe) return10; elseif (Pcg->Filter)
jf = Pcg->Filter;
if (jf) {
query = bson_new_from_json((const uint8_t*)jf, -1, &Error);
// Resolve path collision for (hp = php; hp; hp = hp->Next) { if (strlen(path) < strlen(hp->Path)) {
n = strlen(path);
m = true;
} else {
n = strlen(hp->Path);
m = false;
} // endif path
if (!strncmp(path, hp->Path, n)) break;
} // endfor hp
if (!hp) { // New path
hp = (PTHP)PlugSubAlloc(g, NULL, sizeof(PTH));
hp->Path = path;
hp->Name = cp->GetName();
hp->Next = NULL;
*nphp = hp;
nphp = &hp->Next;
} elseif (m) // Smaller path must replace longer one
hp->Path = path;
} // endfor cp
for (hp = php; hp; hp = hp->Next) { if (b)
s->Append(",\""); else
b = true;
if (*hp->Path == '{') { // This is a Mongo defined column
s->Append(hp->Name);
s->Append("\":");
s->Append(hp->Path);
} else {
s->Append(hp->Path);
s->Append("\":1");
} // endif Path
} // endfor hp
} // end of Project
/***********************************************************************/ /* MakeCursor: make the cursor used to retrieve documents. */ /***********************************************************************/ bool CMgoConn::MakeCursor(PGLOBAL g)
{ constchar *p; bool id, all = false;
PCSZ options = Pcg->Options;
PTDB tp = Pcg->Tdbp;
PCOL cp;
PSTRG s = NULL;
PFIL filp = tp->GetFilter();
id = (tp->GetMode() == MODE_UPDATE || tp->GetMode() == MODE_DELETE);
if (options && !stricmp(options, "all")) {
options = NULL;
all = true;
} elsefor (cp = tp->GetColumns(); cp && !all; cp = cp->GetNext()) if (cp->GetFmt() && !strcmp(cp->GetFmt(), "*") && !options)
all = true; elseif (!id)
id = !strcmp(cp->GetFmt() ? cp->GetFmt() : cp->GetName(), "_id");
if (Pcg->Pipe) { if (trace(1))
htrc("Pipeline: %s\n", options);
p = strrchr(options, ']');
if (!p) {
snprintf(g->Message, sizeof(g->Message), "Missing ] in pipeline"); returntrue;
} else
*(char*)p = 0;
s = new(g) STRING(g, 1023, (PSZ)options);
if (filp) {
s->Append(",{\"$match\":");
if (MakeSelector(g, filp, s)) {
snprintf(g->Message, sizeof(g->Message), "Failed making selector"); returntrue;
} else
s->Append('}');
tp->SetFilter(NULL); // Not needed anymore
} // endif To_Filter
if (tp->GetColumns() && !strstr(s->GetStr(), "$project")) { // Project list
s->Append(",{\"$project\":{\"");
if (!id)
s->Append("_id\":0,\"");
Project(g, s);
s->Append("}}");
} // endif all
s->Append("]}");
s->Resize(s->GetLength() + 1);
*(char*)p = ']'; // Restore Colist for discovery
p = s->GetStr();
if (!all) { if (options && *options) { if (trace(1))
htrc("options=%s\n", options);
p = options;
} elseif (tp->GetColumns()) { // Projection list if (s)
s->Set("{\"projection\":{\""); else
s = new(g) STRING(g, 511, "{\"projection\":{\"");
/***********************************************************************/ /* Fetch next document. */ /***********************************************************************/ int CMgoConn::ReadNext(PGLOBAL g)
{ int rc = RC_OK;
/***********************************************************************/ /* WriteDB: Data Base write routine for CMGO access method. */ /***********************************************************************/ int CMgoConn::Write(PGLOBAL g)
{ int rc = RC_OK;
PTDB tp = Pcg->Tdbp;
if (tp->GetMode() == MODE_INSERT) { if (!Pcg->Line) {
Fpc->Init();
if (bson_iter_find(&iter, "_id")) switch (bson_iter_type(&iter)) { case BSON_TYPE_OID:
b = BSON_APPEND_OID(query, "_id", bson_iter_oid(&iter)); break; case BSON_TYPE_UTF8:
b = BSON_APPEND_UTF8(query, "_id", bson_iter_utf8(&iter, NULL)); break; case BSON_TYPE_INT32:
b = BSON_APPEND_INT32(query, "_id", bson_iter_int32(&iter)); break; case BSON_TYPE_INT64:
b = BSON_APPEND_INT64(query, "_id", bson_iter_int64(&iter)); break; case BSON_TYPE_DOUBLE:
b = BSON_APPEND_DOUBLE(query, "_id", bson_iter_double(&iter)); break; default: break;
} // endswitch iter
if (b) { if (trace(2)) { char *str = bson_as_json(query, NULL);
htrc("update query: %s\n", str);
bson_free(str);
} // endif trace
mongoc_cursor_destroy(Cursor);
Cursor = cursor;
} // end of Rewind
/***********************************************************************/ /* Table close routine for MONGO tables. */ /***********************************************************************/ void CMgoConn::Close(void)
{ if (Query) bson_destroy(Query); if (Opts) bson_destroy(Opts); if (Cursor) mongoc_cursor_destroy(Cursor); if (Collection) mongoc_collection_destroy(Collection); //if (Client) mongoc_client_pool_push(Pool, Client); //if (Pool) mongoc_client_pool_destroy(Pool); if (Client) mongoc_client_destroy(Client); if (Uri) mongoc_uri_destroy(Uri); if (Fpc) Fpc->Destroy(); if (fp) fp->Count = 0;
} // end of Close
/***********************************************************************/ /* Mini: used to suppress blanks to json strings. */ /***********************************************************************/ char *CMgoConn::Mini(PGLOBAL g, PCOL colp, const bson_t *bson, bool b)
{ char *s, *str = NULL; char *Mbuf = (char*)PlugSubAlloc(g, NULL, (size_t)colp->GetLength() + 1); int i, j = 0, k = 0, n = 0, m = GetDefaultPrec(); bool ok = true, dbl = false; double d;
size_t len;
if (b)
s = str = bson_array_as_json(bson, &len); else
s = str = bson_as_json(bson, &len);
if (len > (size_t)colp->GetLength()) {
snprintf(g->Message, sizeof(g->Message), "Value too long for column %s", colp->GetName());
bson_free(str); throw (int)TYPE_AM_MGO;
} // endif len
for (i = 0; i < colp->GetLength() && s[i]; i++) { switch (s[i]) { case' ': if (ok) continue; break; case'"':
ok = !ok; break; case'.': if (j) dbl = true; break; default: if (ok) { if (isdigit(s[i])) { if (!j) j = k; if (dbl) n++;
} elseif (dbl && n > m) {
Mbuf[k] = 0;
d = atof(Mbuf + j);
n = snprintf(Mbuf + j, (size_t)colp->GetLength() + 1 - j, "%.*f", m, d);
k = j + n;
j = n = 0;
} elseif (j)
j = n = 0;
} // endif ok
break;
} // endswitch s[i]
Mbuf[k++] = s[i];
} // endfor i
bson_free(str);
Mbuf[k] = 0; return Mbuf;
} // end of Mini
/***********************************************************************/ /* Retrieve the column value from the document. */ /***********************************************************************/ void CMgoConn::GetColumnValue(PGLOBAL g, PCOL colp)
{ char *jpath = colp->GetJpath(g, false); bool b = false;
PVAL value = colp->GetValue();
bson_iter_t Iter; // Used to retrieve column value
bson_iter_t Desc; // Descendant iter
if (*jpath == '{')
jpath = colp->GetName(); // This is a Mongo defined column
if (!*jpath || !strcmp(jpath, "*")) {
value->SetValue_psz(Mini(g, colp, Document, false));
} elseif (bson_iter_init(&Iter, Document) &&
bson_iter_find_descendant(&Iter, jpath, &Desc)) { switch (bson_iter_type(&Desc)) { case BSON_TYPE_UTF8:
value->SetValue_psz((PSZ)bson_iter_utf8(&Desc, NULL)); break; case BSON_TYPE_INT32:
value->SetValue(bson_iter_int32(&Desc)); break; case BSON_TYPE_INT64:
value->SetValue(bson_iter_int64(&Desc)); break; case BSON_TYPE_DOUBLE:
value->SetValue(bson_iter_double(&Desc)); break; case BSON_TYPE_DATE_TIME:
value->SetValue(bson_iter_date_time(&Desc) / 1000); break; case BSON_TYPE_BOOL:
b = bson_iter_bool(&Desc);
bson_oid_to_string(bson_iter_oid(&Desc), str);
value->SetValue_psz(str);
} break; case BSON_TYPE_ARRAY:
b = true; // passthru case BSON_TYPE_DOCUMENT:
{ // All this because MongoDB can return the wrong type int i = 0; const uint8_t *data = NULL;
uint32_t len = 0;
for (; i < 2; i++) { if (b) // Try array first
bson_iter_array(&Desc, &len, &data); else
bson_iter_document(&Desc, &len, &data);
if (!data) {
len = 0;
b = !b;
} else break;
} // endfor i
if (data) {
bson_t *doc = bson_new_from_data(data, len);
value->SetValue_psz(Mini(g, colp, doc, b));
bson_destroy(doc);
} else { // ... or we can also come here in case of NULL!
value->Reset();
value->SetNull(true);
} // endif data
} break; case BSON_TYPE_NULL: // Apparently this does not work...
value->Reset();
value->SetNull(true); break; case BSON_TYPE_DECIMAL128: { char str[BSON_DECIMAL128_STRING];
bson_decimal128_t dec;
return nwm;
} else {
*osz = n; return m;
} // endif n
} // end of mgo_realloc #endif// 0
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.16Bemerkung:
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.