public const string EJDB_LIB_NAME = "tcejdb";
IntPtr _db = IntPtr.Zero;
- #region Functions
+ //
+ #region NativeRefs
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbnew")]
- static extern IntPtr _ejdbnew();
+ internal static extern IntPtr _ejdbnew();
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbdel")]
- static extern IntPtr _ejdbdel([In] IntPtr db);
+ internal static extern IntPtr _ejdbdel([In] IntPtr db);
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbopen")]
- static extern bool _ejdbopen([In] IntPtr db, [In] IntPtr path, int mode);
+ internal static extern bool _ejdbopen([In] IntPtr db, [In] IntPtr path, int mode);
- static bool _ejdbopen(IntPtr db, string path, int mode) {
+ internal static bool _ejdbopen(IntPtr db, string path, int mode) {
IntPtr pptr = UnixMarshal.StringToHeap(path, Encoding.UTF8);
try {
return _ejdbopen(db, pptr, mode);
}
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbclose")]
- static extern bool _ejdbclose([In] IntPtr db);
+ internal static extern bool _ejdbclose([In] IntPtr db);
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbisopen")]
- static extern bool _ejdbisopen([In] IntPtr db);
+ internal static extern bool _ejdbisopen([In] IntPtr db);
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbecode")]
- static extern int _ejdbecode([In] IntPtr db);
+ internal static extern int _ejdbecode([In] IntPtr db);
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdberrmsg")]
- static extern IntPtr _ejdberrmsg(int ecode);
+ internal static extern IntPtr _ejdberrmsg(int ecode);
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbgetcoll")]
- static extern IntPtr _ejdbgetcoll([In] IntPtr db, [In] IntPtr cname);
+ internal static extern IntPtr _ejdbgetcoll([In] IntPtr db, [In] IntPtr cname);
- static IntPtr _ejdbgetcoll(IntPtr db, string cname) {
+ internal static IntPtr _ejdbgetcoll(IntPtr db, string cname) {
IntPtr cptr = UnixMarshal.StringToHeap(cname, Encoding.UTF8);
try {
return _ejdbgetcoll(db, cptr);
}
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbcreatecoll")]
- static extern IntPtr _ejdbcreatecoll([In] IntPtr db, [In] IntPtr cname, ref EJDBCollectionOptionsN? opts);
+ internal static extern IntPtr _ejdbcreatecoll([In] IntPtr db, [In] IntPtr cname, ref EJDBCollectionOptionsN? opts);
- static IntPtr _ejdbcreatecoll(IntPtr db, String cname, EJDBCollectionOptionsN? opts) {
+ internal static IntPtr _ejdbcreatecoll(IntPtr db, String cname, EJDBCollectionOptionsN? opts) {
IntPtr cptr = UnixMarshal.StringToHeap(cname, Encoding.UTF8);
try {
return _ejdbcreatecoll(db, cptr, ref opts);
}
//EJDB_EXPORT bool ejdbsavebson3(EJCOLL *jcoll, void *bsdata, bson_oid_t *oid, bool merge);
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbsavebson3")]
- static extern bool _ejdbsavebson([In] IntPtr coll, [In] byte[] bsdata, [Out] byte[] oid, [In] bool merge);
+ internal static extern bool _ejdbsavebson([In] IntPtr coll, [In] byte[] bsdata, [Out] byte[] oid, [In] bool merge);
//EJDB_EXPORT bson* ejdbloadbson(EJCOLL *coll, const bson_oid_t *oid);
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbloadbson")]
- static extern IntPtr _ejdbloadbson([In] IntPtr coll, [In] byte[] oid);
+ internal static extern IntPtr _ejdbloadbson([In] IntPtr coll, [In] byte[] oid);
//EJDB_EXPORT const char* bson_data2(const bson *b, int *bsize);
[DllImport(EJDB_LIB_NAME, EntryPoint="bson_data2")]
- static extern IntPtr _bson_data2([In] IntPtr bsptr, out int size);
+ internal static extern IntPtr _bson_data2([In] IntPtr bsptr, out int size);
//EJDB_EXPORT void bson_del(bson *b);
[DllImport(EJDB_LIB_NAME, EntryPoint="bson_del")]
- static extern void _bson_del([In] IntPtr bsptr);
+ internal static extern void _bson_del([In] IntPtr bsptr);
#endregion
/// <summary>
/// Gets the last DB error code or <c>null</c> if underlying native database object does not exist.
/// <returns>The query object.</returns>
/// <param name="qdoc">BSON query spec.</param>
public EJDBQuery CreateQuery(BSONDocument qdoc) {
- return new EJDBQuery(qdoc);
+ CheckDisposed();
+ return new EJDBQuery(this, qdoc);
}
//.//////////////////////////////////////////////////////////////////
// Private staff //
//.//////////////////////////////////////////////////////////////////
+ internal IntPtr DBPtr {
+ get {
+ CheckDisposed();
+ return _db;
+ }
+ }
+
byte[] BsonPtrIntoByteArray(IntPtr bsptr, bool deletebsptr = true) {
if (bsptr == IntPtr.Zero) {
return new byte[0];
return bsdata;
}
- void CheckDisposed() {
+ internal void CheckDisposed() {
if (_db == IntPtr.Zero) {
throw new ObjectDisposedException("Database is disposed");
}
--- /dev/null
+// ============================================================================================
+// .NET API for EJDB database library http://ejdb.org
+// Copyright (C) 2012-2013 Softmotions Ltd <info@softmotions.com>
+//
+// This file is part of EJDB.
+// EJDB is free software; you can redistribute it and/or modify it under the terms of
+// the GNU Lesser General Public License as published by the Free Software Foundation; either
+// version 2.1 of the License or any later version. EJDB is distributed in the hope
+// that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+// You should have received a copy of the GNU Lesser General Public License along with EJDB;
+// if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+// Boston, MA 02111-1307 USA.
+// ============================================================================================
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+using Ejdb.BSON;
+
+namespace Ejdb.DB {
+
+ /// <summary>
+ /// Query result set container.
+ /// </summary>
+ public class EJDBQCursor : IDisposable, IEnumerable<BSONIterator> {
+ //optional query execution log buffer
+ string _log;
+ //current cursor position
+ int _pos;
+ //cursor length
+ int _len;
+ //Pointer to the result set list
+ IntPtr _qresptr;
+ //EJDB_EXPORT void ejdbqresultdispose(EJQRESULT qr);
+ [DllImport(EJDB.EJDB_LIB_NAME, EntryPoint="ejdbqresultdispose")]
+ static extern void _ejdbqresultdispose([In] IntPtr qres);
+ //const void* ejdbqresultbsondata(EJQRESULT qr, int pos, int *size)
+ [DllImport(EJDB.EJDB_LIB_NAME, EntryPoint="ejdbqresultbsondata")]
+ static extern IntPtr _ejdbqresultbsondata([In] IntPtr qres, [In] int pos, out int size);
+
+ /// <summary>
+ /// Gets the number of result records stored in this cursor.
+ /// </summary>
+ public int Length {
+ get {
+ return _len;
+ }
+ }
+
+ /// <summary>
+ /// Gets optional query execution log.
+ /// </summary>
+ /// <value>The log.</value>
+ public string Log {
+ get {
+ return _log;
+ }
+ }
+
+ internal EJDBQCursor(IntPtr qresptr, int len, string log = null) {
+ _qresptr = qresptr;
+ _log = log;
+ _len = len;
+ }
+
+ public BSONIterator Next() {
+ if (_qresptr == IntPtr.Zero || _pos >= _len) {
+ return null;
+ }
+ //static extern IntPtr _ejdbqresultbsondata([In] IntPtr qres, [In] int idx, out int size)
+ int size;
+ IntPtr bsdataptr = _ejdbqresultbsondata(_qresptr, _pos, out size);
+ if (bsdataptr == IntPtr.Zero) {
+ return null;
+ }
+ byte[] bsdata = new byte[size];
+ Marshal.Copy(bsdataptr, bsdata, 0, bsdata.Length);
+ _pos++;
+ return new BSONIterator(bsdata);
+ }
+
+ public IEnumerator<BSONIterator> GetEnumerator() {
+ BSONIterator it;
+ while ((it = Next()) != null) {
+ yield return it;
+ }
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ return GetEnumerator();
+ }
+
+ public void Dispose() {
+ _log = null;
+ _pos = 0;
+ if (_qresptr != IntPtr.Zero) {
+ //static extern void _ejdbqresultdispose([In] IntPtr qres);
+ _ejdbqresultdispose(_qresptr);
+ _qresptr = IntPtr.Zero;
+ }
+ }
+ }
+}
+
// ============================================================================================
using System;
using Ejdb.BSON;
+using System.Runtime.InteropServices;
namespace Ejdb.DB {
+ /// <summary>
+ /// EJDB query.
+ /// </summary>
public class EJDBQuery : IDisposable {
- IntPtr _qptr;
+ //Query search mode flags in ejdbqryexecute()
+ /// <summary>
+ /// Query only count(*)
+ /// </summary>
+ public const int JBQRYCOUNT_FLAG = 1;
- internal EJDBQuery(BSONDocument qdoc) {
+ /// <summary>
+ /// Fetch first record only.
+ /// </summary>
+ public const int JBQRYFINDONE_FLAG = 1 << 1;
+
+ /// <summary>
+ /// Explain query execution and
+ /// store query execution log into <see cref="Ejdb.DB.EJDBQCursor#Log"/>
+ /// </summary>
+ public const int EXPLAIN_FLAG = 1 << 16;
+
+ /// <summary>
+ /// EJDB query object <c>EJQ</c> pointer.
+ /// </summary>
+ IntPtr _qptr = IntPtr.Zero;
+
+ /// <summary>
+ /// Database reference.
+ /// </summary>
+ EJDB _jb;
+
+ /// <summary>
+ /// Last used query hints document.
+ /// </summary>
+ BSONDocument _hints;
+ //
+ #region NativeRefs
+ //EJDB_EXPORT void ejdbquerydel(EJQ *q);
+ [DllImport(EJDB.EJDB_LIB_NAME, EntryPoint="ejdbquerydel")]
+ static extern void _ejdbquerydel([In] IntPtr qptr);
+ //EJDB_EXPORT EJQ* ejdbcreatequery2(EJDB *jb, void *qbsdata);
+ [DllImport(EJDB.EJDB_LIB_NAME, EntryPoint="ejdbcreatequery2")]
+ static extern IntPtr _ejdbcreatequery([In] IntPtr jb, [In] byte[] bsdata);
+ //EJDB_EXPORT EJQ* ejdbqueryhints(EJDB *jb, EJQ *q, void *hintsbsdata)
+ [DllImport(EJDB.EJDB_LIB_NAME, EntryPoint="ejdbqueryhints")]
+ static extern IntPtr _ejdbqueryhints([In] IntPtr jb, [In] IntPtr qptr, [In] byte[] bsdata);
+ //EJDB_EXPORT EJQ* ejdbqueryaddor(EJDB *jb, EJQ *q, void *orbsdata)
+ [DllImport(EJDB.EJDB_LIB_NAME, EntryPoint="ejdbqueryaddor")]
+ static extern IntPtr _ejdbqueryaddor([In] IntPtr jb, [In] IntPtr qptr, [In] byte[] bsdata);
+ //EJDB_EXPORT EJQRESULT ejdbqryexecute(EJCOLL *jcoll, const EJQ *q, uint32_t *count, int qflags, TCXSTR *log)
+ [DllImport(EJDB.EJDB_LIB_NAME, EntryPoint="ejdbqryexecute")]
+ static extern IntPtr _ejdbqryexecute([In] IntPtr jcoll, [In] IntPtr q, out int count, [In] int qflags, [In] IntPtr logxstr);
+ #endregion
+ internal EJDBQuery(EJDB jb, BSONDocument qdoc) {
+ _qptr = _ejdbcreatequery(jb.DBPtr, qdoc.ToByteArray());
+ if (_qptr == IntPtr.Zero) {
+ throw new EJDBQueryException(jb);
+ }
+ _jb = jb;
+ }
+
+ /// <summary>
+ /// Append OR joined restriction to this query.
+ /// </summary>
+ /// <returns>This query object.</returns>
+ /// <param name="doc">Query document.</param>
+ public EJDBQuery AppendOR(BSONDocument doc) {
+ CheckDisposed();
+ //static extern IntPtr _ejdbqueryaddor([In] IntPtr jb, [In] IntPtr qptr, [In] byte[] bsdata);
+ IntPtr qptr = _ejdbqueryaddor(_jb.DBPtr, _qptr, doc.ToByteArray());
+ if (qptr == IntPtr.Zero) {
+ throw new EJDBQueryException(_jb);
+ }
+ return this;
+ }
+
+ /// <summary>
+ /// Sets the query hints.
+ /// </summary>
+ /// <remarks>
+ /// Replaces previous hints associated with this query.
+ /// </remarks>
+ /// <returns>This query object.</returns>
+ /// <param name="hints">Hints document.</param>
+ public EJDBQuery SetHints(BSONDocument hints) {
+ CheckDisposed();
+ //static extern IntPtr _ejdbqueryhints([In] IntPtr jb, [In] IntPtr qptr, [In] byte[] bsdata);
+ IntPtr qptr = _ejdbqueryhints(_jb.DBPtr, _qptr, hints.ToByteArray());
+ if (qptr == IntPtr.Zero) {
+ throw new EJDBQueryException(_jb);
+ }
+ _hints = hints;
+ return this;
+ }
+
+ public EJDBQCursor Find(string cname, int flags = 0) {
+ IntPtr cptr = EJDB._ejdbgetcoll(_jb.DBPtr, cname);
+ if (cptr == IntPtr.Zero) {
+ return new EJDBQCursor(IntPtr.Zero, 0);
+ }
+ //static extern IntPtr _ejdbqryexecute([In] IntPtr jcoll, [In] IntPtr q, out int count, [In] int qflags, [In] IntPtr logxstr);
+ //todo
+ //return new EJDBQCursor();
+ return null;
+ }
+
+ public BSONIterator FinOne(string cname, int flags = 0) {
+ using (EJDBQCursor cur = Find(cname, flags | JBQRYFINDONE_FLAG)) {
+ return cur.Next();
+ }
+ }
+
+ public int Count(string cname, int flags = 0) {
+ using (EJDBQCursor cur = Find(cname, flags | JBQRYCOUNT_FLAG)) {
+ return cur.Length;
+ }
+ }
+
+ public int Update(string cname, int flags = 0) {
+ using (EJDBQCursor cur = Find(cname, flags | JBQRYCOUNT_FLAG)) {
+ return cur.Length;
+ }
}
public void Dispose() {
- throw new NotImplementedException();
+ if (_qptr != IntPtr.Zero) {
+ //static extern void _ejdbquerydel([In] IntPtr qptr);
+ _ejdbquerydel(_qptr);
+ _qptr = IntPtr.Zero;
+ }
+ if (_jb != null) {
+ _jb = null;
+ }
+ _hints = null;
+ }
+
+ internal void CheckDisposed() {
+ if (_jb == null || _qptr == IntPtr.Zero) {
+ throw new ObjectDisposedException("Query object is disposed");
+ }
}
}
}
--- /dev/null
+// ============================================================================================
+// .NET API for EJDB database library http://ejdb.org
+// Copyright (C) 2012-2013 Softmotions Ltd <info@softmotions.com>
+//
+// This file is part of EJDB.
+// EJDB is free software; you can redistribute it and/or modify it under the terms of
+// the GNU Lesser General Public License as published by the Free Software Foundation; either
+// version 2.1 of the License or any later version. EJDB is distributed in the hope
+// that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+// You should have received a copy of the GNU Lesser General Public License along with EJDB;
+// if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+// Boston, MA 02111-1307 USA.
+// ============================================================================================
+using System;
+
+namespace Ejdb.DB {
+
+ public class EJDBQueryException : EJDBException {
+ public EJDBQueryException(EJDB db) : base(db) {
+ }
+ }
+}
+
<Compile Include="Ejdb.DB\EJDBException.cs" />
<Compile Include="Ejdb.Tests\TestEJDB.cs" />
<Compile Include="Ejdb.DB\EJDBQuery.cs" />
+ <Compile Include="Ejdb.DB\EJDBQueryException.cs" />
+ <Compile Include="Ejdb.DB\EJDBQCursor.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<Properties>
<MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" />
- <MonoDevelop.Ide.Workbench ActiveDocument="Ejdb.DB/EJDB.cs">
+ <MonoDevelop.Ide.Workbench ActiveDocument="Ejdb.DB/EJDBQuery.cs">
<Files>
- <File FileName="Ejdb.DB/EJDB.cs" Line="266" Column="13" />
- <File FileName="Ejdb.BSON/BSONType.cs" Line="1" Column="1" />
- <File FileName="Ejdb.Tests/TestEJDB.cs" Line="53" Column="23" />
- <File FileName="Ejdb.BSON/BSONDocument.cs" Line="1" Column="1" />
- <File FileName="Ejdb.BSON/BSONOid.cs" Line="1" Column="1" />
- <File FileName="Ejdb.BSON/BSONIterator.cs" Line="326" Column="3" />
- <File FileName="Ejdb.Tests/TestBSON.cs" Line="15" Column="49" />
- <File FileName="Ejdb.DB/EJDBQuery.cs" Line="31" Column="3" />
- <File FileName="Ejdb.DB/EJDBException.cs" Line="1" Column="1" />
+ <File FileName="Ejdb.DB/EJDB.cs" Line="281" Column="37" />
+ <File FileName="Ejdb.BSON/BSONIterator.cs" Line="25" Column="2" />
+ <File FileName="Ejdb.DB/EJDBQuery.cs" Line="25" Column="38" />
+ <File FileName="Ejdb.DB/EJDBQueryException.cs" Line="21" Column="48" />
+ <File FileName="Ejdb.DB/EJDBQCursor.cs" Line="67" Column="18" />
+ <File FileName="Ejdb.BSON/BSONDocument.cs" Line="63" Column="3" />
</Files>
<Pads>
<Pad Id="ProjectPad">
<Node name="References" expanded="True" />
<Node name="Ejdb.BSON" expanded="True" />
<Node name="Ejdb.DB" expanded="True">
- <Node name="EJDB.cs" selected="True" />
+ <Node name="EJDBQuery.cs" selected="True" />
</Node>
<Node name="Ejdb.IO" expanded="True" />
<Node name="Ejdb.JSON" expanded="True" />
<Value>_input.BaseStream.Position</Value>
</State>
</Pad>
- <Pad Id="MonoDevelop.NUnit.TestPad">
- <State expanded="True" selected="True" />
- </Pad>
<Pad Id="ConnectionManagerPad">
<State selected="True" />
</Pad>
+ <Pad Id="MonoDevelop.NUnit.TestPad">
+ <State expanded="True" selected="True">
+ <Node name="nejdb" expanded="True">
+ <Node name="Ejdb" expanded="True">
+ <Node name="Tests" expanded="True">
+ <Node name="TestBSON" expanded="True" />
+ <Node name="TestEJDB" expanded="True" />
+ </Node>
+ </Node>
+ </Node>
+ </State>
+ </Pad>
</Pads>
</MonoDevelop.Ide.Workbench>
<MonoDevelop.Ide.DebuggingService.Breakpoints>
return qr ? tclistnum(qr) : 0;
}
-const void* ejdbqresultbsondata(EJQRESULT qr, int idx) {
- if (!qr || idx < 0) return NULL;
- return tclistval2(qr, idx);
+const void* ejdbqresultbsondata(EJQRESULT qr, int pos, int *size) {
+ if (!qr || pos < 0) {
+ *size = 0;
+ return NULL;
+ }
+ const void *bsdata = tclistval2(qr, pos);
+ *size = (bsdata != NULL) ? bson_size2(bsdata) : 0;
+ return bsdata;
}
void ejdbqresultdispose(EJQRESULT qr) {
if (BSON_IS_NUM_TYPE(bt)) {
int64_t v = bson_iterator_long(&it);
ejq->max = (uint32_t) ((v < 0) ? 0 : v);
+ } else if (qflags & JBQRYFINDONE) {
+ ejq->max = (uint32_t) 1;
}
if (!(qflags & JBQRYCOUNT)) {
bt = bson_find(&it, ejq->hints, "$fields"); //Collect required fields
};
enum { /*< Query search mode flags in ejdbqryexecute() */
- JBQRYCOUNT = 1 /*< Query only count(*) */
+ JBQRYCOUNT = 1, /*< Query only count(*) */
+ JBQRYFINDONE = 1 << 1 /*< Fetch first record only */
};
EJDB_EXPORT bool ejdbisvalidoidstr(const char *oid);
EJDB_EXPORT int ejdbqresultnum(EJQRESULT qr);
/**
- * Gets the pointer of query result BSON data buffer at the specified index `idx`.
+ * Gets the pointer of query result BSON data buffer at the specified position `pos`.
* If `qr` is `NULL` or `idx` is put of index range then the `NULL` pointer will be returned.
* @param qr Query result set object.
- * @param idx Zero based index of the record.
+ * @param pos Zero based position of the record.
*/
-EJDB_EXPORT const void* ejdbqresultbsondata(EJQRESULT qr, int idx);
+EJDB_EXPORT const void* ejdbqresultbsondata(EJQRESULT qr, int pos, int *size);
/**
* Disposes the query result set and frees a records buffers.