mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
- Add Support of the MongoDB Java Driver.
modified: storage/connect/CMakeLists.txt modified: storage/connect/JavaWrappers.jar modified: storage/connect/colblk.h modified: storage/connect/filter.cpp modified: storage/connect/filter.h modified: storage/connect/ha_connect.cc modified: storage/connect/ha_connect.h modified: storage/connect/jdbccat.h modified: storage/connect/jdbconn.cpp modified: storage/connect/jdbconn.h modified: storage/connect/mongofam.cpp modified: storage/connect/mongofam.h modified: storage/connect/mycat.cc modified: storage/connect/mycat.h modified: storage/connect/tabext.h modified: storage/connect/tabjdbc.cpp modified: storage/connect/tabjdbc.h modified: storage/connect/tabjson.cpp modified: storage/connect/tabjson.h modified: storage/connect/tabmgo.cpp modified: storage/connect/tabmgo.h created: storage/connect/Mongo2Interface.java created: storage/connect/Mongo3Interface.java created: storage/connect/cmgoconn.cpp created: storage/connect/cmgoconn.h created: storage/connect/javaconn.cpp created: storage/connect/javaconn.h created: storage/connect/jmgfam.cpp created: storage/connect/jmgfam.h created: storage/connect/jmgoconn.cpp created: storage/connect/jmgoconn.h created: storage/connect/mongo.cpp created: storage/connect/mongo.h created: storage/connect/tabjmg.cpp created: storage/connect/tabjmg.h - tdbp not initialized when catched exception in CntGetTDB (connect.cc line 188) modified: storage/connect/connect.h - CheckCleanup should sometimes doing cleanup on pure info Sometimes MariaDB loops on info to get the size of all tables in a database. This can sometimes fail by exhausted memory. CheckCleanup now have a force boolean parameter (defaulting to false) modified: storage/connect/ha_connect.cc modified: storage/connect/user_connect.cc modified: storage/connect/user_connect.h Change the copyright of some source files modified: storage/connect/connect.cc modified: storage/connect/connect.h modified: storage/connect/engmsg.h modified: storage/connect/global.h modified: storage/connect/ha_connect.cc modified: storage/connect/ha_connect.h modified: storage/connect/msgid.h modified: storage/connect/mycat.cc modified: storage/connect/mycat.h modified: storage/connect/os.h modified: storage/connect/osutil.c modified: storage/connect/osutil.h modified: storage/connect/user_connect.cc modified: storage/connect/user_connect.h
This commit is contained in:
@@ -245,7 +245,7 @@ int main() {
|
||||
ENDIF(CONNECT_WITH_ODBC)
|
||||
|
||||
#
|
||||
# JDBC
|
||||
# JDBC and MongoDB Java Driver
|
||||
#
|
||||
IF(APPLE)
|
||||
OPTION(CONNECT_WITH_JDBC "Compile CONNECT storage engine without JDBC support" OFF)
|
||||
@@ -262,9 +262,13 @@ IF(CONNECT_WITH_JDBC)
|
||||
INCLUDE_DIRECTORIES(${JAVA_INCLUDE_PATH2})
|
||||
# SET(JDBC_LIBRARY ${JAVA_JVM_LIBRARY}) will be dynamically linked
|
||||
SET(CONNECT_SOURCES ${CONNECT_SOURCES}
|
||||
jdbconn.cpp tabjdbc.cpp jdbconn.h tabjdbc.h jdbccat.h
|
||||
javaconn.cpp jdbconn.cpp tabjdbc.cpp
|
||||
jmgoconn.cpp jmgfam.cpp mongo.cpp tabjmg.cpp
|
||||
jdbccat.h javaconn.h jdbconn.h tabjdbc.h
|
||||
jmgoconn.h jmgfam.h mongo.h tabjmg.h
|
||||
JdbcInterface.java ApacheInterface.java MariadbInterface.java
|
||||
MysqlInterface.java OracleInterface.java PostgresqlInterface.java
|
||||
Mongo2Interface.java Mongo3Interface.java
|
||||
JavaWrappers.jar)
|
||||
# TODO: Find how to compile and install the java wrapper classes
|
||||
# Find required libraries and include directories
|
||||
@@ -292,7 +296,7 @@ IF(CONNECT_WITH_ZIP)
|
||||
ENDIF(CONNECT_WITH_ZIP)
|
||||
|
||||
#
|
||||
# MONGO (CMAKE NOT YET WORKING)
|
||||
# MONGO C Driver (CMAKE NOT YET WORKING)
|
||||
#
|
||||
|
||||
#OPTION(CONNECT_WITH_MONGO "Compile CONNECT storage engine with MONGO support" ON)
|
||||
@@ -302,16 +306,21 @@ ENDIF(CONNECT_WITH_ZIP)
|
||||
# # Adding some typical places to search in
|
||||
# SET(PC_MONGO_INCLUDE_DIRS
|
||||
# C:/mongo-c-driver/include
|
||||
# D:/mongo-c-driver/include)
|
||||
# D:/mongo-c-driver/include)
|
||||
# SET(PC_MONGO_LIBRARY_DIRS
|
||||
# C:/mongo-c-driver/lib
|
||||
# D:/mongo-c-driver/lib)
|
||||
# D:/mongo-c-driver/lib)
|
||||
# ENDIF(WIN32)
|
||||
# FIND_PACKAGE(libmongoc)
|
||||
# IF (MONGO_FOUND)
|
||||
# INCLUDE_DIRECTORIES(${MONGO_INCLUDE_DIR})
|
||||
# SET(MONGO_LIBRARY ${MONGO_LIBRARIES})
|
||||
# SET(CONNECT_SOURCES ${CONNECT_SOURCES} mongofam.cpp mongofam.h)
|
||||
# SET(CONNECT_SOURCES ${CONNECT_SOURCES}
|
||||
# cmgoconn.cpp mongofam.cpp tabmgo.cpp
|
||||
# cmgoconn.h mongofam.h tabmgo.h)
|
||||
# IF (NOT JAVA_FOUND AND JNI_FOUND)
|
||||
# SET(CONNECT_SOURCES ${CONNECT_SOURCES} mongo.cpp mongo.h)
|
||||
# ENDIF (NOT JAVA_FOUND AND JNI_FOUND)
|
||||
# add_definitions(-DMONGO_SUPPORT)
|
||||
# ENDIF(MONGO_FOUND)
|
||||
#ENDIF(CONNECT_WITH_MONGO)
|
||||
@@ -339,3 +348,4 @@ MYSQL_ADD_PLUGIN(connect ${CONNECT_SOURCES}
|
||||
LINK_LIBRARIES ${ZLIB_LIBRARY} ${XML_LIBRARY} ${ICONV_LIBRARY}
|
||||
${ODBC_LIBRARY} ${JDBC_LIBRARY} ${IPHLPAPI_LIBRARY})
|
||||
|
||||
|
||||
|
Binary file not shown.
437
storage/connect/Mongo2Interface.java
Normal file
437
storage/connect/Mongo2Interface.java
Normal file
@@ -0,0 +1,437 @@
|
||||
package wrappers;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.mongodb.AggregationOptions;
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.Cursor;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.MongoClientURI;
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.WriteConcernException;
|
||||
import com.mongodb.WriteResult;
|
||||
import com.mongodb.util.JSON;
|
||||
|
||||
public class Mongo2Interface {
|
||||
boolean DEBUG = false;
|
||||
String Errmsg = "No error";
|
||||
Set<String> Colnames = null;
|
||||
Cursor cursor = null;
|
||||
MongoClient client = null;
|
||||
DB db = null;
|
||||
DBCollection coll = null;
|
||||
BasicDBObject doc = null;
|
||||
BasicDBObject dbq = null;
|
||||
BasicDBObject dbf = null;
|
||||
List<DBObject> pip = null;
|
||||
AggregationOptions aop = null;
|
||||
|
||||
// === Constructors/finalize =========================================
|
||||
public Mongo2Interface() {
|
||||
this(false);
|
||||
} // end of default constructor
|
||||
|
||||
public Mongo2Interface(boolean b) {
|
||||
DEBUG = b;
|
||||
} // end of constructor
|
||||
|
||||
protected void SetErrmsg(String str) {
|
||||
if (DEBUG)
|
||||
System.out.println(str);
|
||||
|
||||
Errmsg = str;
|
||||
} // end of SetErrmsg
|
||||
|
||||
protected void SetErrmsg(Exception e) {
|
||||
if (DEBUG)
|
||||
System.out.println(e.getMessage());
|
||||
|
||||
Errmsg = e.toString();
|
||||
} // end of SetErrmsg
|
||||
|
||||
public String GetErrmsg() {
|
||||
String err = Errmsg;
|
||||
|
||||
Errmsg = "No error";
|
||||
return err;
|
||||
} // end of GetErrmsg
|
||||
|
||||
public int MongoConnect(String[] parms) {
|
||||
int rc = 0;
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("Mongo2: URI=" + parms[0] + " DB=" + parms[1]);
|
||||
|
||||
try {
|
||||
MongoClientURI uri = new MongoClientURI(parms[0]);
|
||||
|
||||
client = new MongoClient(uri);
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("Connection " + client.toString() + " established");
|
||||
|
||||
// Now connect to your databases
|
||||
db = client.getDB(parms[1]);
|
||||
|
||||
if (parms[2] != null && !parms[2].isEmpty()) {
|
||||
if (DEBUG)
|
||||
System.out.println("user=" + parms[2] + " pwd=" + parms[3]);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
boolean auth = db.authenticate(parms[2], parms[3].toCharArray());
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("Authentication: " + auth);
|
||||
|
||||
} // endif user
|
||||
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
rc = -1;
|
||||
} catch (Exception e) {
|
||||
SetErrmsg(e);
|
||||
rc = -3;
|
||||
} // end try/catch
|
||||
|
||||
return rc;
|
||||
} // end of MongoConnect
|
||||
|
||||
public int MongoDisconnect() {
|
||||
int rc = 0;
|
||||
|
||||
try {
|
||||
if (cursor != null) {
|
||||
if (DEBUG)
|
||||
System.out.println("Closing cursor");
|
||||
|
||||
cursor.close();
|
||||
cursor = null;
|
||||
} // endif client
|
||||
|
||||
if (client != null) {
|
||||
if (DEBUG)
|
||||
System.out.println("Closing connection");
|
||||
|
||||
client.close();
|
||||
client = null;
|
||||
} // endif client
|
||||
|
||||
} catch (MongoException se) {
|
||||
SetErrmsg(se);
|
||||
rc += 8;
|
||||
} // end try/catch
|
||||
|
||||
return rc;
|
||||
} // end of MongoDisconnect
|
||||
|
||||
public boolean GetCollection(String name) {
|
||||
if (DEBUG)
|
||||
System.out.println("GetCollection: name=" + name);
|
||||
|
||||
try {
|
||||
coll = db.getCollection(name);
|
||||
} catch (Exception e) {
|
||||
SetErrmsg(e);
|
||||
return true;
|
||||
} // end try/catch
|
||||
|
||||
return false;
|
||||
} // end of GetCollection
|
||||
|
||||
public long GetCollSize() {
|
||||
return (coll != null) ? coll.count() : 0;
|
||||
} // end of GetCollSize
|
||||
|
||||
public boolean FindColl(String query, String fields) {
|
||||
if (DEBUG)
|
||||
System.out.println("FindColl: query=" + query + " fields=" + fields);
|
||||
|
||||
try {
|
||||
if (query != null || fields != null) {
|
||||
dbq = (BasicDBObject) JSON.parse((query != null) ? query : "{}");
|
||||
|
||||
if (fields != null) {
|
||||
dbf = (BasicDBObject) JSON.parse(fields);
|
||||
cursor = coll.find(dbq, dbf);
|
||||
} else
|
||||
cursor = coll.find(dbq);
|
||||
|
||||
} else
|
||||
cursor = coll.find();
|
||||
|
||||
} catch (Exception e) {
|
||||
SetErrmsg(e);
|
||||
return true;
|
||||
} // end try/catch
|
||||
|
||||
return false;
|
||||
} // end of FindColl
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean AggregateColl(String pipeline) {
|
||||
if (DEBUG)
|
||||
System.out.println("AggregateColl: pipeline=" + pipeline);
|
||||
|
||||
try {
|
||||
DBObject pipe = (DBObject) JSON.parse(pipeline);
|
||||
|
||||
pip = (List<DBObject>) pipe.get("pipeline");
|
||||
aop = AggregationOptions.builder().batchSize(0).allowDiskUse(true)
|
||||
.outputMode(AggregationOptions.OutputMode.CURSOR).build();
|
||||
cursor = coll.aggregate(pip, aop);
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
return true;
|
||||
} // end try/catch
|
||||
|
||||
return false;
|
||||
} // end of AggregateColl
|
||||
|
||||
public boolean Rewind() {
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
|
||||
if (pip == null) {
|
||||
if (dbf != null)
|
||||
cursor = coll.find(dbq, dbf);
|
||||
else if (dbq != null)
|
||||
cursor = coll.find(dbq);
|
||||
else
|
||||
cursor = coll.find();
|
||||
|
||||
} else
|
||||
cursor = coll.aggregate(pip, aop);
|
||||
|
||||
return (cursor == null);
|
||||
} // end of Rewind
|
||||
|
||||
public int ReadNext() {
|
||||
try {
|
||||
if (cursor.hasNext()) {
|
||||
doc = (BasicDBObject) cursor.next();
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("Class doc = " + doc.getClass());
|
||||
|
||||
Colnames = doc.keySet();
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
return -1;
|
||||
} // end try/catch
|
||||
|
||||
} // end of ReadNext
|
||||
|
||||
public boolean Fetch(int row) {
|
||||
if (cursor.hasNext()) {
|
||||
doc = (BasicDBObject) cursor.next();
|
||||
Colnames = doc.keySet();
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
||||
} // end of Fetch
|
||||
|
||||
public String GetDoc() {
|
||||
return (doc != null) ? doc.toString() : null;
|
||||
} // end of GetDoc
|
||||
|
||||
public Set<String> GetColumns() {
|
||||
if (doc != null)
|
||||
return doc.keySet();
|
||||
else
|
||||
return null;
|
||||
|
||||
} // end of GetColumns
|
||||
|
||||
public String ColumnDesc(int n, int[] val) {
|
||||
// if (rsmd == null) {
|
||||
// System.out.println("No result metadata");
|
||||
// return null;
|
||||
// } else try {
|
||||
// val[0] = rsmd.getColumnType(n);
|
||||
// val[1] = rsmd.getPrecision(n);
|
||||
// val[2] = rsmd.getScale(n);
|
||||
// val[3] = rsmd.isNullable(n);
|
||||
// return rsmd.getColumnLabel(n);
|
||||
// } catch (SQLException se) {
|
||||
// SetErrmsg(se);
|
||||
// } //end try/catch
|
||||
|
||||
return null;
|
||||
} // end of ColumnDesc
|
||||
|
||||
protected Object GetFieldObject(String path) {
|
||||
Object o = null;
|
||||
BasicDBObject dob = null;
|
||||
BasicDBList lst = null;
|
||||
String[] names = null;
|
||||
|
||||
if (path == null || path.equals("*"))
|
||||
return doc;
|
||||
else if (doc instanceof BasicDBObject)
|
||||
dob = doc;
|
||||
// else if (o instanceof BasicDBList)
|
||||
// lst = (BasicDBList) doc;
|
||||
else
|
||||
return doc;
|
||||
|
||||
try {
|
||||
names = path.split("\\.");
|
||||
|
||||
for (String name : names) {
|
||||
if (lst != null) {
|
||||
o = lst.get(Integer.parseInt(name));
|
||||
} else
|
||||
o = dob.get(name);
|
||||
|
||||
if (o == null)
|
||||
break;
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("Class o = " + o.getClass());
|
||||
|
||||
if (o instanceof BasicDBObject) {
|
||||
dob = (BasicDBObject) o;
|
||||
lst = null;
|
||||
} else if (o instanceof BasicDBList) {
|
||||
lst = (BasicDBList) o;
|
||||
} else
|
||||
break;
|
||||
|
||||
} // endfor name
|
||||
|
||||
} catch (IndexOutOfBoundsException x) {
|
||||
o = null;
|
||||
} catch (MongoException se) {
|
||||
SetErrmsg(se);
|
||||
o = null;
|
||||
} // end try/catch
|
||||
|
||||
return o;
|
||||
} // end of GetFieldObject
|
||||
|
||||
public String GetField(String path) {
|
||||
Object o = GetFieldObject(path);
|
||||
|
||||
if (o != null) {
|
||||
if (o instanceof Date) {
|
||||
Integer TS = (int) (((Date) o).getTime() / 1000);
|
||||
return TS.toString();
|
||||
} // endif Date
|
||||
|
||||
return o.toString();
|
||||
} else
|
||||
return null;
|
||||
|
||||
} // end of GetField
|
||||
|
||||
public Object MakeDocument() {
|
||||
return new BasicDBObject();
|
||||
} // end of MakeDocument
|
||||
|
||||
public boolean DocAdd(Object bdc, String key, Object val) {
|
||||
try {
|
||||
((BasicDBObject) bdc).append(key, val);
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
return true;
|
||||
} // end try/catch
|
||||
|
||||
return false;
|
||||
} // end of DocAdd
|
||||
|
||||
public Object MakeArray() {
|
||||
return new BasicDBList();
|
||||
} // end of MakeArray
|
||||
|
||||
public boolean ArrayAdd(Object bar, int n, Object val) {
|
||||
try {
|
||||
((BasicDBList) bar).put(n, val);
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
SetErrmsg(ex);
|
||||
return true;
|
||||
} // end try/catch
|
||||
|
||||
return false;
|
||||
} // end of ArrayAdd
|
||||
|
||||
public boolean CollInsert(Object dob) {
|
||||
try {
|
||||
coll.insert((BasicDBObject) dob);
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
SetErrmsg(ex);
|
||||
return true;
|
||||
} // end try/catch
|
||||
|
||||
return false;
|
||||
} // end of CollInsert
|
||||
|
||||
public long CollUpdate(Object upd) {
|
||||
long n = -1;
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("upd: " + upd.toString());
|
||||
|
||||
try {
|
||||
DBObject qry = new BasicDBObject("_id", doc.get("_id"));
|
||||
|
||||
WriteResult res = coll.update(qry, (DBObject) upd);
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("CollUpdate: " + res.toString());
|
||||
|
||||
n = res.getN();
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
} catch (Exception ex) {
|
||||
SetErrmsg(ex);
|
||||
} // end try/catch
|
||||
|
||||
return n;
|
||||
} // end of CollUpdate
|
||||
|
||||
public long CollDelete(boolean all) {
|
||||
long n = -1;
|
||||
|
||||
try {
|
||||
WriteResult res;
|
||||
BasicDBObject qry = new BasicDBObject();
|
||||
|
||||
if (!all)
|
||||
qry.append("_id", doc.get("_id"));
|
||||
|
||||
res = coll.remove(qry);
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("CollDelete: " + res.toString());
|
||||
|
||||
n = res.getN();
|
||||
} catch (WriteConcernException wx) {
|
||||
SetErrmsg(wx);
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
} catch (UnsupportedOperationException ux) {
|
||||
SetErrmsg(ux);
|
||||
n = 0;
|
||||
} // end try/catch
|
||||
|
||||
return n;
|
||||
} // end of CollDelete
|
||||
|
||||
} // end of class MongoInterface
|
504
storage/connect/Mongo3Interface.java
Normal file
504
storage/connect/Mongo3Interface.java
Normal file
@@ -0,0 +1,504 @@
|
||||
package wrappers;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bson.BsonArray;
|
||||
import org.bson.BsonBoolean;
|
||||
import org.bson.BsonDateTime;
|
||||
import org.bson.BsonDocument;
|
||||
import org.bson.BsonDouble;
|
||||
import org.bson.BsonInt32;
|
||||
import org.bson.BsonInt64;
|
||||
import org.bson.BsonNull;
|
||||
import org.bson.BsonString;
|
||||
import org.bson.BsonValue;
|
||||
import org.bson.Document;
|
||||
import org.bson.conversions.Bson;
|
||||
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.MongoClientURI;
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.client.AggregateIterable;
|
||||
import com.mongodb.client.FindIterable;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.MongoCursor;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.mongodb.client.model.Filters;
|
||||
import com.mongodb.client.result.DeleteResult;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
|
||||
public class Mongo3Interface {
|
||||
boolean DEBUG = false;
|
||||
String Errmsg = "No error";
|
||||
Set<String> Colnames = null;
|
||||
MongoClient client = null;
|
||||
MongoDatabase db = null;
|
||||
MongoCollection<BsonDocument> coll = null;
|
||||
FindIterable<BsonDocument> finditer = null;
|
||||
AggregateIterable<BsonDocument> aggiter = null;
|
||||
MongoCursor<BsonDocument> cursor = null;
|
||||
BsonDocument doc = null;
|
||||
BsonDocument util = null;
|
||||
BsonNull bsonull = new BsonNull();
|
||||
|
||||
// === Constructors/finalize =========================================
|
||||
public Mongo3Interface() {
|
||||
this(false);
|
||||
} // end of default constructor
|
||||
|
||||
public Mongo3Interface(boolean b) {
|
||||
DEBUG = b;
|
||||
} // end of constructor
|
||||
|
||||
protected void SetErrmsg(String str) {
|
||||
if (DEBUG)
|
||||
System.out.println(str);
|
||||
|
||||
Errmsg = str;
|
||||
} // end of SetErrmsg
|
||||
|
||||
protected void SetErrmsg(Exception e) {
|
||||
if (DEBUG)
|
||||
System.out.println(e.getMessage());
|
||||
|
||||
Errmsg = e.toString();
|
||||
} // end of SetErrmsg
|
||||
|
||||
public String GetErrmsg() {
|
||||
String err = Errmsg;
|
||||
|
||||
Errmsg = "No error";
|
||||
return err;
|
||||
} // end of GetErrmsg
|
||||
|
||||
public int MongoConnect(String[] parms) {
|
||||
int rc = 0;
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("Mongo3: URI=" + parms[0] + " DB=" + parms[1]);
|
||||
|
||||
try {
|
||||
MongoClientURI uri = new MongoClientURI(parms[0]);
|
||||
|
||||
client = new MongoClient(uri);
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("Connection " + client.toString() + " established");
|
||||
|
||||
// Now connect to your databases
|
||||
db = client.getDatabase(parms[1]);
|
||||
|
||||
// if (parms[2] != null && !parms[2].isEmpty()) {
|
||||
// if (DEBUG)
|
||||
// System.out.println("user=" + parms[2] + " pwd=" + parms[3]);
|
||||
|
||||
// @SuppressWarnings("deprecation")
|
||||
// boolean auth = db.authenticate(parms[2], parms[3].toCharArray());
|
||||
|
||||
// if (DEBUG)
|
||||
// System.out.println("Authentication: " + auth);
|
||||
|
||||
// } // endif user
|
||||
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
rc = -1;
|
||||
} catch (Exception e) {
|
||||
SetErrmsg(e);
|
||||
rc = -3;
|
||||
} // end try/catch
|
||||
|
||||
return rc;
|
||||
} // end of MongoConnect
|
||||
|
||||
public int MongoDisconnect() {
|
||||
int rc = 0;
|
||||
|
||||
try {
|
||||
if (cursor != null) {
|
||||
if (DEBUG)
|
||||
System.out.println("Closing cursor");
|
||||
|
||||
cursor.close();
|
||||
cursor = null;
|
||||
} // endif client
|
||||
|
||||
if (client != null) {
|
||||
if (DEBUG)
|
||||
System.out.println("Closing connection");
|
||||
|
||||
client.close();
|
||||
client = null;
|
||||
} // endif client
|
||||
|
||||
} catch (MongoException se) {
|
||||
SetErrmsg(se);
|
||||
rc += 8;
|
||||
} // end try/catch
|
||||
|
||||
return rc;
|
||||
} // end of MongoDisconnect
|
||||
|
||||
public boolean GetCollection(String name) {
|
||||
if (DEBUG)
|
||||
System.out.println("GetCollection: name=" + name);
|
||||
|
||||
try {
|
||||
coll = db.getCollection(name).withDocumentClass(BsonDocument.class);
|
||||
} catch (Exception e) {
|
||||
SetErrmsg(e);
|
||||
return true;
|
||||
} // end try/catch
|
||||
|
||||
return false;
|
||||
} // end of GetCollection
|
||||
|
||||
public long GetCollSize() {
|
||||
return (coll != null) ? coll.count() : 0;
|
||||
} // end of GetCollSize
|
||||
|
||||
public boolean FindColl(String query, String fields) {
|
||||
if (DEBUG)
|
||||
System.out.println("FindColl: query=" + query + " fields=" + fields);
|
||||
|
||||
try {
|
||||
if (query != null) {
|
||||
Bson dbq = Document.parse((query != null) ? query : "{}");
|
||||
finditer = coll.find(dbq);
|
||||
} else
|
||||
finditer = coll.find();
|
||||
|
||||
if (fields != null) {
|
||||
Bson dbf = BsonDocument.parse(fields);
|
||||
finditer = finditer.projection(dbf);
|
||||
} // endif fields
|
||||
|
||||
cursor = finditer.iterator();
|
||||
} catch (Exception e) {
|
||||
SetErrmsg(e);
|
||||
return true;
|
||||
} // end try/catch
|
||||
|
||||
return false;
|
||||
} // end of FindColl
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean AggregateColl(String pipeline) {
|
||||
if (DEBUG)
|
||||
System.out.println("AggregateColl: pipeline=" + pipeline);
|
||||
|
||||
try {
|
||||
Document pipe = Document.parse(pipeline);
|
||||
ArrayList<?> pip = (ArrayList<?>) pipe.get("pipeline");
|
||||
|
||||
aggiter = coll.aggregate((List<? extends Bson>) pip);
|
||||
cursor = aggiter.iterator();
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
return true;
|
||||
} // end try/catch
|
||||
|
||||
return false;
|
||||
} // end of AggregateColl
|
||||
|
||||
public boolean Rewind() {
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
|
||||
if (finditer != null)
|
||||
cursor = finditer.iterator();
|
||||
else if (aggiter != null)
|
||||
cursor = aggiter.iterator();
|
||||
|
||||
return (cursor == null);
|
||||
} // end of Rewind
|
||||
|
||||
public int ReadNext() {
|
||||
if (cursor.hasNext()) {
|
||||
doc = cursor.next();
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("Class doc = " + doc.getClass());
|
||||
|
||||
Colnames = doc.keySet();
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
} // end of ReadNext
|
||||
|
||||
public boolean Fetch(int row) {
|
||||
if (cursor.hasNext()) {
|
||||
doc = cursor.next();
|
||||
Colnames = doc.keySet();
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
||||
} // end of Fetch
|
||||
|
||||
public String GetDoc() {
|
||||
return (doc != null) ? doc.toJson() : null;
|
||||
} // end of GetDoc
|
||||
|
||||
public Set<String> GetColumns() {
|
||||
if (doc != null)
|
||||
return doc.keySet();
|
||||
else
|
||||
return null;
|
||||
|
||||
} // end of GetColumns
|
||||
|
||||
public String ColumnName(int n) {
|
||||
int i = 1;
|
||||
|
||||
for (String name : Colnames)
|
||||
if (i++ == n)
|
||||
return name;
|
||||
|
||||
return null;
|
||||
} // end of ColumnName
|
||||
|
||||
public int ColumnType(int n, String name) {
|
||||
// if (rsmd == null) {
|
||||
// System.out.println("No result metadata");
|
||||
// } else try {
|
||||
// if (n == 0)
|
||||
// n = rs.findColumn(name);
|
||||
|
||||
// return rsmd.getColumnType(n);
|
||||
// } catch (SQLException se) {
|
||||
// SetErrmsg(se);
|
||||
// } //end try/catch
|
||||
|
||||
return 666; // Not a type
|
||||
} // end of ColumnType
|
||||
|
||||
public String ColumnDesc(int n, int[] val) {
|
||||
// if (rsmd == null) {
|
||||
// System.out.println("No result metadata");
|
||||
// return null;
|
||||
// } else try {
|
||||
// val[0] = rsmd.getColumnType(n);
|
||||
// val[1] = rsmd.getPrecision(n);
|
||||
// val[2] = rsmd.getScale(n);
|
||||
// val[3] = rsmd.isNullable(n);
|
||||
// return rsmd.getColumnLabel(n);
|
||||
// } catch (SQLException se) {
|
||||
// SetErrmsg(se);
|
||||
// } //end try/catch
|
||||
|
||||
return null;
|
||||
} // end of ColumnDesc
|
||||
|
||||
protected BsonValue GetFieldObject(String path) {
|
||||
BsonValue o = doc;
|
||||
BsonDocument dob = null;
|
||||
BsonArray ary = null;
|
||||
String[] names = null;
|
||||
|
||||
if (path == null || path.equals("*"))
|
||||
return doc;
|
||||
else if (o instanceof BsonDocument)
|
||||
dob = doc;
|
||||
else if (o instanceof BsonArray)
|
||||
ary = (BsonArray) o;
|
||||
else
|
||||
return doc;
|
||||
|
||||
try {
|
||||
names = path.split("\\.");
|
||||
|
||||
for (String name : names) {
|
||||
if (ary != null) {
|
||||
o = ary.get(Integer.parseInt(name));
|
||||
} else
|
||||
o = dob.get(name);
|
||||
|
||||
if (o == null)
|
||||
break;
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("Class o = " + o.getClass());
|
||||
|
||||
if (o instanceof BsonDocument) {
|
||||
dob = (BsonDocument) o;
|
||||
ary = null;
|
||||
} else if (o instanceof BsonArray) {
|
||||
ary = (BsonArray) o;
|
||||
} else
|
||||
break;
|
||||
|
||||
} // endfor name
|
||||
|
||||
} catch (IndexOutOfBoundsException x) {
|
||||
o = null;
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
o = null;
|
||||
} // end try/catch
|
||||
|
||||
return o;
|
||||
} // end of GetFieldObject
|
||||
|
||||
public String GetField(String path) {
|
||||
BsonValue o = GetFieldObject(path);
|
||||
|
||||
if (o != null) {
|
||||
if (o.isString()) {
|
||||
return o.asString().getValue();
|
||||
} else if (o.isInt32()) {
|
||||
return Integer.toString(o.asInt32().getValue());
|
||||
} else if (o.isInt64()) {
|
||||
return Long.toString(o.asInt64().getValue());
|
||||
} else if (o.isObjectId()) {
|
||||
return o.asObjectId().getValue().toString();
|
||||
} else if (o.isDateTime()) {
|
||||
Integer TS = (int) (o.asDateTime().getValue() / 1000);
|
||||
return TS.toString();
|
||||
} else if (o.isDouble()) {
|
||||
return Double.toString(o.asDouble().getValue());
|
||||
} else if (o.isDocument()) {
|
||||
return o.asDocument().toJson();
|
||||
} else if (o.isArray()) {
|
||||
util = new BsonDocument("arr", o.asArray());
|
||||
String s = util.toJson();
|
||||
int i1 = s.indexOf('[');
|
||||
int i2 = s.lastIndexOf(']');
|
||||
return s.substring(i1, i2 + 1);
|
||||
} else if (o.isNull()) {
|
||||
return null;
|
||||
} else
|
||||
return o.toString();
|
||||
|
||||
} else
|
||||
return null;
|
||||
|
||||
} // end of GetField
|
||||
|
||||
protected BsonValue ObjToBson(Object val) {
|
||||
BsonValue bval = null;
|
||||
|
||||
if (val == null)
|
||||
bval = bsonull;
|
||||
else if (val.getClass() == String.class)
|
||||
bval = new BsonString((String) val);
|
||||
else if (val.getClass() == Integer.class)
|
||||
bval = new BsonInt32((int) val);
|
||||
else if (val.getClass() == Double.class)
|
||||
bval = new BsonDouble((double) val);
|
||||
else if (val.getClass() == BigInteger.class)
|
||||
bval = new BsonInt64((long) val);
|
||||
else if (val.getClass() == Boolean.class)
|
||||
bval = new BsonBoolean((Boolean) val);
|
||||
else if (val.getClass() == Date.class)
|
||||
bval = new BsonDateTime(((Date) val).getTime() * 1000);
|
||||
else if (val.getClass() == BsonDocument.class)
|
||||
bval = (BsonDocument) val;
|
||||
else if (val.getClass() == BsonArray.class)
|
||||
bval = (BsonArray) val;
|
||||
|
||||
return bval;
|
||||
} // end of ObjToBson
|
||||
|
||||
public Object MakeDocument() {
|
||||
return new BsonDocument();
|
||||
} // end of MakeDocument
|
||||
|
||||
public boolean DocAdd(Object bdc, String key, Object val) {
|
||||
try {
|
||||
((BsonDocument) bdc).append(key, ObjToBson(val));
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
return true;
|
||||
} // end try/catch
|
||||
|
||||
return false;
|
||||
} // end of DocAdd
|
||||
|
||||
public Object MakeArray() {
|
||||
return new BsonArray();
|
||||
} // end of MakeArray
|
||||
|
||||
public boolean ArrayAdd(Object bar, int n, Object val) {
|
||||
try {
|
||||
for (int i = ((BsonArray) bar).size(); i < n; i++)
|
||||
((BsonArray) bar).add(bsonull);
|
||||
|
||||
((BsonArray) bar).add(ObjToBson(val));
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
SetErrmsg(ex);
|
||||
return true;
|
||||
} // end try/catch
|
||||
|
||||
return false;
|
||||
} // end of ArrayAdd
|
||||
|
||||
public boolean CollInsert(Object dob) {
|
||||
try {
|
||||
coll.insertOne((BsonDocument) dob);
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
SetErrmsg(ex);
|
||||
return true;
|
||||
} // end try/catch
|
||||
|
||||
return false;
|
||||
} // end of CollInsert
|
||||
|
||||
public long CollUpdate(Object upd) {
|
||||
long n = -1;
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("upd: " + upd.toString());
|
||||
|
||||
try {
|
||||
UpdateResult res = coll.updateOne(Filters.eq("_id", doc.get("_id")), (Bson) upd);
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("CollUpdate: " + res.toString());
|
||||
|
||||
n = res.getModifiedCount();
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
} catch (Exception ex) {
|
||||
SetErrmsg(ex);
|
||||
} // end try/catch
|
||||
|
||||
return n;
|
||||
} // end of CollUpdate
|
||||
|
||||
public long CollDelete(boolean all) {
|
||||
long n = -1;
|
||||
|
||||
try {
|
||||
DeleteResult res;
|
||||
|
||||
if (all)
|
||||
res = coll.deleteMany(new Document());
|
||||
else
|
||||
res = coll.deleteOne(Filters.eq("_id", doc.get("_id")));
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("CollDelete: " + res.toString());
|
||||
|
||||
n = res.getDeletedCount();
|
||||
} catch (MongoException me) {
|
||||
SetErrmsg(me);
|
||||
} catch (Exception ex) {
|
||||
SetErrmsg(ex);
|
||||
} // end try/catch
|
||||
|
||||
return n;
|
||||
} // end of CollDelete
|
||||
|
||||
} // end of class MongoInterface
|
888
storage/connect/cmgoconn.cpp
Normal file
888
storage/connect/cmgoconn.cpp
Normal file
@@ -0,0 +1,888 @@
|
||||
/************ CMgoConn C++ Functions Source Code File (.CPP) ***********/
|
||||
/* Name: CMgoConn.CPP Version 1.0 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2017 */
|
||||
/* */
|
||||
/* This file contains the MongoDB C connection classes functions. */
|
||||
/***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include relevant MariaDB header file. */
|
||||
/***********************************************************************/
|
||||
#include <my_global.h>
|
||||
|
||||
/***********************************************************************/
|
||||
/* Required objects includes. */
|
||||
/***********************************************************************/
|
||||
#include "global.h"
|
||||
#include "plgdbsem.h"
|
||||
#include "colblk.h"
|
||||
#include "xobject.h"
|
||||
#include "xtable.h"
|
||||
#include "filter.h"
|
||||
#include "cmgoconn.h"
|
||||
|
||||
bool IsNum(PSZ s);
|
||||
|
||||
// Required to initialize libmongoc's internals
|
||||
void mongo_init(bool init)
|
||||
{
|
||||
if (init)
|
||||
mongoc_init();
|
||||
else
|
||||
mongoc_cleanup();
|
||||
|
||||
} // end of mongo_init
|
||||
|
||||
/* --------------------------- Class INCOL --------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* Add a column in the column list. */
|
||||
/***********************************************************************/
|
||||
void INCOL::AddCol(PGLOBAL g, PCOL colp, char *jp)
|
||||
{
|
||||
char *p;
|
||||
PKC kp, kcp;
|
||||
|
||||
if ((p = strchr(jp, '.'))) {
|
||||
PINCOL icp;
|
||||
|
||||
*p++ = 0;
|
||||
|
||||
for (kp = Klist; kp; kp = kp->Next)
|
||||
if (kp->Incolp && !strcmp(jp, kp->Key))
|
||||
break;
|
||||
|
||||
if (!kp) {
|
||||
icp = new(g) INCOL(IsNum(p));
|
||||
kcp = (PKC)PlugSubAlloc(g, NULL, sizeof(KEYCOL));
|
||||
kcp->Next = NULL;
|
||||
kcp->Incolp = icp;
|
||||
kcp->Colp = NULL;
|
||||
kcp->Key = PlugDup(g, jp);
|
||||
|
||||
if (Klist) {
|
||||
for (kp = Klist; kp->Next; kp = kp->Next);
|
||||
|
||||
kp->Next = kcp;
|
||||
} else
|
||||
Klist = kcp;
|
||||
|
||||
} else
|
||||
icp = kp->Incolp;
|
||||
|
||||
*(p - 1) = '.';
|
||||
icp->AddCol(g, colp, p);
|
||||
} else {
|
||||
kcp = (PKC)PlugSubAlloc(g, NULL, sizeof(KEYCOL));
|
||||
|
||||
kcp->Next = NULL;
|
||||
kcp->Incolp = NULL;
|
||||
kcp->Colp = colp;
|
||||
kcp->Key = jp;
|
||||
|
||||
if (Klist) {
|
||||
for (kp = Klist; kp->Next; kp = kp->Next);
|
||||
|
||||
kp->Next = kcp;
|
||||
} else
|
||||
Klist = kcp;
|
||||
|
||||
} // endif jp
|
||||
|
||||
} // end of AddCol
|
||||
|
||||
/* -------------------------- 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;
|
||||
Query = NULL;
|
||||
Opts = NULL;
|
||||
Fpc = NULL;
|
||||
m_Connected = false;
|
||||
} // end of CMgoConn standard constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* Connect to the MongoDB server and get the collection. */
|
||||
/***********************************************************************/
|
||||
bool CMgoConn::Connect(PGLOBAL g)
|
||||
{
|
||||
Uri = mongoc_uri_new(Pcg->Uristr);
|
||||
|
||||
if (!Uri) {
|
||||
sprintf(g->Message, "Failed to parse URI: \"%s\"", Pcg->Uristr);
|
||||
return true;
|
||||
} // endif Uri
|
||||
|
||||
// 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);
|
||||
|
||||
if (!Client) {
|
||||
sprintf(g->Message, "Failed to get Client");
|
||||
return true;
|
||||
} // endif Client
|
||||
|
||||
// Get a handle on the collection Coll_name
|
||||
Collection = mongoc_client_get_collection(Client, Pcg->Db_name, Pcg->Coll_name);
|
||||
|
||||
if (!Collection) {
|
||||
sprintf(g->Message, "Failed to get Collection %s.%s",
|
||||
Pcg->Db_name, Pcg->Coll_name);
|
||||
return true;
|
||||
} // endif Collection
|
||||
|
||||
m_Connected = true;
|
||||
return false;
|
||||
} // end of Connect
|
||||
|
||||
/***********************************************************************/
|
||||
/* CollSize: returns the number of documents in the collection. */
|
||||
/***********************************************************************/
|
||||
int CMgoConn::CollSize(PGLOBAL g)
|
||||
{
|
||||
int cnt;
|
||||
bson_t *query;
|
||||
const char *jf = NULL;
|
||||
|
||||
if (Pcg->Pipe)
|
||||
return 10;
|
||||
else if (Pcg->Filter)
|
||||
jf = Pcg->Filter;
|
||||
|
||||
if (jf) {
|
||||
query = bson_new_from_json((const uint8_t *)jf, -1, &Error);
|
||||
|
||||
if (!query) {
|
||||
htrc("Wrong filter: %s", Error.message);
|
||||
return 10;
|
||||
} // endif Query
|
||||
|
||||
} else
|
||||
query = bson_new();
|
||||
|
||||
cnt = (int)mongoc_collection_count(Collection,
|
||||
MONGOC_QUERY_NONE, query, 0, 0, NULL, &Error);
|
||||
|
||||
if (cnt < 0) {
|
||||
htrc("Collection count: %s", Error.message);
|
||||
cnt = 2;
|
||||
} // endif Cardinal
|
||||
|
||||
bson_destroy(query);
|
||||
return cnt;
|
||||
} // end of CollSize
|
||||
|
||||
/***********************************************************************/
|
||||
/* OpenDB: Data Base open routine for MONGO access method. */
|
||||
/***********************************************************************/
|
||||
bool CMgoConn::MakeCursor(PGLOBAL g)
|
||||
{
|
||||
const char *p;
|
||||
bool id, b = false, all = false;
|
||||
PCSZ options = Pcg->Options;
|
||||
PTDB tp = Pcg->Tdbp;
|
||||
PCOL cp;
|
||||
PSTRG s = NULL;
|
||||
|
||||
id = (tp->GetMode() != MODE_READ);
|
||||
|
||||
if (options && !stricmp(options, "all")) {
|
||||
options = NULL;
|
||||
all = true;
|
||||
} // endif Options
|
||||
|
||||
for (cp = tp->GetColumns(); cp; cp = cp->GetNext())
|
||||
if (!strcmp(cp->GetName(), "_id"))
|
||||
id = true;
|
||||
else if (cp->GetFmt() && !strcmp(cp->GetFmt(), "*") && !options)
|
||||
all = true;
|
||||
|
||||
if (Pcg->Pipe) {
|
||||
if (trace)
|
||||
htrc("Pipeline: %s\n", options);
|
||||
|
||||
p = strrchr(options, ']');
|
||||
|
||||
if (!p) {
|
||||
strcpy(g->Message, "Missing ] in pipeline");
|
||||
return true;
|
||||
} else
|
||||
*(char*)p = 0;
|
||||
|
||||
s = new(g) STRING(g, 1023, (PSZ)options);
|
||||
|
||||
if (tp->GetFilter()) {
|
||||
s->Append(",{\"$match\":");
|
||||
|
||||
if (tp->GetFilter()->MakeSelector(g, s)) {
|
||||
strcpy(g->Message, "Failed making selector");
|
||||
return true;
|
||||
} else
|
||||
s->Append('}');
|
||||
|
||||
tp->SetFilter(NULL); // Not needed anymore
|
||||
} // endif To_Filter
|
||||
|
||||
if (!all && tp->GetColumns()) {
|
||||
// Project list
|
||||
s->Append(",{\"$project\":{\"");
|
||||
|
||||
if (!id)
|
||||
s->Append("_id\":0,\"");
|
||||
|
||||
for (cp = tp->GetColumns(); cp; cp = cp->GetNext()) {
|
||||
if (b)
|
||||
s->Append(",\"");
|
||||
else
|
||||
b = true;
|
||||
|
||||
s->Append(cp->GetJpath(g, true));
|
||||
s->Append("\":1");
|
||||
} // endfor cp
|
||||
|
||||
s->Append("}}");
|
||||
} // endif all
|
||||
|
||||
s->Append("]}");
|
||||
s->Resize(s->GetLength() + 1);
|
||||
*(char*)p = ']'; // Restore Colist for discovery
|
||||
p = s->GetStr();
|
||||
|
||||
if (trace)
|
||||
htrc("New Pipeline: %s\n", p);
|
||||
|
||||
Query = bson_new_from_json((const uint8_t *)p, -1, &Error);
|
||||
|
||||
if (!Query) {
|
||||
sprintf(g->Message, "Wrong pipeline: %s", Error.message);
|
||||
return true;
|
||||
} // endif Query
|
||||
|
||||
Cursor = mongoc_collection_aggregate(Collection, MONGOC_QUERY_NONE,
|
||||
Query, NULL, NULL);
|
||||
|
||||
if (mongoc_cursor_error(Cursor, &Error)) {
|
||||
sprintf(g->Message, "Mongo aggregate Failure: %s", Error.message);
|
||||
return true;
|
||||
} // endif error
|
||||
|
||||
} else {
|
||||
if (Pcg->Filter || tp->GetFilter()) {
|
||||
if (trace) {
|
||||
if (Pcg->Filter)
|
||||
htrc("Filter: %s\n", Pcg->Filter);
|
||||
|
||||
if (tp->GetFilter()) {
|
||||
char buf[512];
|
||||
|
||||
tp->GetFilter()->Prints(g, buf, 511);
|
||||
htrc("To_Filter: %s\n", buf);
|
||||
} // endif To_Filter
|
||||
|
||||
} // endif trace
|
||||
|
||||
s = new(g) STRING(g, 1023, (PSZ)Pcg->Filter);
|
||||
|
||||
if (tp->GetFilter()) {
|
||||
if (Pcg->Filter)
|
||||
s->Append(',');
|
||||
|
||||
if (tp->GetFilter()->MakeSelector(g, s)) {
|
||||
strcpy(g->Message, "Failed making selector");
|
||||
return NULL;
|
||||
} // endif Selector
|
||||
|
||||
tp->SetFilter(NULL); // Not needed anymore
|
||||
} // endif To_Filter
|
||||
|
||||
if (trace)
|
||||
htrc("selector: %s\n", s->GetStr());
|
||||
|
||||
s->Resize(s->GetLength() + 1);
|
||||
Query = bson_new_from_json((const uint8_t *)s->GetStr(), -1, &Error);
|
||||
|
||||
if (!Query) {
|
||||
sprintf(g->Message, "Wrong filter: %s", Error.message);
|
||||
return NULL;
|
||||
} // endif Query
|
||||
|
||||
} else
|
||||
Query = bson_new();
|
||||
|
||||
if (!all) {
|
||||
if (options && *options) {
|
||||
if (trace)
|
||||
htrc("options=%s\n", options);
|
||||
|
||||
p = options;
|
||||
} else if (tp->GetColumns()) {
|
||||
// Projection list
|
||||
if (s)
|
||||
s->Set("{\"projection\":{\"");
|
||||
else
|
||||
s = new(g) STRING(g, 511, "{\"projection\":{\"");
|
||||
|
||||
if (!id)
|
||||
s->Append("_id\":0,\"");
|
||||
|
||||
for (cp = tp->GetColumns(); cp; cp = cp->GetNext()) {
|
||||
if (b)
|
||||
s->Append(",\"");
|
||||
else
|
||||
b = true;
|
||||
|
||||
s->Append(cp->GetJpath(g, true));
|
||||
s->Append("\":1");
|
||||
} // endfor cp
|
||||
|
||||
s->Append("}}");
|
||||
s->Resize(s->GetLength() + 1);
|
||||
p = s->GetStr();
|
||||
} else {
|
||||
// count(*) ?
|
||||
p = "{\"projection\":{\"_id\":1}}";
|
||||
} // endif Options
|
||||
|
||||
Opts = bson_new_from_json((const uint8_t *)p, -1, &Error);
|
||||
|
||||
if (!Opts) {
|
||||
sprintf(g->Message, "Wrong options: %s", Error.message);
|
||||
return NULL;
|
||||
} // endif Opts
|
||||
|
||||
} // endif all
|
||||
|
||||
Cursor = mongoc_collection_find_with_opts(Collection, Query, Opts, NULL);
|
||||
} // endif Pipe
|
||||
|
||||
return false;
|
||||
} // end of MakeCursor
|
||||
|
||||
/***********************************************************************/
|
||||
/* Fetch next document. */
|
||||
/***********************************************************************/
|
||||
int CMgoConn::ReadNext(PGLOBAL g)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
|
||||
if (!Cursor && MakeCursor(g)) {
|
||||
rc = RC_FX;
|
||||
} else if (mongoc_cursor_next(Cursor, &Document)) {
|
||||
if (trace > 1) {
|
||||
bson_iter_t iter;
|
||||
ShowDocument(&iter, Document, "");
|
||||
} else if (trace == 1)
|
||||
htrc("%s\n", GetDocument(g));
|
||||
|
||||
} else if (mongoc_cursor_error(Cursor, &Error)) {
|
||||
sprintf(g->Message, "Mongo Cursor Failure: %s", Error.message);
|
||||
rc = RC_FX;
|
||||
} else
|
||||
rc = RC_EF;
|
||||
|
||||
return rc;
|
||||
} // end of Fetch
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the Json string of the current document. */
|
||||
/***********************************************************************/
|
||||
PSZ CMgoConn::GetDocument(PGLOBAL g)
|
||||
{
|
||||
char *str = bson_as_json(Document, NULL);
|
||||
PSZ doc = PlugDup(g, str);
|
||||
|
||||
bson_free(str);
|
||||
return doc;
|
||||
} // end of GetDocument
|
||||
|
||||
/***********************************************************************/
|
||||
/* Use to trace restaurants document contains. */
|
||||
/***********************************************************************/
|
||||
void CMgoConn::ShowDocument(bson_iter_t *iter, const bson_t *doc, const char *k)
|
||||
{
|
||||
if (!doc || bson_iter_init(iter, doc)) {
|
||||
const char *key;
|
||||
|
||||
while (bson_iter_next(iter)) {
|
||||
key = bson_iter_key(iter);
|
||||
htrc("Found element key: \"%s\"\n", key);
|
||||
|
||||
if (BSON_ITER_HOLDS_UTF8(iter))
|
||||
htrc("%s.%s=\"%s\"\n", k, key, bson_iter_utf8(iter, NULL));
|
||||
else if (BSON_ITER_HOLDS_INT32(iter))
|
||||
htrc("%s.%s=%d\n", k, key, bson_iter_int32(iter));
|
||||
else if (BSON_ITER_HOLDS_INT64(iter))
|
||||
htrc("%s.%s=%lld\n", k, key, bson_iter_int64(iter));
|
||||
else if (BSON_ITER_HOLDS_DOUBLE(iter))
|
||||
htrc("%s.%s=%g\n", k, key, bson_iter_double(iter));
|
||||
else if (BSON_ITER_HOLDS_DATE_TIME(iter))
|
||||
htrc("%s.%s=date(%lld)\n", k, key, bson_iter_date_time(iter));
|
||||
else if (BSON_ITER_HOLDS_OID(iter)) {
|
||||
char str[25];
|
||||
|
||||
bson_oid_to_string(bson_iter_oid(iter), str);
|
||||
htrc("%s.%s=%s\n", k, key, str);
|
||||
} else if (BSON_ITER_HOLDS_DECIMAL128(iter)) {
|
||||
char *str = NULL;
|
||||
bson_decimal128_t dec;
|
||||
|
||||
bson_iter_decimal128(iter, &dec);
|
||||
bson_decimal128_to_string(&dec, str);
|
||||
htrc("%s.%s=%s\n", k, key, str);
|
||||
} else if (BSON_ITER_HOLDS_DOCUMENT(iter)) {
|
||||
bson_iter_t child;
|
||||
|
||||
if (bson_iter_recurse(iter, &child))
|
||||
ShowDocument(&child, NULL, key);
|
||||
|
||||
} else if (BSON_ITER_HOLDS_ARRAY(iter)) {
|
||||
bson_t *arr;
|
||||
bson_iter_t itar;
|
||||
const uint8_t *data = NULL;
|
||||
uint32_t len = 0;
|
||||
|
||||
bson_iter_array(iter, &len, &data);
|
||||
arr = bson_new_from_data(data, len);
|
||||
ShowDocument(&itar, arr, key);
|
||||
} // endif's
|
||||
|
||||
} // endwhile bson_iter_next
|
||||
|
||||
} // endif bson_iter_init
|
||||
|
||||
} // end of ShowDocument
|
||||
|
||||
/***********************************************************************/
|
||||
/* Group columns for inserting or updating. */
|
||||
/***********************************************************************/
|
||||
void CMgoConn::MakeColumnGroups(PGLOBAL g)
|
||||
{
|
||||
Fpc = new(g) INCOL(false);
|
||||
|
||||
for (PCOL colp = Pcg->Tdbp->GetColumns(); colp; colp = colp->GetNext())
|
||||
if (!colp->IsSpecial())
|
||||
Fpc->AddCol(g, colp, colp->GetJpath(g, false));
|
||||
|
||||
} // end of MakeColumnGroups
|
||||
|
||||
/***********************************************************************/
|
||||
/* DocWrite. */
|
||||
/***********************************************************************/
|
||||
bool CMgoConn::DocWrite(PGLOBAL g, PINCOL icp)
|
||||
{
|
||||
for (PKC kp = icp->Klist; kp; kp = kp->Next)
|
||||
if (kp->Incolp) {
|
||||
bool isdoc = !kp->Incolp->Array;
|
||||
|
||||
if (isdoc)
|
||||
BSON_APPEND_DOCUMENT_BEGIN(&icp->Child, kp->Key, &kp->Incolp->Child);
|
||||
else
|
||||
BSON_APPEND_ARRAY_BEGIN(&icp->Child, kp->Key, &kp->Incolp->Child);
|
||||
|
||||
if (DocWrite(g, kp->Incolp))
|
||||
return true;
|
||||
|
||||
if (isdoc)
|
||||
bson_append_document_end(&icp->Child, &kp->Incolp->Child);
|
||||
else
|
||||
bson_append_array_end(&icp->Child, &kp->Incolp->Child);
|
||||
|
||||
} else if (AddValue(g, kp->Colp, &icp->Child, kp->Key, false))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
} // end of DocWrite
|
||||
|
||||
/***********************************************************************/
|
||||
/* WriteDB: Data Base write routine for DOS access method. */
|
||||
/***********************************************************************/
|
||||
int CMgoConn::Write(PGLOBAL g)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
PTDB tp = Pcg->Tdbp;
|
||||
|
||||
if (tp->GetMode() == MODE_INSERT) {
|
||||
bson_init(&Fpc->Child);
|
||||
|
||||
if (DocWrite(g, Fpc))
|
||||
return RC_FX;
|
||||
|
||||
if (trace) {
|
||||
char *str = bson_as_json(&Fpc->Child, NULL);
|
||||
htrc("Inserting: %s\n", str);
|
||||
bson_free(str);
|
||||
} // endif trace
|
||||
|
||||
if (!mongoc_collection_insert(Collection, MONGOC_INSERT_NONE,
|
||||
&Fpc->Child, NULL, &Error)) {
|
||||
sprintf(g->Message, "Mongo insert: %s", Error.message);
|
||||
rc = RC_FX;
|
||||
} // endif insert
|
||||
|
||||
} else {
|
||||
bool b = false;
|
||||
bson_iter_t iter;
|
||||
bson_t *query = bson_new();
|
||||
|
||||
bson_iter_init(&iter, Document);
|
||||
|
||||
if (bson_iter_find(&iter, "_id")) {
|
||||
if (BSON_ITER_HOLDS_OID(&iter))
|
||||
b = BSON_APPEND_OID(query, "_id", bson_iter_oid(&iter));
|
||||
else if (BSON_ITER_HOLDS_INT32(&iter))
|
||||
b = BSON_APPEND_INT32(query, "_id", bson_iter_int32(&iter));
|
||||
else if (BSON_ITER_HOLDS_INT64(&iter))
|
||||
b = BSON_APPEND_INT64(query, "_id", bson_iter_int64(&iter));
|
||||
else if (BSON_ITER_HOLDS_DOUBLE(&iter))
|
||||
b = BSON_APPEND_DOUBLE(query, "_id", bson_iter_double(&iter));
|
||||
else if (BSON_ITER_HOLDS_UTF8(&iter))
|
||||
b = BSON_APPEND_UTF8(query, "_id", bson_iter_utf8(&iter, NULL));
|
||||
|
||||
} // endif iter
|
||||
|
||||
if (b) {
|
||||
if (trace) {
|
||||
char *str = bson_as_json(query, NULL);
|
||||
htrc("update query: %s\n", str);
|
||||
bson_free(str);
|
||||
} // endif trace
|
||||
|
||||
if (tp->GetMode() == MODE_UPDATE) {
|
||||
bson_t child;
|
||||
bson_t *update = bson_new();
|
||||
|
||||
BSON_APPEND_DOCUMENT_BEGIN(update, "$set", &child);
|
||||
|
||||
for (PCOL colp = tp->GetSetCols(); colp; colp = colp->GetNext())
|
||||
if (AddValue(g, colp, &child, colp->GetJpath(g, false), true))
|
||||
rc = RC_FX;
|
||||
|
||||
bson_append_document_end(update, &child);
|
||||
|
||||
if (rc == RC_OK)
|
||||
if (!mongoc_collection_update(Collection, MONGOC_UPDATE_NONE,
|
||||
query, update, NULL, &Error)) {
|
||||
sprintf(g->Message, "Mongo update: %s", Error.message);
|
||||
rc = RC_FX;
|
||||
} // endif update
|
||||
|
||||
bson_destroy(update);
|
||||
} else if (!mongoc_collection_remove(Collection,
|
||||
MONGOC_REMOVE_SINGLE_REMOVE, query, NULL, &Error)) {
|
||||
sprintf(g->Message, "Mongo delete: %s", Error.message);
|
||||
rc = RC_FX;
|
||||
} // endif remove
|
||||
|
||||
} else {
|
||||
strcpy(g->Message, "Mongo update: cannot find _id");
|
||||
rc = RC_FX;
|
||||
} // endif b
|
||||
|
||||
bson_destroy(query);
|
||||
} // endif Mode
|
||||
|
||||
return rc;
|
||||
} // end of Write
|
||||
|
||||
/***********************************************************************/
|
||||
/* Remove all documents from the collection. */
|
||||
/***********************************************************************/
|
||||
bool CMgoConn::DocDelete(PGLOBAL g)
|
||||
{
|
||||
Query = bson_new();
|
||||
|
||||
if (!mongoc_collection_remove(Collection, MONGOC_REMOVE_NONE,
|
||||
Query, NULL, &Error)) {
|
||||
sprintf(g->Message, "Mongo remove all: %s", Error.message);
|
||||
return true;
|
||||
} // endif remove
|
||||
|
||||
return false;
|
||||
} // end of DocDelete
|
||||
|
||||
/***********************************************************************/
|
||||
/* Rewind the collection. */
|
||||
/***********************************************************************/
|
||||
void CMgoConn::Rewind(void)
|
||||
{
|
||||
mongoc_cursor_t *cursor = mongoc_cursor_clone(Cursor);
|
||||
|
||||
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 (Uri) mongoc_uri_destroy(Uri);
|
||||
} // 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, colp->GetLength() + 1);
|
||||
int i, k = 0;
|
||||
bool ok = true;
|
||||
|
||||
if (b)
|
||||
s = str = bson_array_as_json(bson, NULL);
|
||||
else
|
||||
s = str = bson_as_json(bson, NULL);
|
||||
|
||||
for (i = 0; i < colp->GetLength() && s[i]; i++) {
|
||||
switch (s[i]) {
|
||||
case ' ':
|
||||
if (ok) continue;
|
||||
case '"':
|
||||
ok = !ok;
|
||||
default:
|
||||
break;
|
||||
} // endswitch s[i]
|
||||
|
||||
Mbuf[k++] = s[i];
|
||||
} // endfor i
|
||||
|
||||
bson_free(str);
|
||||
|
||||
if (i >= colp->GetLength()) {
|
||||
sprintf(g->Message, "Value too long for column %s", colp->GetName());
|
||||
throw (int)TYPE_AM_MGO;
|
||||
} // endif i
|
||||
|
||||
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);
|
||||
PVAL value = colp->GetValue();
|
||||
|
||||
if (!strcmp(jpath, "*")) {
|
||||
value->SetValue_psz(Mini(g, colp, Document, false));
|
||||
} else if (bson_iter_init(&Iter, Document) &&
|
||||
bson_iter_find_descendant(&Iter, jpath, &Desc)) {
|
||||
if (BSON_ITER_HOLDS_UTF8(&Desc))
|
||||
value->SetValue_psz((PSZ)bson_iter_utf8(&Desc, NULL));
|
||||
else if (BSON_ITER_HOLDS_INT32(&Desc))
|
||||
value->SetValue(bson_iter_int32(&Desc));
|
||||
else if (BSON_ITER_HOLDS_INT64(&Desc))
|
||||
value->SetValue(bson_iter_int64(&Desc));
|
||||
else if (BSON_ITER_HOLDS_DOUBLE(&Desc))
|
||||
value->SetValue(bson_iter_double(&Desc));
|
||||
else if (BSON_ITER_HOLDS_DATE_TIME(&Desc))
|
||||
value->SetValue(bson_iter_date_time(&Desc) / 1000);
|
||||
else if (BSON_ITER_HOLDS_BOOL(&Desc)) {
|
||||
bool b = bson_iter_bool(&Desc);
|
||||
|
||||
if (value->IsTypeNum())
|
||||
value->SetValue(b ? 1 : 0);
|
||||
else
|
||||
value->SetValue_psz(b ? "true" : "false");
|
||||
|
||||
} else if (BSON_ITER_HOLDS_OID(&Desc)) {
|
||||
char str[25];
|
||||
|
||||
bson_oid_to_string(bson_iter_oid(&Desc), str);
|
||||
value->SetValue_psz(str);
|
||||
} else if (BSON_ITER_HOLDS_NULL(&Iter)) {
|
||||
// Apparently this does not work...
|
||||
value->Reset();
|
||||
value->SetNull(true);
|
||||
} else if (BSON_ITER_HOLDS_DECIMAL128(&Desc)) {
|
||||
char *str = NULL;
|
||||
bson_decimal128_t dec;
|
||||
|
||||
bson_iter_decimal128(&Desc, &dec);
|
||||
bson_decimal128_to_string(&dec, str);
|
||||
value->SetValue_psz(str);
|
||||
bson_free(str);
|
||||
} else if (BSON_ITER_HOLDS_DOCUMENT(&Iter)) {
|
||||
bson_t *doc;
|
||||
const uint8_t *data = NULL;
|
||||
uint32_t len = 0;
|
||||
|
||||
bson_iter_document(&Desc, &len, &data);
|
||||
|
||||
if (data) {
|
||||
doc = bson_new_from_data(data, len);
|
||||
value->SetValue_psz(Mini(g, colp, doc, false));
|
||||
bson_destroy(doc);
|
||||
} else {
|
||||
// ... but we can come here in case of NULL!
|
||||
value->Reset();
|
||||
value->SetNull(true);
|
||||
} // endif data
|
||||
|
||||
} else if (BSON_ITER_HOLDS_ARRAY(&Iter)) {
|
||||
bson_t *arr;
|
||||
const uint8_t *data = NULL;
|
||||
uint32_t len = 0;
|
||||
|
||||
bson_iter_array(&Desc, &len, &data);
|
||||
|
||||
if (data) {
|
||||
arr = bson_new_from_data(data, len);
|
||||
value->SetValue_psz(Mini(g, colp, arr, true));
|
||||
bson_destroy(arr);
|
||||
} else {
|
||||
// This is a bug in returning the wrong type
|
||||
// This fix is only for document items
|
||||
bson_t *doc;
|
||||
|
||||
bson_iter_document(&Desc, &len, &data);
|
||||
|
||||
if (data) {
|
||||
doc = bson_new_from_data(data, len);
|
||||
value->SetValue_psz(Mini(g, colp, doc, false));
|
||||
bson_destroy(doc);
|
||||
} else {
|
||||
// ... or we can also come here in case of NULL!
|
||||
value->Reset();
|
||||
value->SetNull(true);
|
||||
} // endif data
|
||||
|
||||
} // endif data
|
||||
|
||||
} else
|
||||
value->Reset();
|
||||
|
||||
} else {
|
||||
// Field does not exist
|
||||
value->Reset();
|
||||
value->SetNull(true);
|
||||
} // endif Iter
|
||||
|
||||
} // end of GetColumnValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* AddValue: Add column value to the document to insert or update. */
|
||||
/***********************************************************************/
|
||||
bool CMgoConn::AddValue(PGLOBAL g, PCOL colp, bson_t *doc, char *key, bool upd)
|
||||
{
|
||||
bool rc = false;
|
||||
PVAL value = colp->GetValue();
|
||||
|
||||
if (value->IsNull()) {
|
||||
if (upd)
|
||||
rc = BSON_APPEND_NULL(doc, key);
|
||||
else
|
||||
return false;
|
||||
|
||||
} else switch (colp->GetResultType()) {
|
||||
case TYPE_STRING:
|
||||
rc = BSON_APPEND_UTF8(doc, key, value->GetCharValue());
|
||||
break;
|
||||
case TYPE_INT:
|
||||
case TYPE_SHORT:
|
||||
rc = BSON_APPEND_INT32(doc, key, value->GetIntValue());
|
||||
break;
|
||||
case TYPE_TINY:
|
||||
rc = BSON_APPEND_BOOL(doc, key, value->GetIntValue());
|
||||
break;
|
||||
case TYPE_BIGINT:
|
||||
rc = BSON_APPEND_INT64(doc, key, value->GetBigintValue());
|
||||
break;
|
||||
case TYPE_DOUBLE:
|
||||
rc = BSON_APPEND_DOUBLE(doc, key, value->GetFloatValue());
|
||||
break;
|
||||
case TYPE_DECIM:
|
||||
{bson_decimal128_t dec;
|
||||
|
||||
if (bson_decimal128_from_string(value->GetCharValue(), &dec))
|
||||
rc = BSON_APPEND_DECIMAL128(doc, key, &dec);
|
||||
|
||||
} break;
|
||||
case TYPE_DATE:
|
||||
rc = BSON_APPEND_DATE_TIME(doc, key, value->GetBigintValue() * 1000);
|
||||
break;
|
||||
default:
|
||||
sprintf(g->Message, "Type %d not supported yet", colp->GetResultType());
|
||||
return true;
|
||||
} // endswitch Buf_Type
|
||||
|
||||
if (!rc) {
|
||||
strcpy(g->Message, "Adding value failed");
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
||||
} // end of AddValue
|
||||
|
||||
#if 0
|
||||
void *CMgoConn::mgo_alloc(size_t n)
|
||||
{
|
||||
char *mst = (char*)PlgDBSubAlloc(G, NULL, n + sizeof(size_t));
|
||||
|
||||
if (mst) {
|
||||
*(size_t*)mst = n;
|
||||
return mst + sizeof(size_t);
|
||||
} // endif mst
|
||||
|
||||
return NULL;
|
||||
} // end of mgo_alloc
|
||||
|
||||
void *CMgoConn::mgo_calloc(size_t n, size_t sz)
|
||||
{
|
||||
void *m = mgo_alloc(n * sz);
|
||||
|
||||
if (m)
|
||||
memset(m, 0, n * sz);
|
||||
|
||||
return m;
|
||||
} // end of mgo_calloc
|
||||
|
||||
void *CMgoConn::mgo_realloc(void *m, size_t n)
|
||||
{
|
||||
if (!m)
|
||||
return n ? mgo_alloc(n) : NULL;
|
||||
|
||||
size_t *osz = (size_t*)((char*)m - sizeof(size_t));
|
||||
|
||||
if (n > *osz) {
|
||||
void *nwm = mgo_alloc(n);
|
||||
|
||||
if (nwm)
|
||||
memcpy(nwm, m, *osz);
|
||||
|
||||
return nwm;
|
||||
} else {
|
||||
*osz = n;
|
||||
return m;
|
||||
} // endif n
|
||||
|
||||
} // end of mgo_realloc
|
||||
#endif // 0
|
||||
|
112
storage/connect/cmgoconn.h
Normal file
112
storage/connect/cmgoconn.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/***********************************************************************/
|
||||
/* CMgoConn.h : header file for the MongoDB connection classes. */
|
||||
/***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include MongoDB library header files. */
|
||||
/***********************************************************************/
|
||||
#include <bson.h>
|
||||
#include <bcon.h>
|
||||
#include <mongoc.h>
|
||||
|
||||
// C connection to a MongoDB data source
|
||||
class TDBMGO;
|
||||
class MGOCOL;
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include MongoDB library header files. */
|
||||
/***********************************************************************/
|
||||
typedef class INCOL *PINCOL;
|
||||
typedef class MGODEF *PMGODEF;
|
||||
typedef class TDBMGO *PTDBMGO;
|
||||
typedef class MGOCOL *PMGOCOL;
|
||||
|
||||
typedef struct mongo_parms {
|
||||
PTDB Tdbp;
|
||||
PCSZ Uristr; // Driver URI
|
||||
PCSZ Db_name;
|
||||
PCSZ Coll_name;
|
||||
PCSZ Options;
|
||||
PCSZ Filter;
|
||||
bool Pipe;
|
||||
//PCSZ User; // User connect info
|
||||
//PCSZ Pwd; // Password connect info
|
||||
//int Fsize; // Fetch size
|
||||
//bool Scrollable; // Scrollable cursor
|
||||
} CMGOPARM, *PCPARM;
|
||||
|
||||
typedef struct KEYCOL {
|
||||
KEYCOL *Next;
|
||||
PINCOL Incolp;
|
||||
PCOL Colp;
|
||||
char *Key;
|
||||
} *PKC;
|
||||
|
||||
/***********************************************************************/
|
||||
/* Used when inserting values in a MongoDB collection. */
|
||||
/***********************************************************************/
|
||||
class INCOL : public BLOCK {
|
||||
public:
|
||||
// Constructor
|
||||
INCOL(bool ar) { Klist = NULL; Array = ar; }
|
||||
|
||||
// Methods
|
||||
void AddCol(PGLOBAL g, PCOL colp, char *jp);
|
||||
|
||||
//Members
|
||||
bson_t Child;
|
||||
PKC Klist;
|
||||
bool Array;
|
||||
}; // end of INCOL;
|
||||
|
||||
/***********************************************************************/
|
||||
/* CMgoConn class. */
|
||||
/***********************************************************************/
|
||||
class CMgoConn : public BLOCK {
|
||||
friend class TDBMGO;
|
||||
friend class MGODISC;
|
||||
public:
|
||||
// Constructor
|
||||
CMgoConn(PGLOBAL g, PCPARM pcg);
|
||||
|
||||
//static void *mgo_alloc(size_t n);
|
||||
//static void *mgo_calloc(size_t n, size_t sz);
|
||||
//static void *mgo_realloc(void *m, size_t n);
|
||||
//static void mgo_free(void *) {}
|
||||
|
||||
// Implementation
|
||||
bool IsConnected(void) { return m_Connected; }
|
||||
bool Connect(PGLOBAL g);
|
||||
int CollSize(PGLOBAL g);
|
||||
bool MakeCursor(PGLOBAL g);
|
||||
int ReadNext(PGLOBAL g);
|
||||
PSZ GetDocument(PGLOBAL g);
|
||||
void ShowDocument(bson_iter_t *iter, const bson_t *doc, const char *k);
|
||||
void MakeColumnGroups(PGLOBAL g);
|
||||
bool DocWrite(PGLOBAL g, PINCOL icp);
|
||||
int Write(PGLOBAL g);
|
||||
bool DocDelete(PGLOBAL g);
|
||||
void Rewind(void);
|
||||
void Close(void);
|
||||
PSZ Mini(PGLOBAL g, PCOL colp, const bson_t *bson, bool b);
|
||||
void GetColumnValue(PGLOBAL g, PCOL colp);
|
||||
bool AddValue(PGLOBAL g, PCOL colp, bson_t *doc, char *key, bool upd);
|
||||
|
||||
protected:
|
||||
// Members
|
||||
PCPARM Pcg;
|
||||
mongoc_uri_t *Uri;
|
||||
mongoc_client_pool_t *Pool; // Thread safe client pool
|
||||
mongoc_client_t *Client; // The MongoDB client
|
||||
mongoc_database_t *Database; // The MongoDB database
|
||||
mongoc_collection_t *Collection; // The MongoDB collection
|
||||
mongoc_cursor_t *Cursor;
|
||||
const bson_t *Document;
|
||||
bson_t *Query; // MongoDB cursor filter
|
||||
bson_t *Opts; // MongoDB cursor options
|
||||
bson_error_t Error;
|
||||
bson_iter_t Iter; // Used to retrieve column value
|
||||
bson_iter_t Desc; // Descendant iter
|
||||
PINCOL Fpc; // To insert INCOL classes
|
||||
bool m_Connected;
|
||||
}; // end of class CMgoConn
|
@@ -38,7 +38,8 @@ class DllExport COLBLK : public XOBJECT {
|
||||
virtual PTDB GetTo_Tdb(void) {return To_Tdb;}
|
||||
virtual int GetClustered(void) {return 0;}
|
||||
virtual int IsClustered(void) {return FALSE;}
|
||||
PCOL GetNext(void) {return Next;}
|
||||
virtual PSZ GetJpath(PGLOBAL g, bool proj) {return NULL;}
|
||||
PCOL GetNext(void) {return Next;}
|
||||
PSZ GetName(void) {return Name;}
|
||||
int GetIndex(void) {return Index;}
|
||||
ushort GetColUse(void) {return ColUse;}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) Olivier Bertrand 2004 - 2017
|
||||
/* Copyright (C) MariaDB Corporation Ab
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -185,7 +185,7 @@ bool CntInfo(PGLOBAL g, PTDB tp, PXF info)
|
||||
/***********************************************************************/
|
||||
PTDB CntGetTDB(PGLOBAL g, LPCSTR name, MODE mode, PHC h)
|
||||
{
|
||||
PTDB tdbp;
|
||||
PTDB tdbp = NULL;
|
||||
PTABLE tabp;
|
||||
PDBUSER dup = PlgGetUser(g);
|
||||
volatile PCATLG cat = (dup) ? dup->Catalog : NULL; // Safe over throw
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) Olivier Bertrand 2004 - 2011
|
||||
/* Copyright (C) MariaDB Corporation Ab
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
/**************** Cnt H Declares Source Code File (.H) *****************/
|
||||
/* Name: CONNECT.H Version 2.4 */
|
||||
/* Author Olivier BERTRAND bertrandop@gmail.com */
|
||||
/* This file contains the some based classes declares. */
|
||||
/***********************************************************************/
|
||||
#include "filamtxt.h"
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/* Copyright (C) MariaDB Corporation Ab */
|
||||
#define MSG_ACCESS_VIOLATN "Access violation"
|
||||
#define MSG_ADD_BAD_TYPE "Array add value type mismatch (%s -> %s)"
|
||||
#define MSG_ALLOC_ERROR "Error allocating %s"
|
||||
|
@@ -33,18 +33,11 @@
|
||||
#include "tabcol.h"
|
||||
#include "xtable.h"
|
||||
#include "array.h"
|
||||
//#include "subquery.h"
|
||||
#include "filter.h"
|
||||
//#include "token.h"
|
||||
//#include "select.h"
|
||||
#include "xindex.h"
|
||||
#if defined(MONGO_SUPPORT)
|
||||
#include "filamtxt.h"
|
||||
#include "tabdos.h"
|
||||
#include "tabjson.h"
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
#include "tabext.h"
|
||||
#include "tabmgo.h"
|
||||
#endif // MONGO_SUPPORT
|
||||
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||
|
||||
/***********************************************************************/
|
||||
/* Utility routines. */
|
||||
@@ -1412,11 +1405,11 @@ PFIL FILTER::Copy(PTABS t)
|
||||
} // end of Copy
|
||||
#endif // 0
|
||||
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
/***********************************************************************/
|
||||
/* Make selector json representation for Mongo tables. */
|
||||
/***********************************************************************/
|
||||
#if defined(MONGO_SUPPORT)
|
||||
bool FILTER::MakeSelector(PGLOBAL g, PSTRG s, bool m)
|
||||
bool FILTER::MakeSelector(PGLOBAL g, PSTRG s)
|
||||
{
|
||||
s->Append('{');
|
||||
|
||||
@@ -1428,29 +1421,21 @@ bool FILTER::MakeSelector(PGLOBAL g, PSTRG s, bool m)
|
||||
s->Append(Opc == OP_AND ? "and" : "or");
|
||||
s->Append("\":[");
|
||||
|
||||
if (((PFIL)Arg(0))->MakeSelector(g, s, m))
|
||||
if (((PFIL)Arg(0))->MakeSelector(g, s))
|
||||
return true;
|
||||
|
||||
s->Append(',');
|
||||
|
||||
if (((PFIL)Arg(1))->MakeSelector(g, s, m))
|
||||
if (((PFIL)Arg(1))->MakeSelector(g, s))
|
||||
return true;
|
||||
|
||||
s->Append(']');
|
||||
} else {
|
||||
char *pth, buf[501];
|
||||
|
||||
if (GetArgType(0) != TYPE_COLBLK)
|
||||
return true;
|
||||
|
||||
s->Append('"');
|
||||
|
||||
if (m)
|
||||
pth = ((PMGOCOL)Arg(0))->Jpath;
|
||||
else if (!(pth = ((PJCOL)Arg(0))->GetJpath(g, false)))
|
||||
return true;
|
||||
|
||||
s->Append(pth);
|
||||
s->Append(((PCOL)Arg(0))->GetJpath(g, false));
|
||||
s->Append("\":{\"$");
|
||||
|
||||
switch (Opc) {
|
||||
@@ -1472,33 +1457,33 @@ bool FILTER::MakeSelector(PGLOBAL g, PSTRG s, bool m)
|
||||
case OP_LE:
|
||||
s->Append("lte");
|
||||
break;
|
||||
//case OP_NULL:
|
||||
// s->Append("ne");
|
||||
// break;
|
||||
//case OP_LIKE:
|
||||
// s->Append("ne");
|
||||
// break;
|
||||
//case OP_EXIST:
|
||||
// s->Append("ne");
|
||||
// break;
|
||||
case OP_NULL:
|
||||
case OP_LIKE:
|
||||
case OP_EXIST:
|
||||
default:
|
||||
return true;
|
||||
} // endswitch Opc
|
||||
|
||||
s->Append("\":");
|
||||
|
||||
if (GetArgType(1) == TYPE_COLBLK)
|
||||
return true;
|
||||
if (GetArgType(1) == TYPE_COLBLK) {
|
||||
s->Append("\"$");
|
||||
s->Append(((PEXTCOL)Arg(1))->GetJpath(g, false));
|
||||
s->Append('"');
|
||||
} else {
|
||||
char buf[501];
|
||||
|
||||
Arg(1)->Prints(g, buf, 500);
|
||||
s->Append(buf);
|
||||
} // endif Type
|
||||
|
||||
Arg(1)->Prints(g, buf, 500);
|
||||
s->Append(buf);
|
||||
s->Append('}');
|
||||
} // endif Opc
|
||||
|
||||
s->Append('}');
|
||||
return false;
|
||||
} // end of MakeSelector
|
||||
#endif // MONGO_SUPPORT
|
||||
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||
|
||||
/*********************************************************************/
|
||||
/* Make file output of FILTER contents. */
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*************** Filter H Declares Source Code File (.H) ***************/
|
||||
/* Name: FILTER.H Version 1.2 */
|
||||
/* Name: FILTER.H Version 1.3 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2010-2015 */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2010-2017 */
|
||||
/* */
|
||||
/* This file contains the FILTER and derived classes declares. */
|
||||
/***********************************************************************/
|
||||
@@ -61,9 +61,9 @@ class DllExport FILTER : public XOBJECT { /* Filter description block */
|
||||
//virtual PXOB CheckSubQuery(PGLOBAL, PSQL);
|
||||
//virtual bool CheckLocal(PTDB);
|
||||
//virtual int CheckSpcCol(PTDB tdbp, int n);
|
||||
#if defined(MONGO_SUPPORT)
|
||||
bool MakeSelector(PGLOBAL g, PSTRG s, bool m);
|
||||
#endif // MONGO_SUPPORT
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
bool MakeSelector(PGLOBAL g, PSTRG s);
|
||||
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||
virtual void Printf(PGLOBAL g, FILE *f, uint n);
|
||||
virtual void Prints(PGLOBAL g, char *ps, uint z);
|
||||
// PFIL Linearize(bool nosep);
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/***********************************************************************/
|
||||
/* GLOBAL.H: Declaration file used by all CONNECT implementations. */
|
||||
/* (C) Copyright Olivier Bertrand 1993-2017 */
|
||||
/* (C) Copyright MariaDB Corporation Ab */
|
||||
/* Author Olivier Bertrand 1993-2017 */
|
||||
/***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) Olivier Bertrand 2004 - 2017
|
||||
/* Copyright (C) MariaDB Corporation Ab
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -98,8 +98,7 @@
|
||||
rnd_next signals that it has reached the end of its data. Calls to
|
||||
ha_connect::extra() are hints as to what will be occuring to the request.
|
||||
|
||||
Happy use!<br>
|
||||
-Olivier
|
||||
Author Olivier Bertrand
|
||||
*/
|
||||
|
||||
#ifdef USE_PRAGMA_IMPLEMENTATION
|
||||
@@ -209,10 +208,10 @@ pthread_mutex_t parmut = PTHREAD_MUTEX_INITIALIZER;
|
||||
/***********************************************************************/
|
||||
PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
|
||||
PQRYRES VirColumns(PGLOBAL g, bool info);
|
||||
PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info);
|
||||
PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info);
|
||||
PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info);
|
||||
#if defined(MONGO_SUPPORT)
|
||||
PQRYRES MGOColumns(PGLOBAL g, char *db, PTOS topt, bool info);
|
||||
PQRYRES MGOColumns(PGLOBAL g, PCSZ db, PCSZ url, PTOS topt, bool info);
|
||||
#endif // MONGO_SUPPORT
|
||||
int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v);
|
||||
void PushWarning(PGLOBAL g, THD *thd, int level);
|
||||
@@ -701,7 +700,7 @@ static int connect_init_func(void *p)
|
||||
DTVAL::SetTimeShift(); // Initialize time zone shift once for all
|
||||
BINCOL::SetEndian(); // Initialize host endian setting
|
||||
#if defined(JDBC_SUPPORT)
|
||||
JDBConn::SetJVM();
|
||||
JAVAConn::SetJVM();
|
||||
#endif // JDBC_SUPPORT
|
||||
DBUG_RETURN(0);
|
||||
} // end of connect_init_func
|
||||
@@ -726,7 +725,7 @@ static int connect_done_func(void *)
|
||||
#endif // MONGO_SUPPORT
|
||||
|
||||
#ifdef JDBC_SUPPORT
|
||||
JDBConn::ResetJVM();
|
||||
JAVAConn::ResetJVM();
|
||||
#endif // JDBC_SUPPORT
|
||||
|
||||
#if defined(__WIN__)
|
||||
@@ -4081,7 +4080,7 @@ int ha_connect::info(uint flag)
|
||||
if (xmod == MODE_ANY || xmod == MODE_ALTER) {
|
||||
// Pure info, not a query
|
||||
pure= true;
|
||||
xp->CheckCleanup();
|
||||
xp->CheckCleanup(xmod == MODE_ANY && valid_query_id == 0);
|
||||
} // endif xmod
|
||||
|
||||
// This is necessary for getting file length
|
||||
@@ -4094,8 +4093,10 @@ int ha_connect::info(uint flag)
|
||||
} else
|
||||
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen
|
||||
|
||||
if (!(tdbp= GetTDB(g)))
|
||||
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen
|
||||
if (!(tdbp = GetTDB(g))) {
|
||||
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
|
||||
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
|
||||
} // endif tdbp
|
||||
|
||||
valid_info = false;
|
||||
} // endif tdbp
|
||||
@@ -5299,16 +5300,18 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
|
||||
#if defined(ODBC_SUPPORT)
|
||||
POPARM sop= NULL;
|
||||
PCSZ ucnc= NULL;
|
||||
bool cnc= false;
|
||||
PCSZ tabtyp = NULL;
|
||||
bool cnc= false;
|
||||
int cto= -1, qto= -1;
|
||||
#endif // ODBC_SUPPORT
|
||||
#if defined(JDBC_SUPPORT)
|
||||
PJPARM sjp= NULL;
|
||||
#endif // JDBC_SUPPORT
|
||||
#if defined(JDBC_SUPPORT) || defined(MONGO_SUPPORT)
|
||||
PCSZ driver= NULL;
|
||||
char *url= NULL;
|
||||
//char *prop= NULL;
|
||||
PCSZ tabtyp= NULL;
|
||||
#endif // JDBC_SUPPORT
|
||||
#endif // JDBC_SUPPORT || MONGO_SUPPORT
|
||||
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
|
||||
bool bif, ok= false, dbf= false;
|
||||
TABTYPE ttp= TAB_UNDEF;
|
||||
@@ -5361,19 +5364,17 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
|
||||
#endif // __WIN__
|
||||
port= atoi(GetListOption(g, "port", topt->oplist, "0"));
|
||||
#if defined(ODBC_SUPPORT)
|
||||
mxr= atoi(GetListOption(g,"maxres", topt->oplist, "0"));
|
||||
tabtyp = GetListOption(g, "Tabtype", topt->oplist, NULL);
|
||||
mxr= atoi(GetListOption(g,"maxres", topt->oplist, "0"));
|
||||
cto= atoi(GetListOption(g,"ConnectTimeout", topt->oplist, "-1"));
|
||||
qto= atoi(GetListOption(g,"QueryTimeout", topt->oplist, "-1"));
|
||||
|
||||
if ((ucnc= GetListOption(g, "UseDSN", topt->oplist)))
|
||||
cnc= (!*ucnc || *ucnc == 'y' || *ucnc == 'Y' || atoi(ucnc) != 0);
|
||||
#endif
|
||||
#if defined(JDBC_SUPPORT)
|
||||
#if defined(JDBC_SUPPORT) || defined(MONGO_SUPPORT)
|
||||
driver= GetListOption(g, "Driver", topt->oplist, NULL);
|
||||
// url= GetListOption(g, "URL", topt->oplist, NULL);
|
||||
// prop = GetListOption(g, "Properties", topt->oplist, NULL);
|
||||
tabtyp = GetListOption(g, "Tabtype", topt->oplist, NULL);
|
||||
#endif // JDBC_SUPPORT
|
||||
#endif // JDBC_SUPPORT || MONGO_SUPPORT
|
||||
#if defined(PROMPT_OK)
|
||||
cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0"));
|
||||
#endif // PROMPT_OK
|
||||
@@ -5585,14 +5586,14 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
|
||||
ok = true;
|
||||
|
||||
break;
|
||||
#if defined(MONGO_SUPPORT)
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
case TAB_MONGO:
|
||||
if (!topt->tabname)
|
||||
topt->tabname = tab;
|
||||
|
||||
ok = true;
|
||||
break;
|
||||
#endif // MONGO_SUPPORT
|
||||
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||
case TAB_VIR:
|
||||
ok = true;
|
||||
break;
|
||||
@@ -5733,13 +5734,36 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
|
||||
qrp = VirColumns(g, fnc == FNC_COL);
|
||||
break;
|
||||
case TAB_JSON:
|
||||
qrp = JSONColumns(g, (char*)db, dsn, topt, fnc == FNC_COL);
|
||||
qrp = JSONColumns(g, db, dsn, topt, fnc == FNC_COL);
|
||||
break;
|
||||
#if defined(MONGO_SUPPORT)
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
case TAB_MONGO:
|
||||
qrp = MGOColumns(g, (char*)db, topt, fnc == FNC_COL);
|
||||
if (!(url = strz(g, create_info->connect_string)) || !*url)
|
||||
url = "mongodb://localhost:27017";
|
||||
|
||||
#if !defined(MONGO_SUPPORT)
|
||||
driver = "JAVA";
|
||||
// strcpy(g->Message, "No column discovery for Java MONGO tables yet");
|
||||
// Temporarily use the JSONColumns function
|
||||
qrp = JSONColumns(g, db, url, topt, fnc == FNC_COL);
|
||||
#elif !defined(JDBC_SUPPORT)
|
||||
driver = "C";
|
||||
qrp = MGOColumns(g, db, url, topt, fnc == FNC_COL);
|
||||
#else // MONGO_SUPPORT && JDBC_SUPPORT
|
||||
if (!driver)
|
||||
driver = "C";
|
||||
|
||||
if (toupper(*driver) == 'C') {
|
||||
qrp = MGOColumns(g, db, url, topt, fnc == FNC_COL);
|
||||
} else {
|
||||
// strcpy(g->Message, "No column discovery for Java MONGO tables yet");
|
||||
// Temporarily use the JSONColumns function
|
||||
qrp = JSONColumns(g, db, url, topt, fnc == FNC_COL);
|
||||
} // endif driver
|
||||
|
||||
#endif // MONGO_SUPPORT && JDBC_SUPPORT
|
||||
break;
|
||||
#endif // MONGO_SUPPORT
|
||||
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||
#if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT)
|
||||
case TAB_XML:
|
||||
qrp = XMLColumns(g, (char*)db, tab, topt, fnc == FNC_COL);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) Olivier Bertrand 2004 - 2015
|
||||
/* Copyright (C) MariaDB Corporation Ab
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -14,6 +14,7 @@
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
|
||||
|
||||
/** @file ha_connect.h
|
||||
Author Olivier Bertrand
|
||||
|
||||
@brief
|
||||
The ha_connect engine is a prototype storage engine to access external data.
|
||||
|
599
storage/connect/javaconn.cpp
Normal file
599
storage/connect/javaconn.cpp
Normal file
@@ -0,0 +1,599 @@
|
||||
/************ Javaconn C++ Functions Source Code File (.CPP) ***********/
|
||||
/* Name: JAVAConn.CPP Version 1.0 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2017 */
|
||||
/* */
|
||||
/* This file contains the JAVA connection classes functions. */
|
||||
/***********************************************************************/
|
||||
|
||||
#if defined(__WIN__)
|
||||
// This is needed for RegGetValue
|
||||
#define _WINVER 0x0601
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0601
|
||||
#endif // __WIN__
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include relevant MariaDB header file. */
|
||||
/***********************************************************************/
|
||||
#include <my_global.h>
|
||||
#include <m_string.h>
|
||||
#if defined(__WIN__)
|
||||
#include <direct.h> // for getcwd
|
||||
#if defined(__BORLANDC__)
|
||||
#define __MFC_COMPAT__ // To define min/max as macro
|
||||
#endif // __BORLANDC__
|
||||
#else // !__WIN__
|
||||
#if defined(UNIX)
|
||||
#include <errno.h>
|
||||
#else // !UNIX
|
||||
#endif // !UNIX
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> // for getenv
|
||||
#define NODW
|
||||
#endif // !__WIN__
|
||||
|
||||
/***********************************************************************/
|
||||
/* Required objects includes. */
|
||||
/***********************************************************************/
|
||||
#include "global.h"
|
||||
#include "plgdbsem.h"
|
||||
#include "colblk.h"
|
||||
#include "xobject.h"
|
||||
#include "xtable.h"
|
||||
#include "tabext.h"
|
||||
#include "javaconn.h"
|
||||
#include "resource.h"
|
||||
#include "valblk.h"
|
||||
#include "osutil.h"
|
||||
|
||||
#if defined(__WIN__)
|
||||
extern "C" HINSTANCE s_hModule; // Saved module handle
|
||||
#endif // __WIN__
|
||||
#define nullptr 0
|
||||
|
||||
//TYPCONV GetTypeConv();
|
||||
//int GetConvSize();
|
||||
extern char *JvmPath; // The connect_jvm_path global variable value
|
||||
extern char *ClassPath; // The connect_class_path global variable value
|
||||
|
||||
char *GetJavaWrapper(void); // The connect_java_wrapper variable value
|
||||
|
||||
/***********************************************************************/
|
||||
/* Static JAVAConn objects. */
|
||||
/***********************************************************************/
|
||||
void *JAVAConn::LibJvm = NULL;
|
||||
CRTJVM JAVAConn::CreateJavaVM = NULL;
|
||||
GETJVM JAVAConn::GetCreatedJavaVMs = NULL;
|
||||
#if defined(_DEBUG)
|
||||
GETDEF JAVAConn::GetDefaultJavaVMInitArgs = NULL;
|
||||
#endif // _DEBUG
|
||||
|
||||
/***********************************************************************/
|
||||
/* Some macro's (should be defined elsewhere to be more accessible) */
|
||||
/***********************************************************************/
|
||||
#if defined(_DEBUG)
|
||||
#define ASSERT(f) assert(f)
|
||||
#define DEBUG_ONLY(f) (f)
|
||||
#else // !_DEBUG
|
||||
#define ASSERT(f) ((void)0)
|
||||
#define DEBUG_ONLY(f) ((void)0)
|
||||
#endif // !_DEBUG
|
||||
|
||||
/***********************************************************************/
|
||||
/* Allocate the structure used to refer to the result set. */
|
||||
/***********************************************************************/
|
||||
static JCATPARM *AllocCatInfo(PGLOBAL g, JCATINFO fid, PCSZ db,
|
||||
PCSZ tab, PQRYRES qrp)
|
||||
{
|
||||
JCATPARM *cap;
|
||||
|
||||
#if defined(_DEBUG)
|
||||
assert(qrp);
|
||||
#endif
|
||||
|
||||
if ((cap = (JCATPARM *)PlgDBSubAlloc(g, NULL, sizeof(JCATPARM)))) {
|
||||
memset(cap, 0, sizeof(JCATPARM));
|
||||
cap->Id = fid;
|
||||
cap->Qrp = qrp;
|
||||
cap->DB = db;
|
||||
cap->Tab = tab;
|
||||
} // endif cap
|
||||
|
||||
return cap;
|
||||
} // end of AllocCatInfo
|
||||
|
||||
/***********************************************************************/
|
||||
/* JAVAConn construction/destruction. */
|
||||
/***********************************************************************/
|
||||
JAVAConn::JAVAConn(PGLOBAL g, PCSZ wrapper)
|
||||
{
|
||||
m_G = g;
|
||||
jvm = nullptr; // Pointer to the JVM (Java Virtual Machine)
|
||||
env = nullptr; // Pointer to native interface
|
||||
jdi = nullptr; // Pointer to the java wrapper class
|
||||
job = nullptr; // The java wrapper class object
|
||||
errid = nullptr;
|
||||
DiscFunc = "Disconnect";
|
||||
Msg = NULL;
|
||||
m_Wrap = (wrapper) ? wrapper : GetJavaWrapper();
|
||||
|
||||
if (!strchr(m_Wrap, '/')) {
|
||||
// Add the wrapper package name
|
||||
char *wn = (char*)PlugSubAlloc(g, NULL, strlen(m_Wrap) + 10);
|
||||
m_Wrap = strcat(strcpy(wn, "wrappers/"), m_Wrap);
|
||||
} // endif m_Wrap
|
||||
|
||||
m_Opened = false;
|
||||
m_Connected = false;
|
||||
m_Rows = 0;
|
||||
//*m_ErrMsg = '\0';
|
||||
} // end of JAVAConn
|
||||
|
||||
//JAVAConn::~JAVAConn()
|
||||
// {
|
||||
//if (Connected())
|
||||
// EndCom();
|
||||
|
||||
// } // end of ~JAVAConn
|
||||
|
||||
/***********************************************************************/
|
||||
/* Screen for errors. */
|
||||
/***********************************************************************/
|
||||
bool JAVAConn::Check(jint rc)
|
||||
{
|
||||
jstring s;
|
||||
|
||||
if (env->ExceptionCheck()) {
|
||||
jthrowable exc = env->ExceptionOccurred();
|
||||
jmethodID tid = env->GetMethodID(env->FindClass("java/lang/Object"),
|
||||
"toString", "()Ljava/lang/String;");
|
||||
|
||||
if (exc != nullptr && tid != nullptr) {
|
||||
jstring s = (jstring)env->CallObjectMethod(exc, tid);
|
||||
const char *utf = env->GetStringUTFChars(s, (jboolean)false);
|
||||
env->DeleteLocalRef(s);
|
||||
Msg = PlugDup(m_G, utf);
|
||||
} else
|
||||
Msg = "Exception occured";
|
||||
|
||||
env->ExceptionClear();
|
||||
} else if (rc < 0) {
|
||||
s = (jstring)env->CallObjectMethod(job, errid);
|
||||
Msg = (char*)env->GetStringUTFChars(s, (jboolean)false);
|
||||
} else
|
||||
Msg = NULL;
|
||||
|
||||
return (Msg != NULL);
|
||||
} // end of Check
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get MethodID if not exists yet. */
|
||||
/***********************************************************************/
|
||||
bool JAVAConn::gmID(PGLOBAL g, jmethodID& mid, const char *name, const char *sig)
|
||||
{
|
||||
if (mid == nullptr) {
|
||||
mid = env->GetMethodID(jdi, name, sig);
|
||||
|
||||
if (Check()) {
|
||||
strcpy(g->Message, Msg);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
||||
} else
|
||||
return false;
|
||||
|
||||
} // end of gmID
|
||||
|
||||
#if 0
|
||||
/***********************************************************************/
|
||||
/* Utility routine. */
|
||||
/***********************************************************************/
|
||||
int JAVAConn::GetMaxValue(int n)
|
||||
{
|
||||
jint m;
|
||||
jmethodID maxid = nullptr;
|
||||
|
||||
if (gmID(m_G, maxid, "GetMaxValue", "(I)I"))
|
||||
return -1;
|
||||
|
||||
// call method
|
||||
if (Check(m = env->CallIntMethod(job, maxid, n)))
|
||||
htrc("GetMaxValue: %s", Msg);
|
||||
|
||||
return (int)m;
|
||||
} // end of GetMaxValue
|
||||
#endif // 0
|
||||
|
||||
/***********************************************************************/
|
||||
/* Reset the JVM library. */
|
||||
/***********************************************************************/
|
||||
void JAVAConn::ResetJVM(void)
|
||||
{
|
||||
if (LibJvm) {
|
||||
#if defined(__WIN__)
|
||||
FreeLibrary((HMODULE)LibJvm);
|
||||
#else // !__WIN__
|
||||
dlclose(LibJvm);
|
||||
#endif // !__WIN__
|
||||
LibJvm = NULL;
|
||||
CreateJavaVM = NULL;
|
||||
GetCreatedJavaVMs = NULL;
|
||||
#if defined(_DEBUG)
|
||||
GetDefaultJavaVMInitArgs = NULL;
|
||||
#endif // _DEBUG
|
||||
} // endif LibJvm
|
||||
|
||||
} // end of ResetJVM
|
||||
|
||||
/***********************************************************************/
|
||||
/* Dynamically link the JVM library. */
|
||||
/* The purpose of this function is to allow using the CONNECT plugin */
|
||||
/* for other table types when the Java JDK is not installed. */
|
||||
/***********************************************************************/
|
||||
bool JAVAConn::GetJVM(PGLOBAL g)
|
||||
{
|
||||
int ntry;
|
||||
|
||||
if (!LibJvm) {
|
||||
char soname[512];
|
||||
|
||||
#if defined(__WIN__)
|
||||
for (ntry = 0; !LibJvm && ntry < 3; ntry++) {
|
||||
if (!ntry && JvmPath) {
|
||||
strcat(strcpy(soname, JvmPath), "\\jvm.dll");
|
||||
ntry = 3; // No other try
|
||||
} else if (ntry < 2 && getenv("JAVA_HOME")) {
|
||||
strcpy(soname, getenv("JAVA_HOME"));
|
||||
|
||||
if (ntry == 1)
|
||||
strcat(soname, "\\jre");
|
||||
|
||||
strcat(soname, "\\bin\\client\\jvm.dll");
|
||||
} else {
|
||||
// Try to find it through the registry
|
||||
char version[16];
|
||||
char javaKey[64] = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
|
||||
LONG rc;
|
||||
DWORD BufferSize = 16;
|
||||
|
||||
strcpy(soname, "jvm.dll"); // In case it fails
|
||||
|
||||
if ((rc = RegGetValue(HKEY_LOCAL_MACHINE, javaKey, "CurrentVersion",
|
||||
RRF_RT_ANY, NULL, (PVOID)&version, &BufferSize)) == ERROR_SUCCESS) {
|
||||
strcat(strcat(javaKey, "\\"), version);
|
||||
BufferSize = sizeof(soname);
|
||||
|
||||
if ((rc = RegGetValue(HKEY_LOCAL_MACHINE, javaKey, "RuntimeLib",
|
||||
RRF_RT_ANY, NULL, (PVOID)&soname, &BufferSize)) != ERROR_SUCCESS)
|
||||
printf("RegGetValue: rc=%ld\n", rc);
|
||||
|
||||
} // endif rc
|
||||
|
||||
ntry = 3; // Try this only once
|
||||
} // endelse
|
||||
|
||||
// Load the desired shared library
|
||||
LibJvm = LoadLibrary(soname);
|
||||
} // endfor ntry
|
||||
|
||||
// Get the needed entries
|
||||
if (!LibJvm) {
|
||||
char buf[256];
|
||||
DWORD rc = GetLastError();
|
||||
|
||||
sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname);
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
|
||||
(LPTSTR)buf, sizeof(buf), NULL);
|
||||
strcat(strcat(g->Message, ": "), buf);
|
||||
} else if (!(CreateJavaVM = (CRTJVM)GetProcAddress((HINSTANCE)LibJvm,
|
||||
"JNI_CreateJavaVM"))) {
|
||||
sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), "JNI_CreateJavaVM");
|
||||
FreeLibrary((HMODULE)LibJvm);
|
||||
LibJvm = NULL;
|
||||
} else if (!(GetCreatedJavaVMs = (GETJVM)GetProcAddress((HINSTANCE)LibJvm,
|
||||
"JNI_GetCreatedJavaVMs"))) {
|
||||
sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), "JNI_GetCreatedJavaVMs");
|
||||
FreeLibrary((HMODULE)LibJvm);
|
||||
LibJvm = NULL;
|
||||
#if defined(_DEBUG)
|
||||
} else if (!(GetDefaultJavaVMInitArgs = (GETDEF)GetProcAddress((HINSTANCE)LibJvm,
|
||||
"JNI_GetDefaultJavaVMInitArgs"))) {
|
||||
sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(),
|
||||
"JNI_GetDefaultJavaVMInitArgs");
|
||||
FreeLibrary((HMODULE)LibJvm);
|
||||
LibJvm = NULL;
|
||||
#endif // _DEBUG
|
||||
} // endif LibJvm
|
||||
#else // !__WIN__
|
||||
const char *error = NULL;
|
||||
|
||||
for (ntry = 0; !LibJvm && ntry < 2; ntry++) {
|
||||
if (!ntry && JvmPath) {
|
||||
strcat(strcpy(soname, JvmPath), "/libjvm.so");
|
||||
ntry = 2;
|
||||
} else if (!ntry && getenv("JAVA_HOME")) {
|
||||
// TODO: Replace i386 by a better guess
|
||||
strcat(strcpy(soname, getenv("JAVA_HOME")), "/jre/lib/i386/client/libjvm.so");
|
||||
} else { // Will need LD_LIBRARY_PATH to be set
|
||||
strcpy(soname, "libjvm.so");
|
||||
ntry = 2;
|
||||
} // endelse
|
||||
|
||||
LibJvm = dlopen(soname, RTLD_LAZY);
|
||||
} // endfor ntry
|
||||
|
||||
// Load the desired shared library
|
||||
if (!LibJvm) {
|
||||
error = dlerror();
|
||||
sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
|
||||
} else if (!(CreateJavaVM = (CRTJVM)dlsym(LibJvm, "JNI_CreateJavaVM"))) {
|
||||
error = dlerror();
|
||||
sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_CreateJavaVM", SVP(error));
|
||||
dlclose(LibJvm);
|
||||
LibJvm = NULL;
|
||||
} else if (!(GetCreatedJavaVMs = (GETJVM)dlsym(LibJvm, "JNI_GetCreatedJavaVMs"))) {
|
||||
error = dlerror();
|
||||
sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_GetCreatedJavaVMs", SVP(error));
|
||||
dlclose(LibJvm);
|
||||
LibJvm = NULL;
|
||||
#if defined(_DEBUG)
|
||||
} else if (!(GetDefaultJavaVMInitArgs = (GETDEF)dlsym(LibJvm,
|
||||
"JNI_GetDefaultJavaVMInitArgs"))) {
|
||||
error = dlerror();
|
||||
sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_GetDefaultJavaVMInitArgs", SVP(error));
|
||||
dlclose(LibJvm);
|
||||
LibJvm = NULL;
|
||||
#endif // _DEBUG
|
||||
} // endif LibJvm
|
||||
#endif // !__WIN__
|
||||
|
||||
} // endif LibJvm
|
||||
|
||||
return LibJvm == NULL;
|
||||
} // end of GetJVM
|
||||
|
||||
/***********************************************************************/
|
||||
/* Open: connect to a data source. */
|
||||
/***********************************************************************/
|
||||
bool JAVAConn::Open(PGLOBAL g)
|
||||
{
|
||||
bool brc = true, err = false;
|
||||
jboolean jt = (trace > 0);
|
||||
|
||||
// Link or check whether jvm library was linked
|
||||
if (GetJVM(g))
|
||||
return true;
|
||||
|
||||
// Firstly check whether the jvm was already created
|
||||
JavaVM* jvms[1];
|
||||
jsize jsz;
|
||||
jint rc = GetCreatedJavaVMs(jvms, 1, &jsz);
|
||||
|
||||
if (rc == JNI_OK && jsz == 1) {
|
||||
// jvm already existing
|
||||
jvm = jvms[0];
|
||||
rc = jvm->AttachCurrentThread((void**)&env, nullptr);
|
||||
|
||||
if (rc != JNI_OK) {
|
||||
strcpy(g->Message, "Cannot attach jvm to the current thread");
|
||||
return true;
|
||||
} // endif rc
|
||||
|
||||
} else {
|
||||
/*******************************************************************/
|
||||
/* Create a new jvm */
|
||||
/*******************************************************************/
|
||||
PSTRG jpop = new(g)STRING(g, 512, "-Djava.class.path=.");
|
||||
char *cp = NULL;
|
||||
char sep;
|
||||
|
||||
#if defined(__WIN__)
|
||||
sep = ';';
|
||||
#define N 1
|
||||
//#define N 2
|
||||
//#define N 3
|
||||
#else
|
||||
sep = ':';
|
||||
#define N 1
|
||||
#endif
|
||||
|
||||
// Add wrappers jar files
|
||||
AddJars(jpop, sep);
|
||||
|
||||
//================== prepare loading of Java VM ============================
|
||||
JavaVMInitArgs vm_args; // Initialization arguments
|
||||
JavaVMOption* options = new JavaVMOption[N]; // JVM invocation options
|
||||
|
||||
// where to find java .class
|
||||
if (ClassPath && *ClassPath) {
|
||||
jpop->Append(sep);
|
||||
jpop->Append(ClassPath);
|
||||
} // endif ClassPath
|
||||
|
||||
// Java source will be compiled as a jar file installed in the plugin dir
|
||||
jpop->Append(sep);
|
||||
jpop->Append(GetPluginDir());
|
||||
jpop->Append("JdbcInterface.jar");
|
||||
|
||||
// All wrappers are pre-compiled in JavaWrappers.jar in the plugin dir
|
||||
jpop->Append(sep);
|
||||
jpop->Append(GetPluginDir());
|
||||
jpop->Append("JavaWrappers.jar");
|
||||
|
||||
if ((cp = getenv("CLASSPATH"))) {
|
||||
jpop->Append(sep);
|
||||
jpop->Append(cp);
|
||||
} // endif cp
|
||||
|
||||
if (trace) {
|
||||
htrc("ClassPath=%s\n", ClassPath);
|
||||
htrc("CLASSPATH=%s\n", cp);
|
||||
htrc("%s\n", jpop->GetStr());
|
||||
} // endif trace
|
||||
|
||||
options[0].optionString = jpop->GetStr();
|
||||
#if N == 2
|
||||
options[1].optionString = "-Xcheck:jni";
|
||||
#endif
|
||||
#if N == 3
|
||||
options[1].optionString = "-Xms256M";
|
||||
options[2].optionString = "-Xmx512M";
|
||||
#endif
|
||||
#if defined(_DEBUG)
|
||||
vm_args.version = JNI_VERSION_1_2; // minimum Java version
|
||||
rc = GetDefaultJavaVMInitArgs(&vm_args);
|
||||
#else
|
||||
vm_args.version = JNI_VERSION_1_6; // minimum Java version
|
||||
#endif // _DEBUG
|
||||
vm_args.nOptions = N; // number of options
|
||||
vm_args.options = options;
|
||||
vm_args.ignoreUnrecognized = false; // invalid options make the JVM init fail
|
||||
|
||||
//=============== load and initialize Java VM and JNI interface =============
|
||||
rc = CreateJavaVM(&jvm, (void**)&env, &vm_args); // YES !!
|
||||
delete options; // we then no longer need the initialisation options.
|
||||
|
||||
switch (rc) {
|
||||
case JNI_OK:
|
||||
strcpy(g->Message, "VM successfully created");
|
||||
brc = false;
|
||||
break;
|
||||
case JNI_ERR:
|
||||
strcpy(g->Message, "Initialising JVM failed: unknown error");
|
||||
break;
|
||||
case JNI_EDETACHED:
|
||||
strcpy(g->Message, "Thread detached from the VM");
|
||||
break;
|
||||
case JNI_EVERSION:
|
||||
strcpy(g->Message, "JNI version error");
|
||||
break;
|
||||
case JNI_ENOMEM:
|
||||
strcpy(g->Message, "Not enough memory");
|
||||
break;
|
||||
case JNI_EEXIST:
|
||||
strcpy(g->Message, "VM already created");
|
||||
break;
|
||||
case JNI_EINVAL:
|
||||
strcpy(g->Message, "Invalid arguments");
|
||||
break;
|
||||
default:
|
||||
sprintf(g->Message, "Unknown return code %d", (int)rc);
|
||||
break;
|
||||
} // endswitch rc
|
||||
|
||||
if (trace)
|
||||
htrc("%s\n", g->Message);
|
||||
|
||||
if (brc)
|
||||
return true;
|
||||
|
||||
//=============== Display JVM version ===============
|
||||
jint ver = env->GetVersion();
|
||||
printf("JVM Version %d.%d\n", ((ver >> 16) & 0x0f), (ver & 0x0f));
|
||||
} // endif rc
|
||||
|
||||
// try to find the java wrapper class
|
||||
jdi = env->FindClass(m_Wrap);
|
||||
|
||||
if (jdi == nullptr) {
|
||||
sprintf(g->Message, "ERROR: class %s not found!", m_Wrap);
|
||||
return true;
|
||||
} // endif jdi
|
||||
|
||||
#if 0 // Suppressed because it does not make any usable change
|
||||
if (b && jpath && *jpath) {
|
||||
// Try to add that path the the jvm class path
|
||||
jmethodID alp = env->GetStaticMethodID(jdi, "addLibraryPath",
|
||||
"(Ljava/lang/String;)I");
|
||||
|
||||
if (alp == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
env->ExceptionClear();
|
||||
} else {
|
||||
char *msg;
|
||||
jstring path = env->NewStringUTF(jpath);
|
||||
rc = env->CallStaticIntMethod(jdi, alp, path);
|
||||
|
||||
if ((msg = Check(rc))) {
|
||||
strcpy(g->Message, msg);
|
||||
env->DeleteLocalRef(path);
|
||||
return RC_FX;
|
||||
} else switch (rc) {
|
||||
case JNI_OK:
|
||||
printf("jpath added\n");
|
||||
break;
|
||||
case JNI_EEXIST:
|
||||
printf("jpath already exist\n");
|
||||
break;
|
||||
case JNI_ERR:
|
||||
default:
|
||||
strcpy(g->Message, "Error adding jpath");
|
||||
env->DeleteLocalRef(path);
|
||||
return RC_FX;
|
||||
} // endswitch rc
|
||||
|
||||
env->DeleteLocalRef(path);
|
||||
} // endif alp
|
||||
|
||||
} // endif jpath
|
||||
#endif // 0
|
||||
|
||||
// if class found, continue
|
||||
jmethodID ctor = env->GetMethodID(jdi, "<init>", "(Z)V");
|
||||
|
||||
if (ctor == nullptr) {
|
||||
sprintf(g->Message, "ERROR: %s constructor not found!", m_Wrap);
|
||||
return true;
|
||||
} else
|
||||
job = env->NewObject(jdi, ctor, jt);
|
||||
|
||||
if (job == nullptr) {
|
||||
sprintf(g->Message, "%s class object not constructed!", m_Wrap);
|
||||
return true;
|
||||
} // endif job
|
||||
|
||||
// If the object is successfully constructed,
|
||||
// we can then search for the method we want to call,
|
||||
// and invoke it for the object:
|
||||
errid = env->GetMethodID(jdi, "GetErrmsg", "()Ljava/lang/String;");
|
||||
|
||||
if (env->ExceptionCheck()) {
|
||||
strcpy(g->Message, "ERROR: method GetErrmsg() not found!");
|
||||
env->ExceptionDescribe();
|
||||
env->ExceptionClear();
|
||||
return true;
|
||||
} // endif Check
|
||||
|
||||
m_Opened = true;
|
||||
return false;
|
||||
} // end of Open
|
||||
|
||||
/***********************************************************************/
|
||||
/* Disconnect connection */
|
||||
/***********************************************************************/
|
||||
void JAVAConn::Close()
|
||||
{
|
||||
jint rc;
|
||||
|
||||
if (m_Connected) {
|
||||
jmethodID did = nullptr;
|
||||
|
||||
// Could have been detached in case of join
|
||||
rc = jvm->AttachCurrentThread((void**)&env, nullptr);
|
||||
|
||||
if (gmID(m_G, did, DiscFunc, "()I"))
|
||||
printf("%s\n", Msg);
|
||||
else if (Check(env->CallIntMethod(job, did)))
|
||||
printf("%s: %s\n", DiscFunc, Msg);
|
||||
|
||||
m_Connected = false;
|
||||
} // endif m_Connected
|
||||
|
||||
if ((rc = jvm->DetachCurrentThread()) != JNI_OK)
|
||||
printf("DetachCurrentThread: rc=%d\n", (int)rc);
|
||||
|
||||
m_Opened = false;
|
||||
} // end of Close
|
129
storage/connect/javaconn.h
Normal file
129
storage/connect/javaconn.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/***********************************************************************/
|
||||
/* JavaConn.h : header file for the Java connection classes. */
|
||||
/***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
/* Included C-definition files required by the interface. */
|
||||
/***********************************************************************/
|
||||
#include "block.h"
|
||||
#include "jdbccat.h"
|
||||
|
||||
/***********************************************************************/
|
||||
/* Java native interface. */
|
||||
/***********************************************************************/
|
||||
#include <jni.h>
|
||||
|
||||
/***********************************************************************/
|
||||
/* Constants and defines. */
|
||||
/***********************************************************************/
|
||||
// Miscellaneous sizing info
|
||||
#define MAX_NUM_OF_MSG 10 // Max number of error messages
|
||||
//efine MAX_CURRENCY 30 // Max size of Currency($) string
|
||||
#define MAX_TNAME_LEN 32 // Max size of table names
|
||||
//efine MAX_FNAME_LEN 256 // Max size of field names
|
||||
//efine MAX_STRING_INFO 256 // Max size of string from SQLGetInfo
|
||||
//efine MAX_DNAME_LEN 256 // Max size of Recordset names
|
||||
//efine MAX_CONNECT_LEN 512 // Max size of Connect string
|
||||
//efine MAX_CURSOR_NAME 18 // Max size of a cursor name
|
||||
#define DEFAULT_FIELD_TYPE 0 // TYPE_NULL
|
||||
|
||||
#if !defined(__WIN__)
|
||||
typedef unsigned char *PUCHAR;
|
||||
#endif // !__WIN__
|
||||
|
||||
enum JCATINFO {
|
||||
CAT_TAB = 1, // JDBC Tables
|
||||
CAT_COL = 2, // JDBC Columns
|
||||
CAT_KEY = 3, // JDBC PrimaryKeys
|
||||
//CAT_STAT = 4, // SQLStatistics
|
||||
//CAT_SPC = 5 // SQLSpecialColumns
|
||||
};
|
||||
|
||||
/***********************************************************************/
|
||||
/* This structure is used to control the catalog functions. */
|
||||
/***********************************************************************/
|
||||
typedef struct tagJCATPARM {
|
||||
JCATINFO Id; // Id to indicate function
|
||||
PQRYRES Qrp; // Result set pointer
|
||||
PCSZ DB; // Database (Schema)
|
||||
PCSZ Tab; // Table name or pattern
|
||||
PCSZ Pat; // Table type or column pattern
|
||||
} JCATPARM;
|
||||
|
||||
typedef jint(JNICALL *CRTJVM) (JavaVM **, void **, void *);
|
||||
typedef jint(JNICALL *GETJVM) (JavaVM **, jsize, jsize *);
|
||||
#if defined(_DEBUG)
|
||||
typedef jint(JNICALL *GETDEF) (void *);
|
||||
#endif // _DEBUG
|
||||
|
||||
class JAVAConn;
|
||||
|
||||
/***********************************************************************/
|
||||
/* JAVAConn class. */
|
||||
/***********************************************************************/
|
||||
class JAVAConn : public BLOCK {
|
||||
friend class TDBJMG;
|
||||
private:
|
||||
JAVAConn(); // Standard (unused) constructor
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
JAVAConn(PGLOBAL g, PCSZ wrapper);
|
||||
|
||||
// Set static variables
|
||||
static void SetJVM(void) {
|
||||
LibJvm = NULL;
|
||||
CreateJavaVM = NULL;
|
||||
GetCreatedJavaVMs = NULL;
|
||||
#if defined(_DEBUG)
|
||||
GetDefaultJavaVMInitArgs = NULL;
|
||||
#endif // _DEBUG
|
||||
} // end of SetJVM
|
||||
|
||||
static void ResetJVM(void);
|
||||
static bool GetJVM(PGLOBAL g);
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
//virtual ~JAVAConn();
|
||||
bool IsOpen(void) { return m_Opened; }
|
||||
bool IsConnected(void) { return m_Connected; }
|
||||
|
||||
// Java operations
|
||||
protected:
|
||||
bool gmID(PGLOBAL g, jmethodID& mid, const char *name, const char *sig);
|
||||
bool Check(jint rc = 0);
|
||||
|
||||
public:
|
||||
virtual void AddJars(PSTRG jpop, char sep) = 0;
|
||||
virtual bool Connect(PJPARM sop) = 0;
|
||||
virtual bool Open(PGLOBAL g);
|
||||
virtual bool MakeCursor(PGLOBAL g, PTDB tdbp, PCSZ options,
|
||||
PCSZ filter, bool pipe) = 0;
|
||||
virtual void Close(void);
|
||||
|
||||
protected:
|
||||
// Members
|
||||
#if defined(__WIN__)
|
||||
static HANDLE LibJvm; // Handle to the jvm DLL
|
||||
#else // !__WIN__
|
||||
static void *LibJvm; // Handle for the jvm shared library
|
||||
#endif // !__WIN__
|
||||
static CRTJVM CreateJavaVM;
|
||||
static GETJVM GetCreatedJavaVMs;
|
||||
#if defined(_DEBUG)
|
||||
static GETDEF GetDefaultJavaVMInitArgs;
|
||||
#endif // _DEBUG
|
||||
PGLOBAL m_G;
|
||||
JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine)
|
||||
JNIEnv *env; // Pointer to native interface
|
||||
jclass jdi; // Pointer to the java wrapper class
|
||||
jobject job; // The java wrapper class object
|
||||
jmethodID errid; // The GetErrmsg method ID
|
||||
bool m_Opened;
|
||||
bool m_Connected;
|
||||
PCSZ DiscFunc;
|
||||
PCSZ Msg;
|
||||
PCSZ m_Wrap;
|
||||
int m_Rows;
|
||||
}; // end of JAVAConn class definition
|
@@ -1,3 +1,6 @@
|
||||
#ifndef __JDBCCAT_H
|
||||
#define __JDBCCAT_H
|
||||
|
||||
// Timeout and net wait defaults
|
||||
#define DEFAULT_LOGIN_TIMEOUT -1 // means do not set
|
||||
#define DEFAULT_QUERY_TIMEOUT -1 // means do not set
|
||||
@@ -8,9 +11,9 @@ typedef struct jdbc_parms {
|
||||
PCSZ Url; // Driver URL
|
||||
PCSZ User; // User connect info
|
||||
PCSZ Pwd; // Password connect info
|
||||
//char *Properties; // Connection property list
|
||||
//int Cto; // Connect timeout
|
||||
//int Qto; // Query timeout
|
||||
int Version; // Driver version
|
||||
int Fsize; // Fetch size
|
||||
bool Scrollable; // Scrollable cursor
|
||||
} JDBCPARM, *PJPARM;
|
||||
@@ -28,3 +31,5 @@ PQRYRES JDBCSrcCols(PGLOBAL g, PCSZ src, PJPARM sop);
|
||||
PQRYRES JDBCTables(PGLOBAL g, PCSZ db, PCSZ tabpat,
|
||||
PCSZ tabtyp, int maxres, bool info, PJPARM sop);
|
||||
PQRYRES JDBCDrivers(PGLOBAL g, int maxres, bool info);
|
||||
|
||||
#endif // __JDBCCAT_H
|
||||
|
@@ -53,38 +53,28 @@
|
||||
#include "osutil.h"
|
||||
|
||||
|
||||
#if defined(__WIN__)
|
||||
extern "C" HINSTANCE s_hModule; // Saved module handle
|
||||
#endif // __WIN__
|
||||
#define nullptr 0
|
||||
//#if defined(__WIN__)
|
||||
//extern "C" HINSTANCE s_hModule; // Saved module handle
|
||||
//#endif // __WIN__
|
||||
//#define nullptr 0
|
||||
|
||||
TYPCONV GetTypeConv();
|
||||
int GetConvSize();
|
||||
extern char *JvmPath; // The connect_jvm_path global variable value
|
||||
extern char *ClassPath; // The connect_class_path global variable value
|
||||
//extern char *JvmPath; // The connect_jvm_path global variable value
|
||||
//extern char *ClassPath; // The connect_class_path global variable value
|
||||
|
||||
char *GetJavaWrapper(void); // The connect_java_wrapper variable value
|
||||
|
||||
/***********************************************************************/
|
||||
/* Static JDBConn objects. */
|
||||
/***********************************************************************/
|
||||
void *JDBConn::LibJvm = NULL;
|
||||
CRTJVM JDBConn::CreateJavaVM = NULL;
|
||||
GETJVM JDBConn::GetCreatedJavaVMs = NULL;
|
||||
#if defined(_DEBUG)
|
||||
GETDEF JDBConn::GetDefaultJavaVMInitArgs = NULL;
|
||||
#endif // _DEBUG
|
||||
//char *GetJavaWrapper(void); // The connect_java_wrapper variable value
|
||||
|
||||
/***********************************************************************/
|
||||
/* Some macro's (should be defined elsewhere to be more accessible) */
|
||||
/***********************************************************************/
|
||||
#if defined(_DEBUG)
|
||||
#define ASSERT(f) assert(f)
|
||||
#define DEBUG_ONLY(f) (f)
|
||||
#else // !_DEBUG
|
||||
#define ASSERT(f) ((void)0)
|
||||
#define DEBUG_ONLY(f) ((void)0)
|
||||
#endif // !_DEBUG
|
||||
//#if defined(_DEBUG)
|
||||
//#define ASSERT(f) assert(f)
|
||||
//#define DEBUG_ONLY(f) (f)
|
||||
//#else // !_DEBUG
|
||||
//#define ASSERT(f) ((void)0)
|
||||
//#define DEBUG_ONLY(f) ((void)0)
|
||||
//#endif // !_DEBUG
|
||||
|
||||
// To avoid gcc warning
|
||||
int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v);
|
||||
@@ -239,11 +229,11 @@ PQRYRES JDBCColumns(PGLOBAL g, PCSZ db, PCSZ table, PCSZ colpat,
|
||||
FLD_SCALE, FLD_RADIX, FLD_NULL, FLD_REM};
|
||||
unsigned int length[] = {0, 0, 0, 0, 6, 0, 10, 10, 6, 6, 6, 0};
|
||||
bool b[] = {true, true, false, false, false, false, false, false, true, true, false, true};
|
||||
int i, n, ncol = 12;
|
||||
PCOLRES crp;
|
||||
PQRYRES qrp;
|
||||
int i, n, ncol = 12;
|
||||
PCOLRES crp;
|
||||
PQRYRES qrp;
|
||||
JCATPARM *cap;
|
||||
JDBConn *jcp = NULL;
|
||||
JDBConn *jcp = NULL;
|
||||
|
||||
/************************************************************************/
|
||||
/* Do an evaluation of the result size. */
|
||||
@@ -251,7 +241,7 @@ PQRYRES JDBCColumns(PGLOBAL g, PCSZ db, PCSZ table, PCSZ colpat,
|
||||
if (!info) {
|
||||
jcp = new(g)JDBConn(g, NULL);
|
||||
|
||||
if (jcp->Open(sjp) != RC_OK) // openReadOnly + noJDBCdialog
|
||||
if (jcp->Connect(sjp)) // openReadOnly + noJDBCdialog
|
||||
return NULL;
|
||||
|
||||
if (table && !strchr(table, '%')) {
|
||||
@@ -337,7 +327,7 @@ PQRYRES JDBCSrcCols(PGLOBAL g, PCSZ src, PJPARM sjp)
|
||||
PQRYRES qrp;
|
||||
JDBConn *jcp = new(g)JDBConn(g, NULL);
|
||||
|
||||
if (jcp->Open(sjp))
|
||||
if (jcp->Connect(sjp))
|
||||
return NULL;
|
||||
|
||||
if (strstr(src, "%s")) {
|
||||
@@ -379,7 +369,7 @@ PQRYRES JDBCTables(PGLOBAL g, PCSZ db, PCSZ tabpat, PCSZ tabtyp,
|
||||
/**********************************************************************/
|
||||
jcp = new(g)JDBConn(g, NULL);
|
||||
|
||||
if (jcp->Open(sjp) == RC_FX)
|
||||
if (jcp->Connect(sjp))
|
||||
return NULL;
|
||||
|
||||
if (!maxres)
|
||||
@@ -523,37 +513,16 @@ PQRYRES JDBCDrivers(PGLOBAL g, int maxres, bool info)
|
||||
/***********************************************************************/
|
||||
/* JDBConn construction/destruction. */
|
||||
/***********************************************************************/
|
||||
JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp)
|
||||
JDBConn::JDBConn(PGLOBAL g, PCSZ wrapper) : JAVAConn(g, wrapper)
|
||||
{
|
||||
m_G = g;
|
||||
m_Tdb = tdbp;
|
||||
jvm = nullptr; // Pointer to the JVM (Java Virtual Machine)
|
||||
env= nullptr; // Pointer to native interface
|
||||
jdi = nullptr; // Pointer to the java wrapper class
|
||||
job = nullptr; // The java wrapper class object
|
||||
xqid = xuid = xid = grs = readid = fetchid = typid = errid = nullptr;
|
||||
prepid = xpid = pcid = nullptr;
|
||||
chrfldid = intfldid = dblfldid = fltfldid = bigfldid = nullptr;
|
||||
objfldid = datfldid = timfldid = tspfldid = nullptr;
|
||||
//m_LoginTimeout = DEFAULT_LOGIN_TIMEOUT;
|
||||
//m_QueryTimeout = DEFAULT_QUERY_TIMEOUT;
|
||||
//m_UpdateOptions = 0;
|
||||
Msg = NULL;
|
||||
m_Wrap = (tdbp && tdbp->WrapName) ? tdbp->WrapName : GetJavaWrapper();
|
||||
|
||||
if (!strchr(m_Wrap, '/')) {
|
||||
// Add the wrapper package name
|
||||
char *wn = (char*)PlugSubAlloc(g, NULL, strlen(m_Wrap) + 10);
|
||||
m_Wrap = strcat(strcpy(wn, "wrappers/"), m_Wrap);
|
||||
} // endif m_Wrap
|
||||
|
||||
//m_Driver = NULL;
|
||||
//m_Url = NULL;
|
||||
//m_User = NULL;
|
||||
//m_Pwd = NULL;
|
||||
DiscFunc = "JdbcDisconnect";
|
||||
m_Ncol = 0;
|
||||
m_Aff = 0;
|
||||
m_Rows = 0;
|
||||
//m_Rows = 0;
|
||||
m_Fetch = 0;
|
||||
m_RowsetSize = 0;
|
||||
m_Updatable = true;
|
||||
@@ -563,7 +532,6 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp)
|
||||
m_Opened = false;
|
||||
m_IDQuoteChar[0] = '"';
|
||||
m_IDQuoteChar[1] = 0;
|
||||
//*m_ErrMsg = '\0';
|
||||
} // end of JDBConn
|
||||
|
||||
//JDBConn::~JDBConn()
|
||||
@@ -573,55 +541,6 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp)
|
||||
|
||||
// } // end of ~JDBConn
|
||||
|
||||
/***********************************************************************/
|
||||
/* Screen for errors. */
|
||||
/***********************************************************************/
|
||||
bool JDBConn::Check(jint rc)
|
||||
{
|
||||
jstring s;
|
||||
|
||||
if (env->ExceptionCheck()) {
|
||||
jthrowable exc = env->ExceptionOccurred();
|
||||
jmethodID tid = env->GetMethodID(env->FindClass("java/lang/Object"),
|
||||
"toString", "()Ljava/lang/String;");
|
||||
|
||||
if (exc != nullptr && tid != nullptr) {
|
||||
jstring s = (jstring)env->CallObjectMethod(exc, tid);
|
||||
const char *utf = env->GetStringUTFChars(s, (jboolean)false);
|
||||
env->DeleteLocalRef(s);
|
||||
Msg = PlugDup(m_G, utf);
|
||||
} else
|
||||
Msg = "Exception occured";
|
||||
|
||||
env->ExceptionClear();
|
||||
} else if (rc < 0) {
|
||||
s = (jstring)env->CallObjectMethod(job, errid);
|
||||
Msg = (char*)env->GetStringUTFChars(s, (jboolean)false);
|
||||
} else
|
||||
Msg = NULL;
|
||||
|
||||
return (Msg != NULL);
|
||||
} // end of Check
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get MethodID if not exists yet. */
|
||||
/***********************************************************************/
|
||||
bool JDBConn::gmID(PGLOBAL g, jmethodID& mid, const char *name, const char *sig)
|
||||
{
|
||||
if (mid == nullptr) {
|
||||
mid = env->GetMethodID(jdi, name, sig);
|
||||
|
||||
if (Check()) {
|
||||
strcpy(g->Message, Msg);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
||||
} else
|
||||
return false;
|
||||
|
||||
} // end of gmID
|
||||
|
||||
/***********************************************************************/
|
||||
/* Utility routine. */
|
||||
/***********************************************************************/
|
||||
@@ -641,381 +560,52 @@ int JDBConn::GetMaxValue(int n)
|
||||
} // end of GetMaxValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* Reset the JVM library. */
|
||||
/* AddJars: add some jar file to the Class path. */
|
||||
/***********************************************************************/
|
||||
void JDBConn::ResetJVM(void)
|
||||
void JDBConn::AddJars(PSTRG jpop, char sep)
|
||||
{
|
||||
if (LibJvm) {
|
||||
#if defined(__WIN__)
|
||||
FreeLibrary((HMODULE)LibJvm);
|
||||
#else // !__WIN__
|
||||
dlclose(LibJvm);
|
||||
#endif // !__WIN__
|
||||
LibJvm = NULL;
|
||||
CreateJavaVM = NULL;
|
||||
GetCreatedJavaVMs = NULL;
|
||||
#if defined(_DEBUG)
|
||||
GetDefaultJavaVMInitArgs = NULL;
|
||||
#endif // _DEBUG
|
||||
} // endif LibJvm
|
||||
|
||||
} // end of ResetJVM
|
||||
#if defined(DEVELOPMENT)
|
||||
jpop->Append(
|
||||
";C:/Jconnectors/postgresql-9.4.1208.jar"
|
||||
";C:/Oracle/ojdbc7.jar"
|
||||
";C:/Apache/commons-dbcp2-2.1.1/commons-dbcp2-2.1.1.jar"
|
||||
";C:/Apache/commons-pool2-2.4.2/commons-pool2-2.4.2.jar"
|
||||
";C:/Apache/commons-logging-1.2/commons-logging-1.2.jar"
|
||||
";C:/Jconnectors/mysql-connector-java-6.0.2-bin.jar"
|
||||
";C:/Jconnectors/mariadb-java-client-2.0.1.jar"
|
||||
";C:/Jconnectors/sqljdbc42.jar");
|
||||
#endif // DEVELOPMENT
|
||||
} // end of AddJars
|
||||
|
||||
/***********************************************************************/
|
||||
/* Dynamically link the JVM library. */
|
||||
/* The purpose of this function is to allow using the CONNECT plugin */
|
||||
/* for other table types when the Java JDK is not installed. */
|
||||
/* Connect: connect to a data source. */
|
||||
/***********************************************************************/
|
||||
bool JDBConn::GetJVM(PGLOBAL g)
|
||||
{
|
||||
int ntry;
|
||||
|
||||
if (!LibJvm) {
|
||||
char soname[512];
|
||||
|
||||
#if defined(__WIN__)
|
||||
for (ntry = 0; !LibJvm && ntry < 3; ntry++) {
|
||||
if (!ntry && JvmPath) {
|
||||
strcat(strcpy(soname, JvmPath), "\\jvm.dll");
|
||||
ntry = 3; // No other try
|
||||
} else if (ntry < 2 && getenv("JAVA_HOME")) {
|
||||
strcpy(soname, getenv("JAVA_HOME"));
|
||||
|
||||
if (ntry == 1)
|
||||
strcat(soname, "\\jre");
|
||||
|
||||
strcat(soname, "\\bin\\client\\jvm.dll");
|
||||
} else {
|
||||
// Try to find it through the registry
|
||||
char version[16];
|
||||
char javaKey[64] = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
|
||||
LONG rc;
|
||||
DWORD BufferSize = 16;
|
||||
|
||||
strcpy(soname, "jvm.dll"); // In case it fails
|
||||
|
||||
if ((rc = RegGetValue(HKEY_LOCAL_MACHINE, javaKey, "CurrentVersion",
|
||||
RRF_RT_ANY, NULL, (PVOID)&version, &BufferSize)) == ERROR_SUCCESS) {
|
||||
strcat(strcat(javaKey, "\\"), version);
|
||||
BufferSize = sizeof(soname);
|
||||
|
||||
if ((rc = RegGetValue(HKEY_LOCAL_MACHINE, javaKey, "RuntimeLib",
|
||||
RRF_RT_ANY, NULL, (PVOID)&soname, &BufferSize)) != ERROR_SUCCESS)
|
||||
printf("RegGetValue: rc=%ld\n", rc);
|
||||
|
||||
} // endif rc
|
||||
|
||||
ntry = 3; // Try this only once
|
||||
} // endelse
|
||||
|
||||
// Load the desired shared library
|
||||
LibJvm = LoadLibrary(soname);
|
||||
} // endfor ntry
|
||||
|
||||
// Get the needed entries
|
||||
if (!LibJvm) {
|
||||
char buf[256];
|
||||
DWORD rc = GetLastError();
|
||||
|
||||
sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname);
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
|
||||
(LPTSTR)buf, sizeof(buf), NULL);
|
||||
strcat(strcat(g->Message, ": "), buf);
|
||||
} else if (!(CreateJavaVM = (CRTJVM)GetProcAddress((HINSTANCE)LibJvm,
|
||||
"JNI_CreateJavaVM"))) {
|
||||
sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), "JNI_CreateJavaVM");
|
||||
FreeLibrary((HMODULE)LibJvm);
|
||||
LibJvm = NULL;
|
||||
} else if (!(GetCreatedJavaVMs = (GETJVM)GetProcAddress((HINSTANCE)LibJvm,
|
||||
"JNI_GetCreatedJavaVMs"))) {
|
||||
sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), "JNI_GetCreatedJavaVMs");
|
||||
FreeLibrary((HMODULE)LibJvm);
|
||||
LibJvm = NULL;
|
||||
#if defined(_DEBUG)
|
||||
} else if (!(GetDefaultJavaVMInitArgs = (GETDEF)GetProcAddress((HINSTANCE)LibJvm,
|
||||
"JNI_GetDefaultJavaVMInitArgs"))) {
|
||||
sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(),
|
||||
"JNI_GetDefaultJavaVMInitArgs");
|
||||
FreeLibrary((HMODULE)LibJvm);
|
||||
LibJvm = NULL;
|
||||
#endif // _DEBUG
|
||||
} // endif LibJvm
|
||||
#else // !__WIN__
|
||||
const char *error = NULL;
|
||||
|
||||
for (ntry = 0; !LibJvm && ntry < 2; ntry++) {
|
||||
if (!ntry && JvmPath) {
|
||||
strcat(strcpy(soname, JvmPath), "/libjvm.so");
|
||||
ntry = 2;
|
||||
} else if (!ntry && getenv("JAVA_HOME")) {
|
||||
// TODO: Replace i386 by a better guess
|
||||
strcat(strcpy(soname, getenv("JAVA_HOME")), "/jre/lib/i386/client/libjvm.so");
|
||||
} else { // Will need LD_LIBRARY_PATH to be set
|
||||
strcpy(soname, "libjvm.so");
|
||||
ntry = 2;
|
||||
} // endelse
|
||||
|
||||
LibJvm = dlopen(soname, RTLD_LAZY);
|
||||
} // endfor ntry
|
||||
|
||||
// Load the desired shared library
|
||||
if (!LibJvm) {
|
||||
error = dlerror();
|
||||
sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
|
||||
} else if (!(CreateJavaVM = (CRTJVM)dlsym(LibJvm, "JNI_CreateJavaVM"))) {
|
||||
error = dlerror();
|
||||
sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_CreateJavaVM", SVP(error));
|
||||
dlclose(LibJvm);
|
||||
LibJvm = NULL;
|
||||
} else if (!(GetCreatedJavaVMs = (GETJVM)dlsym(LibJvm, "JNI_GetCreatedJavaVMs"))) {
|
||||
error = dlerror();
|
||||
sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_GetCreatedJavaVMs", SVP(error));
|
||||
dlclose(LibJvm);
|
||||
LibJvm = NULL;
|
||||
#if defined(_DEBUG)
|
||||
} else if (!(GetDefaultJavaVMInitArgs = (GETDEF)dlsym(LibJvm,
|
||||
"JNI_GetDefaultJavaVMInitArgs"))) {
|
||||
error = dlerror();
|
||||
sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_GetDefaultJavaVMInitArgs", SVP(error));
|
||||
dlclose(LibJvm);
|
||||
LibJvm = NULL;
|
||||
#endif // _DEBUG
|
||||
} // endif LibJvm
|
||||
#endif // !__WIN__
|
||||
|
||||
} // endif LibJvm
|
||||
|
||||
return LibJvm == NULL;
|
||||
} // end of GetJVM
|
||||
|
||||
/***********************************************************************/
|
||||
/* Open: connect to a data source. */
|
||||
/***********************************************************************/
|
||||
int JDBConn::Open(PJPARM sop)
|
||||
bool JDBConn::Connect(PJPARM sop)
|
||||
{
|
||||
int irc = RC_FX;
|
||||
bool err = false;
|
||||
jint rc;
|
||||
jboolean jt = (trace > 0);
|
||||
PGLOBAL& g = m_G;
|
||||
|
||||
// Link or check whether jvm library was linked
|
||||
if (GetJVM(g))
|
||||
return RC_FX;
|
||||
|
||||
// Firstly check whether the jvm was already created
|
||||
JavaVM* jvms[1];
|
||||
jsize jsz;
|
||||
jint rc = GetCreatedJavaVMs(jvms, 1, &jsz);
|
||||
|
||||
if (rc == JNI_OK && jsz == 1) {
|
||||
// jvm already existing
|
||||
jvm = jvms[0];
|
||||
rc = jvm->AttachCurrentThread((void**)&env, nullptr);
|
||||
|
||||
if (rc != JNI_OK) {
|
||||
strcpy(g->Message, "Cannot attach jvm to the current thread");
|
||||
return RC_FX;
|
||||
} // endif rc
|
||||
|
||||
} else {
|
||||
/*******************************************************************/
|
||||
/* Create a new jvm */
|
||||
/*******************************************************************/
|
||||
PSTRG jpop = new(g)STRING(g, 512, "-Djava.class.path=.");
|
||||
char *cp = NULL;
|
||||
char sep;
|
||||
|
||||
#if defined(__WIN__)
|
||||
sep = ';';
|
||||
#define N 1
|
||||
//#define N 2
|
||||
//#define N 3
|
||||
#else
|
||||
sep = ':';
|
||||
#define N 1
|
||||
#endif
|
||||
|
||||
// Java source will be compiled as a jar file installed in the plugin dir
|
||||
jpop->Append(sep);
|
||||
jpop->Append(GetPluginDir());
|
||||
jpop->Append("JdbcInterface.jar");
|
||||
|
||||
// All wrappers are pre-compiled in JavaWrappers.jar in the plugin dir
|
||||
jpop->Append(sep);
|
||||
jpop->Append(GetPluginDir());
|
||||
jpop->Append("JavaWrappers.jar");
|
||||
|
||||
//================== prepare loading of Java VM ============================
|
||||
JavaVMInitArgs vm_args; // Initialization arguments
|
||||
JavaVMOption* options = new JavaVMOption[N]; // JVM invocation options
|
||||
|
||||
// where to find java .class
|
||||
if (ClassPath && *ClassPath) {
|
||||
jpop->Append(sep);
|
||||
jpop->Append(ClassPath);
|
||||
} // endif ClassPath
|
||||
|
||||
if ((cp = getenv("CLASSPATH"))) {
|
||||
jpop->Append(sep);
|
||||
jpop->Append(cp);
|
||||
} // endif cp
|
||||
|
||||
if (trace) {
|
||||
htrc("ClassPath=%s\n", ClassPath);
|
||||
htrc("CLASSPATH=%s\n", cp);
|
||||
htrc("%s\n", jpop->GetStr());
|
||||
} // endif trace
|
||||
|
||||
options[0].optionString = jpop->GetStr();
|
||||
#if N == 2
|
||||
options[1].optionString = "-Xcheck:jni";
|
||||
#endif
|
||||
#if N == 3
|
||||
options[1].optionString = "-Xms256M";
|
||||
options[2].optionString = "-Xmx512M";
|
||||
#endif
|
||||
#if defined(_DEBUG)
|
||||
vm_args.version = JNI_VERSION_1_2; // minimum Java version
|
||||
rc = GetDefaultJavaVMInitArgs(&vm_args);
|
||||
#else
|
||||
vm_args.version = JNI_VERSION_1_6; // minimum Java version
|
||||
#endif // _DEBUG
|
||||
vm_args.nOptions = N; // number of options
|
||||
vm_args.options = options;
|
||||
vm_args.ignoreUnrecognized = false; // invalid options make the JVM init fail
|
||||
|
||||
//=============== load and initialize Java VM and JNI interface =============
|
||||
rc = CreateJavaVM(&jvm, (void**)&env, &vm_args); // YES !!
|
||||
delete options; // we then no longer need the initialisation options.
|
||||
|
||||
switch (rc) {
|
||||
case JNI_OK:
|
||||
strcpy(g->Message, "VM successfully created");
|
||||
irc = RC_OK;
|
||||
break;
|
||||
case JNI_ERR:
|
||||
strcpy(g->Message, "Initialising JVM failed: unknown error");
|
||||
break;
|
||||
case JNI_EDETACHED:
|
||||
strcpy(g->Message, "Thread detached from the VM");
|
||||
break;
|
||||
case JNI_EVERSION:
|
||||
strcpy(g->Message, "JNI version error");
|
||||
break;
|
||||
case JNI_ENOMEM:
|
||||
strcpy(g->Message, "Not enough memory");
|
||||
break;
|
||||
case JNI_EEXIST:
|
||||
strcpy(g->Message, "VM already created");
|
||||
break;
|
||||
case JNI_EINVAL:
|
||||
strcpy(g->Message, "Invalid arguments");
|
||||
break;
|
||||
default:
|
||||
sprintf(g->Message, "Unknown return code %d", (int)rc);
|
||||
break;
|
||||
} // endswitch rc
|
||||
|
||||
if (trace)
|
||||
htrc("%s\n", g->Message);
|
||||
|
||||
if (irc != RC_OK)
|
||||
return irc;
|
||||
|
||||
//=============== Display JVM version ===============
|
||||
jint ver = env->GetVersion();
|
||||
printf("JVM Version %d.%d\n", ((ver>>16)&0x0f), (ver&0x0f));
|
||||
} // endif rc
|
||||
|
||||
// try to find the java wrapper class
|
||||
jdi = env->FindClass(m_Wrap);
|
||||
|
||||
if (jdi == nullptr) {
|
||||
sprintf(g->Message, "ERROR: class %s not found!", m_Wrap);
|
||||
return RC_FX;
|
||||
} // endif jdi
|
||||
|
||||
#if 0 // Suppressed because it does not make any usable change
|
||||
if (b && jpath && *jpath) {
|
||||
// Try to add that path the the jvm class path
|
||||
jmethodID alp = env->GetStaticMethodID(jdi, "addLibraryPath",
|
||||
"(Ljava/lang/String;)I");
|
||||
|
||||
if (alp == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
env->ExceptionClear();
|
||||
} else {
|
||||
char *msg;
|
||||
jstring path = env->NewStringUTF(jpath);
|
||||
rc = env->CallStaticIntMethod(jdi, alp, path);
|
||||
|
||||
if ((msg = Check(rc))) {
|
||||
strcpy(g->Message, msg);
|
||||
env->DeleteLocalRef(path);
|
||||
return RC_FX;
|
||||
} else switch (rc) {
|
||||
case JNI_OK:
|
||||
printf("jpath added\n");
|
||||
break;
|
||||
case JNI_EEXIST:
|
||||
printf("jpath already exist\n");
|
||||
break;
|
||||
case JNI_ERR:
|
||||
default:
|
||||
strcpy(g->Message, "Error adding jpath");
|
||||
env->DeleteLocalRef(path);
|
||||
return RC_FX;
|
||||
} // endswitch rc
|
||||
|
||||
env->DeleteLocalRef(path);
|
||||
} // endif alp
|
||||
|
||||
} // endif jpath
|
||||
#endif // 0
|
||||
|
||||
// if class found, continue
|
||||
jmethodID ctor = env->GetMethodID(jdi, "<init>", "(Z)V");
|
||||
|
||||
if (ctor == nullptr) {
|
||||
sprintf(g->Message, "ERROR: %s constructor not found!", m_Wrap);
|
||||
return RC_FX;
|
||||
} else
|
||||
job = env->NewObject(jdi, ctor, jt);
|
||||
|
||||
// If the object is successfully constructed,
|
||||
// we can then search for the method we want to call,
|
||||
// and invoke it for the object:
|
||||
if (job == nullptr) {
|
||||
sprintf(g->Message, "%s class object not constructed!", m_Wrap);
|
||||
return RC_FX;
|
||||
} // endif job
|
||||
|
||||
errid = env->GetMethodID(jdi, "GetErrmsg", "()Ljava/lang/String;");
|
||||
|
||||
if (env->ExceptionCheck()) {
|
||||
strcpy(g->Message, "ERROR: method GetErrmsg() not found!");
|
||||
env->ExceptionDescribe();
|
||||
env->ExceptionClear();
|
||||
return RC_FX;
|
||||
} // endif Check
|
||||
/*******************************************************************/
|
||||
/* Create or attach a JVM. */
|
||||
/*******************************************************************/
|
||||
if (Open(g))
|
||||
return true;
|
||||
|
||||
if (!sop) // DRIVER catalog table
|
||||
return RC_OK;
|
||||
return false;
|
||||
|
||||
jmethodID cid = nullptr;
|
||||
|
||||
if (gmID(g, cid, "JdbcConnect", "([Ljava/lang/String;IZ)I"))
|
||||
return RC_FX;
|
||||
return true;
|
||||
|
||||
// Build the java string array
|
||||
jobjectArray parms = env->NewObjectArray(4, // constructs java array of 4
|
||||
env->FindClass("java/lang/String"), NULL); // Strings
|
||||
|
||||
//m_Driver = sop->Driver;
|
||||
//m_Url = sop->Url;
|
||||
//m_User = sop->User;
|
||||
//m_Pwd = sop->Pwd;
|
||||
m_Scrollable = sop->Scrollable;
|
||||
m_RowsetSize = sop->Fsize;
|
||||
//m_LoginTimeout = sop->Cto;
|
||||
@@ -1035,9 +625,6 @@ int JDBConn::Open(PJPARM sop)
|
||||
if (sop->Pwd)
|
||||
env->SetObjectArrayElement(parms, 3, env->NewStringUTF(sop->Pwd));
|
||||
|
||||
//if (sop->Properties)
|
||||
// env->SetObjectArrayElement(parms, 4, env->NewStringUTF(sop->Properties));
|
||||
|
||||
// call method
|
||||
rc = env->CallIntMethod(job, cid, parms, m_RowsetSize, m_Scrollable);
|
||||
err = Check(rc);
|
||||
@@ -1045,7 +632,7 @@ int JDBConn::Open(PJPARM sop)
|
||||
|
||||
if (err) {
|
||||
sprintf(g->Message, "Connecting: %s rc=%d", Msg, (int)rc);
|
||||
return RC_FX;
|
||||
return true;
|
||||
} // endif Msg
|
||||
|
||||
jmethodID qcid = nullptr;
|
||||
@@ -1064,17 +651,18 @@ int JDBConn::Open(PJPARM sop)
|
||||
} // endif qcid
|
||||
|
||||
if (gmID(g, typid, "ColumnType", "(ILjava/lang/String;)I"))
|
||||
return RC_FX;
|
||||
return true;
|
||||
else
|
||||
m_Opened = true;
|
||||
|
||||
return RC_OK;
|
||||
} // end of Open
|
||||
return false;
|
||||
} // end of Connect
|
||||
|
||||
|
||||
/***********************************************************************/
|
||||
/* Execute an SQL command. */
|
||||
/***********************************************************************/
|
||||
int JDBConn::ExecSQLcommand(PCSZ sql)
|
||||
int JDBConn::ExecuteCommand(PCSZ sql)
|
||||
{
|
||||
int rc;
|
||||
jint n;
|
||||
@@ -1110,7 +698,7 @@ int JDBConn::ExecSQLcommand(PCSZ sql)
|
||||
} // endif ncol
|
||||
|
||||
return rc;
|
||||
} // end of ExecSQLcommand
|
||||
} // end of ExecuteCommand
|
||||
|
||||
/***********************************************************************/
|
||||
/* Fetch next row. */
|
||||
@@ -1170,38 +758,12 @@ int JDBConn::Rewind(PCSZ sql)
|
||||
jboolean b = env->CallBooleanMethod(job, fetchid, 0);
|
||||
|
||||
rbuf = m_Rows;
|
||||
} else if (ExecSQLcommand(sql) != RC_FX)
|
||||
} else if (ExecuteCommand(sql) != RC_FX)
|
||||
rbuf = 0;
|
||||
|
||||
return rbuf;
|
||||
} // end of Rewind
|
||||
|
||||
/***********************************************************************/
|
||||
/* Disconnect connection */
|
||||
/***********************************************************************/
|
||||
void JDBConn::Close()
|
||||
{
|
||||
if (m_Opened) {
|
||||
jint rc;
|
||||
jmethodID did = nullptr;
|
||||
|
||||
// Could have been detached in case of join
|
||||
rc = jvm->AttachCurrentThread((void**)&env, nullptr);
|
||||
|
||||
if (gmID(m_G, did, "JdbcDisconnect", "()I"))
|
||||
printf("%s\n", Msg);
|
||||
else if (Check(env->CallIntMethod(job, did)))
|
||||
printf("jdbcDisconnect: %s\n", Msg);
|
||||
|
||||
if ((rc = jvm->DetachCurrentThread()) != JNI_OK)
|
||||
printf("DetachCurrentThread: rc=%d\n", (int)rc);
|
||||
|
||||
//rc = jvm->DestroyJavaVM();
|
||||
m_Opened = false;
|
||||
} // endif m_Opened
|
||||
|
||||
} // end of Close
|
||||
|
||||
/***********************************************************************/
|
||||
/* Retrieve and set the column value from the result set. */
|
||||
/***********************************************************************/
|
||||
@@ -1424,7 +986,7 @@ int JDBConn::ExecuteUpdate(PCSZ sql)
|
||||
/***********************************************************************/
|
||||
/* Get the number of lines of the result set. */
|
||||
/***********************************************************************/
|
||||
int JDBConn::GetResultSize(PCSZ sql, JDBCCOL *colp)
|
||||
int JDBConn::GetResultSize(PCSZ sql, PCOL colp)
|
||||
{
|
||||
int rc, n = 0;
|
||||
|
||||
@@ -1565,53 +1127,6 @@ bool JDBConn::SetParam(JDBCCOL *colp)
|
||||
return rc;
|
||||
} // end of SetParam
|
||||
|
||||
#if 0
|
||||
/***********************************************************************/
|
||||
/* Get the list of Data Sources and set it in qrp. */
|
||||
/***********************************************************************/
|
||||
bool JDBConn::GetDataSources(PQRYRES qrp)
|
||||
{
|
||||
bool rv = false;
|
||||
UCHAR *dsn, *des;
|
||||
UWORD dir = SQL_FETCH_FIRST;
|
||||
SWORD n1, n2, p1, p2;
|
||||
PCOLRES crp1 = qrp->Colresp, crp2 = qrp->Colresp->Next;
|
||||
RETCODE rc;
|
||||
|
||||
n1 = crp1->Clen;
|
||||
n2 = crp2->Clen;
|
||||
|
||||
try {
|
||||
rc = SQLAllocEnv(&m_henv);
|
||||
|
||||
if (!Check(rc))
|
||||
ThrowDJX(rc, "SQLAllocEnv"); // Fatal
|
||||
|
||||
for (int i = 0; i < qrp->Maxres; i++) {
|
||||
dsn = (UCHAR*)crp1->Kdata->GetValPtr(i);
|
||||
des = (UCHAR*)crp2->Kdata->GetValPtr(i);
|
||||
rc = SQLDataSources(m_henv, dir, dsn, n1, &p1, des, n2, &p2);
|
||||
|
||||
if (rc == SQL_NO_DATA_FOUND)
|
||||
break;
|
||||
else if (!Check(rc))
|
||||
ThrowDJX(rc, "SQLDataSources");
|
||||
|
||||
qrp->Nblin++;
|
||||
dir = SQL_FETCH_NEXT;
|
||||
} // endfor i
|
||||
|
||||
}
|
||||
catch (DJX *x) {
|
||||
sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
|
||||
rv = true;
|
||||
} // end try/catch
|
||||
|
||||
Close();
|
||||
return rv;
|
||||
} // end of GetDataSources
|
||||
#endif // 0
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the list of Drivers and set it in qrp. */
|
||||
/***********************************************************************/
|
||||
@@ -1677,7 +1192,7 @@ bool JDBConn::SetParam(JDBCCOL *colp)
|
||||
jint *n = nullptr;
|
||||
jstring label;
|
||||
jmethodID colid = nullptr;
|
||||
int rc = ExecSQLcommand(src);
|
||||
int rc = ExecuteCommand(src);
|
||||
|
||||
if (rc == RC_NF) {
|
||||
strcpy(g->Message, "Srcdef is not returning a result set");
|
||||
@@ -2002,10 +1517,10 @@ bool JDBConn::SetParam(JDBCCOL *colp)
|
||||
/***********************************************************************/
|
||||
/* Allocate a CONNECT result structure from the JDBC result. */
|
||||
/***********************************************************************/
|
||||
PQRYRES JDBConn::AllocateResult(PGLOBAL g)
|
||||
PQRYRES JDBConn::AllocateResult(PGLOBAL g, PTDB tdbp)
|
||||
{
|
||||
bool uns;
|
||||
PJDBCCOL colp;
|
||||
PCOL colp;
|
||||
PCOLRES *pcrp, crp;
|
||||
PQRYRES qrp;
|
||||
|
||||
@@ -2030,8 +1545,7 @@ bool JDBConn::SetParam(JDBCCOL *colp)
|
||||
qrp->Nblin = 0;
|
||||
qrp->Cursor = 0;
|
||||
|
||||
for (colp = (PJDBCCOL)m_Tdb->Columns; colp;
|
||||
colp = (PJDBCCOL)colp->GetNext())
|
||||
for (colp = tdbp->GetColumns(); colp; colp = colp->GetNext())
|
||||
if (!colp->IsSpecial()) {
|
||||
*pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
|
||||
crp = *pcrp;
|
||||
@@ -2059,10 +1573,9 @@ bool JDBConn::SetParam(JDBCCOL *colp)
|
||||
memset(crp->Nulls, ' ', m_Rows);
|
||||
} // endelse Nullable
|
||||
|
||||
colp->SetCrp(crp);
|
||||
((EXTCOL*)colp)->SetCrp(crp);
|
||||
} // endif colp
|
||||
|
||||
*pcrp = NULL;
|
||||
//qrp->Nblin = n;
|
||||
return qrp;
|
||||
} // end of AllocateResult
|
||||
|
@@ -1,61 +1,7 @@
|
||||
/***********************************************************************/
|
||||
/* JDBConn.h : header file for the JDBC connection classes. */
|
||||
/***********************************************************************/
|
||||
//nclude <windows.h> /* Windows include file */
|
||||
//nclude <windowsx.h> /* Message crackers */
|
||||
|
||||
/***********************************************************************/
|
||||
/* Included C-definition files required by the interface. */
|
||||
/***********************************************************************/
|
||||
#include "block.h"
|
||||
|
||||
/***********************************************************************/
|
||||
/* JDBC interface. */
|
||||
/***********************************************************************/
|
||||
#include <jni.h>
|
||||
|
||||
/***********************************************************************/
|
||||
/* Constants and defines. */
|
||||
/***********************************************************************/
|
||||
// Miscellaneous sizing info
|
||||
#define MAX_NUM_OF_MSG 10 // Max number of error messages
|
||||
//efine MAX_CURRENCY 30 // Max size of Currency($) string
|
||||
#define MAX_TNAME_LEN 32 // Max size of table names
|
||||
//efine MAX_FNAME_LEN 256 // Max size of field names
|
||||
//efine MAX_STRING_INFO 256 // Max size of string from SQLGetInfo
|
||||
//efine MAX_DNAME_LEN 256 // Max size of Recordset names
|
||||
//efine MAX_CONNECT_LEN 512 // Max size of Connect string
|
||||
//efine MAX_CURSOR_NAME 18 // Max size of a cursor name
|
||||
#define DEFAULT_FIELD_TYPE 0 // TYPE_NULL
|
||||
|
||||
#if !defined(__WIN__)
|
||||
typedef unsigned char *PUCHAR;
|
||||
#endif // !__WIN__
|
||||
|
||||
enum JCATINFO {
|
||||
CAT_TAB = 1, // JDBC Tables
|
||||
CAT_COL = 2, // JDBC Columns
|
||||
CAT_KEY = 3, // JDBC PrimaryKeys
|
||||
//CAT_STAT = 4, // SQLStatistics
|
||||
//CAT_SPC = 5 // SQLSpecialColumns
|
||||
};
|
||||
|
||||
/***********************************************************************/
|
||||
/* This structure is used to control the catalog functions. */
|
||||
/***********************************************************************/
|
||||
typedef struct tagJCATPARM {
|
||||
JCATINFO Id; // Id to indicate function
|
||||
PQRYRES Qrp; // Result set pointer
|
||||
PCSZ DB; // Database (Schema)
|
||||
PCSZ Tab; // Table name or pattern
|
||||
PCSZ Pat; // Table type or column pattern
|
||||
} JCATPARM;
|
||||
|
||||
typedef jint(JNICALL *CRTJVM) (JavaVM **, void **, void *);
|
||||
typedef jint(JNICALL *GETJVM) (JavaVM **, jsize, jsize *);
|
||||
#if defined(_DEBUG)
|
||||
typedef jint(JNICALL *GETDEF) (void *);
|
||||
#endif // _DEBUG
|
||||
#include "javaconn.h"
|
||||
|
||||
// JDBC connection to a data source
|
||||
class TDBJDBC;
|
||||
@@ -66,7 +12,7 @@ class TDBXJDC;
|
||||
/***********************************************************************/
|
||||
/* JDBConn class. */
|
||||
/***********************************************************************/
|
||||
class JDBConn : public BLOCK {
|
||||
class JDBConn : public JAVAConn {
|
||||
friend class TDBJDBC;
|
||||
friend class TDBXJDC;
|
||||
//friend PQRYRES GetColumnInfo(PGLOBAL, char*&, char *, int, PVBLK&);
|
||||
@@ -74,118 +20,80 @@ private:
|
||||
JDBConn(); // Standard (unused) constructor
|
||||
|
||||
public:
|
||||
JDBConn(PGLOBAL g, TDBJDBC *tdbp);
|
||||
// Constructor
|
||||
JDBConn(PGLOBAL g, PCSZ wrapper);
|
||||
|
||||
int Open(PJPARM sop);
|
||||
int Rewind(PCSZ sql);
|
||||
void Close(void);
|
||||
PQRYRES AllocateResult(PGLOBAL g);
|
||||
virtual void AddJars(PSTRG jpop, char sep);
|
||||
PQRYRES AllocateResult(PGLOBAL g, PTDB tdbp);
|
||||
|
||||
// Attributes
|
||||
public:
|
||||
char *GetQuoteChar(void) { return m_IDQuoteChar; }
|
||||
// Database successfully opened?
|
||||
bool IsOpen(void) { return m_Opened; }
|
||||
//PSZ GetStringInfo(ushort infotype);
|
||||
int GetMaxValue(int infotype);
|
||||
//PSZ GetConnect(void) { return m_Connect; }
|
||||
char *GetQuoteChar(void) { return m_IDQuoteChar; }
|
||||
virtual int GetMaxValue(int infotype);
|
||||
|
||||
public:
|
||||
// Operations
|
||||
//void SetLoginTimeout(DWORD sec) {m_LoginTimeout = sec;}
|
||||
//void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;}
|
||||
//void SetUserName(PSZ user) {m_User = user;}
|
||||
//void SetUserPwd(PSZ pwd) {m_Pwd = pwd;}
|
||||
int GetResultSize(PCSZ sql, JDBCCOL *colp);
|
||||
int ExecuteQuery(PCSZ sql);
|
||||
int ExecuteUpdate(PCSZ sql);
|
||||
int Fetch(int pos = 0);
|
||||
virtual bool Connect(PJPARM sop);
|
||||
virtual bool MakeCursor(PGLOBAL g, PTDB tdbp, PCSZ options,
|
||||
PCSZ filter, bool pipe) {return true;}
|
||||
virtual int GetResultSize(PCSZ sql, PCOL colp);
|
||||
virtual int ExecuteCommand(PCSZ sql);
|
||||
virtual int ExecuteQuery(PCSZ sql);
|
||||
virtual int ExecuteUpdate(PCSZ sql);
|
||||
virtual int Fetch(int pos = 0);
|
||||
virtual void SetColumnValue(int rank, PSZ name, PVAL val);
|
||||
|
||||
// Jdbc operations
|
||||
bool PrepareSQL(PCSZ sql);
|
||||
int ExecuteSQL(void);
|
||||
int ExecuteSQL(void); // Prepared statement
|
||||
bool SetParam(JDBCCOL *colp);
|
||||
int ExecSQLcommand(PCSZ sql);
|
||||
void SetColumnValue(int rank, PSZ name, PVAL val);
|
||||
int GetCatInfo(JCATPARM *cap);
|
||||
//bool GetDataSources(PQRYRES qrp);
|
||||
bool GetDrivers(PQRYRES qrp);
|
||||
PQRYRES GetMetaData(PGLOBAL g, PCSZ src);
|
||||
|
||||
public:
|
||||
// Set static variables
|
||||
static void SetJVM(void) {
|
||||
LibJvm = NULL;
|
||||
CreateJavaVM = NULL;
|
||||
GetCreatedJavaVMs = NULL;
|
||||
#if defined(_DEBUG)
|
||||
GetDefaultJavaVMInitArgs = NULL;
|
||||
#endif // _DEBUG
|
||||
} // end of SetJVM
|
||||
|
||||
static void ResetJVM(void);
|
||||
static bool GetJVM(PGLOBAL g);
|
||||
int Rewind(PCSZ sql);
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
//virtual ~JDBConn();
|
||||
|
||||
// JDBC operations
|
||||
protected:
|
||||
bool gmID(PGLOBAL g, jmethodID& mid, const char *name, const char *sig);
|
||||
bool Check(jint rc = 0);
|
||||
//void ThrowDJX(int rc, PSZ msg/*, HSTMT hstmt = SQL_NULL_HSTMT*/);
|
||||
//void ThrowDJX(PSZ msg);
|
||||
//void Free(void);
|
||||
|
||||
protected:
|
||||
// Members
|
||||
#if defined(__WIN__)
|
||||
static HANDLE LibJvm; // Handle to the jvm DLL
|
||||
#else // !__WIN__
|
||||
static void *LibJvm; // Handle for the jvm shared library
|
||||
#endif // !__WIN__
|
||||
static CRTJVM CreateJavaVM;
|
||||
static GETJVM GetCreatedJavaVMs;
|
||||
#if defined(_DEBUG)
|
||||
static GETDEF GetDefaultJavaVMInitArgs;
|
||||
#endif // _DEBUG
|
||||
PGLOBAL m_G;
|
||||
TDBJDBC *m_Tdb;
|
||||
JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine)
|
||||
JNIEnv *env; // Pointer to native interface
|
||||
jclass jdi; // Pointer to the java wrapper class
|
||||
jobject job; // The java wrapper class object
|
||||
jmethodID xqid; // The ExecuteQuery method ID
|
||||
jmethodID xuid; // The ExecuteUpdate method ID
|
||||
jmethodID xid; // The Execute method ID
|
||||
jmethodID grs; // The GetResult method ID
|
||||
jmethodID readid; // The ReadNext method ID
|
||||
jmethodID fetchid; // The Fetch method ID
|
||||
jmethodID typid; // The ColumnType method ID
|
||||
jmethodID prepid; // The CreatePrepStmt method ID
|
||||
jmethodID xpid; // The ExecutePrep method ID
|
||||
jmethodID pcid; // The ClosePrepStmt method ID
|
||||
jmethodID errid; // The GetErrmsg method ID
|
||||
jmethodID objfldid; // The ObjectField method ID
|
||||
jmethodID chrfldid; // The StringField method ID
|
||||
jmethodID intfldid; // The IntField method ID
|
||||
jmethodID dblfldid; // The DoubleField method ID
|
||||
jmethodID fltfldid; // The FloatField method ID
|
||||
jmethodID datfldid; // The DateField method ID
|
||||
jmethodID timfldid; // The TimeField method ID
|
||||
jmethodID tspfldid; // The TimestampField method ID
|
||||
jmethodID bigfldid; // The BigintField method ID
|
||||
PCSZ Msg;
|
||||
char *m_Wrap;
|
||||
#if 0
|
||||
JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine)
|
||||
JNIEnv *env; // Pointer to native interface
|
||||
jclass jdi; // Pointer to the java wrapper class
|
||||
jobject job; // The java wrapper class object
|
||||
jmethodID errid; // The GetErrmsg method ID
|
||||
#endif // 0
|
||||
jmethodID xqid; // The ExecuteQuery method ID
|
||||
jmethodID xuid; // The ExecuteUpdate method ID
|
||||
jmethodID xid; // The Execute method ID
|
||||
jmethodID grs; // The GetResult method ID
|
||||
jmethodID readid; // The ReadNext method ID
|
||||
jmethodID fetchid; // The Fetch method ID
|
||||
jmethodID typid; // The ColumnType method ID
|
||||
jmethodID prepid; // The CreatePrepStmt method ID
|
||||
jmethodID xpid; // The ExecutePrep method ID
|
||||
jmethodID pcid; // The ClosePrepStmt method ID
|
||||
jmethodID objfldid; // The ObjectField method ID
|
||||
jmethodID chrfldid; // The StringField method ID
|
||||
jmethodID intfldid; // The IntField method ID
|
||||
jmethodID dblfldid; // The DoubleField method ID
|
||||
jmethodID fltfldid; // The FloatField method ID
|
||||
jmethodID datfldid; // The DateField method ID
|
||||
jmethodID timfldid; // The TimeField method ID
|
||||
jmethodID tspfldid; // The TimestampField method ID
|
||||
jmethodID bigfldid; // The BigintField method ID
|
||||
// PCSZ Msg;
|
||||
// PCSZ m_Wrap;
|
||||
char m_IDQuoteChar[2];
|
||||
PCSZ m_Pwd;
|
||||
int m_Ncol;
|
||||
int m_Aff;
|
||||
int m_Rows;
|
||||
int m_Fetch;
|
||||
int m_RowsetSize;
|
||||
jboolean m_Updatable;
|
||||
jboolean m_Transact;
|
||||
jboolean m_Scrollable;
|
||||
bool m_Opened;
|
||||
bool m_Full;
|
||||
}; // end of JDBConn class definition
|
||||
|
357
storage/connect/jmgfam.cpp
Normal file
357
storage/connect/jmgfam.cpp
Normal file
@@ -0,0 +1,357 @@
|
||||
/************ JMONGO FAM C++ Program Source Code File (.CPP) ***********/
|
||||
/* PROGRAM NAME: jmgfam.cpp */
|
||||
/* ------------- */
|
||||
/* Version 1.0 */
|
||||
/* */
|
||||
/* COPYRIGHT: */
|
||||
/* ---------- */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 20017 */
|
||||
/* */
|
||||
/* WHAT THIS PROGRAM DOES: */
|
||||
/* ----------------------- */
|
||||
/* This program are the Java MongoDB access method classes. */
|
||||
/* */
|
||||
/***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include relevant sections of the System header files. */
|
||||
/***********************************************************************/
|
||||
#include "my_global.h"
|
||||
#if defined(__WIN__)
|
||||
//#include <io.h>
|
||||
//#include <fcntl.h>
|
||||
//#include <errno.h>
|
||||
#if defined(__BORLANDC__)
|
||||
#define __MFC_COMPAT__ // To define min/max as macro
|
||||
#endif // __BORLANDC__
|
||||
//#include <windows.h>
|
||||
#else // !__WIN__
|
||||
#if defined(UNIX) || defined(UNIV_LINUX)
|
||||
//#include <errno.h>
|
||||
#include <unistd.h>
|
||||
//#if !defined(sun) // Sun has the ftruncate fnc.
|
||||
//#define USETEMP // Force copy mode for DELETE
|
||||
//#endif // !sun
|
||||
#else // !UNIX
|
||||
//#include <io.h>
|
||||
#endif // !UNIX
|
||||
//#include <fcntl.h>
|
||||
#endif // !__WIN__
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include application header files: */
|
||||
/* global.h is header containing all global declarations. */
|
||||
/* plgdbsem.h is header containing the DB application declarations. */
|
||||
/* filamtxt.h is header containing the file AM classes declarations. */
|
||||
/***********************************************************************/
|
||||
#include "global.h"
|
||||
#include "plgdbsem.h"
|
||||
#include "reldef.h"
|
||||
#include "filamtxt.h"
|
||||
#include "tabdos.h"
|
||||
#include "tabjson.h"
|
||||
#include "jmgfam.h"
|
||||
|
||||
#if defined(UNIX) || defined(UNIV_LINUX)
|
||||
#include "osutil.h"
|
||||
//#define _fileno fileno
|
||||
//#define _O_RDONLY O_RDONLY
|
||||
#endif
|
||||
|
||||
/* --------------------------- Class JMGFAM -------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* Constructors. */
|
||||
/***********************************************************************/
|
||||
JMGFAM::JMGFAM(PJDEF tdp) : DOSFAM((PDOSDEF)NULL)
|
||||
{
|
||||
Jcp = NULL;
|
||||
//Client = NULL;
|
||||
//Database = NULL;
|
||||
//Collection = NULL;
|
||||
//Cursor = NULL;
|
||||
//Query = NULL;
|
||||
//Opts = NULL;
|
||||
Ops.Driver = tdp->Schema;
|
||||
Ops.Url = tdp->Uri;
|
||||
Ops.User = NULL;
|
||||
Ops.Pwd = NULL;
|
||||
Ops.Scrollable = false;
|
||||
Ops.Fsize = 0;
|
||||
Ops.Version = tdp->Version;
|
||||
To_Fbt = NULL;
|
||||
Mode = MODE_ANY;
|
||||
Uristr = tdp->Uri;
|
||||
Db_name = tdp->Schema;
|
||||
Coll_name = tdp->Collname;
|
||||
Options = tdp->Options;
|
||||
Filter = tdp->Filter;
|
||||
Wrapname = tdp->Wrapname;
|
||||
Done = false;
|
||||
Pipe = tdp->Pipe;
|
||||
Version = tdp->Version;
|
||||
Lrecl = tdp->Lrecl + tdp->Ending;
|
||||
Curpos = 0;
|
||||
} // end of JMGFAM standard constructor
|
||||
|
||||
JMGFAM::JMGFAM(PJMGFAM tdfp) : DOSFAM(tdfp)
|
||||
{
|
||||
//Client = tdfp->Client;
|
||||
//Database = NULL;
|
||||
//Collection = tdfp->Collection;
|
||||
//Cursor = tdfp->Cursor;
|
||||
//Query = tdfp->Query;
|
||||
//Opts = tdfp->Opts;
|
||||
Ops = tdfp->Ops;
|
||||
To_Fbt = tdfp->To_Fbt;
|
||||
Mode = tdfp->Mode;
|
||||
Uristr = tdfp->Uristr;
|
||||
Db_name = tdfp->Db_name;
|
||||
Coll_name = tdfp->Coll_name;
|
||||
Options = tdfp->Options;
|
||||
Filter = NULL;
|
||||
Wrapname = tdfp->Wrapname;
|
||||
Done = tdfp->Done;
|
||||
Pipe = tdfp->Pipe;
|
||||
Version = tdfp->Version;
|
||||
} // end of JMGFAM copy constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* Reset: reset position values at the beginning of file. */
|
||||
/***********************************************************************/
|
||||
void JMGFAM::Reset(void)
|
||||
{
|
||||
TXTFAM::Reset();
|
||||
Fpos = Tpos = Spos = 0;
|
||||
} // end of Reset
|
||||
|
||||
/***********************************************************************/
|
||||
/* MGO GetFileLength: returns file size in number of bytes. */
|
||||
/***********************************************************************/
|
||||
int JMGFAM::GetFileLength(PGLOBAL g)
|
||||
{
|
||||
return 0;
|
||||
} // end of GetFileLength
|
||||
|
||||
/***********************************************************************/
|
||||
/* Cardinality: returns table cardinality in number of rows. */
|
||||
/* This function can be called with a null argument to test the */
|
||||
/* availability of Cardinality implementation (1 yes, 0 no). */
|
||||
/***********************************************************************/
|
||||
int JMGFAM::Cardinality(PGLOBAL g)
|
||||
{
|
||||
if (!g)
|
||||
return 1;
|
||||
|
||||
return (!Init(g)) ? Jcp->CollSize(g) : 0;
|
||||
} // end of Cardinality
|
||||
|
||||
/***********************************************************************/
|
||||
/* Note: This function is not really implemented yet. */
|
||||
/***********************************************************************/
|
||||
int JMGFAM::MaxBlkSize(PGLOBAL, int s)
|
||||
{
|
||||
return s;
|
||||
} // end of MaxBlkSize
|
||||
|
||||
/***********************************************************************/
|
||||
/* Init: initialize MongoDB processing. */
|
||||
/***********************************************************************/
|
||||
bool JMGFAM::Init(PGLOBAL g)
|
||||
{
|
||||
if (Done)
|
||||
return false;
|
||||
|
||||
/*********************************************************************/
|
||||
/* Open an JDBC connection for this table. */
|
||||
/* Note: this may not be the proper way to do. Perhaps it is better */
|
||||
/* to test whether a connection is already open for this datasource */
|
||||
/* and if so to allocate just a new result set. But this only for */
|
||||
/* drivers allowing concurency in getting results ??? */
|
||||
/*********************************************************************/
|
||||
if (!Jcp)
|
||||
Jcp = new(g) JMgoConn(g, Coll_name, Wrapname);
|
||||
else if (Jcp->IsOpen())
|
||||
Jcp->Close();
|
||||
|
||||
if (Jcp->Connect(&Ops))
|
||||
return true;
|
||||
|
||||
Done = true;
|
||||
return false;
|
||||
} // end of Init
|
||||
|
||||
/***********************************************************************/
|
||||
/* OpenTableFile: Open a MongoDB table. */
|
||||
/***********************************************************************/
|
||||
bool JMGFAM::OpenTableFile(PGLOBAL g)
|
||||
{
|
||||
Mode = Tdbp->GetMode();
|
||||
|
||||
if (Pipe && Mode != MODE_READ) {
|
||||
strcpy(g->Message, "Pipeline tables are read only");
|
||||
return true;
|
||||
} // endif Pipe
|
||||
|
||||
if (Init(g))
|
||||
return true;
|
||||
|
||||
if (Jcp->GetMethodId(g, Mode))
|
||||
return true;
|
||||
|
||||
if (Mode == MODE_DELETE && !Tdbp->GetNext()) {
|
||||
// Delete all documents
|
||||
if (!Jcp->MakeCursor(g, Tdbp, "all", Filter, false))
|
||||
if (Jcp->DocDelete(g, true) == RC_OK)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} // endif Mode
|
||||
|
||||
if (Mode == MODE_INSERT)
|
||||
Jcp->MakeColumnGroups(g, Tdbp);
|
||||
|
||||
if (Mode != MODE_UPDATE)
|
||||
return Jcp->MakeCursor(g, Tdbp, Options, Filter, Pipe);
|
||||
|
||||
return false;
|
||||
} // end of OpenTableFile
|
||||
|
||||
/***********************************************************************/
|
||||
/* GetRowID: return the RowID of last read record. */
|
||||
/***********************************************************************/
|
||||
int JMGFAM::GetRowID(void)
|
||||
{
|
||||
return Rows;
|
||||
} // end of GetRowID
|
||||
|
||||
/***********************************************************************/
|
||||
/* GetPos: return the position of last read record. */
|
||||
/***********************************************************************/
|
||||
int JMGFAM::GetPos(void)
|
||||
{
|
||||
return Fpos;
|
||||
} // end of GetPos
|
||||
|
||||
/***********************************************************************/
|
||||
/* GetNextPos: return the position of next record. */
|
||||
/***********************************************************************/
|
||||
int JMGFAM::GetNextPos(void)
|
||||
{
|
||||
return Fpos; // TODO
|
||||
} // end of GetNextPos
|
||||
|
||||
/***********************************************************************/
|
||||
/* SetPos: Replace the table at the specified position. */
|
||||
/***********************************************************************/
|
||||
bool JMGFAM::SetPos(PGLOBAL g, int pos)
|
||||
{
|
||||
Fpos = pos;
|
||||
Placed = true;
|
||||
return false;
|
||||
} // end of SetPos
|
||||
|
||||
/***********************************************************************/
|
||||
/* Record file position in case of UPDATE or DELETE. */
|
||||
/***********************************************************************/
|
||||
bool JMGFAM::RecordPos(PGLOBAL g)
|
||||
{
|
||||
strcpy(g->Message, "JMGFAM::RecordPos NIY");
|
||||
return true;
|
||||
} // end of RecordPos
|
||||
|
||||
/***********************************************************************/
|
||||
/* Initialize Fpos and the current position for indexed DELETE. */
|
||||
/***********************************************************************/
|
||||
int JMGFAM::InitDelete(PGLOBAL g, int fpos, int spos)
|
||||
{
|
||||
strcpy(g->Message, "JMGFAM::InitDelete NIY");
|
||||
return RC_FX;
|
||||
} // end of InitDelete
|
||||
|
||||
/***********************************************************************/
|
||||
/* Skip one record in file. */
|
||||
/***********************************************************************/
|
||||
int JMGFAM::SkipRecord(PGLOBAL g, bool header)
|
||||
{
|
||||
return RC_OK; // Dummy
|
||||
} // end of SkipRecord
|
||||
|
||||
/***********************************************************************/
|
||||
/* ReadBuffer: Get next document from a collection. */
|
||||
/***********************************************************************/
|
||||
int JMGFAM::ReadBuffer(PGLOBAL g)
|
||||
{
|
||||
int rc = RC_FX;
|
||||
|
||||
if (!Curpos && Mode == MODE_UPDATE)
|
||||
if (Jcp->MakeCursor(g, Tdbp, Options, Filter, Pipe))
|
||||
return RC_FX;
|
||||
|
||||
if (++CurNum >= Rbuf) {
|
||||
Rbuf = Jcp->Fetch();
|
||||
Curpos++;
|
||||
CurNum = 0;
|
||||
} // endif CurNum
|
||||
|
||||
if (Rbuf > 0) {
|
||||
PSZ str = Jcp->GetDocument();
|
||||
|
||||
if (str) {
|
||||
if (trace == 1)
|
||||
htrc("%s\n", str);
|
||||
|
||||
strncpy(Tdbp->GetLine(), str, Lrecl);
|
||||
rc = RC_OK;
|
||||
} else
|
||||
strcpy(g->Message, "Null document");
|
||||
|
||||
} else if (!Rbuf)
|
||||
rc = RC_EF;
|
||||
|
||||
return rc;
|
||||
} // end of ReadBuffer
|
||||
|
||||
/***********************************************************************/
|
||||
/* WriteBuffer: File write routine for MGO access method. */
|
||||
/***********************************************************************/
|
||||
int JMGFAM::WriteBuffer(PGLOBAL g)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
|
||||
if (Mode == MODE_INSERT) {
|
||||
rc = Jcp->DocWrite(g);
|
||||
} else if (Mode == MODE_DELETE) {
|
||||
rc = Jcp->DocDelete(g, false);
|
||||
} else if (Mode == MODE_UPDATE) {
|
||||
rc = Jcp->DocUpdate(g, Tdbp);
|
||||
} // endif Mode
|
||||
|
||||
return rc;
|
||||
} // end of WriteBuffer
|
||||
|
||||
/***********************************************************************/
|
||||
/* Data Base delete line routine for MGO and BLK access methods. */
|
||||
/***********************************************************************/
|
||||
int JMGFAM::DeleteRecords(PGLOBAL g, int irc)
|
||||
{
|
||||
return (irc == RC_OK) ? WriteBuffer(g) : RC_OK;
|
||||
} // end of DeleteRecords
|
||||
|
||||
/***********************************************************************/
|
||||
/* Table file close routine for MGO access method. */
|
||||
/***********************************************************************/
|
||||
void JMGFAM::CloseTableFile(PGLOBAL g, bool)
|
||||
{
|
||||
Jcp->Close();
|
||||
Done = false;
|
||||
} // end of CloseTableFile
|
||||
|
||||
/***********************************************************************/
|
||||
/* Rewind routine for MGO access method. */
|
||||
/***********************************************************************/
|
||||
void JMGFAM::Rewind(void)
|
||||
{
|
||||
Jcp->Rewind();
|
||||
} // end of Rewind
|
||||
|
79
storage/connect/jmgfam.h
Normal file
79
storage/connect/jmgfam.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/************** MongoFam H Declares Source Code File (.H) **************/
|
||||
/* Name: jmgfam.h Version 1.0 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2017 */
|
||||
/* */
|
||||
/* This file contains the JAVA MongoDB access method classes declares */
|
||||
/***********************************************************************/
|
||||
#pragma once
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include MongoDB library header files. */
|
||||
/***********************************************************************/
|
||||
#include "block.h"
|
||||
//#include "mongo.h"
|
||||
#include "jmgoconn.h"
|
||||
|
||||
typedef class JMGFAM *PJMGFAM;
|
||||
typedef class MGODEF *PMGODEF;
|
||||
|
||||
/***********************************************************************/
|
||||
/* This is the Java MongoDB Access Method class declaration. */
|
||||
/***********************************************************************/
|
||||
class DllExport JMGFAM : public DOSFAM {
|
||||
friend void mongo_init(bool);
|
||||
public:
|
||||
// Constructor
|
||||
JMGFAM(PJDEF tdp);
|
||||
JMGFAM(PJMGFAM txfp);
|
||||
|
||||
// Implementation
|
||||
virtual AMT GetAmType(void) { return TYPE_AM_MGO; }
|
||||
virtual bool GetUseTemp(void) { return false; }
|
||||
virtual int GetPos(void);
|
||||
virtual int GetNextPos(void);
|
||||
virtual PTXF Duplicate(PGLOBAL g) { return (PTXF)new(g) JMGFAM(this); }
|
||||
void SetLrecl(int lrecl) { Lrecl = lrecl; }
|
||||
|
||||
// Methods
|
||||
virtual void Reset(void);
|
||||
virtual int GetFileLength(PGLOBAL g);
|
||||
virtual int Cardinality(PGLOBAL g);
|
||||
virtual int MaxBlkSize(PGLOBAL g, int s);
|
||||
virtual bool AllocateBuffer(PGLOBAL g) { return false; }
|
||||
virtual int GetRowID(void);
|
||||
virtual bool RecordPos(PGLOBAL g);
|
||||
virtual bool SetPos(PGLOBAL g, int recpos);
|
||||
virtual int SkipRecord(PGLOBAL g, bool header);
|
||||
virtual bool OpenTableFile(PGLOBAL g);
|
||||
virtual int ReadBuffer(PGLOBAL g);
|
||||
virtual int WriteBuffer(PGLOBAL g);
|
||||
virtual int DeleteRecords(PGLOBAL g, int irc);
|
||||
virtual void CloseTableFile(PGLOBAL g, bool abort);
|
||||
virtual void Rewind(void);
|
||||
|
||||
protected:
|
||||
virtual bool OpenTempFile(PGLOBAL g) { return false; }
|
||||
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b) { return false; }
|
||||
virtual int RenameTempFile(PGLOBAL g) { return RC_OK; }
|
||||
virtual int InitDelete(PGLOBAL g, int fpos, int spos);
|
||||
bool Init(PGLOBAL g);
|
||||
//bool MakeCursor(PGLOBAL g);
|
||||
|
||||
// Members
|
||||
JMgoConn *Jcp; // Points to a Mongo connection class
|
||||
JDBCPARM Ops; // Additional parameters
|
||||
PFBLOCK To_Fbt; // Pointer to temp file block
|
||||
MODE Mode;
|
||||
PCSZ Uristr;
|
||||
PCSZ Db_name;
|
||||
PCSZ Coll_name;
|
||||
PCSZ Options;
|
||||
PCSZ Filter;
|
||||
PSZ Wrapname;
|
||||
bool Done; // Init done
|
||||
bool Pipe;
|
||||
int Version;
|
||||
int Curpos; // Cursor position of last fetch
|
||||
}; // end of class JMGFAM
|
||||
|
811
storage/connect/jmgoconn.cpp
Normal file
811
storage/connect/jmgoconn.cpp
Normal file
@@ -0,0 +1,811 @@
|
||||
/************ JMgoConn C++ Functions Source Code File (.CPP) ***********/
|
||||
/* Name: JMgoConn.CPP Version 1.1 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2017 */
|
||||
/* */
|
||||
/* This file contains the MongoDB Java connection classes functions. */
|
||||
/***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include relevant MariaDB header file. */
|
||||
/***********************************************************************/
|
||||
#include <my_global.h>
|
||||
|
||||
/***********************************************************************/
|
||||
/* Required objects includes. */
|
||||
/***********************************************************************/
|
||||
#include "global.h"
|
||||
#include "plgdbsem.h"
|
||||
#include "colblk.h"
|
||||
#include "xobject.h"
|
||||
#include "xtable.h"
|
||||
#include "filter.h"
|
||||
#include "jmgoconn.h"
|
||||
|
||||
#define nullptr 0
|
||||
|
||||
bool IsNum(PSZ s);
|
||||
|
||||
/* --------------------------- Class JNCOL --------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* Add a column in the column list. */
|
||||
/***********************************************************************/
|
||||
void JNCOL::AddCol(PGLOBAL g, PCOL colp, PSZ jp)
|
||||
{
|
||||
char *p;
|
||||
PJKC kp, kcp;
|
||||
|
||||
if ((p = strchr(jp, '.'))) {
|
||||
PJNCOL icp;
|
||||
|
||||
*p++ = 0;
|
||||
|
||||
for (kp = Klist; kp; kp = kp->Next)
|
||||
if (kp->Jncolp && !strcmp(jp, kp->Key))
|
||||
break;
|
||||
|
||||
if (!kp) {
|
||||
icp = new(g) JNCOL(IsNum(p));
|
||||
kcp = (PJKC)PlugSubAlloc(g, NULL, sizeof(JKCOL));
|
||||
kcp->Next = NULL;
|
||||
kcp->Jncolp = icp;
|
||||
kcp->Colp = NULL;
|
||||
|
||||
if (Array) {
|
||||
kcp->Key = NULL;
|
||||
kcp->N = atoi(p);
|
||||
} else {
|
||||
kcp->Key = PlugDup(g, jp);
|
||||
kcp->N = 0;
|
||||
} // endif Array
|
||||
|
||||
if (Klist) {
|
||||
for (kp = Klist; kp->Next; kp = kp->Next);
|
||||
|
||||
kp->Next = kcp;
|
||||
} else
|
||||
Klist = kcp;
|
||||
|
||||
} else
|
||||
icp = kp->Jncolp;
|
||||
|
||||
*(p - 1) = '.';
|
||||
icp->AddCol(g, colp, p);
|
||||
} else {
|
||||
kcp = (PJKC)PlugSubAlloc(g, NULL, sizeof(JKCOL));
|
||||
|
||||
kcp->Next = NULL;
|
||||
kcp->Jncolp = NULL;
|
||||
kcp->Colp = colp;
|
||||
|
||||
if (Array) {
|
||||
kcp->Key = NULL;
|
||||
kcp->N = atoi(jp);
|
||||
} else {
|
||||
kcp->Key = jp;
|
||||
kcp->N = 0;
|
||||
} // endif Array
|
||||
|
||||
if (Klist) {
|
||||
for (kp = Klist; kp->Next; kp = kp->Next);
|
||||
|
||||
kp->Next = kcp;
|
||||
} else
|
||||
Klist = kcp;
|
||||
|
||||
} // endif jp
|
||||
|
||||
} // end of AddCol
|
||||
|
||||
/***********************************************************************/
|
||||
/* JMgoConn construction/destruction. */
|
||||
/***********************************************************************/
|
||||
JMgoConn::JMgoConn(PGLOBAL g, PCSZ collname, PCSZ wrapper)
|
||||
: JAVAConn(g, wrapper)
|
||||
{
|
||||
CollName = collname;
|
||||
readid = fetchid = getdocid = objfldid = fcollid = acollid =
|
||||
mkdocid = docaddid = mkarid = araddid = insertid = updateid =
|
||||
deleteid = gcollid = countid = rewindid = nullptr;
|
||||
DiscFunc = "MongoDisconnect";
|
||||
Fpc = NULL;
|
||||
m_Version = 0;
|
||||
m_Fetch = 0;
|
||||
m_Version = 0;
|
||||
} // end of JMgoConn
|
||||
|
||||
/***********************************************************************/
|
||||
/* AddJars: add some jar file to the Class path. */
|
||||
/***********************************************************************/
|
||||
void JMgoConn::AddJars(PSTRG jpop, char sep)
|
||||
{
|
||||
#if defined(DEVELOPMENT)
|
||||
if (m_Version == 2) {
|
||||
//jpop->Append(sep);
|
||||
//jpop->Append("C:/Eclipse/workspace/MongoWrap2/bin");
|
||||
jpop->Append(sep);
|
||||
jpop->Append("C:/mongo-java-driver/mongo-java-driver-2.13.3.jar");
|
||||
} else {
|
||||
//jpop->Append(sep);
|
||||
//jpop->Append("C:/Eclipse/workspace/MongoWrap3/bin");
|
||||
jpop->Append(sep);
|
||||
jpop->Append("C:/mongo-java-driver/mongo-java-driver-3.4.2.jar");
|
||||
} // endif m_Version
|
||||
#endif // DEVELOPMENT
|
||||
} // end of AddJars
|
||||
|
||||
/***********************************************************************/
|
||||
/* Connect: connect to a data source. */
|
||||
/***********************************************************************/
|
||||
bool JMgoConn::Connect(PJPARM sop)
|
||||
{
|
||||
bool err = false;
|
||||
jint rc;
|
||||
jboolean brc;
|
||||
jstring cln;
|
||||
PGLOBAL& g = m_G;
|
||||
|
||||
m_Version = sop->Version;
|
||||
|
||||
/*******************************************************************/
|
||||
/* Create or attach a JVM. */
|
||||
/*******************************************************************/
|
||||
if (Open(g))
|
||||
return true;
|
||||
|
||||
/*******************************************************************/
|
||||
/* Connect to MongoDB. */
|
||||
/*******************************************************************/
|
||||
jmethodID cid = nullptr;
|
||||
|
||||
if (gmID(g, cid, "MongoConnect", "([Ljava/lang/String;)I"))
|
||||
return true;
|
||||
|
||||
// Build the java string array
|
||||
jobjectArray parms = env->NewObjectArray(4, // constructs java array of 4
|
||||
env->FindClass("java/lang/String"), NULL); // Strings
|
||||
|
||||
//m_Scrollable = sop->Scrollable;
|
||||
//m_RowsetSize = sop->Fsize;
|
||||
|
||||
// change some elements
|
||||
if (sop->Driver)
|
||||
env->SetObjectArrayElement(parms, 0, env->NewStringUTF(sop->Url));
|
||||
|
||||
if (sop->Url)
|
||||
env->SetObjectArrayElement(parms, 1, env->NewStringUTF(sop->Driver));
|
||||
|
||||
if (sop->User)
|
||||
env->SetObjectArrayElement(parms, 2, env->NewStringUTF(sop->User));
|
||||
|
||||
if (sop->Pwd)
|
||||
env->SetObjectArrayElement(parms, 3, env->NewStringUTF(sop->Pwd));
|
||||
|
||||
// call method
|
||||
rc = env->CallIntMethod(job, cid, parms);
|
||||
err = Check(rc);
|
||||
env->DeleteLocalRef(parms); // Not used anymore
|
||||
|
||||
if (err) {
|
||||
sprintf(g->Message, "Connecting: %s rc=%d", Msg, (int)rc);
|
||||
return true;
|
||||
} // endif Msg
|
||||
|
||||
/*********************************************************************/
|
||||
/* Get the collection. */
|
||||
/*********************************************************************/
|
||||
if (gmID(g, gcollid, "GetCollection", "(Ljava/lang/String;)Z"))
|
||||
return true;
|
||||
|
||||
cln = env->NewStringUTF(CollName);
|
||||
brc = env->CallBooleanMethod(job, gcollid, cln);
|
||||
env->DeleteLocalRef(cln);
|
||||
|
||||
if (Check(brc ? -1 : 0)) {
|
||||
sprintf(g->Message, "GetCollection: %s", Msg);
|
||||
return true;
|
||||
} // endif Msg
|
||||
|
||||
m_Connected = true;
|
||||
return false;
|
||||
} // end of Connect
|
||||
|
||||
/***********************************************************************/
|
||||
/* CollSize: returns the number of documents in the collection. */
|
||||
/***********************************************************************/
|
||||
int JMgoConn::CollSize(PGLOBAL g)
|
||||
{
|
||||
if (!gmID(g, countid, "GetCollSize", "()J")) {
|
||||
jlong card = env->CallLongMethod(job, countid);
|
||||
|
||||
return (int)card;
|
||||
} else
|
||||
return 2; // Make MariaDB happy
|
||||
|
||||
} // end of CollSize
|
||||
|
||||
/***********************************************************************/
|
||||
/* OpenDB: Data Base open routine for MONGO access method. */
|
||||
/***********************************************************************/
|
||||
bool JMgoConn::MakeCursor(PGLOBAL g, PTDB tdbp, PCSZ options,
|
||||
PCSZ filter, bool pipe)
|
||||
{
|
||||
const char *p;
|
||||
bool b = false, id = (tdbp->GetMode() != MODE_READ), all = false;
|
||||
uint len;
|
||||
PCOL cp;
|
||||
PSZ jp;
|
||||
PCSZ op = NULL, sf = NULL, Options = options;
|
||||
PSTRG s = NULL;
|
||||
|
||||
if (Options && !stricmp(Options, "all")) {
|
||||
Options = NULL;
|
||||
all = true;
|
||||
} // endif Options
|
||||
|
||||
for (cp = tdbp->GetColumns(); cp; cp = cp->GetNext())
|
||||
if (!strcmp(cp->GetName(), "_id"))
|
||||
id = true;
|
||||
else if (cp->GetFmt() && !strcmp(cp->GetFmt(), "*") && (!Options || pipe))
|
||||
all = true;
|
||||
|
||||
if (pipe && Options) {
|
||||
if (trace)
|
||||
htrc("Pipeline: %s\n", Options);
|
||||
|
||||
p = strrchr(Options, ']');
|
||||
|
||||
if (!p) {
|
||||
strcpy(g->Message, "Missing ] in pipeline");
|
||||
return true;
|
||||
} else
|
||||
*(char*)p = 0;
|
||||
|
||||
s = new(g) STRING(g, 1023, (PSZ)Options);
|
||||
|
||||
if (tdbp->GetFilter()) {
|
||||
s->Append(",{\"$match\":");
|
||||
|
||||
if (tdbp->GetFilter()->MakeSelector(g, s)) {
|
||||
strcpy(g->Message, "Failed making selector");
|
||||
return NULL;
|
||||
} else
|
||||
s->Append('}');
|
||||
|
||||
tdbp->SetFilter(NULL); // Not needed anymore
|
||||
} // endif To_Filter
|
||||
|
||||
if (!all && tdbp->GetColumns()) {
|
||||
// Project list
|
||||
len = s->GetLength();
|
||||
s->Append(",{\"$project\":{\"");
|
||||
|
||||
if (!id)
|
||||
s->Append("_id\":0,\"");
|
||||
|
||||
for (PCOL cp = tdbp->GetColumns(); cp; cp = cp->GetNext()) {
|
||||
if (b)
|
||||
s->Append(",\"");
|
||||
else
|
||||
b = true;
|
||||
|
||||
if ((jp = cp->GetJpath(g, true)))
|
||||
s->Append(jp);
|
||||
else {
|
||||
s->Truncate(len);
|
||||
goto nop;
|
||||
} // endif Jpath
|
||||
|
||||
s->Append("\":1");
|
||||
} // endfor cp
|
||||
|
||||
s->Append("}}");
|
||||
} // endif all
|
||||
|
||||
nop:
|
||||
s->Append("]}");
|
||||
s->Resize(s->GetLength() + 1);
|
||||
*(char*)p = ']'; // Restore Colist for discovery
|
||||
p = s->GetStr();
|
||||
|
||||
if (trace)
|
||||
htrc("New Pipeline: %s\n", p);
|
||||
|
||||
return AggregateCollection(p);
|
||||
} else {
|
||||
if (filter || tdbp->GetFilter()) {
|
||||
if (trace) {
|
||||
if (filter)
|
||||
htrc("Filter: %s\n", filter);
|
||||
|
||||
if (tdbp->GetFilter()) {
|
||||
char buf[512];
|
||||
|
||||
tdbp->GetFilter()->Prints(g, buf, 511);
|
||||
htrc("To_Filter: %s\n", buf);
|
||||
} // endif To_Filter
|
||||
|
||||
} // endif trace
|
||||
|
||||
s = new(g) STRING(g, 1023, (PSZ)filter);
|
||||
len = s->GetLength();
|
||||
|
||||
if (tdbp->GetFilter()) {
|
||||
if (filter)
|
||||
s->Append(',');
|
||||
|
||||
if (tdbp->GetFilter()->MakeSelector(g, s)) {
|
||||
strcpy(g->Message, "Failed making selector");
|
||||
return NULL;
|
||||
} // endif Selector
|
||||
|
||||
tdbp->SetFilter(NULL); // Not needed anymore
|
||||
} // endif To_Filter
|
||||
|
||||
if (trace)
|
||||
htrc("selector: %s\n", s->GetStr());
|
||||
|
||||
s->Resize(s->GetLength() + 1);
|
||||
sf = PlugDup(g, s->GetStr());
|
||||
} // endif Filter
|
||||
|
||||
if (!all) {
|
||||
if (Options && *Options) {
|
||||
if (trace)
|
||||
htrc("options=%s\n", Options);
|
||||
|
||||
op = Options;
|
||||
} else if (tdbp->GetColumns()) {
|
||||
// Projection list
|
||||
if (s)
|
||||
s->Set("{\"");
|
||||
else
|
||||
s = new(g) STRING(g, 511, "{\"");
|
||||
|
||||
if (!id)
|
||||
s->Append("_id\":0,\"");
|
||||
|
||||
for (PCOL cp = tdbp->GetColumns(); cp; cp = cp->GetNext()) {
|
||||
if (b)
|
||||
s->Append(",\"");
|
||||
else
|
||||
b = true;
|
||||
|
||||
if ((jp = cp->GetJpath(g, true)))
|
||||
s->Append(jp);
|
||||
else {
|
||||
// Can this happen?
|
||||
htrc("Fail getting projection path of %s\n", cp->GetName());
|
||||
goto nope;
|
||||
} // endif Jpath
|
||||
|
||||
s->Append("\":1");
|
||||
} // endfor cp
|
||||
|
||||
s->Append("}");
|
||||
s->Resize(s->GetLength() + 1);
|
||||
op = s->GetStr();
|
||||
} else {
|
||||
// count(*) ?
|
||||
op = "{\"_id\":1}";
|
||||
} // endif Options
|
||||
|
||||
} // endif all
|
||||
|
||||
nope:
|
||||
return FindCollection(sf, op);
|
||||
} // endif Pipe
|
||||
|
||||
} // end of MakeCursor
|
||||
|
||||
/***********************************************************************/
|
||||
/* Find a collection and make cursor. */
|
||||
/***********************************************************************/
|
||||
bool JMgoConn::FindCollection(PCSZ query, PCSZ proj)
|
||||
{
|
||||
bool rc = true;
|
||||
jboolean brc;
|
||||
jstring qry = nullptr, prj = nullptr;
|
||||
PGLOBAL& g = m_G;
|
||||
|
||||
// Get the methods used to execute a query and get the result
|
||||
if (!gmID(g, fcollid, "FindColl", "(Ljava/lang/String;Ljava/lang/String;)Z")) {
|
||||
if (query)
|
||||
qry = env->NewStringUTF(query);
|
||||
|
||||
if (proj)
|
||||
prj = env->NewStringUTF(proj);
|
||||
|
||||
brc = env->CallBooleanMethod(job, fcollid, qry, prj);
|
||||
|
||||
if (!Check(brc ? -1 : 0)) {
|
||||
rc = false;
|
||||
} else
|
||||
sprintf(g->Message, "FindColl: %s", Msg);
|
||||
|
||||
if (query)
|
||||
env->DeleteLocalRef(qry);
|
||||
|
||||
if (proj)
|
||||
env->DeleteLocalRef(prj);
|
||||
|
||||
} // endif xqid
|
||||
|
||||
return rc;
|
||||
} // end of FindCollection
|
||||
|
||||
/***********************************************************************/
|
||||
/* Find a collection and make cursor. */
|
||||
/***********************************************************************/
|
||||
bool JMgoConn::AggregateCollection(PCSZ pipeline)
|
||||
{
|
||||
bool rc = true;
|
||||
jboolean brc;
|
||||
jstring pip = nullptr;
|
||||
PGLOBAL& g = m_G;
|
||||
|
||||
// Get the methods used to execute a query and get the result
|
||||
if (!gmID(g, acollid, "AggregateColl", "(Ljava/lang/String;)Z")) {
|
||||
pip = env->NewStringUTF(pipeline);
|
||||
|
||||
brc = env->CallBooleanMethod(job, acollid, pip);
|
||||
|
||||
if (!Check(brc ? -1 : 0)) {
|
||||
rc = false;
|
||||
} else
|
||||
sprintf(g->Message, "AggregateColl: %s", Msg);
|
||||
|
||||
env->DeleteLocalRef(pip);
|
||||
} // endif acollid
|
||||
|
||||
return rc;
|
||||
} // end of AggregateCollection
|
||||
|
||||
/***********************************************************************/
|
||||
/* Fetch next row. */
|
||||
/***********************************************************************/
|
||||
int JMgoConn::Fetch(int pos)
|
||||
{
|
||||
jint rc = JNI_ERR;
|
||||
PGLOBAL& g = m_G;
|
||||
|
||||
//if (m_Full) // Result set has one row
|
||||
// return 1;
|
||||
|
||||
//if (pos) {
|
||||
// if (!m_Scrollable) {
|
||||
// strcpy(g->Message, "Cannot fetch(pos) if FORWARD ONLY");
|
||||
// return rc;
|
||||
// } else if (gmID(m_G, fetchid, "Fetch", "(I)Z"))
|
||||
// return rc;
|
||||
|
||||
// if (env->CallBooleanMethod(job, fetchid, pos))
|
||||
// rc = m_Rows;
|
||||
|
||||
//} else {
|
||||
if (gmID(g, readid, "ReadNext", "()I"))
|
||||
return (int)rc;
|
||||
|
||||
rc = env->CallIntMethod(job, readid);
|
||||
|
||||
if (!Check(rc)) {
|
||||
//if (rc == 0)
|
||||
// m_Full = (m_Fetch == 1);
|
||||
//else
|
||||
// m_Fetch++;
|
||||
|
||||
m_Rows += (int)rc;
|
||||
} else
|
||||
sprintf(g->Message, "Fetch: %s", Msg);
|
||||
|
||||
//} // endif pos
|
||||
|
||||
return (int)rc;
|
||||
} // end of Fetch
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the Json string of the current document. */
|
||||
/***********************************************************************/
|
||||
PSZ JMgoConn::GetDocument(void)
|
||||
{
|
||||
PGLOBAL& g = m_G;
|
||||
PSZ doc = NULL;
|
||||
jstring jdc;
|
||||
|
||||
if (!gmID(g, getdocid, "GetDoc", "()Ljava/lang/String;")) {
|
||||
jdc = (jstring)env->CallObjectMethod(job, getdocid);
|
||||
|
||||
if (jdc)
|
||||
doc = (PSZ)env->GetStringUTFChars(jdc, (jboolean)false);
|
||||
|
||||
} // endif getdocid
|
||||
|
||||
return doc;
|
||||
} // end of GetDocument
|
||||
|
||||
/***********************************************************************/
|
||||
/* Group columns for inserting or updating. */
|
||||
/***********************************************************************/
|
||||
void JMgoConn::MakeColumnGroups(PGLOBAL g, PTDB tdbp)
|
||||
{
|
||||
Fpc = new(g) JNCOL(false);
|
||||
|
||||
for (PCOL colp = tdbp->GetColumns(); colp; colp = colp->GetNext())
|
||||
if (!colp->IsSpecial())
|
||||
Fpc->AddCol(g, colp, colp->GetJpath(g, false));
|
||||
|
||||
} // end of MakeColumnGroups
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get additional method ID. */
|
||||
/***********************************************************************/
|
||||
bool JMgoConn::GetMethodId(PGLOBAL g, MODE mode)
|
||||
{
|
||||
if (mode == MODE_UPDATE) {
|
||||
if (gmID(g, mkdocid, "MakeDocument", "()Ljava/lang/Object;"))
|
||||
return true;
|
||||
|
||||
if (gmID(g, docaddid, "DocAdd",
|
||||
"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z"))
|
||||
return true;
|
||||
|
||||
if (gmID(g, updateid, "CollUpdate", "(Ljava/lang/Object;)J"))
|
||||
return true;
|
||||
|
||||
} else if (mode == MODE_INSERT) {
|
||||
if (gmID(g, mkdocid, "MakeDocument", "()Ljava/lang/Object;"))
|
||||
return true;
|
||||
|
||||
if (gmID(g, docaddid, "DocAdd",
|
||||
"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z"))
|
||||
return true;
|
||||
|
||||
if (gmID(g, mkarid, "MakeArray", "()Ljava/lang/Object;"))
|
||||
return true;
|
||||
|
||||
if (gmID(g, araddid, "ArrayAdd", "(Ljava/lang/Object;ILjava/lang/Object;)Z"))
|
||||
return true;
|
||||
|
||||
if (gmID(g, insertid, "CollInsert", "(Ljava/lang/Object;)Z"))
|
||||
return true;
|
||||
|
||||
} else if (mode == MODE_DELETE)
|
||||
if (gmID(g, deleteid, "CollDelete", "(Z)J"))
|
||||
return true;
|
||||
|
||||
return gmID(g, rewindid, "Rewind", "()Z");
|
||||
} // end of GetMethodId
|
||||
|
||||
/***********************************************************************/
|
||||
/* MakeObject. */
|
||||
/***********************************************************************/
|
||||
jobject JMgoConn::MakeObject(PGLOBAL g, PCOL colp, bool&error )
|
||||
{
|
||||
jclass cls;
|
||||
jmethodID cns = nullptr; // Constructor
|
||||
jobject val = nullptr;
|
||||
PVAL valp = colp->GetValue();
|
||||
|
||||
error = false;
|
||||
|
||||
if (valp->IsNull())
|
||||
return NULL;
|
||||
|
||||
try {
|
||||
switch (valp->GetType()) {
|
||||
case TYPE_STRING:
|
||||
val = env->NewStringUTF(valp->GetCharValue());
|
||||
break;
|
||||
case TYPE_INT:
|
||||
case TYPE_SHORT:
|
||||
cls = env->FindClass("java/lang/Integer");
|
||||
cns = env->GetMethodID(cls, "<init>", "(I)V");
|
||||
val = env->NewObject(cls, cns, valp->GetIntValue());
|
||||
break;
|
||||
case TYPE_TINY:
|
||||
cls = env->FindClass("java/lang/Boolean");
|
||||
cns = env->GetMethodID(cls, "<init>", "(Z)V");
|
||||
val = env->NewObject(cls, cns, (valp->GetIntValue() != 0));
|
||||
break;
|
||||
case TYPE_BIGINT:
|
||||
cls = env->FindClass("java/lang/Long");
|
||||
cns = env->GetMethodID(cls, "<init>", "(J)V");
|
||||
val = env->NewObject(cls, cns, valp->GetBigintValue());
|
||||
break;
|
||||
case TYPE_DOUBLE:
|
||||
cls = env->FindClass("java/lang/Double");
|
||||
cns = env->GetMethodID(cls, "<init>", "(D)V");
|
||||
val = env->NewObject(cls, cns, valp->GetFloatValue());
|
||||
break;
|
||||
default:
|
||||
sprintf(g->Message, "Cannot make object from %d type", valp->GetType());
|
||||
error = true;
|
||||
break;
|
||||
} // endswitch Type
|
||||
|
||||
} catch (...) {
|
||||
sprintf(g->Message, "Cannot make object from %s value", colp->GetName());
|
||||
error = true;
|
||||
} // end try/catch
|
||||
|
||||
return val;
|
||||
} // end of MakeObject
|
||||
|
||||
/***********************************************************************/
|
||||
/* MakeDoc. */
|
||||
/***********************************************************************/
|
||||
jobject JMgoConn::MakeDoc(PGLOBAL g, PJNCOL jcp)
|
||||
{
|
||||
bool error = false;
|
||||
jobject parent, child, val;
|
||||
jstring jkey;
|
||||
|
||||
if (jcp->Array)
|
||||
parent = env->CallObjectMethod(job, mkarid);
|
||||
else
|
||||
parent = env->CallObjectMethod(job, mkdocid);
|
||||
|
||||
for (PJKC kp = jcp->Klist; kp; kp = kp->Next)
|
||||
if (kp->Jncolp) {
|
||||
if (!(child = MakeDoc(g, kp->Jncolp)))
|
||||
return NULL;
|
||||
|
||||
if (!jcp->Array) {
|
||||
jkey = env->NewStringUTF(kp->Key);
|
||||
|
||||
if (env->CallBooleanMethod(job, docaddid, parent, jkey, child))
|
||||
return NULL;
|
||||
|
||||
env->DeleteLocalRef(jkey);
|
||||
} else
|
||||
if (env->CallBooleanMethod(job, araddid, parent, kp->N, child))
|
||||
return NULL;
|
||||
|
||||
} else {
|
||||
if (!(val = MakeObject(g, kp->Colp, error))) {
|
||||
if (error)
|
||||
return NULL;
|
||||
|
||||
} else if (!jcp->Array) {
|
||||
jkey = env->NewStringUTF(kp->Key);
|
||||
|
||||
if (env->CallBooleanMethod(job, docaddid, parent, jkey, val))
|
||||
return NULL;
|
||||
|
||||
env->DeleteLocalRef(jkey);
|
||||
} else if (env->CallBooleanMethod(job, araddid, parent, kp->N, val)) {
|
||||
if (Check(-1))
|
||||
sprintf(g->Message, "ArrayAdd: %s", Msg);
|
||||
else
|
||||
sprintf(g->Message, "ArrayAdd: unknown error");
|
||||
|
||||
return NULL;
|
||||
} // endif ArrayAdd
|
||||
|
||||
} // endif Jncolp
|
||||
|
||||
return parent;
|
||||
} // end of MakeDoc
|
||||
|
||||
/***********************************************************************/
|
||||
/* Insert a new document in the collation. */
|
||||
/***********************************************************************/
|
||||
int JMgoConn::DocWrite(PGLOBAL g)
|
||||
{
|
||||
jobject doc;
|
||||
|
||||
if (!Fpc || !(doc = MakeDoc(g, Fpc)))
|
||||
return RC_FX;
|
||||
|
||||
if (env->CallBooleanMethod(job, insertid, doc)) {
|
||||
if (Check(-1))
|
||||
sprintf(g->Message, "CollInsert: %s", Msg);
|
||||
else
|
||||
sprintf(g->Message, "CollInsert: unknown error");
|
||||
|
||||
return RC_FX;
|
||||
} // endif Insert
|
||||
|
||||
return RC_OK;
|
||||
} // end of DocWrite
|
||||
|
||||
/***********************************************************************/
|
||||
/* Update the current document from the collection. */
|
||||
/***********************************************************************/
|
||||
int JMgoConn::DocUpdate(PGLOBAL g, PTDB tdbp)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
bool error;
|
||||
PCOL colp;
|
||||
jstring jkey;
|
||||
jobject val, upd, updlist = env->CallObjectMethod(job, mkdocid);
|
||||
|
||||
// Make the list of changes to do
|
||||
for (colp = tdbp->GetSetCols(); colp; colp = colp->GetNext()) {
|
||||
jkey = env->NewStringUTF(colp->GetJpath(g, false));
|
||||
val = MakeObject(g, colp, error);
|
||||
|
||||
if (error)
|
||||
return RC_FX;
|
||||
|
||||
if (env->CallBooleanMethod(job, docaddid, updlist, jkey, val))
|
||||
return NULL;
|
||||
|
||||
env->DeleteLocalRef(jkey);
|
||||
} // endfor colp
|
||||
|
||||
// Make the update parameter
|
||||
upd = env->CallObjectMethod(job, mkdocid);
|
||||
jkey = env->NewStringUTF("$set");
|
||||
|
||||
if (env->CallBooleanMethod(job, docaddid, upd, jkey, updlist))
|
||||
return NULL;
|
||||
|
||||
env->DeleteLocalRef(jkey);
|
||||
|
||||
jlong ar = env->CallLongMethod(job, updateid, upd);
|
||||
|
||||
if (trace)
|
||||
htrc("DocUpdate: ar = %ld\n", ar);
|
||||
|
||||
if (Check((int)ar)) {
|
||||
sprintf(g->Message, "CollUpdate: %s", Msg);
|
||||
rc = RC_FX;
|
||||
} // endif ar
|
||||
|
||||
return rc;
|
||||
} // end of DocUpdate
|
||||
|
||||
/***********************************************************************/
|
||||
/* Remove all or only the current document from the collection. */
|
||||
/***********************************************************************/
|
||||
int JMgoConn::DocDelete(PGLOBAL g, bool all)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
jlong ar = env->CallLongMethod(job, deleteid, all);
|
||||
|
||||
if (trace)
|
||||
htrc("DocDelete: ar = %ld\n", ar);
|
||||
|
||||
if (Check((int)ar)) {
|
||||
sprintf(g->Message, "CollDelete: %s", Msg);
|
||||
rc = RC_FX;
|
||||
} // endif ar
|
||||
|
||||
return rc;
|
||||
} // end of DocDelete
|
||||
|
||||
/***********************************************************************/
|
||||
/* Rewind the collection. */
|
||||
/***********************************************************************/
|
||||
bool JMgoConn::Rewind(void)
|
||||
{
|
||||
return env->CallBooleanMethod(job, rewindid);
|
||||
} // end of Rewind
|
||||
|
||||
/***********************************************************************/
|
||||
/* Retrieve the column string value from the document. */
|
||||
/***********************************************************************/
|
||||
PSZ JMgoConn::GetColumnValue(PSZ path)
|
||||
{
|
||||
PGLOBAL& g = m_G;
|
||||
PSZ fld = NULL;
|
||||
jstring fn, jn = nullptr;
|
||||
|
||||
if (!path || (jn = env->NewStringUTF(path)) == nullptr) {
|
||||
sprintf(g->Message, "Fail to allocate jstring %s", SVP(path));
|
||||
throw (int)TYPE_AM_MGO;
|
||||
} // endif name
|
||||
|
||||
if (!gmID(g, objfldid, "GetField", "(Ljava/lang/String;)Ljava/lang/String;")) {
|
||||
fn = (jstring)env->CallObjectMethod(job, objfldid, jn);
|
||||
|
||||
if (fn)
|
||||
fld = (PSZ)env->GetStringUTFChars(fn, (jboolean)false);
|
||||
|
||||
} // endif objfldid
|
||||
|
||||
return fld;
|
||||
} // end of GetColumnValue
|
||||
|
136
storage/connect/jmgoconn.h
Normal file
136
storage/connect/jmgoconn.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/***********************************************************************/
|
||||
/* JMgoConn.h : header file for the MongoDB connection classes. */
|
||||
/***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
/* Java interface. */
|
||||
/***********************************************************************/
|
||||
#include "javaconn.h"
|
||||
|
||||
// Java connection to a MongoDB data source
|
||||
class TDBJMG;
|
||||
class JMGCOL;
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include MongoDB library header files. */
|
||||
/***********************************************************************/
|
||||
typedef class JNCOL *PJNCOL;
|
||||
typedef class MGODEF *PMGODEF;
|
||||
typedef class TDBJMG *PTDBJMG;
|
||||
typedef class JMGCOL *PJMGCOL;
|
||||
|
||||
#if 0
|
||||
/***********************************************************************/
|
||||
/* Class used to get the columns of a mongo collection. */
|
||||
/***********************************************************************/
|
||||
class MGODISC : public BLOCK {
|
||||
public:
|
||||
// Constructor
|
||||
MGODISC(PGLOBAL g, int *lg);
|
||||
|
||||
// Functions
|
||||
int GetColumns(PGLOBAL g, char *db, PTOS topt);
|
||||
bool FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc,
|
||||
char *pcn, char *pfmt, int i, int k, bool b);
|
||||
|
||||
// Members
|
||||
BCOL bcol;
|
||||
PBCOL bcp, fbcp, pbcp;
|
||||
PMGODEF tdp;
|
||||
TDBJMG *tmgp;
|
||||
int *length;
|
||||
int n, k, lvl;
|
||||
bool all;
|
||||
}; // end of MGODISC
|
||||
#endif // 0
|
||||
|
||||
typedef struct JKCOL {
|
||||
JKCOL *Next;
|
||||
PJNCOL Jncolp;
|
||||
PCOL Colp;
|
||||
char *Key;
|
||||
int N;
|
||||
} *PJKC;
|
||||
|
||||
/***********************************************************************/
|
||||
/* Used when inserting values in a MongoDB collection. */
|
||||
/***********************************************************************/
|
||||
class JNCOL : public BLOCK {
|
||||
public:
|
||||
// Constructor
|
||||
JNCOL(bool ar) { Klist = NULL; Array = ar; }
|
||||
|
||||
// Methods
|
||||
void AddCol(PGLOBAL g, PCOL colp, PSZ jp);
|
||||
|
||||
//Members
|
||||
PJKC Klist;
|
||||
bool Array;
|
||||
}; // end of JNCOL;
|
||||
|
||||
/***********************************************************************/
|
||||
/* JMgoConn class. */
|
||||
/***********************************************************************/
|
||||
class JMgoConn : public JAVAConn {
|
||||
friend class TDBJMG;
|
||||
//friend class TDBXJDC;
|
||||
//friend PQRYRES GetColumnInfo(PGLOBAL, char*&, char *, int, PVBLK&);
|
||||
private:
|
||||
JMgoConn(); // Standard (unused) constructor
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
JMgoConn(PGLOBAL g, PCSZ collname, PCSZ wrapper);
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
virtual void AddJars(PSTRG jpop, char sep);
|
||||
virtual bool Connect(PJPARM sop);
|
||||
virtual bool MakeCursor(PGLOBAL g, PTDB tdbp, PCSZ options, PCSZ filter, bool pipe);
|
||||
// PQRYRES AllocateResult(PGLOBAL g, TDBEXT *tdbp, int n);
|
||||
|
||||
// Attributes
|
||||
public:
|
||||
// virtual int GetMaxValue(int infotype);
|
||||
|
||||
public:
|
||||
// Operations
|
||||
virtual int Fetch(int pos = 0);
|
||||
virtual PSZ GetColumnValue(PSZ name);
|
||||
|
||||
int CollSize(PGLOBAL g);
|
||||
bool FindCollection(PCSZ query, PCSZ proj);
|
||||
bool AggregateCollection(PCSZ pipeline);
|
||||
void MakeColumnGroups(PGLOBAL g, PTDB tdbp);
|
||||
bool GetMethodId(PGLOBAL g, MODE mode);
|
||||
jobject MakeObject(PGLOBAL g, PCOL colp, bool& error);
|
||||
jobject MakeDoc(PGLOBAL g, PJNCOL jcp);
|
||||
int DocWrite(PGLOBAL g);
|
||||
int DocUpdate(PGLOBAL g, PTDB tdbp);
|
||||
int DocDelete(PGLOBAL g, bool all);
|
||||
bool Rewind(void);
|
||||
PSZ GetDocument(void);
|
||||
|
||||
protected:
|
||||
// Members
|
||||
PCSZ CollName; // The collation name
|
||||
jmethodID gcollid; // The GetCollection method ID
|
||||
jmethodID countid; // The GetCollSize method ID
|
||||
jmethodID fcollid; // The FindColl method ID
|
||||
jmethodID acollid; // The AggregateColl method ID
|
||||
jmethodID readid; // The ReadNext method ID
|
||||
jmethodID fetchid; // The Fetch method ID
|
||||
jmethodID rewindid; // The Rewind method ID
|
||||
jmethodID getdocid; // The GetDoc method ID
|
||||
jmethodID objfldid; // The ObjectField method ID
|
||||
jmethodID mkdocid; // The MakeDocument method ID
|
||||
jmethodID docaddid; // The DocAdd method ID
|
||||
jmethodID mkarid; // The MakeArray method ID
|
||||
jmethodID araddid; // The ArrayAdd method ID
|
||||
jmethodID insertid; // The CollInsert method ID
|
||||
jmethodID updateid; // The CollUpdate method ID
|
||||
jmethodID deleteid; // The CollDelete method ID
|
||||
PJNCOL Fpc; // To JNCOL classes
|
||||
int m_Fetch;
|
||||
int m_Version; // Java driver version (2 or 3)
|
||||
}; // end of JMgoConn class definition
|
99
storage/connect/mongo.cpp
Normal file
99
storage/connect/mongo.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/************** mongo C++ Program Source Code File (.CPP) **************/
|
||||
/* PROGRAM NAME: mongo Version 1.0 */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2017 */
|
||||
/* These programs are the MGODEF class execution routines. */
|
||||
/***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include relevant sections of the MariaDB header file. */
|
||||
/***********************************************************************/
|
||||
#include <my_global.h>
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include application header files: */
|
||||
/* global.h is header containing all global declarations. */
|
||||
/* plgdbsem.h is header containing the DB application declarations. */
|
||||
/***********************************************************************/
|
||||
#include "global.h"
|
||||
#include "plgdbsem.h"
|
||||
#include "xtable.h"
|
||||
#include "tabext.h"
|
||||
#if defined(MONGO_SUPPORT)
|
||||
#include "tabmgo.h"
|
||||
#endif // MONGO_SUPPORT
|
||||
#if defined(JDBC_SUPPORT)
|
||||
#include "tabjmg.h"
|
||||
#endif // JDBC_SUPPORT
|
||||
|
||||
/* -------------------------- Class MGODEF --------------------------- */
|
||||
|
||||
MGODEF::MGODEF(void)
|
||||
{
|
||||
Driver = NULL;
|
||||
Uri = NULL;
|
||||
Colist = NULL;
|
||||
Filter = NULL;
|
||||
Level = 0;
|
||||
Base = 0;
|
||||
Version = 0;
|
||||
Pipe = false;
|
||||
} // end of MGODEF constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* DefineAM: define specific AM block values. */
|
||||
/***********************************************************************/
|
||||
bool MGODEF::DefineAM(PGLOBAL g, LPCSTR, int poff)
|
||||
{
|
||||
if (EXTDEF::DefineAM(g, "MGO", poff))
|
||||
return true;
|
||||
else if (!Tabschema)
|
||||
Tabschema = GetStringCatInfo(g, "Dbname", "*");
|
||||
|
||||
# if !defined(JDBC_SUPPORT)
|
||||
Driver = "C";
|
||||
#elif !defined(MONGO_SUPPORT)
|
||||
Driver = "JAVA";
|
||||
#else
|
||||
Driver = GetStringCatInfo(g, "Driver", "C");
|
||||
#endif
|
||||
Uri = GetStringCatInfo(g, "Connect", "mongodb://localhost:27017");
|
||||
Colist = GetStringCatInfo(g, "Colist", NULL);
|
||||
Filter = GetStringCatInfo(g, "Filter", NULL);
|
||||
Base = GetIntCatInfo("Base", 0) ? 1 : 0;
|
||||
Version = GetIntCatInfo("Version", 3);
|
||||
|
||||
if (Version == 2)
|
||||
Wrapname = GetStringCatInfo(g, "Wrapper", "Mongo2Interface");
|
||||
else
|
||||
Wrapname = GetStringCatInfo(g, "Wrapper", "Mongo3Interface");
|
||||
|
||||
Pipe = GetBoolCatInfo("Pipeline", false);
|
||||
return false;
|
||||
} // end of DefineAM
|
||||
|
||||
/***********************************************************************/
|
||||
/* GetTable: makes a new Table Description Block. */
|
||||
/***********************************************************************/
|
||||
PTDB MGODEF::GetTable(PGLOBAL g, MODE m)
|
||||
{
|
||||
if (Catfunc == FNC_COL) {
|
||||
#if defined(MONGO_SUPPORT)
|
||||
if (Driver && toupper(*Driver) == 'C')
|
||||
return new(g)TDBGOL(this);
|
||||
#endif // MONGO_SUPPORT
|
||||
strcpy(g->Message, "No column find for Java Mongo yet");
|
||||
return NULL;
|
||||
} // endif Catfunc
|
||||
|
||||
#if defined(MONGO_SUPPORT)
|
||||
if (Driver && toupper(*Driver) == 'C')
|
||||
return new(g) TDBMGO(this);
|
||||
#endif // MONGO_SUPPORT
|
||||
#if defined(JDBC_SUPPORT)
|
||||
return new(g) TDBJMG(this);
|
||||
#else // !JDBC_SUPPORT
|
||||
strcpy(g->Message, "No MONGO nor Java support");
|
||||
return NULL;
|
||||
#endif // !JDBC_SUPPORT
|
||||
} // end of GetTable
|
||||
|
62
storage/connect/mongo.h
Normal file
62
storage/connect/mongo.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/**************** mongo H Declares Source Code File (.H) ***************/
|
||||
/* Name: mongo.h Version 1.0 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2017 */
|
||||
/* */
|
||||
/* This file contains the common MongoDB classes declares. */
|
||||
/***********************************************************************/
|
||||
#ifndef __MONGO_H
|
||||
#define __MONGO_H
|
||||
|
||||
#include "osutil.h"
|
||||
#include "block.h"
|
||||
#include "colblk.h"
|
||||
|
||||
typedef class MGODEF *PMGODEF;
|
||||
|
||||
typedef struct _bncol {
|
||||
struct _bncol *Next;
|
||||
char *Name;
|
||||
char *Fmt;
|
||||
int Type;
|
||||
int Len;
|
||||
int Scale;
|
||||
bool Cbn;
|
||||
bool Found;
|
||||
} BCOL, *PBCOL;
|
||||
|
||||
/***********************************************************************/
|
||||
/* MongoDB table. */
|
||||
/***********************************************************************/
|
||||
class DllExport MGODEF : public EXTDEF { /* Table description */
|
||||
friend class TDBMGO;
|
||||
friend class TDBJMG;
|
||||
friend class TDBGOL;
|
||||
friend class MGOFAM;
|
||||
friend class MGODISC;
|
||||
friend PQRYRES MGOColumns(PGLOBAL, PCSZ, PCSZ, PTOS, bool);
|
||||
public:
|
||||
// Constructor
|
||||
MGODEF(void);
|
||||
|
||||
// Implementation
|
||||
virtual const char *GetType(void) { return "MONGO"; }
|
||||
|
||||
// Methods
|
||||
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
|
||||
virtual PTDB GetTable(PGLOBAL g, MODE m);
|
||||
|
||||
protected:
|
||||
// Members
|
||||
PCSZ Driver; /* MongoDB Driver (C or JAVA) */
|
||||
PCSZ Uri; /* MongoDB connection URI */
|
||||
PSZ Wrapname; /* Java wrapper name */
|
||||
PCSZ Colist; /* Options list */
|
||||
PCSZ Filter; /* Filtering query */
|
||||
int Level; /* Used for catalog table */
|
||||
int Base; /* The array index base */
|
||||
int Version; /* The Java driver version */
|
||||
bool Pipe; /* True is Colist is a pipeline */
|
||||
}; // end of MGODEF
|
||||
|
||||
#endif // __MONGO_H
|
@@ -1,7 +1,7 @@
|
||||
/************ MONGO FAM C++ Program Source Code File (.CPP) ************/
|
||||
/* PROGRAM NAME: mongofam.cpp */
|
||||
/* ------------- */
|
||||
/* Version 1.1 */
|
||||
/* Version 1.3 */
|
||||
/* */
|
||||
/* COPYRIGHT: */
|
||||
/* ---------- */
|
||||
@@ -17,26 +17,6 @@
|
||||
/* Include relevant sections of the System header files. */
|
||||
/***********************************************************************/
|
||||
#include "my_global.h"
|
||||
#if defined(__WIN__)
|
||||
//#include <io.h>
|
||||
//#include <fcntl.h>
|
||||
//#include <errno.h>
|
||||
#if defined(__BORLANDC__)
|
||||
#define __MFC_COMPAT__ // To define min/max as macro
|
||||
#endif // __BORLANDC__
|
||||
//#include <windows.h>
|
||||
#else // !__WIN__
|
||||
#if defined(UNIX) || defined(UNIV_LINUX)
|
||||
//#include <errno.h>
|
||||
#include <unistd.h>
|
||||
//#if !defined(sun) // Sun has the ftruncate fnc.
|
||||
//#define USETEMP // Force copy mode for DELETE
|
||||
//#endif // !sun
|
||||
#else // !UNIX
|
||||
//#include <io.h>
|
||||
#endif // !UNIX
|
||||
//#include <fcntl.h>
|
||||
#endif // !__WIN__
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include application header files: */
|
||||
@@ -54,20 +34,8 @@
|
||||
|
||||
#if defined(UNIX) || defined(UNIV_LINUX)
|
||||
#include "osutil.h"
|
||||
//#define _fileno fileno
|
||||
//#define _O_RDONLY O_RDONLY
|
||||
#endif
|
||||
|
||||
// Required to initialize libmongoc's internals
|
||||
void mongo_init(bool init)
|
||||
{
|
||||
if (init)
|
||||
mongoc_init();
|
||||
else
|
||||
mongoc_cleanup();
|
||||
|
||||
} // end of mongo_init
|
||||
|
||||
/* --------------------------- Class MGOFAM -------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -75,88 +43,39 @@ void mongo_init(bool init)
|
||||
/***********************************************************************/
|
||||
MGOFAM::MGOFAM(PJDEF tdp) : DOSFAM((PDOSDEF)NULL)
|
||||
{
|
||||
Client = NULL;
|
||||
Database = NULL;
|
||||
Collection = NULL;
|
||||
Cursor = NULL;
|
||||
Query = NULL;
|
||||
Opts = NULL;
|
||||
Cmgp = NULL;
|
||||
Pcg.Tdbp = NULL;
|
||||
|
||||
if (tdp) {
|
||||
Pcg.Uristr = tdp->Uri;
|
||||
Pcg.Db_name = tdp->Schema;
|
||||
Pcg.Coll_name = tdp->Collname;
|
||||
Pcg.Options = tdp->Options;
|
||||
Pcg.Filter = tdp->Filter;
|
||||
Pcg.Pipe = tdp->Pipe && tdp->Options != NULL;
|
||||
} else {
|
||||
Pcg.Uristr = NULL;
|
||||
Pcg.Db_name = NULL;
|
||||
Pcg.Coll_name = NULL;
|
||||
Pcg.Options = NULL;
|
||||
Pcg.Filter = NULL;
|
||||
Pcg.Pipe = false;
|
||||
} // endif tdp
|
||||
|
||||
To_Fbt = NULL;
|
||||
Mode = MODE_ANY;
|
||||
Uristr = tdp->Uri;
|
||||
Db_name = tdp->Schema;
|
||||
Coll_name = tdp->Collname;
|
||||
Options = tdp->Options;
|
||||
Filter = tdp->Filter;
|
||||
Done = false;
|
||||
Pipe = tdp->Pipe;
|
||||
Lrecl = tdp->Lrecl + tdp->Ending;
|
||||
} // end of MGOFAM standard constructor
|
||||
|
||||
MGOFAM::MGOFAM(PMGOFAM tdfp) : DOSFAM(tdfp)
|
||||
{
|
||||
Client = tdfp->Client;
|
||||
Database = NULL;
|
||||
Collection = tdfp->Collection;
|
||||
Cursor = tdfp->Cursor;
|
||||
Query = tdfp->Query;
|
||||
Opts = tdfp->Opts;
|
||||
Pcg = tdfp->Pcg;
|
||||
To_Fbt = tdfp->To_Fbt;
|
||||
Mode = tdfp->Mode;
|
||||
Uristr = tdfp->Uristr;
|
||||
Db_name = tdfp->Db_name;
|
||||
Coll_name = tdfp->Coll_name;
|
||||
Options = tdfp->Options;
|
||||
Filter = NULL;
|
||||
Done = tdfp->Done;
|
||||
Pipe = tdfp->Pipe;
|
||||
} // end of MGOFAM copy constructor
|
||||
|
||||
#if 0
|
||||
void *MGOFAM::mgo_alloc(size_t n)
|
||||
{
|
||||
char *mst = (char*)PlgDBSubAlloc(G, NULL, n + sizeof(size_t));
|
||||
|
||||
if (mst) {
|
||||
*(size_t*)mst = n;
|
||||
return mst + sizeof(size_t);
|
||||
} // endif mst
|
||||
|
||||
return NULL;
|
||||
} // end of mgo_alloc
|
||||
|
||||
void *MGOFAM::mgo_calloc(size_t n, size_t sz)
|
||||
{
|
||||
void *m = mgo_alloc(n * sz);
|
||||
|
||||
if (m)
|
||||
memset(m, 0, n * sz);
|
||||
|
||||
return m;
|
||||
} // end of mgo_calloc
|
||||
|
||||
void *MGOFAM::mgo_realloc(void *m, size_t n)
|
||||
{
|
||||
if (!m)
|
||||
return n ? mgo_alloc(n) : NULL;
|
||||
|
||||
size_t *osz = (size_t*)((char*)m - sizeof(size_t));
|
||||
|
||||
if (n > *osz) {
|
||||
void *nwm = mgo_alloc(n);
|
||||
|
||||
if (nwm)
|
||||
memcpy(nwm, m, *osz);
|
||||
|
||||
return nwm;
|
||||
} else {
|
||||
*osz = n;
|
||||
return m;
|
||||
} // endif n
|
||||
|
||||
} // end of mgo_realloc
|
||||
#endif // 0
|
||||
|
||||
/***********************************************************************/
|
||||
/* Reset: reset position values at the beginning of file. */
|
||||
/***********************************************************************/
|
||||
@@ -175,47 +94,16 @@ int MGOFAM::GetFileLength(PGLOBAL g)
|
||||
} // end of GetFileLength
|
||||
|
||||
/***********************************************************************/
|
||||
/* Cardinality: returns table cardinality in number of rows. */
|
||||
/* Cardinality: returns the number of documents in the collection. */
|
||||
/* This function can be called with a null argument to test the */
|
||||
/* availability of Cardinality implementation (1 yes, 0 no). */
|
||||
/***********************************************************************/
|
||||
int MGOFAM::Cardinality(PGLOBAL g)
|
||||
{
|
||||
if (g) {
|
||||
if (!Init(g)) {
|
||||
bson_t *query;
|
||||
const char *jf = NULL;
|
||||
|
||||
if (Pipe)
|
||||
return 10;
|
||||
else if (Filter)
|
||||
jf = Filter;
|
||||
|
||||
if (jf) {
|
||||
query = bson_new_from_json((const uint8_t *)jf, -1, &Error);
|
||||
|
||||
if (!query) {
|
||||
htrc("Wrong filter: %s", Error.message);
|
||||
return 10;
|
||||
} // endif Query
|
||||
|
||||
} else
|
||||
query = bson_new();
|
||||
|
||||
int64_t card = (int)mongoc_collection_count(Collection,
|
||||
MONGOC_QUERY_NONE, query, 0, 0, NULL, &Error);
|
||||
|
||||
if (card < 0)
|
||||
sprintf(g->Message, "Collection count: %s", Error.message);
|
||||
|
||||
bson_destroy(query);
|
||||
return card;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
} else
|
||||
if (!g)
|
||||
return 1;
|
||||
|
||||
return (!Init(g)) ? Cmgp->CollSize(g) : 0;
|
||||
} // end of Cardinality
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -234,268 +122,22 @@ bool MGOFAM::Init(PGLOBAL g)
|
||||
if (Done)
|
||||
return false;
|
||||
|
||||
Uri = mongoc_uri_new(Uristr);
|
||||
/*********************************************************************/
|
||||
/* Open an C connection for this table. */
|
||||
/*********************************************************************/
|
||||
if (!Cmgp) {
|
||||
Pcg.Tdbp = Tdbp;
|
||||
Cmgp = new(g) CMgoConn(g, &Pcg);
|
||||
} else if (Cmgp->IsConnected())
|
||||
Cmgp->Close();
|
||||
|
||||
if (!Uri) {
|
||||
sprintf(g->Message, "Failed to parse URI: \"%s\"", Uristr);
|
||||
if (Cmgp->Connect(g))
|
||||
return true;
|
||||
} // endif Uri
|
||||
|
||||
// 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);
|
||||
//Client = mongoc_client_new(uristr);
|
||||
|
||||
if (!Client) {
|
||||
sprintf(g->Message, "Failed to get Client");
|
||||
return true;
|
||||
} // endif Client
|
||||
|
||||
//mongoc_client_set_error_api(Client, 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_set_appname(Client, "Connect");
|
||||
|
||||
// Get a handle on the database Db_name and collection Coll_name
|
||||
// Database = mongoc_client_get_database(Client, Db_name);
|
||||
// Collection = mongoc_database_get_collection(Database, Coll_name);
|
||||
Collection = mongoc_client_get_collection(Client, Db_name, Coll_name);
|
||||
|
||||
if (!Collection) {
|
||||
sprintf(g->Message, "Failed to get Collection %s.%s", Db_name, Coll_name);
|
||||
return true;
|
||||
} // endif Collection
|
||||
|
||||
Done = true;
|
||||
return false;
|
||||
} // end of Init
|
||||
|
||||
/***********************************************************************/
|
||||
/* OpenDB: Data Base open routine for MONGO access method. */
|
||||
/***********************************************************************/
|
||||
bool MGOFAM::MakeCursor(PGLOBAL g)
|
||||
{
|
||||
const char *p;
|
||||
bool b = false, id = (Mode != MODE_READ), all = false;
|
||||
uint len;
|
||||
PSZ jp;
|
||||
PCOL cp;
|
||||
PSTRG s = NULL;
|
||||
|
||||
if (Options && !stricmp(Options, "all")) {
|
||||
Options = NULL;
|
||||
all = true;
|
||||
} // endif Options
|
||||
|
||||
for (cp = Tdbp->GetColumns(); cp; cp = cp->GetNext())
|
||||
if (!strcmp(cp->GetName(), "_id"))
|
||||
id = true;
|
||||
else if (cp->GetFmt() && !strcmp(cp->GetFmt(), "*") && !Options)
|
||||
all = true;
|
||||
|
||||
if (Pipe) {
|
||||
if (trace)
|
||||
htrc("Pipeline: %s\n", Options);
|
||||
|
||||
p = strrchr(Options, ']');
|
||||
|
||||
if (!p) {
|
||||
strcpy(g->Message, "Missing ] in pipeline");
|
||||
return true;
|
||||
} else
|
||||
*(char*)p = 0;
|
||||
|
||||
s = new(g) STRING(g, 1023, (PSZ)Options);
|
||||
len = s->GetLength();
|
||||
|
||||
if (Tdbp->GetFilter()) {
|
||||
s->Append(",{\"$match\":");
|
||||
|
||||
if (!Tdbp->GetFilter()->MakeSelector(g, s, false)) {
|
||||
s->Append('}');
|
||||
Tdbp->SetFilter(NULL); // Not needed anymore
|
||||
} else {
|
||||
if (((TDBJSN*)Tdbp)->Xcol)
|
||||
Tdbp->SetFilter(NULL); // Incompatible
|
||||
|
||||
htrc("Failed making selector\n");
|
||||
s->Truncate(len);
|
||||
} // endif Selector
|
||||
|
||||
} // endif To_Filter
|
||||
|
||||
if (!all) {
|
||||
// Project list
|
||||
len = s->GetLength();
|
||||
|
||||
if (Tdbp->GetColumns()) {
|
||||
s->Append(",{\"$project\":{\"");
|
||||
|
||||
if (!id)
|
||||
s->Append("_id\":0,\"");
|
||||
|
||||
for (PCOL cp = Tdbp->GetColumns(); cp; cp = cp->GetNext()) {
|
||||
if (b)
|
||||
s->Append(",\"");
|
||||
else
|
||||
b = true;
|
||||
|
||||
if ((jp = ((PJCOL)cp)->GetJpath(g, true)))
|
||||
s->Append(jp);
|
||||
else {
|
||||
s->Truncate(len);
|
||||
goto nop;
|
||||
} // endif Jpath
|
||||
|
||||
s->Append("\":1");
|
||||
} // endfor cp
|
||||
|
||||
} else
|
||||
s->Append(",{\"$project\":{\"_id\":1}}");
|
||||
|
||||
s->Append("}}");
|
||||
} // endif all
|
||||
|
||||
nop:
|
||||
s->Append("]}");
|
||||
s->Resize(s->GetLength() + 1);
|
||||
p = s->GetStr();
|
||||
|
||||
if (trace)
|
||||
htrc("New Pipeline: %s\n", p);
|
||||
|
||||
Query = bson_new_from_json((const uint8_t *)p, -1, &Error);
|
||||
|
||||
if (!Query) {
|
||||
sprintf(g->Message, "Wrong pipeline: %s", Error.message);
|
||||
return true;
|
||||
} // endif Query
|
||||
|
||||
Cursor = mongoc_collection_aggregate(Collection, MONGOC_QUERY_NONE,
|
||||
Query, NULL, NULL);
|
||||
|
||||
if (mongoc_cursor_error(Cursor, &Error)) {
|
||||
sprintf(g->Message, "Mongo aggregate Failure: %s", Error.message);
|
||||
return true;
|
||||
} // endif cursor
|
||||
|
||||
} else {
|
||||
if (Filter || Tdbp->GetFilter()) {
|
||||
if (trace) {
|
||||
if (Filter)
|
||||
htrc("Filter: %s\n", Filter);
|
||||
|
||||
if (Tdbp->GetFilter()) {
|
||||
char buf[512];
|
||||
|
||||
Tdbp->GetFilter()->Prints(g, buf, 511);
|
||||
htrc("To_Filter: %s\n", buf);
|
||||
} // endif To_Filter
|
||||
|
||||
} // endif trace
|
||||
|
||||
s = new(g) STRING(g, 1023, (PSZ)Filter);
|
||||
len = s->GetLength();
|
||||
|
||||
if (Tdbp->GetFilter()) {
|
||||
if (Filter)
|
||||
s->Append(',');
|
||||
|
||||
if (Tdbp->GetFilter()->MakeSelector(g, s, false)) {
|
||||
if (((TDBJSN*)Tdbp)->Xcol)
|
||||
Tdbp->SetFilter(NULL); // Incompatible
|
||||
|
||||
htrc("Cannot make selector\n");
|
||||
s->Truncate(len);
|
||||
} else
|
||||
Tdbp->SetFilter(NULL); // Not needed anymore
|
||||
|
||||
} // endif To_Filter
|
||||
|
||||
if (trace)
|
||||
htrc("selector: %s\n", s->GetStr());
|
||||
|
||||
s->Resize(s->GetLength() + 1);
|
||||
|
||||
if (s->GetLength()) {
|
||||
Query = bson_new_from_json((const uint8_t *)s->GetStr(), -1, &Error);
|
||||
|
||||
if (!Query) {
|
||||
sprintf(g->Message, "Wrong filter: %s", Error.message);
|
||||
return true;
|
||||
} // endif Query
|
||||
|
||||
} else
|
||||
Query = bson_new();
|
||||
|
||||
} else
|
||||
Query = bson_new();
|
||||
|
||||
if (!all) {
|
||||
if (Options && *Options) {
|
||||
if (trace)
|
||||
htrc("options=%s\n", Options);
|
||||
|
||||
p = Options;
|
||||
} else if (Tdbp->GetColumns()) {
|
||||
// Projection list
|
||||
if (s)
|
||||
s->Set("{\"projection\":{\"");
|
||||
else
|
||||
s = new(g) STRING(g, 511, "{\"projection\":{\"");
|
||||
|
||||
if (!id)
|
||||
s->Append("_id\":0,\"");
|
||||
|
||||
for (PCOL cp = Tdbp->GetColumns(); cp; cp = cp->GetNext()) {
|
||||
if (b)
|
||||
s->Append(",\"");
|
||||
else
|
||||
b = true;
|
||||
|
||||
if ((jp = ((PJCOL)cp)->GetJpath(g, true)))
|
||||
s->Append(jp);
|
||||
else {
|
||||
s->Reset();
|
||||
s->Resize(0);
|
||||
goto nope;
|
||||
} // endif Jpath
|
||||
|
||||
s->Append("\":1");
|
||||
} // endfor cp
|
||||
|
||||
s->Append("}}");
|
||||
s->Resize(s->GetLength() + 1);
|
||||
p = s->GetStr();
|
||||
} else {
|
||||
// count(*) ?
|
||||
p = "{\"projection\":{\"_id\":1}}";
|
||||
} // endif Options
|
||||
|
||||
Opts = bson_new_from_json((const uint8_t *)p, -1, &Error);
|
||||
|
||||
if (!Opts) {
|
||||
sprintf(g->Message, "Wrong options: %s", Error.message);
|
||||
return true;
|
||||
} // endif Opts
|
||||
|
||||
} // endif all
|
||||
|
||||
nope:
|
||||
Cursor = mongoc_collection_find_with_opts(Collection, Query, Opts, NULL);
|
||||
} // endif Pipe
|
||||
|
||||
return false;
|
||||
} // end of MakeCursor
|
||||
|
||||
/***********************************************************************/
|
||||
/* OpenTableFile: Open a MongoDB table. */
|
||||
/***********************************************************************/
|
||||
@@ -503,7 +145,7 @@ bool MGOFAM::OpenTableFile(PGLOBAL g)
|
||||
{
|
||||
Mode = Tdbp->GetMode();
|
||||
|
||||
if (Pipe && Mode != MODE_READ) {
|
||||
if (Pcg.Pipe && Mode != MODE_READ) {
|
||||
strcpy(g->Message, "Pipeline tables are read only");
|
||||
return true;
|
||||
} // endif Pipe
|
||||
@@ -511,20 +153,11 @@ bool MGOFAM::OpenTableFile(PGLOBAL g)
|
||||
if (Init(g))
|
||||
return true;
|
||||
|
||||
if (Mode == MODE_DELETE && !Tdbp->GetNext()) {
|
||||
// Store the number of deleted lines
|
||||
DelRows = Cardinality(g);
|
||||
|
||||
if (Mode == MODE_DELETE && !Tdbp->GetNext())
|
||||
// Delete all documents
|
||||
if (!mongoc_collection_remove(Collection, MONGOC_REMOVE_NONE,
|
||||
Query, NULL, &Error)) {
|
||||
sprintf(g->Message, "Remove all: %s", Error.message);
|
||||
return true;
|
||||
} // endif remove
|
||||
|
||||
} else if (Mode != MODE_INSERT)
|
||||
if (MakeCursor(g))
|
||||
return true;
|
||||
return Cmgp->DocDelete(g);
|
||||
else if (Mode == MODE_INSERT)
|
||||
Cmgp->MakeColumnGroups(g);
|
||||
|
||||
return false;
|
||||
} // end of OpenTableFile
|
||||
@@ -589,91 +222,18 @@ int MGOFAM::SkipRecord(PGLOBAL g, bool header)
|
||||
return RC_OK; // Dummy
|
||||
} // end of SkipRecord
|
||||
|
||||
/***********************************************************************/
|
||||
/* Use to trace restaurants document contains. */
|
||||
/***********************************************************************/
|
||||
void MGOFAM::ShowDocument(bson_iter_t *iter, const bson_t *doc, const char *k)
|
||||
{
|
||||
|
||||
if (!doc || bson_iter_init(iter, doc)) {
|
||||
const char *key;
|
||||
|
||||
while (bson_iter_next(iter)) {
|
||||
key = bson_iter_key(iter);
|
||||
htrc("Found element key: \"%s\"\n", key);
|
||||
|
||||
if (BSON_ITER_HOLDS_UTF8(iter))
|
||||
htrc("%s.%s=\"%s\"\n", k, key, bson_iter_utf8(iter, NULL));
|
||||
else if (BSON_ITER_HOLDS_INT32(iter))
|
||||
htrc("%s.%s=%d\n", k, key, bson_iter_int32(iter));
|
||||
else if (BSON_ITER_HOLDS_INT64(iter))
|
||||
htrc("%s.%s=%lld\n", k, key, bson_iter_int64(iter));
|
||||
else if (BSON_ITER_HOLDS_DOUBLE(iter))
|
||||
htrc("%s.%s=%g\n", k, key, bson_iter_double(iter));
|
||||
else if (BSON_ITER_HOLDS_DATE_TIME(iter))
|
||||
htrc("%s.%s=date(%lld)\n", k, key, bson_iter_date_time(iter));
|
||||
else if (BSON_ITER_HOLDS_OID(iter)) {
|
||||
char str[25];
|
||||
|
||||
bson_oid_to_string(bson_iter_oid(iter), str);
|
||||
htrc("%s.%s=%s\n", k, key, str);
|
||||
} else if (BSON_ITER_HOLDS_DECIMAL128(iter)) {
|
||||
char *str = NULL;
|
||||
bson_decimal128_t dec;
|
||||
|
||||
bson_iter_decimal128(iter, &dec);
|
||||
bson_decimal128_to_string(&dec, str);
|
||||
htrc("%s.%s=%s\n", k, key, str);
|
||||
} else if (BSON_ITER_HOLDS_DOCUMENT(iter)) {
|
||||
bson_iter_t child;
|
||||
|
||||
if (bson_iter_recurse(iter, &child))
|
||||
ShowDocument(&child, NULL, key);
|
||||
|
||||
} else if (BSON_ITER_HOLDS_ARRAY(iter)) {
|
||||
bson_t *arr;
|
||||
bson_iter_t itar;
|
||||
const uint8_t *data = NULL;
|
||||
uint32_t len = 0;
|
||||
|
||||
bson_iter_array(iter, &len, &data);
|
||||
arr = bson_new_from_data(data, len);
|
||||
ShowDocument(&itar, arr, key);
|
||||
} // endif's
|
||||
|
||||
} // endwhile bson_iter_next
|
||||
|
||||
} // endif bson_iter_init
|
||||
|
||||
} // end of ShowDocument
|
||||
|
||||
/***********************************************************************/
|
||||
/* ReadBuffer: Get next document from a collection. */
|
||||
/***********************************************************************/
|
||||
int MGOFAM::ReadBuffer(PGLOBAL g)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
int rc = Cmgp->ReadNext(g);
|
||||
|
||||
if (mongoc_cursor_next(Cursor, &Document)) {
|
||||
char *str = bson_as_json(Document, NULL);
|
||||
if (rc != RC_OK)
|
||||
return rc;
|
||||
|
||||
if (trace > 1) {
|
||||
bson_iter_t iter;
|
||||
ShowDocument(&iter, Document, "");
|
||||
} else if (trace == 1)
|
||||
htrc("%s\n", str);
|
||||
|
||||
strncpy(Tdbp->GetLine(), str, Lrecl);
|
||||
bson_free(str);
|
||||
} else if (mongoc_cursor_error(Cursor, &Error)) {
|
||||
sprintf(g->Message, "Mongo Cursor Failure: %s", Error.message);
|
||||
rc = RC_FX;
|
||||
} else {
|
||||
//mongoc_cursor_destroy(Cursor);
|
||||
rc = RC_EF;
|
||||
} // endif's Cursor
|
||||
|
||||
return rc;
|
||||
strncpy(Tdbp->GetLine(), Cmgp->GetDocument(g), Lrecl);
|
||||
return RC_OK;
|
||||
} // end of ReadBuffer
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -681,84 +241,7 @@ int MGOFAM::ReadBuffer(PGLOBAL g)
|
||||
/***********************************************************************/
|
||||
int MGOFAM::WriteBuffer(PGLOBAL g)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
bson_t *doc;
|
||||
|
||||
//if (Mode == MODE_INSERT && !Collection) {
|
||||
// if ((Database = mongoc_client_get_database(Client, db_name)))
|
||||
// Collection = mongoc_database_create_collection(Database, coll_name,
|
||||
// NULL, &Error);
|
||||
|
||||
// if (!Collection)
|
||||
// if (Database) {
|
||||
// sprintf(g->Message, "Create collection: %s", Error.message);
|
||||
// return RC_FX;
|
||||
// } else {
|
||||
// sprintf(g->Message, "Fail to get database %s", db_name);
|
||||
// return RC_FX;
|
||||
// } // endif Database
|
||||
|
||||
//} // endif Collection
|
||||
|
||||
if (!(doc = bson_new_from_json((const uint8_t *)Tdbp->GetLine(),
|
||||
-1, &Error))) {
|
||||
sprintf(g->Message, "Wrong document: %s", Error.message);
|
||||
return RC_FX;
|
||||
} // endif doc
|
||||
|
||||
if (Mode != MODE_INSERT) {
|
||||
bool b = false;
|
||||
bson_iter_t iter;
|
||||
bson_t *selector = bson_new();
|
||||
|
||||
bson_iter_init(&iter, Document);
|
||||
|
||||
if (bson_iter_find(&iter, "_id")) {
|
||||
if (BSON_ITER_HOLDS_OID(&iter))
|
||||
b = BSON_APPEND_OID(selector, "_id", bson_iter_oid(&iter));
|
||||
else if (BSON_ITER_HOLDS_INT32(&iter))
|
||||
b = BSON_APPEND_INT32(selector, "_id", bson_iter_int32(&iter));
|
||||
else if (BSON_ITER_HOLDS_INT64(&iter))
|
||||
b = BSON_APPEND_INT64(selector, "_id", bson_iter_int64(&iter));
|
||||
else if (BSON_ITER_HOLDS_DOUBLE(&iter))
|
||||
b = BSON_APPEND_DOUBLE(selector, "_id", bson_iter_double(&iter));
|
||||
else if (BSON_ITER_HOLDS_UTF8(&iter))
|
||||
b = BSON_APPEND_UTF8(selector, "_id", bson_iter_utf8(&iter, NULL));
|
||||
|
||||
} // endif iter
|
||||
|
||||
if (!b) {
|
||||
strcpy(g->Message, "Cannot find _id");
|
||||
return RC_FX;
|
||||
} // endif oid
|
||||
|
||||
if (Mode == MODE_DELETE) {
|
||||
if (!mongoc_collection_remove(Collection, MONGOC_REMOVE_NONE,
|
||||
selector, NULL, &Error)) {
|
||||
sprintf(g->Message, "Remove: %s", Error.message);
|
||||
bson_destroy(selector);
|
||||
return RC_FX;
|
||||
} // endif remove
|
||||
|
||||
} else {
|
||||
if (!mongoc_collection_update(Collection, MONGOC_UPDATE_NONE,
|
||||
selector, doc, NULL, &Error)) {
|
||||
sprintf(g->Message, "Update: %s", Error.message);
|
||||
bson_destroy(selector);
|
||||
return RC_FX;
|
||||
} // endif remove
|
||||
|
||||
} // endif Mode
|
||||
|
||||
bson_destroy(selector);
|
||||
} else if (!mongoc_collection_insert(Collection, MONGOC_INSERT_NONE,
|
||||
doc, NULL, &Error)) {
|
||||
sprintf(g->Message, "Inserting: %s", Error.message);
|
||||
rc = RC_FX;
|
||||
} // endif insert
|
||||
|
||||
bson_destroy(doc);
|
||||
return rc;
|
||||
return Cmgp->Write(g);
|
||||
} // end of WriteBuffer
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -774,18 +257,7 @@ int MGOFAM::DeleteRecords(PGLOBAL g, int irc)
|
||||
/***********************************************************************/
|
||||
void MGOFAM::CloseTableFile(PGLOBAL g, bool)
|
||||
{
|
||||
if (Query) bson_destroy(Query);
|
||||
if (Opts) bson_destroy(Opts);
|
||||
if (Cursor) mongoc_cursor_destroy(Cursor);
|
||||
if (Collection) mongoc_collection_destroy(Collection);
|
||||
// mongoc_database_destroy(Database);
|
||||
// mongoc_client_destroy(Client);
|
||||
if (Client) mongoc_client_pool_push(Pool, Client);
|
||||
if (Pool) mongoc_client_pool_destroy(Pool);
|
||||
if (Uri) mongoc_uri_destroy(Uri);
|
||||
//bson_mem_restore_vtable();
|
||||
//mongoc_cleanup();
|
||||
//G = NULL;
|
||||
Cmgp->Close();
|
||||
Done = false;
|
||||
} // end of CloseTableFile
|
||||
|
||||
@@ -794,9 +266,6 @@ void MGOFAM::CloseTableFile(PGLOBAL g, bool)
|
||||
/***********************************************************************/
|
||||
void MGOFAM::Rewind(void)
|
||||
{
|
||||
mongoc_cursor_t *cursor = mongoc_cursor_clone(Cursor);
|
||||
|
||||
mongoc_cursor_destroy(Cursor);
|
||||
Cursor = cursor;
|
||||
Cmgp->Rewind();
|
||||
} // end of Rewind
|
||||
|
||||
|
@@ -1,21 +1,11 @@
|
||||
/************** MongoFam H Declares Source Code File (.H) **************/
|
||||
/* Name: mongofam.h Version 1.3 */
|
||||
/* Name: mongofam.h Version 1.4 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2017 */
|
||||
/* */
|
||||
/* This file contains the MongoDB access method classes declares. */
|
||||
/***********************************************************************/
|
||||
#pragma once
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include MongoDB library header files. */
|
||||
/***********************************************************************/
|
||||
#include <bson.h>
|
||||
#include <bcon.h>
|
||||
#include <mongoc.h>
|
||||
|
||||
#include "block.h"
|
||||
//#include "array.h"
|
||||
#include "cmgoconn.h"
|
||||
|
||||
typedef class TXTFAM *PTXF;
|
||||
typedef class MGOFAM *PMGOFAM;
|
||||
@@ -37,6 +27,7 @@ public:
|
||||
virtual bool GetUseTemp(void) { return false; }
|
||||
virtual int GetPos(void);
|
||||
virtual int GetNextPos(void);
|
||||
void SetTdbp(PTDBDOS tdbp) { Tdbp = tdbp; }
|
||||
virtual PTXF Duplicate(PGLOBAL g) { return (PTXF)new(g) MGOFAM(this); }
|
||||
void SetLrecl(int lrecl) { Lrecl = lrecl; }
|
||||
|
||||
@@ -63,35 +54,12 @@ protected:
|
||||
virtual int RenameTempFile(PGLOBAL g) { return RC_OK; }
|
||||
virtual int InitDelete(PGLOBAL g, int fpos, int spos);
|
||||
bool Init(PGLOBAL g);
|
||||
bool MakeCursor(PGLOBAL g);
|
||||
void ShowDocument(bson_iter_t *i, const bson_t *b, const char *k);
|
||||
//static void *mgo_alloc(size_t n);
|
||||
//static void *mgo_calloc(size_t n, size_t sz);
|
||||
//static void *mgo_realloc(void *m, size_t n);
|
||||
//static void mgo_free(void *) {}
|
||||
|
||||
|
||||
// Members
|
||||
//static PGLOBAL G;
|
||||
mongoc_uri_t *Uri;
|
||||
mongoc_client_pool_t *Pool; // Thread safe client pool
|
||||
mongoc_client_t *Client; // The MongoDB client
|
||||
mongoc_database_t *Database; // The MongoDB database
|
||||
mongoc_collection_t *Collection; // The MongoDB collection
|
||||
mongoc_cursor_t *Cursor;
|
||||
const bson_t *Document;
|
||||
//bson_mem_vtable_t Vtable;
|
||||
bson_t *Query; // MongoDB cursor filter
|
||||
bson_t *Opts; // MongoDB cursor options
|
||||
bson_error_t Error;
|
||||
PFBLOCK To_Fbt; // Pointer to temp file block
|
||||
MODE Mode;
|
||||
const char *Uristr;
|
||||
const char *Db_name;
|
||||
const char *Coll_name;
|
||||
const char *Options;
|
||||
const char *Filter;
|
||||
bool Done; // Init done
|
||||
bool Pipe;
|
||||
CMgoConn *Cmgp; // Points to a C Mongo connection class
|
||||
CMGOPARM Pcg; // Parms passed to Cmgp
|
||||
PFBLOCK To_Fbt; // Pointer to temp file block
|
||||
MODE Mode;
|
||||
bool Done; // Init done
|
||||
}; // end of class MGOFAM
|
||||
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/* Copyright (C) MariaDB Corporation Ab */
|
||||
#define MSG_ACCESS_VIOLATN 200
|
||||
#define MSG_ADD_BAD_TYPE 201
|
||||
#define MSG_ALLOC_ERROR 202
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) Olivier Bertrand 2004 - 2017
|
||||
/* Copyright (C) MariaDB Corporation Ab
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -86,7 +86,7 @@
|
||||
#if defined(JDBC_SUPPORT)
|
||||
#define NJDBC
|
||||
#include "tabjdbc.h"
|
||||
#endif // ODBC_SUPPORT
|
||||
#endif // JDBC_SUPPORT
|
||||
#if defined(PIVOT_SUPPORT)
|
||||
#include "tabpivot.h"
|
||||
#endif // PIVOT_SUPPORT
|
||||
@@ -96,9 +96,9 @@
|
||||
#if defined(XML_SUPPORT)
|
||||
#include "tabxml.h"
|
||||
#endif // XML_SUPPORT
|
||||
#if defined(MONGO_SUPPORT)
|
||||
#include "tabmgo.h"
|
||||
#endif // MONGO_SUPPORT
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
#include "mongo.h"
|
||||
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||
#if defined(ZIP_SUPPORT)
|
||||
#include "tabzip.h"
|
||||
#endif // ZIP_SUPPORT
|
||||
@@ -133,21 +133,21 @@ TABTYPE GetTypeID(const char *type)
|
||||
: (!stricmp(type, "CSV")) ? TAB_CSV
|
||||
: (!stricmp(type, "FMT")) ? TAB_FMT
|
||||
: (!stricmp(type, "DBF")) ? TAB_DBF
|
||||
#ifdef XML_SUPPORT
|
||||
#if defined(XML_SUPPORT)
|
||||
: (!stricmp(type, "XML")) ? TAB_XML
|
||||
#endif
|
||||
: (!stricmp(type, "INI")) ? TAB_INI
|
||||
: (!stricmp(type, "VEC")) ? TAB_VEC
|
||||
#ifdef ODBC_SUPPORT
|
||||
#if defined(ODBC_SUPPORT)
|
||||
: (!stricmp(type, "ODBC")) ? TAB_ODBC
|
||||
#endif
|
||||
#ifdef JDBC_SUPPORT
|
||||
#if defined(JDBC_SUPPORT)
|
||||
: (!stricmp(type, "JDBC")) ? TAB_JDBC
|
||||
#endif
|
||||
: (!stricmp(type, "MYSQL")) ? TAB_MYSQL
|
||||
: (!stricmp(type, "MYPRX")) ? TAB_MYSQL
|
||||
: (!stricmp(type, "DIR")) ? TAB_DIR
|
||||
#ifdef __WIN__
|
||||
#if defined(__WIN__)
|
||||
: (!stricmp(type, "MAC")) ? TAB_MAC
|
||||
: (!stricmp(type, "WMI")) ? TAB_WMI
|
||||
#endif
|
||||
@@ -156,15 +156,15 @@ TABTYPE GetTypeID(const char *type)
|
||||
: (!stricmp(type, "OCCUR")) ? TAB_OCCUR
|
||||
: (!stricmp(type, "CATLG")) ? TAB_PRX // Legacy
|
||||
: (!stricmp(type, "PROXY")) ? TAB_PRX
|
||||
#ifdef PIVOT_SUPPORT
|
||||
#if defined(PIVOT_SUPPORT)
|
||||
: (!stricmp(type, "PIVOT")) ? TAB_PIVOT
|
||||
#endif
|
||||
: (!stricmp(type, "VIR")) ? TAB_VIR
|
||||
: (!stricmp(type, "JSON")) ? TAB_JSON
|
||||
#ifdef ZIP_SUPPORT
|
||||
#if defined(ZIP_SUPPORT)
|
||||
: (!stricmp(type, "ZIP")) ? TAB_ZIP
|
||||
#endif
|
||||
#ifdef MONGO_SUPPORT
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
: (!stricmp(type, "MONGO")) ? TAB_MONGO
|
||||
#endif
|
||||
: (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY;
|
||||
@@ -557,9 +557,9 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
|
||||
#endif // PIVOT_SUPPORT
|
||||
case TAB_VIR: tdp= new(g) VIRDEF; break;
|
||||
case TAB_JSON: tdp= new(g) JSONDEF; break;
|
||||
#if defined(MONGO_SUPPORT)
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
case TAB_MONGO: tdp = new(g) MGODEF; break;
|
||||
#endif // MONGO_SUPPORT
|
||||
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||
#if defined(ZIP_SUPPORT)
|
||||
case TAB_ZIP: tdp= new(g) ZIPDEF; break;
|
||||
#endif // ZIP_SUPPORT
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) Olivier Bertrand 2004 - 2015
|
||||
/* Copyright (C) MariaDB Corporation Ab
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
/**************** MYCAT H Declares Source Code File (.H) ***************/
|
||||
/* Name: MYCAT.H Version 2.3 */
|
||||
/* */
|
||||
/* Author: Olivier Bertrand */
|
||||
/* This file contains the CONNECT plugin MYCAT class definitions. */
|
||||
/***********************************************************************/
|
||||
#ifndef __MYCAT__H
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/* Copyright (C) MariaDB Corporation Ab */
|
||||
#ifndef _OS_H_INCLUDED
|
||||
#define _OS_H_INCLUDED
|
||||
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/* Copyright (C) MariaDB Corporation Ab */
|
||||
#include "my_global.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/* Copyright (C) MariaDB Corporation Ab */
|
||||
#ifndef __OSUTIL_H__
|
||||
#define __OSUTIL_H__
|
||||
|
||||
|
@@ -138,12 +138,12 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
|
||||
TYPE_AM_VIR = 171, /* Virtual tables am type no */
|
||||
TYPE_AM_DMY = 172, /* DMY Dummy tables am type no */
|
||||
TYPE_AM_SET = 180, /* SET Set tables am type no */
|
||||
TYPE_AM_MYSQL = 192, /* MYSQL access method type no */
|
||||
TYPE_AM_MYX = 193, /* MYSQL EXEC access method type */
|
||||
TYPE_AM_CAT = 195, /* Catalog access method type no */
|
||||
TYPE_AM_ZIP = 198, /* ZIP access method type no */
|
||||
TYPE_AM_MGO = 199, /* MGO access method type no */
|
||||
TYPE_AM_OUT = 200}; /* Output relations (storage) */
|
||||
TYPE_AM_MYSQL = 190, /* MYSQL access method type no */
|
||||
TYPE_AM_MYX = 191, /* MYSQL EXEC access method type */
|
||||
TYPE_AM_CAT = 192, /* Catalog access method type no */
|
||||
TYPE_AM_ZIP = 193, /* ZIP access method type no */
|
||||
TYPE_AM_MGO = 194, /* MGO access method type no */
|
||||
TYPE_AM_OUT = 200}; /* Output relations (storage) */
|
||||
|
||||
enum RECFM {RECFM_NAF = -2, /* Not a file */
|
||||
RECFM_OEM = -1, /* OEM file access method */
|
||||
|
@@ -104,6 +104,8 @@ protected:
|
||||
/* This is the base class for all external tables. */
|
||||
/***********************************************************************/
|
||||
class DllExport TDBEXT : public TDB {
|
||||
friend class JAVAConn;
|
||||
friend class JMgoConn;
|
||||
public:
|
||||
// Constructors
|
||||
TDBEXT(EXTDEF *tdp);
|
||||
@@ -164,7 +166,7 @@ protected:
|
||||
}; // end of class TDBEXT
|
||||
|
||||
/***********************************************************************/
|
||||
/* Virual class EXTCOL: external column. */
|
||||
/* Virtual class EXTCOL: external column. */
|
||||
/***********************************************************************/
|
||||
class DllExport EXTCOL : public COLBLK {
|
||||
friend class TDBEXT;
|
||||
|
@@ -223,10 +223,10 @@ bool JDBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
} // endif Connect
|
||||
|
||||
if (Url)
|
||||
rc = ParseURL(g, Url);
|
||||
|
||||
if (rc == RC_FX) // Error
|
||||
return true;
|
||||
if ((rc = ParseURL(g, Url)) == RC_FX) {
|
||||
sprintf(g->Message, "Wrong JDBC URL %s", Url);
|
||||
return true;
|
||||
} // endif rc
|
||||
|
||||
Wrapname = GetStringCatInfo(g, "Wrapper", NULL);
|
||||
return false;
|
||||
@@ -305,12 +305,12 @@ TDBJDBC::TDBJDBC(PJDBCDEF tdp) : TDBEXT(tdp)
|
||||
if (tdp) {
|
||||
Ops.Driver = tdp->Driver;
|
||||
Ops.Url = tdp->Url;
|
||||
WrapName = tdp->Wrapname;
|
||||
Wrapname = tdp->Wrapname;
|
||||
Ops.User = tdp->Username;
|
||||
Ops.Pwd = tdp->Password;
|
||||
Ops.Scrollable = tdp->Scrollable;
|
||||
} else {
|
||||
WrapName = NULL;
|
||||
Wrapname = NULL;
|
||||
Ops.Driver = NULL;
|
||||
Ops.Url = NULL;
|
||||
Ops.User = NULL;
|
||||
@@ -328,7 +328,7 @@ TDBJDBC::TDBJDBC(PTDBJDBC tdbp) : TDBEXT(tdbp)
|
||||
{
|
||||
Jcp = tdbp->Jcp; // is that right ?
|
||||
Cnp = tdbp->Cnp;
|
||||
WrapName = tdbp->WrapName;
|
||||
Wrapname = tdbp->Wrapname;
|
||||
Ops = tdbp->Ops;
|
||||
Prepared = tdbp->Prepared;
|
||||
Werr = tdbp->Werr;
|
||||
@@ -562,7 +562,7 @@ bool TDBJDBC::OpenDB(PGLOBAL g)
|
||||
/* Table already open, just replace it at its beginning. */
|
||||
/*******************************************************************/
|
||||
if (Memory == 1) {
|
||||
if ((Qrp = Jcp->AllocateResult(g)))
|
||||
if ((Qrp = Jcp->AllocateResult(g, this)))
|
||||
Memory = 2; // Must be filled
|
||||
else
|
||||
Memory = 0; // Allocation failed, don't use it
|
||||
@@ -596,11 +596,11 @@ bool TDBJDBC::OpenDB(PGLOBAL g)
|
||||
/* drivers allowing concurency in getting results ??? */
|
||||
/*********************************************************************/
|
||||
if (!Jcp)
|
||||
Jcp = new(g)JDBConn(g, this);
|
||||
Jcp = new(g)JDBConn(g, Wrapname);
|
||||
else if (Jcp->IsOpen())
|
||||
Jcp->Close();
|
||||
|
||||
if (Jcp->Open(&Ops) == RC_FX)
|
||||
if (Jcp->Connect(&Ops))
|
||||
return true;
|
||||
else if (Quoted)
|
||||
Quote = Jcp->GetQuoteChar();
|
||||
@@ -608,7 +608,7 @@ bool TDBJDBC::OpenDB(PGLOBAL g)
|
||||
Use = USE_OPEN; // Do it now in case we are recursively called
|
||||
|
||||
/*********************************************************************/
|
||||
/* Make the command and allocate whatever is used for getting results. */
|
||||
/* Make the command and allocate whatever is used for getting results*/
|
||||
/*********************************************************************/
|
||||
if (Mode == MODE_READ || Mode == MODE_READX) {
|
||||
if (Memory > 1 && !Srcdef) {
|
||||
@@ -625,7 +625,7 @@ bool TDBJDBC::OpenDB(PGLOBAL g)
|
||||
} else if (n) {
|
||||
Jcp->m_Rows = n;
|
||||
|
||||
if ((Qrp = Jcp->AllocateResult(g)))
|
||||
if ((Qrp = Jcp->AllocateResult(g, this)))
|
||||
Memory = 2; // Must be filled
|
||||
else {
|
||||
strcpy(g->Message, "Result set memory allocation failed");
|
||||
@@ -1134,11 +1134,11 @@ bool TDBXJDC::OpenDB(PGLOBAL g)
|
||||
/* drivers allowing concurency in getting results ??? */
|
||||
/*********************************************************************/
|
||||
if (!Jcp) {
|
||||
Jcp = new(g) JDBConn(g, this);
|
||||
Jcp = new(g) JDBConn(g, Wrapname);
|
||||
} else if (Jcp->IsOpen())
|
||||
Jcp->Close();
|
||||
|
||||
if (Jcp->Open(&Ops) == RC_FX)
|
||||
if (Jcp->Connect(&Ops))
|
||||
return true;
|
||||
|
||||
Use = USE_OPEN; // Do it now in case we are recursively called
|
||||
@@ -1173,7 +1173,7 @@ int TDBXJDC::ReadDB(PGLOBAL g)
|
||||
else
|
||||
Query->Set(Cmdlist->Cmd);
|
||||
|
||||
if ((rc = Jcp->ExecSQLcommand(Query->GetStr())) == RC_FX)
|
||||
if ((rc = Jcp->ExecuteCommand(Query->GetStr())) == RC_FX)
|
||||
Nerr++;
|
||||
|
||||
if (rc == RC_NF)
|
||||
|
@@ -41,7 +41,7 @@ protected:
|
||||
// Members
|
||||
PSZ Driver; /* JDBC driver */
|
||||
PSZ Url; /* JDBC driver URL */
|
||||
PSZ Wrapname; /* Java wrapper name */
|
||||
PSZ Wrapname; /* Java driver name */
|
||||
}; // end of JDBCDEF
|
||||
|
||||
#if !defined(NJDBC)
|
||||
@@ -89,7 +89,7 @@ protected:
|
||||
JDBConn *Jcp; // Points to a JDBC connection class
|
||||
JDBCCOL *Cnp; // Points to count(*) column
|
||||
JDBCPARM Ops; // Additional parameters
|
||||
char *WrapName; // Points to Java wrapper name
|
||||
PSZ Wrapname; // Points to Java wrapper name
|
||||
bool Prepared; // True when using prepared statement
|
||||
bool Werr; // Write error
|
||||
bool Rerr; // Rewind error
|
||||
|
505
storage/connect/tabjmg.cpp
Normal file
505
storage/connect/tabjmg.cpp
Normal file
@@ -0,0 +1,505 @@
|
||||
/************** tabjmg C++ Program Source Code File (.CPP) *************/
|
||||
/* PROGRAM NAME: tabjmg Version 1.2 */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2017 */
|
||||
/* This file contains the MongoDB classes using the Java Driver. */
|
||||
/***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include relevant sections of the MariaDB header file. */
|
||||
/***********************************************************************/
|
||||
#include <my_global.h>
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include application header files: */
|
||||
/* global.h is header containing all global declarations. */
|
||||
/* plgdbsem.h is header containing the DB application declarations. */
|
||||
/***********************************************************************/
|
||||
#include "global.h"
|
||||
#include "plgdbsem.h"
|
||||
#include "xtable.h"
|
||||
#include "maputil.h"
|
||||
#include "filamtxt.h"
|
||||
#include "tabext.h"
|
||||
#include "tabjmg.h"
|
||||
#include "tabmul.h"
|
||||
#include "checklvl.h"
|
||||
#include "resource.h"
|
||||
#include "mycat.h" // for FNC_COL
|
||||
#include "filter.h"
|
||||
|
||||
/***********************************************************************/
|
||||
/* This should be an option. */
|
||||
/***********************************************************************/
|
||||
#define MAXCOL 200 /* Default max column nb in result */
|
||||
#define TYPE_UNKNOWN 12 /* Must be greater than other types */
|
||||
|
||||
/* --------------------------- Class TDBJMG -------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* Implementation of the TDBJMG class. */
|
||||
/***********************************************************************/
|
||||
TDBJMG::TDBJMG(PMGODEF tdp) : TDBEXT(tdp)
|
||||
{
|
||||
Jcp = NULL;
|
||||
//Cnp = NULL;
|
||||
|
||||
if (tdp) {
|
||||
Ops.Driver = tdp->Tabschema;
|
||||
Ops.Url = tdp->Uri;
|
||||
Ops.Version = tdp->Version;
|
||||
Uri = tdp->Uri;
|
||||
Db_name = tdp->Tabschema;
|
||||
Wrapname = tdp->Wrapname;
|
||||
Coll_name = tdp->Tabname;
|
||||
Options = tdp->Colist;
|
||||
Filter = tdp->Filter;
|
||||
B = tdp->Base ? 1 : 0;
|
||||
Pipe = tdp->Pipe && Options != NULL;
|
||||
} else {
|
||||
Ops.Driver = NULL;
|
||||
Ops.Url = NULL;
|
||||
Ops.Version = 0;
|
||||
Uri = NULL;
|
||||
Db_name = NULL;
|
||||
Coll_name = NULL;
|
||||
Options = NULL;
|
||||
Filter = NULL;
|
||||
B = 0;
|
||||
Pipe = false;
|
||||
} // endif tdp
|
||||
|
||||
Ops.User = NULL;
|
||||
Ops.Pwd = NULL;
|
||||
Ops.Scrollable = false;
|
||||
Ops.Fsize = Ops.CheckSize(Rows);
|
||||
Fpos = -1;
|
||||
N = 0;
|
||||
Done = false;
|
||||
} // end of TDBJMG standard constructor
|
||||
|
||||
TDBJMG::TDBJMG(TDBJMG *tdbp) : TDBEXT(tdbp)
|
||||
{
|
||||
Uri = tdbp->Uri;
|
||||
//Pool = tdbp->Pool;
|
||||
//Client = tdbp->Client;
|
||||
//Database = NULL;
|
||||
//Collection = tdbp->Collection;
|
||||
//Cursor = tdbp->Cursor;
|
||||
//Query = tdbp->Query;
|
||||
//Opts = tdbp->Opts;
|
||||
//Fpc = tdbp->Fpc;
|
||||
//Cnd = tdbp->Cnd;
|
||||
//Uristr = tdbp->Uristr;
|
||||
Db_name = tdbp->Db_name;;
|
||||
Coll_name = tdbp->Coll_name;
|
||||
Options = tdbp->Options;
|
||||
Filter = tdbp->Filter;
|
||||
B = tdbp->B;
|
||||
Fpos = tdbp->Fpos;
|
||||
N = tdbp->N;
|
||||
Done = tdbp->Done;
|
||||
Pipe = tdbp->Pipe;
|
||||
} // end of TDBJMG copy constructor
|
||||
|
||||
// Used for update
|
||||
PTDB TDBJMG::Clone(PTABS t)
|
||||
{
|
||||
PTDB tp;
|
||||
PJMGCOL cp1, cp2;
|
||||
PGLOBAL g = t->G;
|
||||
|
||||
tp = new(g) TDBJMG(this);
|
||||
|
||||
for (cp1 = (PJMGCOL)Columns; cp1; cp1 = (PJMGCOL)cp1->GetNext())
|
||||
if (!cp1->IsSpecial()) {
|
||||
cp2 = new(g) JMGCOL(cp1, tp); // Make a copy
|
||||
NewPointer(t, cp1, cp2);
|
||||
} // endif cp1
|
||||
|
||||
return tp;
|
||||
} // end of Clone
|
||||
|
||||
/***********************************************************************/
|
||||
/* Allocate JSN column description block. */
|
||||
/***********************************************************************/
|
||||
PCOL TDBJMG::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
|
||||
{
|
||||
PJMGCOL colp = new(g) JMGCOL(g, cdp, this, cprec, n);
|
||||
|
||||
//colp->Mbuf = (char*)PlugSubAlloc(g, NULL, colp->Long + 1);
|
||||
return colp;
|
||||
//return (colp->ParseJpath(g)) ? NULL : colp;
|
||||
} // end of MakeCol
|
||||
|
||||
/***********************************************************************/
|
||||
/* InsertSpecialColumn: Put a special column ahead of the column list.*/
|
||||
/***********************************************************************/
|
||||
PCOL TDBJMG::InsertSpecialColumn(PCOL colp)
|
||||
{
|
||||
if (!colp->IsSpecial())
|
||||
return NULL;
|
||||
|
||||
colp->SetNext(Columns);
|
||||
Columns = colp;
|
||||
return colp;
|
||||
} // end of InsertSpecialColumn
|
||||
|
||||
/***********************************************************************/
|
||||
/* MONGO Cardinality: returns table size in number of rows. */
|
||||
/***********************************************************************/
|
||||
int TDBJMG::Cardinality(PGLOBAL g)
|
||||
{
|
||||
if (!g)
|
||||
return 1;
|
||||
else if (Cardinal < 0)
|
||||
Cardinal = (!Init(g)) ? Jcp->CollSize(g) : 0;
|
||||
|
||||
return Cardinal;
|
||||
} // end of Cardinality
|
||||
|
||||
/***********************************************************************/
|
||||
/* MONGO GetMaxSize: returns collection size estimate. */
|
||||
/***********************************************************************/
|
||||
int TDBJMG::GetMaxSize(PGLOBAL g)
|
||||
{
|
||||
if (MaxSize < 0)
|
||||
MaxSize = Cardinality(g);
|
||||
|
||||
return MaxSize;
|
||||
} // end of GetMaxSize
|
||||
|
||||
/***********************************************************************/
|
||||
/* Init: initialize MongoDB processing. */
|
||||
/***********************************************************************/
|
||||
bool TDBJMG::Init(PGLOBAL g)
|
||||
{
|
||||
if (Done)
|
||||
return false;
|
||||
|
||||
/*********************************************************************/
|
||||
/* Open an JDBC connection for this table. */
|
||||
/* Note: this may not be the proper way to do. Perhaps it is better */
|
||||
/* to test whether a connection is already open for this datasource */
|
||||
/* and if so to allocate just a new result set. But this only for */
|
||||
/* drivers allowing concurency in getting results ??? */
|
||||
/*********************************************************************/
|
||||
if (!Jcp)
|
||||
Jcp = new(g) JMgoConn(g, Coll_name, Wrapname);
|
||||
else if (Jcp->IsOpen())
|
||||
Jcp->Close();
|
||||
|
||||
if (Jcp->Connect(&Ops))
|
||||
return true;
|
||||
|
||||
Done = true;
|
||||
return false;
|
||||
} // end of Init
|
||||
|
||||
/***********************************************************************/
|
||||
/* OpenDB: Data Base open routine for MONGO access method. */
|
||||
/***********************************************************************/
|
||||
bool TDBJMG::OpenDB(PGLOBAL g)
|
||||
{
|
||||
if (Use == USE_OPEN) {
|
||||
/*******************************************************************/
|
||||
/* Table already open replace it at its beginning. */
|
||||
/*******************************************************************/
|
||||
if (Jcp->Rewind())
|
||||
return true;
|
||||
|
||||
Fpos = -1;
|
||||
return false;
|
||||
} // endif Use
|
||||
|
||||
/*********************************************************************/
|
||||
/* First opening. */
|
||||
/*********************************************************************/
|
||||
if (Pipe && Mode != MODE_READ) {
|
||||
strcpy(g->Message, "Pipeline tables are read only");
|
||||
return true;
|
||||
} // endif Pipe
|
||||
|
||||
if (Init(g))
|
||||
return true;
|
||||
|
||||
if (Jcp->GetMethodId(g, Mode))
|
||||
return true;
|
||||
|
||||
if (Mode == MODE_DELETE && !Next) {
|
||||
// Delete all documents
|
||||
if (!Jcp->MakeCursor(g, this, "all", Filter, false))
|
||||
if (Jcp->DocDelete(g, true) == RC_OK)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} // endif Mode
|
||||
|
||||
if (Mode == MODE_INSERT)
|
||||
Jcp->MakeColumnGroups(g, this);
|
||||
|
||||
if (Mode != MODE_UPDATE)
|
||||
return Jcp->MakeCursor(g, this, Options, Filter, Pipe);
|
||||
|
||||
return false;
|
||||
} // end of OpenDB
|
||||
|
||||
/***********************************************************************/
|
||||
/* Data Base indexed read routine for ODBC access method. */
|
||||
/***********************************************************************/
|
||||
bool TDBJMG::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr)
|
||||
{
|
||||
strcpy(g->Message, "MONGO tables are not indexable");
|
||||
return true;
|
||||
} // end of ReadKey
|
||||
|
||||
/***********************************************************************/
|
||||
/* ReadDB: Get next document from a collection. */
|
||||
/***********************************************************************/
|
||||
int TDBJMG::ReadDB(PGLOBAL g)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
|
||||
if (!N && Mode == MODE_UPDATE)
|
||||
if (Jcp->MakeCursor(g, this, Options, Filter, Pipe))
|
||||
return RC_FX;
|
||||
|
||||
if (++CurNum >= Rbuf) {
|
||||
Rbuf = Jcp->Fetch();
|
||||
Curpos = Fpos + 1;
|
||||
CurNum = 0;
|
||||
N++;
|
||||
} // endif CurNum
|
||||
|
||||
rc = (Rbuf > 0) ? RC_OK : (Rbuf == 0) ? RC_EF : RC_FX;
|
||||
|
||||
return rc;
|
||||
} // end of ReadDB
|
||||
|
||||
/***********************************************************************/
|
||||
/* WriteDB: Data Base write routine for DOS access method. */
|
||||
/***********************************************************************/
|
||||
int TDBJMG::WriteDB(PGLOBAL g)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
|
||||
if (Mode == MODE_INSERT) {
|
||||
rc = Jcp->DocWrite(g);
|
||||
} else if (Mode == MODE_DELETE) {
|
||||
rc = Jcp->DocDelete(g, false);
|
||||
} else if (Mode == MODE_UPDATE) {
|
||||
rc = Jcp->DocUpdate(g, this);
|
||||
} // endif Mode
|
||||
|
||||
return rc;
|
||||
} // end of WriteDB
|
||||
|
||||
/***********************************************************************/
|
||||
/* Data Base delete line routine for ODBC access method. */
|
||||
/***********************************************************************/
|
||||
int TDBJMG::DeleteDB(PGLOBAL g, int irc)
|
||||
{
|
||||
return (irc == RC_OK) ? WriteDB(g) : RC_OK;
|
||||
} // end of DeleteDB
|
||||
|
||||
/***********************************************************************/
|
||||
/* Table close routine for MONGO tables. */
|
||||
/***********************************************************************/
|
||||
void TDBJMG::CloseDB(PGLOBAL g)
|
||||
{
|
||||
Jcp->Close();
|
||||
Done = false;
|
||||
} // end of CloseDB
|
||||
|
||||
/* ----------------------------- JMGCOL ------------------------------ */
|
||||
|
||||
/***********************************************************************/
|
||||
/* JMGCOL public constructor. */
|
||||
/***********************************************************************/
|
||||
JMGCOL::JMGCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
|
||||
: EXTCOL(cdp, tdbp, cprec, i, "MGO")
|
||||
{
|
||||
Tmgp = (PTDBJMG)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp);
|
||||
Jpath = cdp->GetFmt() ? cdp->GetFmt() : cdp->GetName();
|
||||
//Mbuf = NULL;
|
||||
} // end of JMGCOL constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* JMGCOL constructor used for copying columns. */
|
||||
/* tdbp is the pointer to the new table descriptor. */
|
||||
/***********************************************************************/
|
||||
JMGCOL::JMGCOL(JMGCOL *col1, PTDB tdbp) : EXTCOL(col1, tdbp)
|
||||
{
|
||||
Tmgp = col1->Tmgp;
|
||||
Jpath = col1->Jpath;
|
||||
//Mbuf = col1->Mbuf;
|
||||
} // end of JMGCOL copy constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get path when proj is false or projection path when proj is true. */
|
||||
/***********************************************************************/
|
||||
PSZ JMGCOL::GetJpath(PGLOBAL g, bool proj)
|
||||
{
|
||||
if (Jpath) {
|
||||
if (proj) {
|
||||
char *p1, *p2, *projpath = PlugDup(g, Jpath);
|
||||
int i = 0;
|
||||
|
||||
for (p1 = p2 = projpath; *p1; p1++)
|
||||
if (*p1 == '.') {
|
||||
if (!i)
|
||||
*p2++ = *p1;
|
||||
|
||||
i = 1;
|
||||
} else if (i) {
|
||||
if (!isdigit(*p1)) {
|
||||
*p2++ = *p1;
|
||||
i = 0;
|
||||
} // endif p1
|
||||
|
||||
} else
|
||||
*p2++ = *p1;
|
||||
|
||||
*p2 = 0;
|
||||
return projpath;
|
||||
} else
|
||||
return Jpath;
|
||||
|
||||
} else
|
||||
return Name;
|
||||
|
||||
} // end of GetJpath
|
||||
|
||||
#if 0
|
||||
/***********************************************************************/
|
||||
/* Mini: used to suppress blanks to json strings. */
|
||||
/***********************************************************************/
|
||||
char *JMGCOL::Mini(PGLOBAL g, const bson_t *bson, bool b)
|
||||
{
|
||||
char *s, *str = NULL;
|
||||
int i, k = 0;
|
||||
bool ok = true;
|
||||
|
||||
if (b)
|
||||
s = str = bson_array_as_json(bson, NULL);
|
||||
else
|
||||
s = str = bson_as_json(bson, NULL);
|
||||
|
||||
for (i = 0; i < Long && s[i]; i++) {
|
||||
switch (s[i]) {
|
||||
case ' ':
|
||||
if (ok) continue;
|
||||
case '"':
|
||||
ok = !ok;
|
||||
default:
|
||||
break;
|
||||
} // endswitch s[i]
|
||||
|
||||
Mbuf[k++] = s[i];
|
||||
} // endfor i
|
||||
|
||||
bson_free(str);
|
||||
|
||||
if (i >= Long) {
|
||||
sprintf(g->Message, "Value too long for column %s", Name);
|
||||
throw (int)TYPE_AM_MGO;
|
||||
} // endif i
|
||||
|
||||
Mbuf[k] = 0;
|
||||
return Mbuf;
|
||||
} // end of Mini
|
||||
#endif // 0
|
||||
|
||||
/***********************************************************************/
|
||||
/* ReadColumn: */
|
||||
/***********************************************************************/
|
||||
void JMGCOL::ReadColumn(PGLOBAL g)
|
||||
{
|
||||
Value->SetValue_psz(Tmgp->Jcp->GetColumnValue(Jpath));
|
||||
} // end of ReadColumn
|
||||
|
||||
/***********************************************************************/
|
||||
/* WriteColumn: */
|
||||
/***********************************************************************/
|
||||
void JMGCOL::WriteColumn(PGLOBAL g)
|
||||
{
|
||||
// Check whether this node must be written
|
||||
if (Value != To_Val)
|
||||
Value->SetValue_pval(To_Val, FALSE); // Convert the updated value
|
||||
|
||||
} // end of WriteColumn
|
||||
|
||||
#if 0
|
||||
/***********************************************************************/
|
||||
/* AddValue: Add column value to the document to insert or update. */
|
||||
/***********************************************************************/
|
||||
bool JMGCOL::AddValue(PGLOBAL g, bson_t *doc, char *key, bool upd)
|
||||
{
|
||||
bool rc = false;
|
||||
|
||||
if (Value->IsNull()) {
|
||||
if (upd)
|
||||
rc = BSON_APPEND_NULL(doc, key);
|
||||
else
|
||||
return false;
|
||||
|
||||
} else switch (Buf_Type) {
|
||||
case TYPE_STRING:
|
||||
rc = BSON_APPEND_UTF8(doc, key, Value->GetCharValue());
|
||||
break;
|
||||
case TYPE_INT:
|
||||
case TYPE_SHORT:
|
||||
rc = BSON_APPEND_INT32(doc, key, Value->GetIntValue());
|
||||
break;
|
||||
case TYPE_TINY:
|
||||
rc = BSON_APPEND_BOOL(doc, key, Value->GetIntValue());
|
||||
break;
|
||||
case TYPE_BIGINT:
|
||||
rc = BSON_APPEND_INT64(doc, key, Value->GetBigintValue());
|
||||
break;
|
||||
case TYPE_DOUBLE:
|
||||
rc = BSON_APPEND_DOUBLE(doc, key, Value->GetFloatValue());
|
||||
break;
|
||||
case TYPE_DECIM:
|
||||
{bson_decimal128_t dec;
|
||||
|
||||
if (bson_decimal128_from_string(Value->GetCharValue(), &dec))
|
||||
rc = BSON_APPEND_DECIMAL128(doc, key, &dec);
|
||||
|
||||
} break;
|
||||
case TYPE_DATE:
|
||||
rc = BSON_APPEND_DATE_TIME(doc, key, Value->GetBigintValue() * 1000);
|
||||
break;
|
||||
default:
|
||||
sprintf(g->Message, "Type %d not supported yet", Buf_Type);
|
||||
return true;
|
||||
} // endswitch Buf_Type
|
||||
|
||||
if (!rc) {
|
||||
strcpy(g->Message, "Adding value failed");
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
||||
} // end of AddValue
|
||||
|
||||
/* ---------------------------TDBGOL class --------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* TDBGOL class constructor. */
|
||||
/***********************************************************************/
|
||||
TDBGOL::TDBGOL(PMGODEF tdp) : TDBCAT(tdp)
|
||||
{
|
||||
Topt = tdp->GetTopt();
|
||||
Db = (char*)tdp->GetTabschema();
|
||||
} // end of TDBJCL constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* GetResult: Get the list the JSON file columns. */
|
||||
/***********************************************************************/
|
||||
PQRYRES TDBGOL::GetResult(PGLOBAL g)
|
||||
{
|
||||
return MGOColumns(g, Db, Topt, false);
|
||||
} // end of GetResult
|
||||
#endif // 0
|
||||
|
||||
/* -------------------------- End of mongo --------------------------- */
|
122
storage/connect/tabjmg.h
Normal file
122
storage/connect/tabjmg.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/**************** tabjmg H Declares Source Code File (.H) **************/
|
||||
/* Name: tabjmg.h Version 1.0 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2017 */
|
||||
/* */
|
||||
/* This file contains the MongoDB classes using the Java Driver. */
|
||||
/***********************************************************************/
|
||||
#include "mongo.h"
|
||||
#include "jmgoconn.h"
|
||||
#include "jdbccat.h"
|
||||
|
||||
/* -------------------------- TDBJMG class --------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* This is the MongoDB Table Type using the Java Driver. */
|
||||
/* The table is a collection, each record being a document. */
|
||||
/***********************************************************************/
|
||||
class DllExport TDBJMG : public TDBEXT {
|
||||
friend class JMGCOL;
|
||||
friend class MGODEF;
|
||||
friend class MGODISC;
|
||||
friend class JAVAConn;
|
||||
friend PQRYRES MGOColumns(PGLOBAL, PCSZ, PCSZ, PTOS, bool);
|
||||
public:
|
||||
// Constructor
|
||||
TDBJMG(PMGODEF tdp);
|
||||
TDBJMG(TDBJMG *tdbp);
|
||||
|
||||
// Implementation
|
||||
virtual AMT GetAmType(void) { return TYPE_AM_MGO; }
|
||||
virtual PTDB Duplicate(PGLOBAL g) { return (PTDB)new(g) TDBJMG(this); }
|
||||
|
||||
// Methods
|
||||
virtual PTDB Clone(PTABS t);
|
||||
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
|
||||
virtual PCOL InsertSpecialColumn(PCOL colp);
|
||||
//virtual void SetFilter(PFIL fp);
|
||||
virtual int RowNumber(PGLOBAL g, bool b = FALSE) { return N; }
|
||||
|
||||
// Database routines
|
||||
virtual int Cardinality(PGLOBAL g);
|
||||
virtual int GetMaxSize(PGLOBAL g);
|
||||
virtual bool OpenDB(PGLOBAL g);
|
||||
virtual int ReadDB(PGLOBAL g);
|
||||
virtual int WriteDB(PGLOBAL g);
|
||||
virtual int DeleteDB(PGLOBAL g, int irc);
|
||||
virtual void CloseDB(PGLOBAL g);
|
||||
virtual bool ReadKey(PGLOBAL g, OPVAL op, const key_range *kr);
|
||||
|
||||
protected:
|
||||
bool Init(PGLOBAL g);
|
||||
|
||||
// Members
|
||||
JMgoConn *Jcp; // Points to a Mongo connection class
|
||||
//JMGCOL *Cnp; // Points to count(*) column
|
||||
JDBCPARM Ops; // Additional parameters
|
||||
PCSZ Uri;
|
||||
PCSZ Db_name;
|
||||
PCSZ Coll_name;
|
||||
PCSZ Options; // The MongoDB options
|
||||
PCSZ Filter; // The filtering query
|
||||
PSZ Wrapname; // Java wrapper name
|
||||
int Fpos; // The current row index
|
||||
int N; // The current Rownum
|
||||
int B; // Array index base
|
||||
bool Done; // Init done
|
||||
bool Pipe; // True for pipeline
|
||||
}; // end of class TDBJMG
|
||||
|
||||
/* --------------------------- JMGCOL class -------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* Class JMGCOL: MongoDB access method column descriptor. */
|
||||
/***********************************************************************/
|
||||
class DllExport JMGCOL : public EXTCOL {
|
||||
friend class TDBJMG;
|
||||
friend class FILTER;
|
||||
public:
|
||||
// Constructors
|
||||
JMGCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
|
||||
JMGCOL(JMGCOL *colp, PTDB tdbp); // Constructor used in copy process
|
||||
|
||||
// Implementation
|
||||
virtual int GetAmType(void) {return Tmgp->GetAmType();}
|
||||
|
||||
// Methods
|
||||
//virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
|
||||
virtual PSZ GetJpath(PGLOBAL g, bool proj);
|
||||
virtual void ReadColumn(PGLOBAL g);
|
||||
virtual void WriteColumn(PGLOBAL g);
|
||||
//bool AddValue(PGLOBAL g, bson_t *doc, char *key, bool upd);
|
||||
|
||||
protected:
|
||||
// Default constructor not to be used
|
||||
JMGCOL(void) {}
|
||||
//char *GetProjPath(PGLOBAL g);
|
||||
//char *Mini(PGLOBAL g, const bson_t *bson, bool b);
|
||||
|
||||
// Members
|
||||
TDBJMG *Tmgp; // To the MGO table block
|
||||
char *Jpath; // The json path
|
||||
//char *Mbuf; // The Mini buffer
|
||||
}; // end of class JMGCOL
|
||||
|
||||
#if 0
|
||||
/***********************************************************************/
|
||||
/* This is the class declaration for the MONGO catalog table. */
|
||||
/***********************************************************************/
|
||||
class DllExport TDBGOL : public TDBCAT {
|
||||
public:
|
||||
// Constructor
|
||||
TDBGOL(PMGODEF tdp);
|
||||
|
||||
protected:
|
||||
// Specific routines
|
||||
virtual PQRYRES GetResult(PGLOBAL g);
|
||||
|
||||
// Members
|
||||
PTOS Topt;
|
||||
char *Db;
|
||||
}; // end of class TDBGOL
|
||||
#endif 0
|
@@ -31,6 +31,9 @@
|
||||
#if defined(ZIP_SUPPORT)
|
||||
#include "filamzip.h"
|
||||
#endif // ZIP_SUPPORT
|
||||
#if defined(JDBC_SUPPORT)
|
||||
#include "jmgfam.h"
|
||||
#endif // JDBC_SUPPORT
|
||||
#if defined(MONGO_SUPPORT)
|
||||
#include "mongofam.h"
|
||||
#endif // MONGO_SUPPORT
|
||||
@@ -68,7 +71,7 @@ typedef struct _jncol {
|
||||
/* JSONColumns: construct the result blocks containing the description */
|
||||
/* of all the columns of a table contained inside a JSON file. */
|
||||
/***********************************************************************/
|
||||
PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info)
|
||||
PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info)
|
||||
{
|
||||
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
|
||||
TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING};
|
||||
@@ -78,7 +81,8 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info)
|
||||
char *p, colname[65], fmt[129];
|
||||
int i, j, lvl, n = 0;
|
||||
int ncol = sizeof(buftyp) / sizeof(int);
|
||||
PCSZ sep;
|
||||
bool mgo = (GetTypeID(topt->type) == TAB_MONGO);
|
||||
PCSZ sep, level;
|
||||
PVAL valp;
|
||||
JCOL jcol;
|
||||
PJCL jcp, fjcp = NULL, pjcp = NULL;
|
||||
@@ -108,8 +112,14 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info)
|
||||
/*********************************************************************/
|
||||
/* Open the input file. */
|
||||
/*********************************************************************/
|
||||
lvl = GetIntegerTableOption(g, topt, "Level", 0);
|
||||
lvl = (lvl < 0) ? 0 : (lvl > 16) ? 16 : lvl;
|
||||
level = GetStringTableOption(g, topt, "Level", NULL);
|
||||
|
||||
if (level) {
|
||||
lvl = atoi(level);
|
||||
lvl = (lvl > 16) ? 16 : lvl;
|
||||
} else
|
||||
lvl = 0;
|
||||
|
||||
sep = GetStringTableOption(g, topt, "Separator", ".");
|
||||
|
||||
tdp = new(g) JSONDEF;
|
||||
@@ -119,11 +129,6 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info)
|
||||
#endif // ZIP_SUPPORT
|
||||
tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL);
|
||||
|
||||
if (!tdp->Fn && !dsn) {
|
||||
strcpy(g->Message, MSG(MISSING_FNAME));
|
||||
return NULL;
|
||||
} // endif Fn
|
||||
|
||||
if (!(tdp->Database = SetPath(g, db)))
|
||||
return NULL;
|
||||
|
||||
@@ -133,22 +138,30 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info)
|
||||
tdp->Xcol = GetStringTableOption(g, topt, "Expand", NULL);
|
||||
tdp->Uri = (dsn && *dsn ? dsn : NULL);
|
||||
|
||||
if (trace)
|
||||
if (!tdp->Fn && !tdp->Uri) {
|
||||
strcpy(g->Message, MSG(MISSING_FNAME));
|
||||
return NULL;
|
||||
} // endif Fn
|
||||
|
||||
if (trace)
|
||||
htrc("File %s objname=%s pretty=%d lvl=%d\n",
|
||||
tdp->Fn, tdp->Objname, tdp->Pretty, lvl);
|
||||
|
||||
if (tdp->Uri) {
|
||||
#if defined(MONGO_SUPPORT)
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
tdp->Collname = GetStringTableOption(g, topt, "Name", NULL);
|
||||
tdp->Collname = GetStringTableOption(g, topt, "Tabname", tdp->Collname);
|
||||
tdp->Schema = GetStringTableOption(g, topt, "Dbname", "test");
|
||||
tdp->Options = PlugDup(g, "all");
|
||||
// tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false);
|
||||
tdp->Options = (PSZ)GetStringTableOption(g, topt, "Colist", "all");
|
||||
tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false);
|
||||
tdp->Version = GetIntegerTableOption(g, topt, "Version", 3);
|
||||
tdp->Wrapname = (PSZ)GetStringTableOption(g, topt, "Wrapper",
|
||||
(tdp->Version == 2) ? "Mongo2Interface" : "Mongo3Interface");
|
||||
tdp->Pretty = 0;
|
||||
#else // !MONGO_SUPPORT
|
||||
#else // !MONGO_SUPPORT || JDBC_SUPPORT
|
||||
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO");
|
||||
return NULL;
|
||||
#endif // !MONGO_SUPPORT
|
||||
#endif // !MONGO_SUPPORT || JDBC_SUPPORT
|
||||
} // endif Uri
|
||||
|
||||
if (tdp->Pretty == 2) {
|
||||
@@ -167,10 +180,12 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info)
|
||||
|
||||
jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetValue(0) : NULL;
|
||||
} else {
|
||||
if (!(tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0))) {
|
||||
sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty);
|
||||
return NULL;
|
||||
} // endif lrecl
|
||||
if (!(tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0)))
|
||||
if (!mgo) {
|
||||
sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty);
|
||||
return NULL;
|
||||
} else
|
||||
tdp->Lrecl = 8192; // Should be enough
|
||||
|
||||
tdp->Ending = GetIntegerTableOption(g, topt, "Ending", CRLF);
|
||||
|
||||
@@ -182,12 +197,21 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info)
|
||||
return NULL;
|
||||
#endif // !ZIP_SUPPORT
|
||||
} else if (tdp->Uri) {
|
||||
#if defined(MONGO_SUPPORT)
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
#if !defined(JDBC_SUPPORT)
|
||||
tjnp = new(g) TDBJSN(tdp, new(g) MGOFAM(tdp));
|
||||
#else // !MONGO_SUPPORT
|
||||
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO");
|
||||
#elif !defined(MONGO_SUPPORT)
|
||||
tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp));
|
||||
#else
|
||||
if (tdp->Driver && toupper(*tdp->Driver) == 'C')
|
||||
tjnp = new(g) TDBJSN(tdp, new(g) MGOFAM(tdp));
|
||||
else
|
||||
tjnp = new(g) TDBJSN(tdp, new(g) JMGFAM(tdp));
|
||||
#endif
|
||||
#else // !MONGO_SUPPORT && !JDBC_SUPPORT
|
||||
sprintf(g->Message, "No MongoDB support");
|
||||
return NULL;
|
||||
#endif // !MONGO_SUPPORT
|
||||
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||
} else
|
||||
tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp));
|
||||
|
||||
@@ -229,15 +253,15 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info)
|
||||
jcol.Found = true;
|
||||
colname[64] = 0;
|
||||
fmt[128] = 0;
|
||||
*fmt = '$';
|
||||
|
||||
if (!tdp->Uri) {
|
||||
*fmt = '$';
|
||||
fmt[1] = '.';
|
||||
p = fmt + 2;
|
||||
} else
|
||||
p = fmt + 1;
|
||||
p = fmt;
|
||||
|
||||
jrp = (PJPR*)PlugSubAlloc(g, NULL, sizeof(PJPR) * lvl);
|
||||
jrp = (PJPR*)PlugSubAlloc(g, NULL, sizeof(PJPR) * MY_MAX(lvl, 0));
|
||||
|
||||
/*********************************************************************/
|
||||
/* Analyse the JSON tree and define columns. */
|
||||
@@ -300,12 +324,13 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info)
|
||||
} // endswitch jsp
|
||||
|
||||
goto retry;
|
||||
} else {
|
||||
} else if (lvl >= 0) {
|
||||
jcol.Type = TYPE_STRING;
|
||||
jcol.Len = 256;
|
||||
jcol.Scale = 0;
|
||||
jcol.Cbn = true;
|
||||
} // endif's
|
||||
} else
|
||||
continue;
|
||||
|
||||
// Check whether this column was already found
|
||||
for (jcp = fjcp; jcp; jcp = jcp->Next)
|
||||
@@ -461,11 +486,16 @@ JSONDEF::JSONDEF(void)
|
||||
Base = 0;
|
||||
Strict = false;
|
||||
Sep = '.';
|
||||
#if defined(MONGO_SUPPORT)
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
Uri = NULL;
|
||||
Collname = Schema = Options = Filter = NULL;
|
||||
Pipe = false;
|
||||
#endif // MONGO_SUPPORT
|
||||
Driver = NULL;
|
||||
Version = 0;
|
||||
#if defined(JDBC_SUPPORT)
|
||||
Wrapname = NULL;
|
||||
#endif // JDBC_SUPPORT
|
||||
#endif // !MONGO_SUPPORT && !JDBC_SUPPORT
|
||||
} // end of JSONDEF constructor
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -482,7 +512,7 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR, int poff)
|
||||
Sep = *GetStringCatInfo(g, "Separator", ".");
|
||||
|
||||
if (Uri = GetStringCatInfo(g, "Connect", NULL)) {
|
||||
#if defined(MONGO_SUPPORT)
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
Collname = GetStringCatInfo(g, "Name",
|
||||
(Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name);
|
||||
Collname = GetStringCatInfo(g, "Tabname", Collname);
|
||||
@@ -490,11 +520,19 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR, int poff)
|
||||
Options = GetStringCatInfo(g, "Colist", NULL);
|
||||
Filter = GetStringCatInfo(g, "Filter", NULL);
|
||||
Pipe = GetBoolCatInfo("Pipeline", false);
|
||||
Driver = GetStringCatInfo(g, "Driver", NULL);
|
||||
Version = GetIntCatInfo("Version", 3);
|
||||
Pretty = 0;
|
||||
#else // !MONGO_SUPPORT
|
||||
#if defined(JDBC_SUPPORT)
|
||||
if (Version == 2)
|
||||
Wrapname = GetStringCatInfo(g, "Wrapper", "Mongo2Interface");
|
||||
else
|
||||
Wrapname = GetStringCatInfo(g, "Wrapper", "Mongo3Interface");
|
||||
#endif // JDBC_SUPPORT
|
||||
#else // !MONGO_SUPPORT && !JDBC_SUPPORT
|
||||
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO");
|
||||
return true;
|
||||
#endif // !MONGO_SUPPORT
|
||||
#endif // !MONGO_SUPPORT && !JDBC_SUPPORT
|
||||
} // endif Uri
|
||||
|
||||
return DOSDEF::DefineAM(g, (Uri ? "XMGO" : "DOS"), poff);
|
||||
@@ -520,12 +558,18 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
|
||||
(m == MODE_UPDATE || m == MODE_DELETE));
|
||||
|
||||
if (Uri) {
|
||||
#if defined(MONGO_SUPPORT)
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
#if !defined(JDBC_SUPPORT)
|
||||
txfp = new(g) MGOFAM(this);
|
||||
#else // !MONGO_SUPPORT
|
||||
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO");
|
||||
return NULL;
|
||||
#endif // !MONGO_SUPPORT
|
||||
#elif !defined(MONGO_SUPPORT)
|
||||
txfp = new(g) JMGFAM(this);
|
||||
#else
|
||||
if (Driver && toupper(*Driver) == 'C')
|
||||
txfp = new(g) MGOFAM(this);
|
||||
else
|
||||
txfp = new(g) JMGFAM(this);
|
||||
#endif
|
||||
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||
} else if (Zipped) {
|
||||
#if defined(ZIP_SUPPORT)
|
||||
if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) {
|
||||
@@ -559,14 +603,19 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
|
||||
tdbp = new(g) TDBJSN(this, txfp);
|
||||
|
||||
#if USE_G
|
||||
// Allocate the parse work memory
|
||||
PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL));
|
||||
memset(G, 0, sizeof(GLOBAL));
|
||||
G->Sarea_Size = Lrecl * 10;
|
||||
G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size);
|
||||
PlugSubSet(G, G->Sarea, G->Sarea_Size);
|
||||
G->jump_level = 0;
|
||||
((TDBJSN*)tdbp)->G = G;
|
||||
if (Lrecl) {
|
||||
// Allocate the parse work memory
|
||||
PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL));
|
||||
memset(G, 0, sizeof(GLOBAL));
|
||||
G->Sarea_Size = Lrecl * 10;
|
||||
G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size);
|
||||
PlugSubSet(G, G->Sarea, G->Sarea_Size);
|
||||
G->jump_level = 0;
|
||||
((TDBJSN*)tdbp)->G = G;
|
||||
} else {
|
||||
strcpy(g->Message, "LRECL is not defined");
|
||||
return NULL;
|
||||
} // endif Lrecl
|
||||
#else
|
||||
((TDBJSN*)tdbp)->G = g;
|
||||
#endif
|
||||
@@ -791,13 +840,16 @@ bool TDBJSN::OpenDB(PGLOBAL g)
|
||||
return true;
|
||||
} // endswitch Jmode
|
||||
|
||||
if (Xcol && Txfp->GetAmType() != TYPE_AM_MGO)
|
||||
To_Filter = NULL; // Imcompatible
|
||||
|
||||
} // endif Use
|
||||
|
||||
return TDBDOS::OpenDB(g);
|
||||
} // end of OpenDB
|
||||
if (TDBDOS::OpenDB(g))
|
||||
return true;
|
||||
|
||||
if (Xcol)
|
||||
To_Filter = NULL; // Imcompatible
|
||||
|
||||
return false;
|
||||
} // end of OpenDB
|
||||
|
||||
/***********************************************************************/
|
||||
/* SkipHeader: Physically skip first header line if applicable. */
|
||||
@@ -1282,7 +1334,7 @@ fin:
|
||||
/***********************************************************************/
|
||||
/* Get Jpath converted to Mongo path. */
|
||||
/***********************************************************************/
|
||||
char *JSONCOL::GetJpath(PGLOBAL g, bool proj)
|
||||
PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj)
|
||||
{
|
||||
if (Jpath) {
|
||||
char *p1, *p2, *mgopath;
|
||||
@@ -2204,8 +2256,8 @@ void TDBJSON::CloseDB(PGLOBAL g)
|
||||
TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp)
|
||||
{
|
||||
Topt = tdp->GetTopt();
|
||||
Db = (char*)tdp->GetDB();
|
||||
Dsn = (char*)tdp->Uri;
|
||||
Db = tdp->GetDB();
|
||||
Dsn = tdp->Uri;
|
||||
} // end of TDBJCL constructor
|
||||
|
||||
/***********************************************************************/
|
||||
|
@@ -36,10 +36,13 @@ class DllExport JSONDEF : public DOSDEF { /* Table description */
|
||||
friend class TDBJSON;
|
||||
friend class TDBJSN;
|
||||
friend class TDBJCL;
|
||||
friend PQRYRES JSONColumns(PGLOBAL, char*, char*, PTOS, bool);
|
||||
#if defined(JDBC_SUPPORT)
|
||||
friend class JMGFAM;
|
||||
#endif // JDBC_SUPPORT
|
||||
#if defined(MONGO_SUPPORT)
|
||||
friend class MGOFAM;
|
||||
#endif // MONGO_SUPPORT
|
||||
friend PQRYRES JSONColumns(PGLOBAL, PCSZ, PCSZ, PTOS, bool);
|
||||
public:
|
||||
// Constructor
|
||||
JSONDEF(void);
|
||||
@@ -63,13 +66,18 @@ public:
|
||||
bool Strict; /* Strict syntax checking */
|
||||
char Sep; /* The Jpath separator */
|
||||
const char *Uri; /* MongoDB connection URI */
|
||||
#if defined(MONGO_SUPPORT)
|
||||
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||
PCSZ Collname; /* External collection name */
|
||||
PCSZ Schema; /* External schema (DB) name */
|
||||
PSZ Options; /* Colist ; Pipe */
|
||||
PSZ Filter; /* Filter */
|
||||
PSZ Driver; /* MongoDB Driver (C or JAVA) */
|
||||
bool Pipe; /* True if Colist is a pipeline */
|
||||
#endif // MONGO_SUPPORT
|
||||
int Version; /* Driver version */
|
||||
#if defined(JDBC_SUPPORT)
|
||||
PSZ Wrapname; /* MongoDB java wrapper name */
|
||||
#endif // JDBC_SUPPORT
|
||||
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||
}; // end of JSONDEF
|
||||
|
||||
/* -------------------------- TDBJSN class --------------------------- */
|
||||
@@ -81,6 +89,9 @@ public:
|
||||
class DllExport TDBJSN : public TDBDOS {
|
||||
friend class JSONCOL;
|
||||
friend class JSONDEF;
|
||||
#if defined(JDBC_SUPPORT)
|
||||
friend class JMGFAM;
|
||||
#endif // JDBC_SUPPORT
|
||||
#if defined(MONGO_SUPPORT)
|
||||
friend class MGOFAM;
|
||||
#endif // MONGO_SUPPORT
|
||||
@@ -148,8 +159,13 @@ public:
|
||||
class DllExport JSONCOL : public DOSCOL {
|
||||
friend class TDBJSN;
|
||||
friend class TDBJSON;
|
||||
#if defined(JDBC_SUPPORT)
|
||||
friend class JMGFAM;
|
||||
#endif // JDBC_SUPPORT
|
||||
#if defined(MONGO_SUPPORT)
|
||||
friend class MGOFAM;
|
||||
public:
|
||||
#endif // MONGO_SUPPORT
|
||||
public:
|
||||
// Constructors
|
||||
JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
|
||||
JSONCOL(JSONCOL *colp, PTDB tdbp); // Constructor used in copy process
|
||||
@@ -160,7 +176,7 @@ class DllExport JSONCOL : public DOSCOL {
|
||||
// Methods
|
||||
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
|
||||
bool ParseJpath(PGLOBAL g);
|
||||
char *GetJpath(PGLOBAL g, bool proj);
|
||||
virtual PSZ GetJpath(PGLOBAL g, bool proj);
|
||||
virtual void ReadColumn(PGLOBAL g);
|
||||
virtual void WriteColumn(PGLOBAL g);
|
||||
|
||||
@@ -252,7 +268,7 @@ class DllExport TDBJCL : public TDBCAT {
|
||||
virtual PQRYRES GetResult(PGLOBAL g);
|
||||
|
||||
// Members
|
||||
PTOS Topt;
|
||||
char *Db;
|
||||
char *Dsn;
|
||||
PTOS Topt;
|
||||
PCSZ Db;
|
||||
PCSZ Dsn;
|
||||
}; // end of class TDBJCL
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,43 +1,12 @@
|
||||
/**************** tabmgo H Declares Source Code File (.H) **************/
|
||||
/* Name: tabmgo.h Version 1.0 */
|
||||
/* Name: tabmgo.h Version 1.1 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2017 */
|
||||
/* */
|
||||
/* This file contains the MongoDB classes declares. */
|
||||
/***********************************************************************/
|
||||
#include "osutil.h"
|
||||
#include "block.h"
|
||||
#include "colblk.h"
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include MongoDB library header files. */
|
||||
/***********************************************************************/
|
||||
#include <bson.h>
|
||||
#include <bcon.h>
|
||||
#include <mongoc.h>
|
||||
|
||||
typedef class MGODEF *PMGODEF;
|
||||
typedef class TDBMGO *PTDBMGO;
|
||||
typedef class MGOCOL *PMGOCOL;
|
||||
typedef class INCOL *PINCOL;
|
||||
|
||||
typedef struct _bncol {
|
||||
struct _bncol *Next;
|
||||
char *Name;
|
||||
char *Fmt;
|
||||
int Type;
|
||||
int Len;
|
||||
int Scale;
|
||||
bool Cbn;
|
||||
bool Found;
|
||||
} BCOL, *PBCOL;
|
||||
|
||||
typedef struct KEYCOL {
|
||||
KEYCOL *Next;
|
||||
PINCOL Incolp;
|
||||
PCOL Colp;
|
||||
char *Key;
|
||||
} *PKC;
|
||||
#include "mongo.h"
|
||||
#include "cmgoconn.h"
|
||||
|
||||
/***********************************************************************/
|
||||
/* Class used to get the columns of a mongo collection. */
|
||||
@@ -48,7 +17,7 @@ public:
|
||||
MGODISC(PGLOBAL g, int *lg);
|
||||
|
||||
// Functions
|
||||
int GetColumns(PGLOBAL g, char *db, PTOS topt);
|
||||
int GetColumns(PGLOBAL g, PCSZ db, PCSZ uri, PTOS topt);
|
||||
bool FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc,
|
||||
char *pcn, char *pfmt, int i, int k, bool b);
|
||||
|
||||
@@ -62,52 +31,7 @@ public:
|
||||
bool all;
|
||||
}; // end of MGODISC
|
||||
|
||||
/***********************************************************************/
|
||||
/* MongoDB table. */
|
||||
/***********************************************************************/
|
||||
class DllExport MGODEF : public EXTDEF { /* Table description */
|
||||
friend class TDBMGO;
|
||||
friend class MGOFAM;
|
||||
friend class MGODISC;
|
||||
friend PQRYRES MGOColumns(PGLOBAL, char *, PTOS, bool);
|
||||
public:
|
||||
// Constructor
|
||||
MGODEF(void);
|
||||
|
||||
// Implementation
|
||||
virtual const char *GetType(void) { return "MONGO"; }
|
||||
|
||||
// Methods
|
||||
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
|
||||
virtual PTDB GetTable(PGLOBAL g, MODE m);
|
||||
|
||||
protected:
|
||||
// Members
|
||||
PCSZ Uri; /* MongoDB connection URI */
|
||||
PCSZ Colist; /* Options list */
|
||||
PCSZ Filter; /* Filtering query */
|
||||
int Level; /* Used for catalog table */
|
||||
int Base; /* The array index base */
|
||||
bool Pipe; /* True is Colist is a pipeline */
|
||||
}; // end of MGODEF
|
||||
|
||||
/* ------------------------- TDBMGO classes -------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* Used when inserting values in a MongoDB collection. */
|
||||
/***********************************************************************/
|
||||
class INCOL : public BLOCK {
|
||||
public:
|
||||
// Constructor
|
||||
INCOL(void) { Klist = NULL; }
|
||||
|
||||
// Methods
|
||||
void AddCol(PGLOBAL g, PCOL colp, char *jp);
|
||||
|
||||
//Members
|
||||
bson_t Child;
|
||||
PKC Klist;
|
||||
}; // end of INCOL;
|
||||
/* -------------------------- TDBMGO class --------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* This is the MongoDB Table Type class declaration. */
|
||||
@@ -117,10 +41,10 @@ class DllExport TDBMGO : public TDBEXT {
|
||||
friend class MGOCOL;
|
||||
friend class MGODEF;
|
||||
friend class MGODISC;
|
||||
friend PQRYRES MGOColumns(PGLOBAL, char *, PTOS, bool);
|
||||
friend PQRYRES MGOColumns(PGLOBAL, PCSZ, PCSZ, PTOS, bool);
|
||||
public:
|
||||
// Constructor
|
||||
TDBMGO(PMGODEF tdp);
|
||||
TDBMGO(MGODEF *tdp);
|
||||
TDBMGO(TDBMGO *tdbp);
|
||||
|
||||
// Implementation
|
||||
@@ -131,7 +55,6 @@ public:
|
||||
virtual PTDB Clone(PTABS t);
|
||||
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
|
||||
virtual PCOL InsertSpecialColumn(PCOL colp);
|
||||
virtual void SetFilter(PFIL fp);
|
||||
virtual int RowNumber(PGLOBAL g, bool b = FALSE) {return N;}
|
||||
|
||||
// Database routines
|
||||
@@ -146,35 +69,15 @@ public:
|
||||
|
||||
protected:
|
||||
bool Init(PGLOBAL g);
|
||||
mongoc_cursor_t *MakeCursor(PGLOBAL g);
|
||||
void ShowDocument(bson_iter_t *i, const bson_t *b, const char *k);
|
||||
void MakeColumnGroups(PGLOBAL g);
|
||||
bool DocWrite(PGLOBAL g, PINCOL icp);
|
||||
|
||||
// Members
|
||||
PGLOBAL G; // Needed by SetFilter
|
||||
mongoc_uri_t *Uri;
|
||||
mongoc_client_pool_t *Pool; // Thread safe client pool
|
||||
mongoc_client_t *Client; // The MongoDB client
|
||||
mongoc_database_t *Database; // The MongoDB database
|
||||
mongoc_collection_t *Collection; // The MongoDB collection
|
||||
mongoc_cursor_t *Cursor;
|
||||
const bson_t *Document;
|
||||
bson_t *Query; // MongoDB cursor filter
|
||||
bson_t *Opts; // MongoDB cursor options
|
||||
bson_error_t Error;
|
||||
PINCOL Fpc; // To insert INCOL classes
|
||||
CMgoConn *Cmgp; // Points to a C Mongo connection class
|
||||
CMGOPARM Pcg; // Parms passed to Cmgp
|
||||
const Item *Cnd; // The first condition
|
||||
const char *Uristr;
|
||||
const char *Db_name;
|
||||
const char *Coll_name;
|
||||
const char *Options; // The MongoDB options
|
||||
const char *Filter; // The filtering query
|
||||
int Fpos; // The current row index
|
||||
int N; // The current Rownum
|
||||
int B; // Array index base
|
||||
bool Done; // Init done
|
||||
bool Pipe; // True for pipeline
|
||||
}; // end of class TDBMGO
|
||||
|
||||
/* --------------------------- MGOCOL class -------------------------- */
|
||||
@@ -191,26 +94,20 @@ public:
|
||||
MGOCOL(MGOCOL *colp, PTDB tdbp); // Constructor used in copy process
|
||||
|
||||
// Implementation
|
||||
virtual int GetAmType(void) { return Tmgp->GetAmType(); }
|
||||
virtual int GetAmType(void) { return Tmgp->GetAmType(); }
|
||||
|
||||
// Methods
|
||||
//virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
|
||||
virtual void ReadColumn(PGLOBAL g);
|
||||
virtual void WriteColumn(PGLOBAL g);
|
||||
bool AddValue(PGLOBAL g, bson_t *doc, char *key, bool upd);
|
||||
virtual PSZ GetJpath(PGLOBAL g, bool proj);
|
||||
virtual void ReadColumn(PGLOBAL g);
|
||||
virtual void WriteColumn(PGLOBAL g);
|
||||
|
||||
protected:
|
||||
// Default constructor not to be used
|
||||
MGOCOL(void) {}
|
||||
char *GetProjPath(PGLOBAL g);
|
||||
char *Mini(PGLOBAL g, const bson_t *bson, bool b);
|
||||
|
||||
// Members
|
||||
TDBMGO *Tmgp; // To the MGO table block
|
||||
bson_iter_t Iter; // Used to retrieve column value
|
||||
bson_iter_t Desc; // Descendant iter
|
||||
char *Jpath; // The json path
|
||||
char *Mbuf; // The Mini buffer
|
||||
}; // end of class MGOCOL
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -226,6 +123,7 @@ protected:
|
||||
virtual PQRYRES GetResult(PGLOBAL g);
|
||||
|
||||
// Members
|
||||
PTOS Topt;
|
||||
char *Db;
|
||||
PTOS Topt;
|
||||
PCSZ Uri;
|
||||
PCSZ Db;
|
||||
}; // end of class TDBGOL
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) Olivier Bertrand 2004 - 2015
|
||||
/* Copyright (C) MariaDB Corporation Ab
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -24,7 +24,7 @@
|
||||
that is a connection with its personnal memory allocation.
|
||||
|
||||
@note
|
||||
|
||||
Author Olivier Bertrand
|
||||
*/
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -144,9 +144,9 @@ void user_connect::SetHandler(ha_connect *hc)
|
||||
/****************************************************************************/
|
||||
/* Check whether we begin a new query and if so cleanup the previous one. */
|
||||
/****************************************************************************/
|
||||
bool user_connect::CheckCleanup(void)
|
||||
bool user_connect::CheckCleanup(bool force)
|
||||
{
|
||||
if (thdp->query_id > last_query_id) {
|
||||
if (thdp->query_id > last_query_id || force) {
|
||||
uint worksize= GetWorkSize();
|
||||
|
||||
PlugCleanup(g, true);
|
||||
@@ -171,7 +171,7 @@ bool user_connect::CheckCleanup(void)
|
||||
g->Mrr = 0;
|
||||
last_query_id= thdp->query_id;
|
||||
|
||||
if (trace)
|
||||
if (trace && !force)
|
||||
printf("=====> Begin new query %llu\n", last_query_id);
|
||||
|
||||
return true;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) Olivier Bertrand 2004 - 2011
|
||||
/* Copyright (C) MariaDB Corporation Ab
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -19,6 +19,7 @@
|
||||
Declaration of the user_connect class.
|
||||
|
||||
@note
|
||||
Author Olivier Bertrand
|
||||
|
||||
@see
|
||||
/sql/handler.h and /storage/connect/user_connect.cc
|
||||
@@ -53,7 +54,7 @@ public:
|
||||
// Implementation
|
||||
bool user_init();
|
||||
void SetHandler(ha_connect *hc);
|
||||
bool CheckCleanup(void);
|
||||
bool CheckCleanup(bool force = false);
|
||||
bool CheckQueryID(void) {return thdp->query_id > last_query_id;}
|
||||
bool CheckQuery(query_id_t vid) {return last_query_id > vid;}
|
||||
|
||||
|
Reference in New Issue
Block a user