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)
|
ENDIF(CONNECT_WITH_ODBC)
|
||||||
|
|
||||||
#
|
#
|
||||||
# JDBC
|
# JDBC and MongoDB Java Driver
|
||||||
#
|
#
|
||||||
IF(APPLE)
|
IF(APPLE)
|
||||||
OPTION(CONNECT_WITH_JDBC "Compile CONNECT storage engine without JDBC support" OFF)
|
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})
|
INCLUDE_DIRECTORIES(${JAVA_INCLUDE_PATH2})
|
||||||
# SET(JDBC_LIBRARY ${JAVA_JVM_LIBRARY}) will be dynamically linked
|
# SET(JDBC_LIBRARY ${JAVA_JVM_LIBRARY}) will be dynamically linked
|
||||||
SET(CONNECT_SOURCES ${CONNECT_SOURCES}
|
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
|
JdbcInterface.java ApacheInterface.java MariadbInterface.java
|
||||||
MysqlInterface.java OracleInterface.java PostgresqlInterface.java
|
MysqlInterface.java OracleInterface.java PostgresqlInterface.java
|
||||||
|
Mongo2Interface.java Mongo3Interface.java
|
||||||
JavaWrappers.jar)
|
JavaWrappers.jar)
|
||||||
# TODO: Find how to compile and install the java wrapper classes
|
# TODO: Find how to compile and install the java wrapper classes
|
||||||
# Find required libraries and include directories
|
# Find required libraries and include directories
|
||||||
@@ -292,7 +296,7 @@ IF(CONNECT_WITH_ZIP)
|
|||||||
ENDIF(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)
|
#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
|
# # Adding some typical places to search in
|
||||||
# SET(PC_MONGO_INCLUDE_DIRS
|
# SET(PC_MONGO_INCLUDE_DIRS
|
||||||
# C:/mongo-c-driver/include
|
# C:/mongo-c-driver/include
|
||||||
# D:/mongo-c-driver/include)
|
# D:/mongo-c-driver/include)
|
||||||
# SET(PC_MONGO_LIBRARY_DIRS
|
# SET(PC_MONGO_LIBRARY_DIRS
|
||||||
# C:/mongo-c-driver/lib
|
# C:/mongo-c-driver/lib
|
||||||
# D:/mongo-c-driver/lib)
|
# D:/mongo-c-driver/lib)
|
||||||
# ENDIF(WIN32)
|
# ENDIF(WIN32)
|
||||||
# FIND_PACKAGE(libmongoc)
|
# FIND_PACKAGE(libmongoc)
|
||||||
# IF (MONGO_FOUND)
|
# IF (MONGO_FOUND)
|
||||||
# INCLUDE_DIRECTORIES(${MONGO_INCLUDE_DIR})
|
# INCLUDE_DIRECTORIES(${MONGO_INCLUDE_DIR})
|
||||||
# SET(MONGO_LIBRARY ${MONGO_LIBRARIES})
|
# 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)
|
# add_definitions(-DMONGO_SUPPORT)
|
||||||
# ENDIF(MONGO_FOUND)
|
# ENDIF(MONGO_FOUND)
|
||||||
#ENDIF(CONNECT_WITH_MONGO)
|
#ENDIF(CONNECT_WITH_MONGO)
|
||||||
@@ -339,3 +348,4 @@ MYSQL_ADD_PLUGIN(connect ${CONNECT_SOURCES}
|
|||||||
LINK_LIBRARIES ${ZLIB_LIBRARY} ${XML_LIBRARY} ${ICONV_LIBRARY}
|
LINK_LIBRARIES ${ZLIB_LIBRARY} ${XML_LIBRARY} ${ICONV_LIBRARY}
|
||||||
${ODBC_LIBRARY} ${JDBC_LIBRARY} ${IPHLPAPI_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 PTDB GetTo_Tdb(void) {return To_Tdb;}
|
||||||
virtual int GetClustered(void) {return 0;}
|
virtual int GetClustered(void) {return 0;}
|
||||||
virtual int IsClustered(void) {return FALSE;}
|
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;}
|
PSZ GetName(void) {return Name;}
|
||||||
int GetIndex(void) {return Index;}
|
int GetIndex(void) {return Index;}
|
||||||
ushort GetColUse(void) {return ColUse;}
|
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
|
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
|
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 CntGetTDB(PGLOBAL g, LPCSTR name, MODE mode, PHC h)
|
||||||
{
|
{
|
||||||
PTDB tdbp;
|
PTDB tdbp = NULL;
|
||||||
PTABLE tabp;
|
PTABLE tabp;
|
||||||
PDBUSER dup = PlgGetUser(g);
|
PDBUSER dup = PlgGetUser(g);
|
||||||
volatile PCATLG cat = (dup) ? dup->Catalog : NULL; // Safe over throw
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
/**************** Cnt H Declares Source Code File (.H) *****************/
|
/**************** Cnt H Declares Source Code File (.H) *****************/
|
||||||
/* Name: CONNECT.H Version 2.4 */
|
/* Name: CONNECT.H Version 2.4 */
|
||||||
|
/* Author Olivier BERTRAND bertrandop@gmail.com */
|
||||||
/* This file contains the some based classes declares. */
|
/* This file contains the some based classes declares. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
#include "filamtxt.h"
|
#include "filamtxt.h"
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
/* Copyright (C) MariaDB Corporation Ab */
|
||||||
#define MSG_ACCESS_VIOLATN "Access violation"
|
#define MSG_ACCESS_VIOLATN "Access violation"
|
||||||
#define MSG_ADD_BAD_TYPE "Array add value type mismatch (%s -> %s)"
|
#define MSG_ADD_BAD_TYPE "Array add value type mismatch (%s -> %s)"
|
||||||
#define MSG_ALLOC_ERROR "Error allocating %s"
|
#define MSG_ALLOC_ERROR "Error allocating %s"
|
||||||
|
@@ -33,18 +33,11 @@
|
|||||||
#include "tabcol.h"
|
#include "tabcol.h"
|
||||||
#include "xtable.h"
|
#include "xtable.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
//#include "subquery.h"
|
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
//#include "token.h"
|
|
||||||
//#include "select.h"
|
|
||||||
#include "xindex.h"
|
#include "xindex.h"
|
||||||
#if defined(MONGO_SUPPORT)
|
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||||
#include "filamtxt.h"
|
|
||||||
#include "tabdos.h"
|
|
||||||
#include "tabjson.h"
|
|
||||||
#include "tabext.h"
|
#include "tabext.h"
|
||||||
#include "tabmgo.h"
|
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||||
#endif // MONGO_SUPPORT
|
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Utility routines. */
|
/* Utility routines. */
|
||||||
@@ -1412,11 +1405,11 @@ PFIL FILTER::Copy(PTABS t)
|
|||||||
} // end of Copy
|
} // end of Copy
|
||||||
#endif // 0
|
#endif // 0
|
||||||
|
|
||||||
|
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Make selector json representation for Mongo tables. */
|
/* Make selector json representation for Mongo tables. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
#if defined(MONGO_SUPPORT)
|
bool FILTER::MakeSelector(PGLOBAL g, PSTRG s)
|
||||||
bool FILTER::MakeSelector(PGLOBAL g, PSTRG s, bool m)
|
|
||||||
{
|
{
|
||||||
s->Append('{');
|
s->Append('{');
|
||||||
|
|
||||||
@@ -1428,29 +1421,21 @@ bool FILTER::MakeSelector(PGLOBAL g, PSTRG s, bool m)
|
|||||||
s->Append(Opc == OP_AND ? "and" : "or");
|
s->Append(Opc == OP_AND ? "and" : "or");
|
||||||
s->Append("\":[");
|
s->Append("\":[");
|
||||||
|
|
||||||
if (((PFIL)Arg(0))->MakeSelector(g, s, m))
|
if (((PFIL)Arg(0))->MakeSelector(g, s))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
s->Append(',');
|
s->Append(',');
|
||||||
|
|
||||||
if (((PFIL)Arg(1))->MakeSelector(g, s, m))
|
if (((PFIL)Arg(1))->MakeSelector(g, s))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
s->Append(']');
|
s->Append(']');
|
||||||
} else {
|
} else {
|
||||||
char *pth, buf[501];
|
|
||||||
|
|
||||||
if (GetArgType(0) != TYPE_COLBLK)
|
if (GetArgType(0) != TYPE_COLBLK)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
s->Append('"');
|
s->Append('"');
|
||||||
|
s->Append(((PCOL)Arg(0))->GetJpath(g, false));
|
||||||
if (m)
|
|
||||||
pth = ((PMGOCOL)Arg(0))->Jpath;
|
|
||||||
else if (!(pth = ((PJCOL)Arg(0))->GetJpath(g, false)))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
s->Append(pth);
|
|
||||||
s->Append("\":{\"$");
|
s->Append("\":{\"$");
|
||||||
|
|
||||||
switch (Opc) {
|
switch (Opc) {
|
||||||
@@ -1472,33 +1457,33 @@ bool FILTER::MakeSelector(PGLOBAL g, PSTRG s, bool m)
|
|||||||
case OP_LE:
|
case OP_LE:
|
||||||
s->Append("lte");
|
s->Append("lte");
|
||||||
break;
|
break;
|
||||||
//case OP_NULL:
|
case OP_NULL:
|
||||||
// s->Append("ne");
|
case OP_LIKE:
|
||||||
// break;
|
case OP_EXIST:
|
||||||
//case OP_LIKE:
|
|
||||||
// s->Append("ne");
|
|
||||||
// break;
|
|
||||||
//case OP_EXIST:
|
|
||||||
// s->Append("ne");
|
|
||||||
// break;
|
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
} // endswitch Opc
|
} // endswitch Opc
|
||||||
|
|
||||||
s->Append("\":");
|
s->Append("\":");
|
||||||
|
|
||||||
if (GetArgType(1) == TYPE_COLBLK)
|
if (GetArgType(1) == TYPE_COLBLK) {
|
||||||
return true;
|
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('}');
|
s->Append('}');
|
||||||
} // endif Opc
|
} // endif Opc
|
||||||
|
|
||||||
s->Append('}');
|
s->Append('}');
|
||||||
return false;
|
return false;
|
||||||
} // end of MakeSelector
|
} // end of MakeSelector
|
||||||
#endif // MONGO_SUPPORT
|
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
/* Make file output of FILTER contents. */
|
/* Make file output of FILTER contents. */
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*************** Filter H Declares Source Code File (.H) ***************/
|
/*************** 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. */
|
/* 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 PXOB CheckSubQuery(PGLOBAL, PSQL);
|
||||||
//virtual bool CheckLocal(PTDB);
|
//virtual bool CheckLocal(PTDB);
|
||||||
//virtual int CheckSpcCol(PTDB tdbp, int n);
|
//virtual int CheckSpcCol(PTDB tdbp, int n);
|
||||||
#if defined(MONGO_SUPPORT)
|
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||||
bool MakeSelector(PGLOBAL g, PSTRG s, bool m);
|
bool MakeSelector(PGLOBAL g, PSTRG s);
|
||||||
#endif // MONGO_SUPPORT
|
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||||
virtual void Printf(PGLOBAL g, FILE *f, uint n);
|
virtual void Printf(PGLOBAL g, FILE *f, uint n);
|
||||||
virtual void Prints(PGLOBAL g, char *ps, uint z);
|
virtual void Prints(PGLOBAL g, char *ps, uint z);
|
||||||
// PFIL Linearize(bool nosep);
|
// PFIL Linearize(bool nosep);
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* GLOBAL.H: Declaration file used by all CONNECT implementations. */
|
/* 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
|
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
|
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
|
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.
|
ha_connect::extra() are hints as to what will be occuring to the request.
|
||||||
|
|
||||||
Happy use!<br>
|
Author Olivier Bertrand
|
||||||
-Olivier
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef USE_PRAGMA_IMPLEMENTATION
|
#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 OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
|
||||||
PQRYRES VirColumns(PGLOBAL g, 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);
|
PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info);
|
||||||
#if defined(MONGO_SUPPORT)
|
#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
|
#endif // MONGO_SUPPORT
|
||||||
int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v);
|
int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v);
|
||||||
void PushWarning(PGLOBAL g, THD *thd, int level);
|
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
|
DTVAL::SetTimeShift(); // Initialize time zone shift once for all
|
||||||
BINCOL::SetEndian(); // Initialize host endian setting
|
BINCOL::SetEndian(); // Initialize host endian setting
|
||||||
#if defined(JDBC_SUPPORT)
|
#if defined(JDBC_SUPPORT)
|
||||||
JDBConn::SetJVM();
|
JAVAConn::SetJVM();
|
||||||
#endif // JDBC_SUPPORT
|
#endif // JDBC_SUPPORT
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
} // end of connect_init_func
|
} // end of connect_init_func
|
||||||
@@ -726,7 +725,7 @@ static int connect_done_func(void *)
|
|||||||
#endif // MONGO_SUPPORT
|
#endif // MONGO_SUPPORT
|
||||||
|
|
||||||
#ifdef JDBC_SUPPORT
|
#ifdef JDBC_SUPPORT
|
||||||
JDBConn::ResetJVM();
|
JAVAConn::ResetJVM();
|
||||||
#endif // JDBC_SUPPORT
|
#endif // JDBC_SUPPORT
|
||||||
|
|
||||||
#if defined(__WIN__)
|
#if defined(__WIN__)
|
||||||
@@ -4081,7 +4080,7 @@ int ha_connect::info(uint flag)
|
|||||||
if (xmod == MODE_ANY || xmod == MODE_ALTER) {
|
if (xmod == MODE_ANY || xmod == MODE_ALTER) {
|
||||||
// Pure info, not a query
|
// Pure info, not a query
|
||||||
pure= true;
|
pure= true;
|
||||||
xp->CheckCleanup();
|
xp->CheckCleanup(xmod == MODE_ANY && valid_query_id == 0);
|
||||||
} // endif xmod
|
} // endif xmod
|
||||||
|
|
||||||
// This is necessary for getting file length
|
// This is necessary for getting file length
|
||||||
@@ -4094,8 +4093,10 @@ int ha_connect::info(uint flag)
|
|||||||
} else
|
} else
|
||||||
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen
|
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen
|
||||||
|
|
||||||
if (!(tdbp= GetTDB(g)))
|
if (!(tdbp = GetTDB(g))) {
|
||||||
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen
|
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
|
||||||
|
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
|
||||||
|
} // endif tdbp
|
||||||
|
|
||||||
valid_info = false;
|
valid_info = false;
|
||||||
} // endif tdbp
|
} // endif tdbp
|
||||||
@@ -5299,16 +5300,18 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
|
|||||||
#if defined(ODBC_SUPPORT)
|
#if defined(ODBC_SUPPORT)
|
||||||
POPARM sop= NULL;
|
POPARM sop= NULL;
|
||||||
PCSZ ucnc= NULL;
|
PCSZ ucnc= NULL;
|
||||||
bool cnc= false;
|
PCSZ tabtyp = NULL;
|
||||||
|
bool cnc= false;
|
||||||
int cto= -1, qto= -1;
|
int cto= -1, qto= -1;
|
||||||
#endif // ODBC_SUPPORT
|
#endif // ODBC_SUPPORT
|
||||||
#if defined(JDBC_SUPPORT)
|
#if defined(JDBC_SUPPORT)
|
||||||
PJPARM sjp= NULL;
|
PJPARM sjp= NULL;
|
||||||
|
#endif // JDBC_SUPPORT
|
||||||
|
#if defined(JDBC_SUPPORT) || defined(MONGO_SUPPORT)
|
||||||
PCSZ driver= NULL;
|
PCSZ driver= NULL;
|
||||||
char *url= NULL;
|
char *url= NULL;
|
||||||
//char *prop= NULL;
|
//char *prop= NULL;
|
||||||
PCSZ tabtyp= NULL;
|
#endif // JDBC_SUPPORT || MONGO_SUPPORT
|
||||||
#endif // JDBC_SUPPORT
|
|
||||||
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
|
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
|
||||||
bool bif, ok= false, dbf= false;
|
bool bif, ok= false, dbf= false;
|
||||||
TABTYPE ttp= TAB_UNDEF;
|
TABTYPE ttp= TAB_UNDEF;
|
||||||
@@ -5361,19 +5364,17 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
|
|||||||
#endif // __WIN__
|
#endif // __WIN__
|
||||||
port= atoi(GetListOption(g, "port", topt->oplist, "0"));
|
port= atoi(GetListOption(g, "port", topt->oplist, "0"));
|
||||||
#if defined(ODBC_SUPPORT)
|
#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"));
|
cto= atoi(GetListOption(g,"ConnectTimeout", topt->oplist, "-1"));
|
||||||
qto= atoi(GetListOption(g,"QueryTimeout", topt->oplist, "-1"));
|
qto= atoi(GetListOption(g,"QueryTimeout", topt->oplist, "-1"));
|
||||||
|
|
||||||
if ((ucnc= GetListOption(g, "UseDSN", topt->oplist)))
|
if ((ucnc= GetListOption(g, "UseDSN", topt->oplist)))
|
||||||
cnc= (!*ucnc || *ucnc == 'y' || *ucnc == 'Y' || atoi(ucnc) != 0);
|
cnc= (!*ucnc || *ucnc == 'y' || *ucnc == 'Y' || atoi(ucnc) != 0);
|
||||||
#endif
|
#endif
|
||||||
#if defined(JDBC_SUPPORT)
|
#if defined(JDBC_SUPPORT) || defined(MONGO_SUPPORT)
|
||||||
driver= GetListOption(g, "Driver", topt->oplist, NULL);
|
driver= GetListOption(g, "Driver", topt->oplist, NULL);
|
||||||
// url= GetListOption(g, "URL", topt->oplist, NULL);
|
#endif // JDBC_SUPPORT || MONGO_SUPPORT
|
||||||
// prop = GetListOption(g, "Properties", topt->oplist, NULL);
|
|
||||||
tabtyp = GetListOption(g, "Tabtype", topt->oplist, NULL);
|
|
||||||
#endif // JDBC_SUPPORT
|
|
||||||
#if defined(PROMPT_OK)
|
#if defined(PROMPT_OK)
|
||||||
cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0"));
|
cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0"));
|
||||||
#endif // PROMPT_OK
|
#endif // PROMPT_OK
|
||||||
@@ -5585,14 +5586,14 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
|
|||||||
ok = true;
|
ok = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
#if defined(MONGO_SUPPORT)
|
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||||
case TAB_MONGO:
|
case TAB_MONGO:
|
||||||
if (!topt->tabname)
|
if (!topt->tabname)
|
||||||
topt->tabname = tab;
|
topt->tabname = tab;
|
||||||
|
|
||||||
ok = true;
|
ok = true;
|
||||||
break;
|
break;
|
||||||
#endif // MONGO_SUPPORT
|
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||||
case TAB_VIR:
|
case TAB_VIR:
|
||||||
ok = true;
|
ok = true;
|
||||||
break;
|
break;
|
||||||
@@ -5733,13 +5734,36 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
|
|||||||
qrp = VirColumns(g, fnc == FNC_COL);
|
qrp = VirColumns(g, fnc == FNC_COL);
|
||||||
break;
|
break;
|
||||||
case TAB_JSON:
|
case TAB_JSON:
|
||||||
qrp = JSONColumns(g, (char*)db, dsn, topt, fnc == FNC_COL);
|
qrp = JSONColumns(g, db, dsn, topt, fnc == FNC_COL);
|
||||||
break;
|
break;
|
||||||
#if defined(MONGO_SUPPORT)
|
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||||
case TAB_MONGO:
|
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;
|
break;
|
||||||
#endif // MONGO_SUPPORT
|
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||||
#if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT)
|
#if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT)
|
||||||
case TAB_XML:
|
case TAB_XML:
|
||||||
qrp = XMLColumns(g, (char*)db, tab, topt, fnc == FNC_COL);
|
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
|
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
|
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 */
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
|
||||||
|
|
||||||
/** @file ha_connect.h
|
/** @file ha_connect.h
|
||||||
|
Author Olivier Bertrand
|
||||||
|
|
||||||
@brief
|
@brief
|
||||||
The ha_connect engine is a prototype storage engine to access external data.
|
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
|
// Timeout and net wait defaults
|
||||||
#define DEFAULT_LOGIN_TIMEOUT -1 // means do not set
|
#define DEFAULT_LOGIN_TIMEOUT -1 // means do not set
|
||||||
#define DEFAULT_QUERY_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 Url; // Driver URL
|
||||||
PCSZ User; // User connect info
|
PCSZ User; // User connect info
|
||||||
PCSZ Pwd; // Password connect info
|
PCSZ Pwd; // Password connect info
|
||||||
//char *Properties; // Connection property list
|
|
||||||
//int Cto; // Connect timeout
|
//int Cto; // Connect timeout
|
||||||
//int Qto; // Query timeout
|
//int Qto; // Query timeout
|
||||||
|
int Version; // Driver version
|
||||||
int Fsize; // Fetch size
|
int Fsize; // Fetch size
|
||||||
bool Scrollable; // Scrollable cursor
|
bool Scrollable; // Scrollable cursor
|
||||||
} JDBCPARM, *PJPARM;
|
} JDBCPARM, *PJPARM;
|
||||||
@@ -28,3 +31,5 @@ PQRYRES JDBCSrcCols(PGLOBAL g, PCSZ src, PJPARM sop);
|
|||||||
PQRYRES JDBCTables(PGLOBAL g, PCSZ db, PCSZ tabpat,
|
PQRYRES JDBCTables(PGLOBAL g, PCSZ db, PCSZ tabpat,
|
||||||
PCSZ tabtyp, int maxres, bool info, PJPARM sop);
|
PCSZ tabtyp, int maxres, bool info, PJPARM sop);
|
||||||
PQRYRES JDBCDrivers(PGLOBAL g, int maxres, bool info);
|
PQRYRES JDBCDrivers(PGLOBAL g, int maxres, bool info);
|
||||||
|
|
||||||
|
#endif // __JDBCCAT_H
|
||||||
|
@@ -53,38 +53,28 @@
|
|||||||
#include "osutil.h"
|
#include "osutil.h"
|
||||||
|
|
||||||
|
|
||||||
#if defined(__WIN__)
|
//#if defined(__WIN__)
|
||||||
extern "C" HINSTANCE s_hModule; // Saved module handle
|
//extern "C" HINSTANCE s_hModule; // Saved module handle
|
||||||
#endif // __WIN__
|
//#endif // __WIN__
|
||||||
#define nullptr 0
|
//#define nullptr 0
|
||||||
|
|
||||||
TYPCONV GetTypeConv();
|
TYPCONV GetTypeConv();
|
||||||
int GetConvSize();
|
int GetConvSize();
|
||||||
extern char *JvmPath; // The connect_jvm_path global variable value
|
//extern char *JvmPath; // The connect_jvm_path global variable value
|
||||||
extern char *ClassPath; // The connect_class_path global variable value
|
//extern char *ClassPath; // The connect_class_path global variable value
|
||||||
|
|
||||||
char *GetJavaWrapper(void); // The connect_java_wrapper 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
|
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Some macro's (should be defined elsewhere to be more accessible) */
|
/* Some macro's (should be defined elsewhere to be more accessible) */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
#if defined(_DEBUG)
|
//#if defined(_DEBUG)
|
||||||
#define ASSERT(f) assert(f)
|
//#define ASSERT(f) assert(f)
|
||||||
#define DEBUG_ONLY(f) (f)
|
//#define DEBUG_ONLY(f) (f)
|
||||||
#else // !_DEBUG
|
//#else // !_DEBUG
|
||||||
#define ASSERT(f) ((void)0)
|
//#define ASSERT(f) ((void)0)
|
||||||
#define DEBUG_ONLY(f) ((void)0)
|
//#define DEBUG_ONLY(f) ((void)0)
|
||||||
#endif // !_DEBUG
|
//#endif // !_DEBUG
|
||||||
|
|
||||||
// To avoid gcc warning
|
// To avoid gcc warning
|
||||||
int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v);
|
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};
|
FLD_SCALE, FLD_RADIX, FLD_NULL, FLD_REM};
|
||||||
unsigned int length[] = {0, 0, 0, 0, 6, 0, 10, 10, 6, 6, 6, 0};
|
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};
|
bool b[] = {true, true, false, false, false, false, false, false, true, true, false, true};
|
||||||
int i, n, ncol = 12;
|
int i, n, ncol = 12;
|
||||||
PCOLRES crp;
|
PCOLRES crp;
|
||||||
PQRYRES qrp;
|
PQRYRES qrp;
|
||||||
JCATPARM *cap;
|
JCATPARM *cap;
|
||||||
JDBConn *jcp = NULL;
|
JDBConn *jcp = NULL;
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* Do an evaluation of the result size. */
|
/* Do an evaluation of the result size. */
|
||||||
@@ -251,7 +241,7 @@ PQRYRES JDBCColumns(PGLOBAL g, PCSZ db, PCSZ table, PCSZ colpat,
|
|||||||
if (!info) {
|
if (!info) {
|
||||||
jcp = new(g)JDBConn(g, NULL);
|
jcp = new(g)JDBConn(g, NULL);
|
||||||
|
|
||||||
if (jcp->Open(sjp) != RC_OK) // openReadOnly + noJDBCdialog
|
if (jcp->Connect(sjp)) // openReadOnly + noJDBCdialog
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (table && !strchr(table, '%')) {
|
if (table && !strchr(table, '%')) {
|
||||||
@@ -337,7 +327,7 @@ PQRYRES JDBCSrcCols(PGLOBAL g, PCSZ src, PJPARM sjp)
|
|||||||
PQRYRES qrp;
|
PQRYRES qrp;
|
||||||
JDBConn *jcp = new(g)JDBConn(g, NULL);
|
JDBConn *jcp = new(g)JDBConn(g, NULL);
|
||||||
|
|
||||||
if (jcp->Open(sjp))
|
if (jcp->Connect(sjp))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (strstr(src, "%s")) {
|
if (strstr(src, "%s")) {
|
||||||
@@ -379,7 +369,7 @@ PQRYRES JDBCTables(PGLOBAL g, PCSZ db, PCSZ tabpat, PCSZ tabtyp,
|
|||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
jcp = new(g)JDBConn(g, NULL);
|
jcp = new(g)JDBConn(g, NULL);
|
||||||
|
|
||||||
if (jcp->Open(sjp) == RC_FX)
|
if (jcp->Connect(sjp))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!maxres)
|
if (!maxres)
|
||||||
@@ -523,37 +513,16 @@ PQRYRES JDBCDrivers(PGLOBAL g, int maxres, bool info)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* JDBConn construction/destruction. */
|
/* 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;
|
xqid = xuid = xid = grs = readid = fetchid = typid = errid = nullptr;
|
||||||
prepid = xpid = pcid = nullptr;
|
prepid = xpid = pcid = nullptr;
|
||||||
chrfldid = intfldid = dblfldid = fltfldid = bigfldid = nullptr;
|
chrfldid = intfldid = dblfldid = fltfldid = bigfldid = nullptr;
|
||||||
objfldid = datfldid = timfldid = tspfldid = nullptr;
|
objfldid = datfldid = timfldid = tspfldid = nullptr;
|
||||||
//m_LoginTimeout = DEFAULT_LOGIN_TIMEOUT;
|
DiscFunc = "JdbcDisconnect";
|
||||||
//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;
|
|
||||||
m_Ncol = 0;
|
m_Ncol = 0;
|
||||||
m_Aff = 0;
|
m_Aff = 0;
|
||||||
m_Rows = 0;
|
//m_Rows = 0;
|
||||||
m_Fetch = 0;
|
m_Fetch = 0;
|
||||||
m_RowsetSize = 0;
|
m_RowsetSize = 0;
|
||||||
m_Updatable = true;
|
m_Updatable = true;
|
||||||
@@ -563,7 +532,6 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp)
|
|||||||
m_Opened = false;
|
m_Opened = false;
|
||||||
m_IDQuoteChar[0] = '"';
|
m_IDQuoteChar[0] = '"';
|
||||||
m_IDQuoteChar[1] = 0;
|
m_IDQuoteChar[1] = 0;
|
||||||
//*m_ErrMsg = '\0';
|
|
||||||
} // end of JDBConn
|
} // end of JDBConn
|
||||||
|
|
||||||
//JDBConn::~JDBConn()
|
//JDBConn::~JDBConn()
|
||||||
@@ -573,55 +541,6 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp)
|
|||||||
|
|
||||||
// } // end of ~JDBConn
|
// } // 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. */
|
/* Utility routine. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -641,381 +560,52 @@ int JDBConn::GetMaxValue(int n)
|
|||||||
} // end of GetMaxValue
|
} // 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(DEVELOPMENT)
|
||||||
#if defined(__WIN__)
|
jpop->Append(
|
||||||
FreeLibrary((HMODULE)LibJvm);
|
";C:/Jconnectors/postgresql-9.4.1208.jar"
|
||||||
#else // !__WIN__
|
";C:/Oracle/ojdbc7.jar"
|
||||||
dlclose(LibJvm);
|
";C:/Apache/commons-dbcp2-2.1.1/commons-dbcp2-2.1.1.jar"
|
||||||
#endif // !__WIN__
|
";C:/Apache/commons-pool2-2.4.2/commons-pool2-2.4.2.jar"
|
||||||
LibJvm = NULL;
|
";C:/Apache/commons-logging-1.2/commons-logging-1.2.jar"
|
||||||
CreateJavaVM = NULL;
|
";C:/Jconnectors/mysql-connector-java-6.0.2-bin.jar"
|
||||||
GetCreatedJavaVMs = NULL;
|
";C:/Jconnectors/mariadb-java-client-2.0.1.jar"
|
||||||
#if defined(_DEBUG)
|
";C:/Jconnectors/sqljdbc42.jar");
|
||||||
GetDefaultJavaVMInitArgs = NULL;
|
#endif // DEVELOPMENT
|
||||||
#endif // _DEBUG
|
} // end of AddJars
|
||||||
} // endif LibJvm
|
|
||||||
|
|
||||||
} // end of ResetJVM
|
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Dynamically link the JVM library. */
|
/* Connect: connect to a data source. */
|
||||||
/* The purpose of this function is to allow using the CONNECT plugin */
|
|
||||||
/* for other table types when the Java JDK is not installed. */
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
bool JDBConn::GetJVM(PGLOBAL g)
|
bool JDBConn::Connect(PJPARM sop)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
int irc = RC_FX;
|
int irc = RC_FX;
|
||||||
bool err = false;
|
bool err = false;
|
||||||
|
jint rc;
|
||||||
jboolean jt = (trace > 0);
|
jboolean jt = (trace > 0);
|
||||||
PGLOBAL& g = m_G;
|
PGLOBAL& g = m_G;
|
||||||
|
|
||||||
// Link or check whether jvm library was linked
|
/*******************************************************************/
|
||||||
if (GetJVM(g))
|
/* Create or attach a JVM. */
|
||||||
return RC_FX;
|
/*******************************************************************/
|
||||||
|
if (Open(g))
|
||||||
// Firstly check whether the jvm was already created
|
return true;
|
||||||
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
|
|
||||||
|
|
||||||
if (!sop) // DRIVER catalog table
|
if (!sop) // DRIVER catalog table
|
||||||
return RC_OK;
|
return false;
|
||||||
|
|
||||||
jmethodID cid = nullptr;
|
jmethodID cid = nullptr;
|
||||||
|
|
||||||
if (gmID(g, cid, "JdbcConnect", "([Ljava/lang/String;IZ)I"))
|
if (gmID(g, cid, "JdbcConnect", "([Ljava/lang/String;IZ)I"))
|
||||||
return RC_FX;
|
return true;
|
||||||
|
|
||||||
// Build the java string array
|
// Build the java string array
|
||||||
jobjectArray parms = env->NewObjectArray(4, // constructs java array of 4
|
jobjectArray parms = env->NewObjectArray(4, // constructs java array of 4
|
||||||
env->FindClass("java/lang/String"), NULL); // Strings
|
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_Scrollable = sop->Scrollable;
|
||||||
m_RowsetSize = sop->Fsize;
|
m_RowsetSize = sop->Fsize;
|
||||||
//m_LoginTimeout = sop->Cto;
|
//m_LoginTimeout = sop->Cto;
|
||||||
@@ -1035,9 +625,6 @@ int JDBConn::Open(PJPARM sop)
|
|||||||
if (sop->Pwd)
|
if (sop->Pwd)
|
||||||
env->SetObjectArrayElement(parms, 3, env->NewStringUTF(sop->Pwd));
|
env->SetObjectArrayElement(parms, 3, env->NewStringUTF(sop->Pwd));
|
||||||
|
|
||||||
//if (sop->Properties)
|
|
||||||
// env->SetObjectArrayElement(parms, 4, env->NewStringUTF(sop->Properties));
|
|
||||||
|
|
||||||
// call method
|
// call method
|
||||||
rc = env->CallIntMethod(job, cid, parms, m_RowsetSize, m_Scrollable);
|
rc = env->CallIntMethod(job, cid, parms, m_RowsetSize, m_Scrollable);
|
||||||
err = Check(rc);
|
err = Check(rc);
|
||||||
@@ -1045,7 +632,7 @@ int JDBConn::Open(PJPARM sop)
|
|||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
sprintf(g->Message, "Connecting: %s rc=%d", Msg, (int)rc);
|
sprintf(g->Message, "Connecting: %s rc=%d", Msg, (int)rc);
|
||||||
return RC_FX;
|
return true;
|
||||||
} // endif Msg
|
} // endif Msg
|
||||||
|
|
||||||
jmethodID qcid = nullptr;
|
jmethodID qcid = nullptr;
|
||||||
@@ -1064,17 +651,18 @@ int JDBConn::Open(PJPARM sop)
|
|||||||
} // endif qcid
|
} // endif qcid
|
||||||
|
|
||||||
if (gmID(g, typid, "ColumnType", "(ILjava/lang/String;)I"))
|
if (gmID(g, typid, "ColumnType", "(ILjava/lang/String;)I"))
|
||||||
return RC_FX;
|
return true;
|
||||||
else
|
else
|
||||||
m_Opened = true;
|
m_Opened = true;
|
||||||
|
|
||||||
return RC_OK;
|
return false;
|
||||||
} // end of Open
|
} // end of Connect
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Execute an SQL command. */
|
/* Execute an SQL command. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
int JDBConn::ExecSQLcommand(PCSZ sql)
|
int JDBConn::ExecuteCommand(PCSZ sql)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
jint n;
|
jint n;
|
||||||
@@ -1110,7 +698,7 @@ int JDBConn::ExecSQLcommand(PCSZ sql)
|
|||||||
} // endif ncol
|
} // endif ncol
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
} // end of ExecSQLcommand
|
} // end of ExecuteCommand
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Fetch next row. */
|
/* Fetch next row. */
|
||||||
@@ -1170,38 +758,12 @@ int JDBConn::Rewind(PCSZ sql)
|
|||||||
jboolean b = env->CallBooleanMethod(job, fetchid, 0);
|
jboolean b = env->CallBooleanMethod(job, fetchid, 0);
|
||||||
|
|
||||||
rbuf = m_Rows;
|
rbuf = m_Rows;
|
||||||
} else if (ExecSQLcommand(sql) != RC_FX)
|
} else if (ExecuteCommand(sql) != RC_FX)
|
||||||
rbuf = 0;
|
rbuf = 0;
|
||||||
|
|
||||||
return rbuf;
|
return rbuf;
|
||||||
} // end of Rewind
|
} // 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. */
|
/* 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. */
|
/* 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;
|
int rc, n = 0;
|
||||||
|
|
||||||
@@ -1565,53 +1127,6 @@ bool JDBConn::SetParam(JDBCCOL *colp)
|
|||||||
return rc;
|
return rc;
|
||||||
} // end of SetParam
|
} // 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. */
|
/* Get the list of Drivers and set it in qrp. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -1677,7 +1192,7 @@ bool JDBConn::SetParam(JDBCCOL *colp)
|
|||||||
jint *n = nullptr;
|
jint *n = nullptr;
|
||||||
jstring label;
|
jstring label;
|
||||||
jmethodID colid = nullptr;
|
jmethodID colid = nullptr;
|
||||||
int rc = ExecSQLcommand(src);
|
int rc = ExecuteCommand(src);
|
||||||
|
|
||||||
if (rc == RC_NF) {
|
if (rc == RC_NF) {
|
||||||
strcpy(g->Message, "Srcdef is not returning a result set");
|
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. */
|
/* Allocate a CONNECT result structure from the JDBC result. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
PQRYRES JDBConn::AllocateResult(PGLOBAL g)
|
PQRYRES JDBConn::AllocateResult(PGLOBAL g, PTDB tdbp)
|
||||||
{
|
{
|
||||||
bool uns;
|
bool uns;
|
||||||
PJDBCCOL colp;
|
PCOL colp;
|
||||||
PCOLRES *pcrp, crp;
|
PCOLRES *pcrp, crp;
|
||||||
PQRYRES qrp;
|
PQRYRES qrp;
|
||||||
|
|
||||||
@@ -2030,8 +1545,7 @@ bool JDBConn::SetParam(JDBCCOL *colp)
|
|||||||
qrp->Nblin = 0;
|
qrp->Nblin = 0;
|
||||||
qrp->Cursor = 0;
|
qrp->Cursor = 0;
|
||||||
|
|
||||||
for (colp = (PJDBCCOL)m_Tdb->Columns; colp;
|
for (colp = tdbp->GetColumns(); colp; colp = colp->GetNext())
|
||||||
colp = (PJDBCCOL)colp->GetNext())
|
|
||||||
if (!colp->IsSpecial()) {
|
if (!colp->IsSpecial()) {
|
||||||
*pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
|
*pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
|
||||||
crp = *pcrp;
|
crp = *pcrp;
|
||||||
@@ -2059,10 +1573,9 @@ bool JDBConn::SetParam(JDBCCOL *colp)
|
|||||||
memset(crp->Nulls, ' ', m_Rows);
|
memset(crp->Nulls, ' ', m_Rows);
|
||||||
} // endelse Nullable
|
} // endelse Nullable
|
||||||
|
|
||||||
colp->SetCrp(crp);
|
((EXTCOL*)colp)->SetCrp(crp);
|
||||||
} // endif colp
|
} // endif colp
|
||||||
|
|
||||||
*pcrp = NULL;
|
*pcrp = NULL;
|
||||||
//qrp->Nblin = n;
|
|
||||||
return qrp;
|
return qrp;
|
||||||
} // end of AllocateResult
|
} // end of AllocateResult
|
||||||
|
@@ -1,61 +1,7 @@
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* JDBConn.h : header file for the JDBC connection classes. */
|
/* JDBConn.h : header file for the JDBC connection classes. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
//nclude <windows.h> /* Windows include file */
|
#include "javaconn.h"
|
||||||
//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
|
|
||||||
|
|
||||||
// JDBC connection to a data source
|
// JDBC connection to a data source
|
||||||
class TDBJDBC;
|
class TDBJDBC;
|
||||||
@@ -66,7 +12,7 @@ class TDBXJDC;
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* JDBConn class. */
|
/* JDBConn class. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
class JDBConn : public BLOCK {
|
class JDBConn : public JAVAConn {
|
||||||
friend class TDBJDBC;
|
friend class TDBJDBC;
|
||||||
friend class TDBXJDC;
|
friend class TDBXJDC;
|
||||||
//friend PQRYRES GetColumnInfo(PGLOBAL, char*&, char *, int, PVBLK&);
|
//friend PQRYRES GetColumnInfo(PGLOBAL, char*&, char *, int, PVBLK&);
|
||||||
@@ -74,118 +20,80 @@ private:
|
|||||||
JDBConn(); // Standard (unused) constructor
|
JDBConn(); // Standard (unused) constructor
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JDBConn(PGLOBAL g, TDBJDBC *tdbp);
|
// Constructor
|
||||||
|
JDBConn(PGLOBAL g, PCSZ wrapper);
|
||||||
|
|
||||||
int Open(PJPARM sop);
|
virtual void AddJars(PSTRG jpop, char sep);
|
||||||
int Rewind(PCSZ sql);
|
PQRYRES AllocateResult(PGLOBAL g, PTDB tdbp);
|
||||||
void Close(void);
|
|
||||||
PQRYRES AllocateResult(PGLOBAL g);
|
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
public:
|
public:
|
||||||
char *GetQuoteChar(void) { return m_IDQuoteChar; }
|
char *GetQuoteChar(void) { return m_IDQuoteChar; }
|
||||||
// Database successfully opened?
|
virtual int GetMaxValue(int infotype);
|
||||||
bool IsOpen(void) { return m_Opened; }
|
|
||||||
//PSZ GetStringInfo(ushort infotype);
|
|
||||||
int GetMaxValue(int infotype);
|
|
||||||
//PSZ GetConnect(void) { return m_Connect; }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Operations
|
// Operations
|
||||||
//void SetLoginTimeout(DWORD sec) {m_LoginTimeout = sec;}
|
virtual bool Connect(PJPARM sop);
|
||||||
//void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;}
|
virtual bool MakeCursor(PGLOBAL g, PTDB tdbp, PCSZ options,
|
||||||
//void SetUserName(PSZ user) {m_User = user;}
|
PCSZ filter, bool pipe) {return true;}
|
||||||
//void SetUserPwd(PSZ pwd) {m_Pwd = pwd;}
|
virtual int GetResultSize(PCSZ sql, PCOL colp);
|
||||||
int GetResultSize(PCSZ sql, JDBCCOL *colp);
|
virtual int ExecuteCommand(PCSZ sql);
|
||||||
int ExecuteQuery(PCSZ sql);
|
virtual int ExecuteQuery(PCSZ sql);
|
||||||
int ExecuteUpdate(PCSZ sql);
|
virtual int ExecuteUpdate(PCSZ sql);
|
||||||
int Fetch(int pos = 0);
|
virtual int Fetch(int pos = 0);
|
||||||
|
virtual void SetColumnValue(int rank, PSZ name, PVAL val);
|
||||||
|
|
||||||
|
// Jdbc operations
|
||||||
bool PrepareSQL(PCSZ sql);
|
bool PrepareSQL(PCSZ sql);
|
||||||
int ExecuteSQL(void);
|
int ExecuteSQL(void); // Prepared statement
|
||||||
bool SetParam(JDBCCOL *colp);
|
bool SetParam(JDBCCOL *colp);
|
||||||
int ExecSQLcommand(PCSZ sql);
|
|
||||||
void SetColumnValue(int rank, PSZ name, PVAL val);
|
|
||||||
int GetCatInfo(JCATPARM *cap);
|
int GetCatInfo(JCATPARM *cap);
|
||||||
//bool GetDataSources(PQRYRES qrp);
|
|
||||||
bool GetDrivers(PQRYRES qrp);
|
bool GetDrivers(PQRYRES qrp);
|
||||||
PQRYRES GetMetaData(PGLOBAL g, PCSZ src);
|
PQRYRES GetMetaData(PGLOBAL g, PCSZ src);
|
||||||
|
int Rewind(PCSZ sql);
|
||||||
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);
|
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
public:
|
public:
|
||||||
//virtual ~JDBConn();
|
//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:
|
protected:
|
||||||
// Members
|
// Members
|
||||||
#if defined(__WIN__)
|
#if 0
|
||||||
static HANDLE LibJvm; // Handle to the jvm DLL
|
JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine)
|
||||||
#else // !__WIN__
|
JNIEnv *env; // Pointer to native interface
|
||||||
static void *LibJvm; // Handle for the jvm shared library
|
jclass jdi; // Pointer to the java wrapper class
|
||||||
#endif // !__WIN__
|
jobject job; // The java wrapper class object
|
||||||
static CRTJVM CreateJavaVM;
|
jmethodID errid; // The GetErrmsg method ID
|
||||||
static GETJVM GetCreatedJavaVMs;
|
#endif // 0
|
||||||
#if defined(_DEBUG)
|
jmethodID xqid; // The ExecuteQuery method ID
|
||||||
static GETDEF GetDefaultJavaVMInitArgs;
|
jmethodID xuid; // The ExecuteUpdate method ID
|
||||||
#endif // _DEBUG
|
jmethodID xid; // The Execute method ID
|
||||||
PGLOBAL m_G;
|
jmethodID grs; // The GetResult method ID
|
||||||
TDBJDBC *m_Tdb;
|
jmethodID readid; // The ReadNext method ID
|
||||||
JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine)
|
jmethodID fetchid; // The Fetch method ID
|
||||||
JNIEnv *env; // Pointer to native interface
|
jmethodID typid; // The ColumnType method ID
|
||||||
jclass jdi; // Pointer to the java wrapper class
|
jmethodID prepid; // The CreatePrepStmt method ID
|
||||||
jobject job; // The java wrapper class object
|
jmethodID xpid; // The ExecutePrep method ID
|
||||||
jmethodID xqid; // The ExecuteQuery method ID
|
jmethodID pcid; // The ClosePrepStmt method ID
|
||||||
jmethodID xuid; // The ExecuteUpdate method ID
|
jmethodID objfldid; // The ObjectField method ID
|
||||||
jmethodID xid; // The Execute method ID
|
jmethodID chrfldid; // The StringField method ID
|
||||||
jmethodID grs; // The GetResult method ID
|
jmethodID intfldid; // The IntField method ID
|
||||||
jmethodID readid; // The ReadNext method ID
|
jmethodID dblfldid; // The DoubleField method ID
|
||||||
jmethodID fetchid; // The Fetch method ID
|
jmethodID fltfldid; // The FloatField method ID
|
||||||
jmethodID typid; // The ColumnType method ID
|
jmethodID datfldid; // The DateField method ID
|
||||||
jmethodID prepid; // The CreatePrepStmt method ID
|
jmethodID timfldid; // The TimeField method ID
|
||||||
jmethodID xpid; // The ExecutePrep method ID
|
jmethodID tspfldid; // The TimestampField method ID
|
||||||
jmethodID pcid; // The ClosePrepStmt method ID
|
jmethodID bigfldid; // The BigintField method ID
|
||||||
jmethodID errid; // The GetErrmsg method ID
|
// PCSZ Msg;
|
||||||
jmethodID objfldid; // The ObjectField method ID
|
// PCSZ m_Wrap;
|
||||||
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;
|
|
||||||
char m_IDQuoteChar[2];
|
char m_IDQuoteChar[2];
|
||||||
PCSZ m_Pwd;
|
PCSZ m_Pwd;
|
||||||
int m_Ncol;
|
int m_Ncol;
|
||||||
int m_Aff;
|
int m_Aff;
|
||||||
int m_Rows;
|
|
||||||
int m_Fetch;
|
int m_Fetch;
|
||||||
int m_RowsetSize;
|
int m_RowsetSize;
|
||||||
jboolean m_Updatable;
|
jboolean m_Updatable;
|
||||||
jboolean m_Transact;
|
jboolean m_Transact;
|
||||||
jboolean m_Scrollable;
|
jboolean m_Scrollable;
|
||||||
bool m_Opened;
|
|
||||||
bool m_Full;
|
bool m_Full;
|
||||||
}; // end of JDBConn class definition
|
}; // 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) ************/
|
/************ MONGO FAM C++ Program Source Code File (.CPP) ************/
|
||||||
/* PROGRAM NAME: mongofam.cpp */
|
/* PROGRAM NAME: mongofam.cpp */
|
||||||
/* ------------- */
|
/* ------------- */
|
||||||
/* Version 1.1 */
|
/* Version 1.3 */
|
||||||
/* */
|
/* */
|
||||||
/* COPYRIGHT: */
|
/* COPYRIGHT: */
|
||||||
/* ---------- */
|
/* ---------- */
|
||||||
@@ -17,26 +17,6 @@
|
|||||||
/* Include relevant sections of the System header files. */
|
/* Include relevant sections of the System header files. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
#include "my_global.h"
|
#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: */
|
/* Include application header files: */
|
||||||
@@ -54,20 +34,8 @@
|
|||||||
|
|
||||||
#if defined(UNIX) || defined(UNIV_LINUX)
|
#if defined(UNIX) || defined(UNIV_LINUX)
|
||||||
#include "osutil.h"
|
#include "osutil.h"
|
||||||
//#define _fileno fileno
|
|
||||||
//#define _O_RDONLY O_RDONLY
|
|
||||||
#endif
|
#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 -------------------------- */
|
/* --------------------------- Class MGOFAM -------------------------- */
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -75,88 +43,39 @@ void mongo_init(bool init)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
MGOFAM::MGOFAM(PJDEF tdp) : DOSFAM((PDOSDEF)NULL)
|
MGOFAM::MGOFAM(PJDEF tdp) : DOSFAM((PDOSDEF)NULL)
|
||||||
{
|
{
|
||||||
Client = NULL;
|
Cmgp = NULL;
|
||||||
Database = NULL;
|
Pcg.Tdbp = NULL;
|
||||||
Collection = NULL;
|
|
||||||
Cursor = NULL;
|
if (tdp) {
|
||||||
Query = NULL;
|
Pcg.Uristr = tdp->Uri;
|
||||||
Opts = NULL;
|
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;
|
To_Fbt = NULL;
|
||||||
Mode = MODE_ANY;
|
Mode = MODE_ANY;
|
||||||
Uristr = tdp->Uri;
|
|
||||||
Db_name = tdp->Schema;
|
|
||||||
Coll_name = tdp->Collname;
|
|
||||||
Options = tdp->Options;
|
|
||||||
Filter = tdp->Filter;
|
|
||||||
Done = false;
|
Done = false;
|
||||||
Pipe = tdp->Pipe;
|
|
||||||
Lrecl = tdp->Lrecl + tdp->Ending;
|
Lrecl = tdp->Lrecl + tdp->Ending;
|
||||||
} // end of MGOFAM standard constructor
|
} // end of MGOFAM standard constructor
|
||||||
|
|
||||||
MGOFAM::MGOFAM(PMGOFAM tdfp) : DOSFAM(tdfp)
|
MGOFAM::MGOFAM(PMGOFAM tdfp) : DOSFAM(tdfp)
|
||||||
{
|
{
|
||||||
Client = tdfp->Client;
|
Pcg = tdfp->Pcg;
|
||||||
Database = NULL;
|
|
||||||
Collection = tdfp->Collection;
|
|
||||||
Cursor = tdfp->Cursor;
|
|
||||||
Query = tdfp->Query;
|
|
||||||
Opts = tdfp->Opts;
|
|
||||||
To_Fbt = tdfp->To_Fbt;
|
To_Fbt = tdfp->To_Fbt;
|
||||||
Mode = tdfp->Mode;
|
Mode = tdfp->Mode;
|
||||||
Uristr = tdfp->Uristr;
|
|
||||||
Db_name = tdfp->Db_name;
|
|
||||||
Coll_name = tdfp->Coll_name;
|
|
||||||
Options = tdfp->Options;
|
|
||||||
Filter = NULL;
|
|
||||||
Done = tdfp->Done;
|
Done = tdfp->Done;
|
||||||
Pipe = tdfp->Pipe;
|
|
||||||
} // end of MGOFAM copy constructor
|
} // 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. */
|
/* Reset: reset position values at the beginning of file. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -175,47 +94,16 @@ int MGOFAM::GetFileLength(PGLOBAL g)
|
|||||||
} // end of GetFileLength
|
} // 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 */
|
/* This function can be called with a null argument to test the */
|
||||||
/* availability of Cardinality implementation (1 yes, 0 no). */
|
/* availability of Cardinality implementation (1 yes, 0 no). */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
int MGOFAM::Cardinality(PGLOBAL g)
|
int MGOFAM::Cardinality(PGLOBAL g)
|
||||||
{
|
{
|
||||||
if (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
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
return (!Init(g)) ? Cmgp->CollSize(g) : 0;
|
||||||
} // end of Cardinality
|
} // end of Cardinality
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -234,268 +122,22 @@ bool MGOFAM::Init(PGLOBAL g)
|
|||||||
if (Done)
|
if (Done)
|
||||||
return false;
|
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) {
|
if (Cmgp->Connect(g))
|
||||||
sprintf(g->Message, "Failed to parse URI: \"%s\"", Uristr);
|
|
||||||
return true;
|
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;
|
Done = true;
|
||||||
return false;
|
return false;
|
||||||
} // end of Init
|
} // 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. */
|
/* OpenTableFile: Open a MongoDB table. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -503,7 +145,7 @@ bool MGOFAM::OpenTableFile(PGLOBAL g)
|
|||||||
{
|
{
|
||||||
Mode = Tdbp->GetMode();
|
Mode = Tdbp->GetMode();
|
||||||
|
|
||||||
if (Pipe && Mode != MODE_READ) {
|
if (Pcg.Pipe && Mode != MODE_READ) {
|
||||||
strcpy(g->Message, "Pipeline tables are read only");
|
strcpy(g->Message, "Pipeline tables are read only");
|
||||||
return true;
|
return true;
|
||||||
} // endif Pipe
|
} // endif Pipe
|
||||||
@@ -511,20 +153,11 @@ bool MGOFAM::OpenTableFile(PGLOBAL g)
|
|||||||
if (Init(g))
|
if (Init(g))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (Mode == MODE_DELETE && !Tdbp->GetNext()) {
|
if (Mode == MODE_DELETE && !Tdbp->GetNext())
|
||||||
// Store the number of deleted lines
|
|
||||||
DelRows = Cardinality(g);
|
|
||||||
|
|
||||||
// Delete all documents
|
// Delete all documents
|
||||||
if (!mongoc_collection_remove(Collection, MONGOC_REMOVE_NONE,
|
return Cmgp->DocDelete(g);
|
||||||
Query, NULL, &Error)) {
|
else if (Mode == MODE_INSERT)
|
||||||
sprintf(g->Message, "Remove all: %s", Error.message);
|
Cmgp->MakeColumnGroups(g);
|
||||||
return true;
|
|
||||||
} // endif remove
|
|
||||||
|
|
||||||
} else if (Mode != MODE_INSERT)
|
|
||||||
if (MakeCursor(g))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} // end of OpenTableFile
|
} // end of OpenTableFile
|
||||||
@@ -589,91 +222,18 @@ int MGOFAM::SkipRecord(PGLOBAL g, bool header)
|
|||||||
return RC_OK; // Dummy
|
return RC_OK; // Dummy
|
||||||
} // end of SkipRecord
|
} // 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. */
|
/* ReadBuffer: Get next document from a collection. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
int MGOFAM::ReadBuffer(PGLOBAL g)
|
int MGOFAM::ReadBuffer(PGLOBAL g)
|
||||||
{
|
{
|
||||||
int rc = RC_OK;
|
int rc = Cmgp->ReadNext(g);
|
||||||
|
|
||||||
if (mongoc_cursor_next(Cursor, &Document)) {
|
if (rc != RC_OK)
|
||||||
char *str = bson_as_json(Document, NULL);
|
return rc;
|
||||||
|
|
||||||
if (trace > 1) {
|
strncpy(Tdbp->GetLine(), Cmgp->GetDocument(g), Lrecl);
|
||||||
bson_iter_t iter;
|
return RC_OK;
|
||||||
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;
|
|
||||||
} // end of ReadBuffer
|
} // end of ReadBuffer
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -681,84 +241,7 @@ int MGOFAM::ReadBuffer(PGLOBAL g)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
int MGOFAM::WriteBuffer(PGLOBAL g)
|
int MGOFAM::WriteBuffer(PGLOBAL g)
|
||||||
{
|
{
|
||||||
int rc = RC_OK;
|
return Cmgp->Write(g);
|
||||||
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;
|
|
||||||
} // end of WriteBuffer
|
} // end of WriteBuffer
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -774,18 +257,7 @@ int MGOFAM::DeleteRecords(PGLOBAL g, int irc)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
void MGOFAM::CloseTableFile(PGLOBAL g, bool)
|
void MGOFAM::CloseTableFile(PGLOBAL g, bool)
|
||||||
{
|
{
|
||||||
if (Query) bson_destroy(Query);
|
Cmgp->Close();
|
||||||
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;
|
|
||||||
Done = false;
|
Done = false;
|
||||||
} // end of CloseTableFile
|
} // end of CloseTableFile
|
||||||
|
|
||||||
@@ -794,9 +266,6 @@ void MGOFAM::CloseTableFile(PGLOBAL g, bool)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
void MGOFAM::Rewind(void)
|
void MGOFAM::Rewind(void)
|
||||||
{
|
{
|
||||||
mongoc_cursor_t *cursor = mongoc_cursor_clone(Cursor);
|
Cmgp->Rewind();
|
||||||
|
|
||||||
mongoc_cursor_destroy(Cursor);
|
|
||||||
Cursor = cursor;
|
|
||||||
} // end of Rewind
|
} // end of Rewind
|
||||||
|
|
||||||
|
@@ -1,21 +1,11 @@
|
|||||||
/************** MongoFam H Declares Source Code File (.H) **************/
|
/************** 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 */
|
/* (C) Copyright to the author Olivier BERTRAND 2017 */
|
||||||
/* */
|
/* */
|
||||||
/* This file contains the MongoDB access method classes declares. */
|
/* This file contains the MongoDB access method classes declares. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
#pragma once
|
#include "cmgoconn.h"
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
/* Include MongoDB library header files. */
|
|
||||||
/***********************************************************************/
|
|
||||||
#include <bson.h>
|
|
||||||
#include <bcon.h>
|
|
||||||
#include <mongoc.h>
|
|
||||||
|
|
||||||
#include "block.h"
|
|
||||||
//#include "array.h"
|
|
||||||
|
|
||||||
typedef class TXTFAM *PTXF;
|
typedef class TXTFAM *PTXF;
|
||||||
typedef class MGOFAM *PMGOFAM;
|
typedef class MGOFAM *PMGOFAM;
|
||||||
@@ -37,6 +27,7 @@ public:
|
|||||||
virtual bool GetUseTemp(void) { return false; }
|
virtual bool GetUseTemp(void) { return false; }
|
||||||
virtual int GetPos(void);
|
virtual int GetPos(void);
|
||||||
virtual int GetNextPos(void);
|
virtual int GetNextPos(void);
|
||||||
|
void SetTdbp(PTDBDOS tdbp) { Tdbp = tdbp; }
|
||||||
virtual PTXF Duplicate(PGLOBAL g) { return (PTXF)new(g) MGOFAM(this); }
|
virtual PTXF Duplicate(PGLOBAL g) { return (PTXF)new(g) MGOFAM(this); }
|
||||||
void SetLrecl(int lrecl) { Lrecl = lrecl; }
|
void SetLrecl(int lrecl) { Lrecl = lrecl; }
|
||||||
|
|
||||||
@@ -63,35 +54,12 @@ protected:
|
|||||||
virtual int RenameTempFile(PGLOBAL g) { return RC_OK; }
|
virtual int RenameTempFile(PGLOBAL g) { return RC_OK; }
|
||||||
virtual int InitDelete(PGLOBAL g, int fpos, int spos);
|
virtual int InitDelete(PGLOBAL g, int fpos, int spos);
|
||||||
bool Init(PGLOBAL g);
|
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
|
// Members
|
||||||
//static PGLOBAL G;
|
CMgoConn *Cmgp; // Points to a C Mongo connection class
|
||||||
mongoc_uri_t *Uri;
|
CMGOPARM Pcg; // Parms passed to Cmgp
|
||||||
mongoc_client_pool_t *Pool; // Thread safe client pool
|
PFBLOCK To_Fbt; // Pointer to temp file block
|
||||||
mongoc_client_t *Client; // The MongoDB client
|
MODE Mode;
|
||||||
mongoc_database_t *Database; // The MongoDB database
|
bool Done; // Init done
|
||||||
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;
|
|
||||||
}; // end of class MGOFAM
|
}; // end of class MGOFAM
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
/* Copyright (C) MariaDB Corporation Ab */
|
||||||
#define MSG_ACCESS_VIOLATN 200
|
#define MSG_ACCESS_VIOLATN 200
|
||||||
#define MSG_ADD_BAD_TYPE 201
|
#define MSG_ADD_BAD_TYPE 201
|
||||||
#define MSG_ALLOC_ERROR 202
|
#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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
#if defined(JDBC_SUPPORT)
|
#if defined(JDBC_SUPPORT)
|
||||||
#define NJDBC
|
#define NJDBC
|
||||||
#include "tabjdbc.h"
|
#include "tabjdbc.h"
|
||||||
#endif // ODBC_SUPPORT
|
#endif // JDBC_SUPPORT
|
||||||
#if defined(PIVOT_SUPPORT)
|
#if defined(PIVOT_SUPPORT)
|
||||||
#include "tabpivot.h"
|
#include "tabpivot.h"
|
||||||
#endif // PIVOT_SUPPORT
|
#endif // PIVOT_SUPPORT
|
||||||
@@ -96,9 +96,9 @@
|
|||||||
#if defined(XML_SUPPORT)
|
#if defined(XML_SUPPORT)
|
||||||
#include "tabxml.h"
|
#include "tabxml.h"
|
||||||
#endif // XML_SUPPORT
|
#endif // XML_SUPPORT
|
||||||
#if defined(MONGO_SUPPORT)
|
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||||
#include "tabmgo.h"
|
#include "mongo.h"
|
||||||
#endif // MONGO_SUPPORT
|
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||||
#if defined(ZIP_SUPPORT)
|
#if defined(ZIP_SUPPORT)
|
||||||
#include "tabzip.h"
|
#include "tabzip.h"
|
||||||
#endif // ZIP_SUPPORT
|
#endif // ZIP_SUPPORT
|
||||||
@@ -133,21 +133,21 @@ TABTYPE GetTypeID(const char *type)
|
|||||||
: (!stricmp(type, "CSV")) ? TAB_CSV
|
: (!stricmp(type, "CSV")) ? TAB_CSV
|
||||||
: (!stricmp(type, "FMT")) ? TAB_FMT
|
: (!stricmp(type, "FMT")) ? TAB_FMT
|
||||||
: (!stricmp(type, "DBF")) ? TAB_DBF
|
: (!stricmp(type, "DBF")) ? TAB_DBF
|
||||||
#ifdef XML_SUPPORT
|
#if defined(XML_SUPPORT)
|
||||||
: (!stricmp(type, "XML")) ? TAB_XML
|
: (!stricmp(type, "XML")) ? TAB_XML
|
||||||
#endif
|
#endif
|
||||||
: (!stricmp(type, "INI")) ? TAB_INI
|
: (!stricmp(type, "INI")) ? TAB_INI
|
||||||
: (!stricmp(type, "VEC")) ? TAB_VEC
|
: (!stricmp(type, "VEC")) ? TAB_VEC
|
||||||
#ifdef ODBC_SUPPORT
|
#if defined(ODBC_SUPPORT)
|
||||||
: (!stricmp(type, "ODBC")) ? TAB_ODBC
|
: (!stricmp(type, "ODBC")) ? TAB_ODBC
|
||||||
#endif
|
#endif
|
||||||
#ifdef JDBC_SUPPORT
|
#if defined(JDBC_SUPPORT)
|
||||||
: (!stricmp(type, "JDBC")) ? TAB_JDBC
|
: (!stricmp(type, "JDBC")) ? TAB_JDBC
|
||||||
#endif
|
#endif
|
||||||
: (!stricmp(type, "MYSQL")) ? TAB_MYSQL
|
: (!stricmp(type, "MYSQL")) ? TAB_MYSQL
|
||||||
: (!stricmp(type, "MYPRX")) ? TAB_MYSQL
|
: (!stricmp(type, "MYPRX")) ? TAB_MYSQL
|
||||||
: (!stricmp(type, "DIR")) ? TAB_DIR
|
: (!stricmp(type, "DIR")) ? TAB_DIR
|
||||||
#ifdef __WIN__
|
#if defined(__WIN__)
|
||||||
: (!stricmp(type, "MAC")) ? TAB_MAC
|
: (!stricmp(type, "MAC")) ? TAB_MAC
|
||||||
: (!stricmp(type, "WMI")) ? TAB_WMI
|
: (!stricmp(type, "WMI")) ? TAB_WMI
|
||||||
#endif
|
#endif
|
||||||
@@ -156,15 +156,15 @@ TABTYPE GetTypeID(const char *type)
|
|||||||
: (!stricmp(type, "OCCUR")) ? TAB_OCCUR
|
: (!stricmp(type, "OCCUR")) ? TAB_OCCUR
|
||||||
: (!stricmp(type, "CATLG")) ? TAB_PRX // Legacy
|
: (!stricmp(type, "CATLG")) ? TAB_PRX // Legacy
|
||||||
: (!stricmp(type, "PROXY")) ? TAB_PRX
|
: (!stricmp(type, "PROXY")) ? TAB_PRX
|
||||||
#ifdef PIVOT_SUPPORT
|
#if defined(PIVOT_SUPPORT)
|
||||||
: (!stricmp(type, "PIVOT")) ? TAB_PIVOT
|
: (!stricmp(type, "PIVOT")) ? TAB_PIVOT
|
||||||
#endif
|
#endif
|
||||||
: (!stricmp(type, "VIR")) ? TAB_VIR
|
: (!stricmp(type, "VIR")) ? TAB_VIR
|
||||||
: (!stricmp(type, "JSON")) ? TAB_JSON
|
: (!stricmp(type, "JSON")) ? TAB_JSON
|
||||||
#ifdef ZIP_SUPPORT
|
#if defined(ZIP_SUPPORT)
|
||||||
: (!stricmp(type, "ZIP")) ? TAB_ZIP
|
: (!stricmp(type, "ZIP")) ? TAB_ZIP
|
||||||
#endif
|
#endif
|
||||||
#ifdef MONGO_SUPPORT
|
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||||
: (!stricmp(type, "MONGO")) ? TAB_MONGO
|
: (!stricmp(type, "MONGO")) ? TAB_MONGO
|
||||||
#endif
|
#endif
|
||||||
: (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY;
|
: (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY;
|
||||||
@@ -557,9 +557,9 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
|
|||||||
#endif // PIVOT_SUPPORT
|
#endif // PIVOT_SUPPORT
|
||||||
case TAB_VIR: tdp= new(g) VIRDEF; break;
|
case TAB_VIR: tdp= new(g) VIRDEF; break;
|
||||||
case TAB_JSON: tdp= new(g) JSONDEF; 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;
|
case TAB_MONGO: tdp = new(g) MGODEF; break;
|
||||||
#endif // MONGO_SUPPORT
|
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||||
#if defined(ZIP_SUPPORT)
|
#if defined(ZIP_SUPPORT)
|
||||||
case TAB_ZIP: tdp= new(g) ZIPDEF; break;
|
case TAB_ZIP: tdp= new(g) ZIPDEF; break;
|
||||||
#endif // ZIP_SUPPORT
|
#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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
/**************** MYCAT H Declares Source Code File (.H) ***************/
|
/**************** MYCAT H Declares Source Code File (.H) ***************/
|
||||||
/* Name: MYCAT.H Version 2.3 */
|
/* Name: MYCAT.H Version 2.3 */
|
||||||
/* */
|
/* Author: Olivier Bertrand */
|
||||||
/* This file contains the CONNECT plugin MYCAT class definitions. */
|
/* This file contains the CONNECT plugin MYCAT class definitions. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
#ifndef __MYCAT__H
|
#ifndef __MYCAT__H
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
/* Copyright (C) MariaDB Corporation Ab */
|
||||||
#ifndef _OS_H_INCLUDED
|
#ifndef _OS_H_INCLUDED
|
||||||
#define _OS_H_INCLUDED
|
#define _OS_H_INCLUDED
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
/* Copyright (C) MariaDB Corporation Ab */
|
||||||
#include "my_global.h"
|
#include "my_global.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
/* Copyright (C) MariaDB Corporation Ab */
|
||||||
#ifndef __OSUTIL_H__
|
#ifndef __OSUTIL_H__
|
||||||
#define __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_VIR = 171, /* Virtual tables am type no */
|
||||||
TYPE_AM_DMY = 172, /* DMY Dummy 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_SET = 180, /* SET Set tables am type no */
|
||||||
TYPE_AM_MYSQL = 192, /* MYSQL access method type no */
|
TYPE_AM_MYSQL = 190, /* MYSQL access method type no */
|
||||||
TYPE_AM_MYX = 193, /* MYSQL EXEC access method type */
|
TYPE_AM_MYX = 191, /* MYSQL EXEC access method type */
|
||||||
TYPE_AM_CAT = 195, /* Catalog access method type no */
|
TYPE_AM_CAT = 192, /* Catalog access method type no */
|
||||||
TYPE_AM_ZIP = 198, /* ZIP access method type no */
|
TYPE_AM_ZIP = 193, /* ZIP access method type no */
|
||||||
TYPE_AM_MGO = 199, /* MGO access method type no */
|
TYPE_AM_MGO = 194, /* MGO access method type no */
|
||||||
TYPE_AM_OUT = 200}; /* Output relations (storage) */
|
TYPE_AM_OUT = 200}; /* Output relations (storage) */
|
||||||
|
|
||||||
enum RECFM {RECFM_NAF = -2, /* Not a file */
|
enum RECFM {RECFM_NAF = -2, /* Not a file */
|
||||||
RECFM_OEM = -1, /* OEM file access method */
|
RECFM_OEM = -1, /* OEM file access method */
|
||||||
|
@@ -104,6 +104,8 @@ protected:
|
|||||||
/* This is the base class for all external tables. */
|
/* This is the base class for all external tables. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
class DllExport TDBEXT : public TDB {
|
class DllExport TDBEXT : public TDB {
|
||||||
|
friend class JAVAConn;
|
||||||
|
friend class JMgoConn;
|
||||||
public:
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
TDBEXT(EXTDEF *tdp);
|
TDBEXT(EXTDEF *tdp);
|
||||||
@@ -164,7 +166,7 @@ protected:
|
|||||||
}; // end of class TDBEXT
|
}; // end of class TDBEXT
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Virual class EXTCOL: external column. */
|
/* Virtual class EXTCOL: external column. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
class DllExport EXTCOL : public COLBLK {
|
class DllExport EXTCOL : public COLBLK {
|
||||||
friend class TDBEXT;
|
friend class TDBEXT;
|
||||||
|
@@ -223,10 +223,10 @@ bool JDBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
|||||||
} // endif Connect
|
} // endif Connect
|
||||||
|
|
||||||
if (Url)
|
if (Url)
|
||||||
rc = ParseURL(g, Url);
|
if ((rc = ParseURL(g, Url)) == RC_FX) {
|
||||||
|
sprintf(g->Message, "Wrong JDBC URL %s", Url);
|
||||||
if (rc == RC_FX) // Error
|
return true;
|
||||||
return true;
|
} // endif rc
|
||||||
|
|
||||||
Wrapname = GetStringCatInfo(g, "Wrapper", NULL);
|
Wrapname = GetStringCatInfo(g, "Wrapper", NULL);
|
||||||
return false;
|
return false;
|
||||||
@@ -305,12 +305,12 @@ TDBJDBC::TDBJDBC(PJDBCDEF tdp) : TDBEXT(tdp)
|
|||||||
if (tdp) {
|
if (tdp) {
|
||||||
Ops.Driver = tdp->Driver;
|
Ops.Driver = tdp->Driver;
|
||||||
Ops.Url = tdp->Url;
|
Ops.Url = tdp->Url;
|
||||||
WrapName = tdp->Wrapname;
|
Wrapname = tdp->Wrapname;
|
||||||
Ops.User = tdp->Username;
|
Ops.User = tdp->Username;
|
||||||
Ops.Pwd = tdp->Password;
|
Ops.Pwd = tdp->Password;
|
||||||
Ops.Scrollable = tdp->Scrollable;
|
Ops.Scrollable = tdp->Scrollable;
|
||||||
} else {
|
} else {
|
||||||
WrapName = NULL;
|
Wrapname = NULL;
|
||||||
Ops.Driver = NULL;
|
Ops.Driver = NULL;
|
||||||
Ops.Url = NULL;
|
Ops.Url = NULL;
|
||||||
Ops.User = NULL;
|
Ops.User = NULL;
|
||||||
@@ -328,7 +328,7 @@ TDBJDBC::TDBJDBC(PTDBJDBC tdbp) : TDBEXT(tdbp)
|
|||||||
{
|
{
|
||||||
Jcp = tdbp->Jcp; // is that right ?
|
Jcp = tdbp->Jcp; // is that right ?
|
||||||
Cnp = tdbp->Cnp;
|
Cnp = tdbp->Cnp;
|
||||||
WrapName = tdbp->WrapName;
|
Wrapname = tdbp->Wrapname;
|
||||||
Ops = tdbp->Ops;
|
Ops = tdbp->Ops;
|
||||||
Prepared = tdbp->Prepared;
|
Prepared = tdbp->Prepared;
|
||||||
Werr = tdbp->Werr;
|
Werr = tdbp->Werr;
|
||||||
@@ -562,7 +562,7 @@ bool TDBJDBC::OpenDB(PGLOBAL g)
|
|||||||
/* Table already open, just replace it at its beginning. */
|
/* Table already open, just replace it at its beginning. */
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
if (Memory == 1) {
|
if (Memory == 1) {
|
||||||
if ((Qrp = Jcp->AllocateResult(g)))
|
if ((Qrp = Jcp->AllocateResult(g, this)))
|
||||||
Memory = 2; // Must be filled
|
Memory = 2; // Must be filled
|
||||||
else
|
else
|
||||||
Memory = 0; // Allocation failed, don't use it
|
Memory = 0; // Allocation failed, don't use it
|
||||||
@@ -596,11 +596,11 @@ bool TDBJDBC::OpenDB(PGLOBAL g)
|
|||||||
/* drivers allowing concurency in getting results ??? */
|
/* drivers allowing concurency in getting results ??? */
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
if (!Jcp)
|
if (!Jcp)
|
||||||
Jcp = new(g)JDBConn(g, this);
|
Jcp = new(g)JDBConn(g, Wrapname);
|
||||||
else if (Jcp->IsOpen())
|
else if (Jcp->IsOpen())
|
||||||
Jcp->Close();
|
Jcp->Close();
|
||||||
|
|
||||||
if (Jcp->Open(&Ops) == RC_FX)
|
if (Jcp->Connect(&Ops))
|
||||||
return true;
|
return true;
|
||||||
else if (Quoted)
|
else if (Quoted)
|
||||||
Quote = Jcp->GetQuoteChar();
|
Quote = Jcp->GetQuoteChar();
|
||||||
@@ -608,7 +608,7 @@ bool TDBJDBC::OpenDB(PGLOBAL g)
|
|||||||
Use = USE_OPEN; // Do it now in case we are recursively called
|
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 (Mode == MODE_READ || Mode == MODE_READX) {
|
||||||
if (Memory > 1 && !Srcdef) {
|
if (Memory > 1 && !Srcdef) {
|
||||||
@@ -625,7 +625,7 @@ bool TDBJDBC::OpenDB(PGLOBAL g)
|
|||||||
} else if (n) {
|
} else if (n) {
|
||||||
Jcp->m_Rows = n;
|
Jcp->m_Rows = n;
|
||||||
|
|
||||||
if ((Qrp = Jcp->AllocateResult(g)))
|
if ((Qrp = Jcp->AllocateResult(g, this)))
|
||||||
Memory = 2; // Must be filled
|
Memory = 2; // Must be filled
|
||||||
else {
|
else {
|
||||||
strcpy(g->Message, "Result set memory allocation failed");
|
strcpy(g->Message, "Result set memory allocation failed");
|
||||||
@@ -1134,11 +1134,11 @@ bool TDBXJDC::OpenDB(PGLOBAL g)
|
|||||||
/* drivers allowing concurency in getting results ??? */
|
/* drivers allowing concurency in getting results ??? */
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
if (!Jcp) {
|
if (!Jcp) {
|
||||||
Jcp = new(g) JDBConn(g, this);
|
Jcp = new(g) JDBConn(g, Wrapname);
|
||||||
} else if (Jcp->IsOpen())
|
} else if (Jcp->IsOpen())
|
||||||
Jcp->Close();
|
Jcp->Close();
|
||||||
|
|
||||||
if (Jcp->Open(&Ops) == RC_FX)
|
if (Jcp->Connect(&Ops))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Use = USE_OPEN; // Do it now in case we are recursively called
|
Use = USE_OPEN; // Do it now in case we are recursively called
|
||||||
@@ -1173,7 +1173,7 @@ int TDBXJDC::ReadDB(PGLOBAL g)
|
|||||||
else
|
else
|
||||||
Query->Set(Cmdlist->Cmd);
|
Query->Set(Cmdlist->Cmd);
|
||||||
|
|
||||||
if ((rc = Jcp->ExecSQLcommand(Query->GetStr())) == RC_FX)
|
if ((rc = Jcp->ExecuteCommand(Query->GetStr())) == RC_FX)
|
||||||
Nerr++;
|
Nerr++;
|
||||||
|
|
||||||
if (rc == RC_NF)
|
if (rc == RC_NF)
|
||||||
|
@@ -41,7 +41,7 @@ protected:
|
|||||||
// Members
|
// Members
|
||||||
PSZ Driver; /* JDBC driver */
|
PSZ Driver; /* JDBC driver */
|
||||||
PSZ Url; /* JDBC driver URL */
|
PSZ Url; /* JDBC driver URL */
|
||||||
PSZ Wrapname; /* Java wrapper name */
|
PSZ Wrapname; /* Java driver name */
|
||||||
}; // end of JDBCDEF
|
}; // end of JDBCDEF
|
||||||
|
|
||||||
#if !defined(NJDBC)
|
#if !defined(NJDBC)
|
||||||
@@ -89,7 +89,7 @@ protected:
|
|||||||
JDBConn *Jcp; // Points to a JDBC connection class
|
JDBConn *Jcp; // Points to a JDBC connection class
|
||||||
JDBCCOL *Cnp; // Points to count(*) column
|
JDBCCOL *Cnp; // Points to count(*) column
|
||||||
JDBCPARM Ops; // Additional parameters
|
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 Prepared; // True when using prepared statement
|
||||||
bool Werr; // Write error
|
bool Werr; // Write error
|
||||||
bool Rerr; // Rewind 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)
|
#if defined(ZIP_SUPPORT)
|
||||||
#include "filamzip.h"
|
#include "filamzip.h"
|
||||||
#endif // ZIP_SUPPORT
|
#endif // ZIP_SUPPORT
|
||||||
|
#if defined(JDBC_SUPPORT)
|
||||||
|
#include "jmgfam.h"
|
||||||
|
#endif // JDBC_SUPPORT
|
||||||
#if defined(MONGO_SUPPORT)
|
#if defined(MONGO_SUPPORT)
|
||||||
#include "mongofam.h"
|
#include "mongofam.h"
|
||||||
#endif // MONGO_SUPPORT
|
#endif // MONGO_SUPPORT
|
||||||
@@ -68,7 +71,7 @@ typedef struct _jncol {
|
|||||||
/* JSONColumns: construct the result blocks containing the description */
|
/* JSONColumns: construct the result blocks containing the description */
|
||||||
/* of all the columns of a table contained inside a JSON file. */
|
/* 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,
|
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
|
||||||
TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING};
|
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];
|
char *p, colname[65], fmt[129];
|
||||||
int i, j, lvl, n = 0;
|
int i, j, lvl, n = 0;
|
||||||
int ncol = sizeof(buftyp) / sizeof(int);
|
int ncol = sizeof(buftyp) / sizeof(int);
|
||||||
PCSZ sep;
|
bool mgo = (GetTypeID(topt->type) == TAB_MONGO);
|
||||||
|
PCSZ sep, level;
|
||||||
PVAL valp;
|
PVAL valp;
|
||||||
JCOL jcol;
|
JCOL jcol;
|
||||||
PJCL jcp, fjcp = NULL, pjcp = NULL;
|
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. */
|
/* Open the input file. */
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
lvl = GetIntegerTableOption(g, topt, "Level", 0);
|
level = GetStringTableOption(g, topt, "Level", NULL);
|
||||||
lvl = (lvl < 0) ? 0 : (lvl > 16) ? 16 : lvl;
|
|
||||||
|
if (level) {
|
||||||
|
lvl = atoi(level);
|
||||||
|
lvl = (lvl > 16) ? 16 : lvl;
|
||||||
|
} else
|
||||||
|
lvl = 0;
|
||||||
|
|
||||||
sep = GetStringTableOption(g, topt, "Separator", ".");
|
sep = GetStringTableOption(g, topt, "Separator", ".");
|
||||||
|
|
||||||
tdp = new(g) JSONDEF;
|
tdp = new(g) JSONDEF;
|
||||||
@@ -119,11 +129,6 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, char *dsn, PTOS topt, bool info)
|
|||||||
#endif // ZIP_SUPPORT
|
#endif // ZIP_SUPPORT
|
||||||
tdp->Fn = GetStringTableOption(g, topt, "Filename", NULL);
|
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)))
|
if (!(tdp->Database = SetPath(g, db)))
|
||||||
return NULL;
|
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->Xcol = GetStringTableOption(g, topt, "Expand", NULL);
|
||||||
tdp->Uri = (dsn && *dsn ? dsn : 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",
|
htrc("File %s objname=%s pretty=%d lvl=%d\n",
|
||||||
tdp->Fn, tdp->Objname, tdp->Pretty, lvl);
|
tdp->Fn, tdp->Objname, tdp->Pretty, lvl);
|
||||||
|
|
||||||
if (tdp->Uri) {
|
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, "Name", NULL);
|
||||||
tdp->Collname = GetStringTableOption(g, topt, "Tabname", tdp->Collname);
|
tdp->Collname = GetStringTableOption(g, topt, "Tabname", tdp->Collname);
|
||||||
tdp->Schema = GetStringTableOption(g, topt, "Dbname", "test");
|
tdp->Schema = GetStringTableOption(g, topt, "Dbname", "test");
|
||||||
tdp->Options = PlugDup(g, "all");
|
tdp->Options = (PSZ)GetStringTableOption(g, topt, "Colist", "all");
|
||||||
// tdp->Pipe = GetBooleanTableOption(g, topt, "Pipeline", false);
|
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;
|
tdp->Pretty = 0;
|
||||||
#else // !MONGO_SUPPORT
|
#else // !MONGO_SUPPORT || JDBC_SUPPORT
|
||||||
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO");
|
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO");
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif // !MONGO_SUPPORT
|
#endif // !MONGO_SUPPORT || JDBC_SUPPORT
|
||||||
} // endif Uri
|
} // endif Uri
|
||||||
|
|
||||||
if (tdp->Pretty == 2) {
|
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;
|
jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetValue(0) : NULL;
|
||||||
} else {
|
} else {
|
||||||
if (!(tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0))) {
|
if (!(tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0)))
|
||||||
sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty);
|
if (!mgo) {
|
||||||
return NULL;
|
sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty);
|
||||||
} // endif lrecl
|
return NULL;
|
||||||
|
} else
|
||||||
|
tdp->Lrecl = 8192; // Should be enough
|
||||||
|
|
||||||
tdp->Ending = GetIntegerTableOption(g, topt, "Ending", CRLF);
|
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;
|
return NULL;
|
||||||
#endif // !ZIP_SUPPORT
|
#endif // !ZIP_SUPPORT
|
||||||
} else if (tdp->Uri) {
|
} 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));
|
tjnp = new(g) TDBJSN(tdp, new(g) MGOFAM(tdp));
|
||||||
#else // !MONGO_SUPPORT
|
#elif !defined(MONGO_SUPPORT)
|
||||||
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO");
|
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;
|
return NULL;
|
||||||
#endif // !MONGO_SUPPORT
|
#endif // MONGO_SUPPORT || JDBC_SUPPORT
|
||||||
} else
|
} else
|
||||||
tjnp = new(g) TDBJSN(tdp, new(g) DOSFAM(tdp));
|
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;
|
jcol.Found = true;
|
||||||
colname[64] = 0;
|
colname[64] = 0;
|
||||||
fmt[128] = 0;
|
fmt[128] = 0;
|
||||||
*fmt = '$';
|
|
||||||
|
|
||||||
if (!tdp->Uri) {
|
if (!tdp->Uri) {
|
||||||
|
*fmt = '$';
|
||||||
fmt[1] = '.';
|
fmt[1] = '.';
|
||||||
p = fmt + 2;
|
p = fmt + 2;
|
||||||
} else
|
} 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. */
|
/* 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
|
} // endswitch jsp
|
||||||
|
|
||||||
goto retry;
|
goto retry;
|
||||||
} else {
|
} else if (lvl >= 0) {
|
||||||
jcol.Type = TYPE_STRING;
|
jcol.Type = TYPE_STRING;
|
||||||
jcol.Len = 256;
|
jcol.Len = 256;
|
||||||
jcol.Scale = 0;
|
jcol.Scale = 0;
|
||||||
jcol.Cbn = true;
|
jcol.Cbn = true;
|
||||||
} // endif's
|
} else
|
||||||
|
continue;
|
||||||
|
|
||||||
// Check whether this column was already found
|
// Check whether this column was already found
|
||||||
for (jcp = fjcp; jcp; jcp = jcp->Next)
|
for (jcp = fjcp; jcp; jcp = jcp->Next)
|
||||||
@@ -461,11 +486,16 @@ JSONDEF::JSONDEF(void)
|
|||||||
Base = 0;
|
Base = 0;
|
||||||
Strict = false;
|
Strict = false;
|
||||||
Sep = '.';
|
Sep = '.';
|
||||||
#if defined(MONGO_SUPPORT)
|
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||||
Uri = NULL;
|
Uri = NULL;
|
||||||
Collname = Schema = Options = Filter = NULL;
|
Collname = Schema = Options = Filter = NULL;
|
||||||
Pipe = false;
|
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
|
} // end of JSONDEF constructor
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -482,7 +512,7 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR, int poff)
|
|||||||
Sep = *GetStringCatInfo(g, "Separator", ".");
|
Sep = *GetStringCatInfo(g, "Separator", ".");
|
||||||
|
|
||||||
if (Uri = GetStringCatInfo(g, "Connect", NULL)) {
|
if (Uri = GetStringCatInfo(g, "Connect", NULL)) {
|
||||||
#if defined(MONGO_SUPPORT)
|
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||||
Collname = GetStringCatInfo(g, "Name",
|
Collname = GetStringCatInfo(g, "Name",
|
||||||
(Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name);
|
(Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name);
|
||||||
Collname = GetStringCatInfo(g, "Tabname", Collname);
|
Collname = GetStringCatInfo(g, "Tabname", Collname);
|
||||||
@@ -490,11 +520,19 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR, int poff)
|
|||||||
Options = GetStringCatInfo(g, "Colist", NULL);
|
Options = GetStringCatInfo(g, "Colist", NULL);
|
||||||
Filter = GetStringCatInfo(g, "Filter", NULL);
|
Filter = GetStringCatInfo(g, "Filter", NULL);
|
||||||
Pipe = GetBoolCatInfo("Pipeline", false);
|
Pipe = GetBoolCatInfo("Pipeline", false);
|
||||||
|
Driver = GetStringCatInfo(g, "Driver", NULL);
|
||||||
|
Version = GetIntCatInfo("Version", 3);
|
||||||
Pretty = 0;
|
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");
|
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO");
|
||||||
return true;
|
return true;
|
||||||
#endif // !MONGO_SUPPORT
|
#endif // !MONGO_SUPPORT && !JDBC_SUPPORT
|
||||||
} // endif Uri
|
} // endif Uri
|
||||||
|
|
||||||
return DOSDEF::DefineAM(g, (Uri ? "XMGO" : "DOS"), poff);
|
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));
|
(m == MODE_UPDATE || m == MODE_DELETE));
|
||||||
|
|
||||||
if (Uri) {
|
if (Uri) {
|
||||||
#if defined(MONGO_SUPPORT)
|
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||||
|
#if !defined(JDBC_SUPPORT)
|
||||||
txfp = new(g) MGOFAM(this);
|
txfp = new(g) MGOFAM(this);
|
||||||
#else // !MONGO_SUPPORT
|
#elif !defined(MONGO_SUPPORT)
|
||||||
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "MONGO");
|
txfp = new(g) JMGFAM(this);
|
||||||
return NULL;
|
#else
|
||||||
#endif // !MONGO_SUPPORT
|
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) {
|
} else if (Zipped) {
|
||||||
#if defined(ZIP_SUPPORT)
|
#if defined(ZIP_SUPPORT)
|
||||||
if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) {
|
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);
|
tdbp = new(g) TDBJSN(this, txfp);
|
||||||
|
|
||||||
#if USE_G
|
#if USE_G
|
||||||
// Allocate the parse work memory
|
if (Lrecl) {
|
||||||
PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL));
|
// Allocate the parse work memory
|
||||||
memset(G, 0, sizeof(GLOBAL));
|
PGLOBAL G = (PGLOBAL)PlugSubAlloc(g, NULL, sizeof(GLOBAL));
|
||||||
G->Sarea_Size = Lrecl * 10;
|
memset(G, 0, sizeof(GLOBAL));
|
||||||
G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size);
|
G->Sarea_Size = Lrecl * 10;
|
||||||
PlugSubSet(G, G->Sarea, G->Sarea_Size);
|
G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size);
|
||||||
G->jump_level = 0;
|
PlugSubSet(G, G->Sarea, G->Sarea_Size);
|
||||||
((TDBJSN*)tdbp)->G = G;
|
G->jump_level = 0;
|
||||||
|
((TDBJSN*)tdbp)->G = G;
|
||||||
|
} else {
|
||||||
|
strcpy(g->Message, "LRECL is not defined");
|
||||||
|
return NULL;
|
||||||
|
} // endif Lrecl
|
||||||
#else
|
#else
|
||||||
((TDBJSN*)tdbp)->G = g;
|
((TDBJSN*)tdbp)->G = g;
|
||||||
#endif
|
#endif
|
||||||
@@ -791,13 +840,16 @@ bool TDBJSN::OpenDB(PGLOBAL g)
|
|||||||
return true;
|
return true;
|
||||||
} // endswitch Jmode
|
} // endswitch Jmode
|
||||||
|
|
||||||
if (Xcol && Txfp->GetAmType() != TYPE_AM_MGO)
|
|
||||||
To_Filter = NULL; // Imcompatible
|
|
||||||
|
|
||||||
} // endif Use
|
} // endif Use
|
||||||
|
|
||||||
return TDBDOS::OpenDB(g);
|
if (TDBDOS::OpenDB(g))
|
||||||
} // end of OpenDB
|
return true;
|
||||||
|
|
||||||
|
if (Xcol)
|
||||||
|
To_Filter = NULL; // Imcompatible
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} // end of OpenDB
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* SkipHeader: Physically skip first header line if applicable. */
|
/* SkipHeader: Physically skip first header line if applicable. */
|
||||||
@@ -1282,7 +1334,7 @@ fin:
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Get Jpath converted to Mongo path. */
|
/* Get Jpath converted to Mongo path. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
char *JSONCOL::GetJpath(PGLOBAL g, bool proj)
|
PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj)
|
||||||
{
|
{
|
||||||
if (Jpath) {
|
if (Jpath) {
|
||||||
char *p1, *p2, *mgopath;
|
char *p1, *p2, *mgopath;
|
||||||
@@ -2204,8 +2256,8 @@ void TDBJSON::CloseDB(PGLOBAL g)
|
|||||||
TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp)
|
TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp)
|
||||||
{
|
{
|
||||||
Topt = tdp->GetTopt();
|
Topt = tdp->GetTopt();
|
||||||
Db = (char*)tdp->GetDB();
|
Db = tdp->GetDB();
|
||||||
Dsn = (char*)tdp->Uri;
|
Dsn = tdp->Uri;
|
||||||
} // end of TDBJCL constructor
|
} // end of TDBJCL constructor
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
|
@@ -36,10 +36,13 @@ class DllExport JSONDEF : public DOSDEF { /* Table description */
|
|||||||
friend class TDBJSON;
|
friend class TDBJSON;
|
||||||
friend class TDBJSN;
|
friend class TDBJSN;
|
||||||
friend class TDBJCL;
|
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)
|
#if defined(MONGO_SUPPORT)
|
||||||
friend class MGOFAM;
|
friend class MGOFAM;
|
||||||
#endif // MONGO_SUPPORT
|
#endif // MONGO_SUPPORT
|
||||||
|
friend PQRYRES JSONColumns(PGLOBAL, PCSZ, PCSZ, PTOS, bool);
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
JSONDEF(void);
|
JSONDEF(void);
|
||||||
@@ -63,13 +66,18 @@ public:
|
|||||||
bool Strict; /* Strict syntax checking */
|
bool Strict; /* Strict syntax checking */
|
||||||
char Sep; /* The Jpath separator */
|
char Sep; /* The Jpath separator */
|
||||||
const char *Uri; /* MongoDB connection URI */
|
const char *Uri; /* MongoDB connection URI */
|
||||||
#if defined(MONGO_SUPPORT)
|
#if defined(MONGO_SUPPORT) || defined(JDBC_SUPPORT)
|
||||||
PCSZ Collname; /* External collection name */
|
PCSZ Collname; /* External collection name */
|
||||||
PCSZ Schema; /* External schema (DB) name */
|
PCSZ Schema; /* External schema (DB) name */
|
||||||
PSZ Options; /* Colist ; Pipe */
|
PSZ Options; /* Colist ; Pipe */
|
||||||
PSZ Filter; /* Filter */
|
PSZ Filter; /* Filter */
|
||||||
|
PSZ Driver; /* MongoDB Driver (C or JAVA) */
|
||||||
bool Pipe; /* True if Colist is a pipeline */
|
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
|
}; // end of JSONDEF
|
||||||
|
|
||||||
/* -------------------------- TDBJSN class --------------------------- */
|
/* -------------------------- TDBJSN class --------------------------- */
|
||||||
@@ -81,6 +89,9 @@ public:
|
|||||||
class DllExport TDBJSN : public TDBDOS {
|
class DllExport TDBJSN : public TDBDOS {
|
||||||
friend class JSONCOL;
|
friend class JSONCOL;
|
||||||
friend class JSONDEF;
|
friend class JSONDEF;
|
||||||
|
#if defined(JDBC_SUPPORT)
|
||||||
|
friend class JMGFAM;
|
||||||
|
#endif // JDBC_SUPPORT
|
||||||
#if defined(MONGO_SUPPORT)
|
#if defined(MONGO_SUPPORT)
|
||||||
friend class MGOFAM;
|
friend class MGOFAM;
|
||||||
#endif // MONGO_SUPPORT
|
#endif // MONGO_SUPPORT
|
||||||
@@ -148,8 +159,13 @@ public:
|
|||||||
class DllExport JSONCOL : public DOSCOL {
|
class DllExport JSONCOL : public DOSCOL {
|
||||||
friend class TDBJSN;
|
friend class TDBJSN;
|
||||||
friend class TDBJSON;
|
friend class TDBJSON;
|
||||||
|
#if defined(JDBC_SUPPORT)
|
||||||
|
friend class JMGFAM;
|
||||||
|
#endif // JDBC_SUPPORT
|
||||||
|
#if defined(MONGO_SUPPORT)
|
||||||
friend class MGOFAM;
|
friend class MGOFAM;
|
||||||
public:
|
#endif // MONGO_SUPPORT
|
||||||
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
|
JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
|
||||||
JSONCOL(JSONCOL *colp, PTDB tdbp); // Constructor used in copy process
|
JSONCOL(JSONCOL *colp, PTDB tdbp); // Constructor used in copy process
|
||||||
@@ -160,7 +176,7 @@ class DllExport JSONCOL : public DOSCOL {
|
|||||||
// Methods
|
// Methods
|
||||||
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
|
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
|
||||||
bool ParseJpath(PGLOBAL g);
|
bool ParseJpath(PGLOBAL g);
|
||||||
char *GetJpath(PGLOBAL g, bool proj);
|
virtual PSZ GetJpath(PGLOBAL g, bool proj);
|
||||||
virtual void ReadColumn(PGLOBAL g);
|
virtual void ReadColumn(PGLOBAL g);
|
||||||
virtual void WriteColumn(PGLOBAL g);
|
virtual void WriteColumn(PGLOBAL g);
|
||||||
|
|
||||||
@@ -252,7 +268,7 @@ class DllExport TDBJCL : public TDBCAT {
|
|||||||
virtual PQRYRES GetResult(PGLOBAL g);
|
virtual PQRYRES GetResult(PGLOBAL g);
|
||||||
|
|
||||||
// Members
|
// Members
|
||||||
PTOS Topt;
|
PTOS Topt;
|
||||||
char *Db;
|
PCSZ Db;
|
||||||
char *Dsn;
|
PCSZ Dsn;
|
||||||
}; // end of class TDBJCL
|
}; // 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) **************/
|
/**************** 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 */
|
/* (C) Copyright to the author Olivier BERTRAND 2017 */
|
||||||
/* */
|
/* */
|
||||||
/* This file contains the MongoDB classes declares. */
|
/* This file contains the MongoDB classes declares. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
#include "osutil.h"
|
#include "mongo.h"
|
||||||
#include "block.h"
|
#include "cmgoconn.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;
|
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Class used to get the columns of a mongo collection. */
|
/* Class used to get the columns of a mongo collection. */
|
||||||
@@ -48,7 +17,7 @@ public:
|
|||||||
MGODISC(PGLOBAL g, int *lg);
|
MGODISC(PGLOBAL g, int *lg);
|
||||||
|
|
||||||
// Functions
|
// 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,
|
bool FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc,
|
||||||
char *pcn, char *pfmt, int i, int k, bool b);
|
char *pcn, char *pfmt, int i, int k, bool b);
|
||||||
|
|
||||||
@@ -62,52 +31,7 @@ public:
|
|||||||
bool all;
|
bool all;
|
||||||
}; // end of MGODISC
|
}; // end of MGODISC
|
||||||
|
|
||||||
/***********************************************************************/
|
/* -------------------------- TDBMGO class --------------------------- */
|
||||||
/* 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;
|
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* This is the MongoDB Table Type class declaration. */
|
/* This is the MongoDB Table Type class declaration. */
|
||||||
@@ -117,10 +41,10 @@ class DllExport TDBMGO : public TDBEXT {
|
|||||||
friend class MGOCOL;
|
friend class MGOCOL;
|
||||||
friend class MGODEF;
|
friend class MGODEF;
|
||||||
friend class MGODISC;
|
friend class MGODISC;
|
||||||
friend PQRYRES MGOColumns(PGLOBAL, char *, PTOS, bool);
|
friend PQRYRES MGOColumns(PGLOBAL, PCSZ, PCSZ, PTOS, bool);
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
TDBMGO(PMGODEF tdp);
|
TDBMGO(MGODEF *tdp);
|
||||||
TDBMGO(TDBMGO *tdbp);
|
TDBMGO(TDBMGO *tdbp);
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
@@ -131,7 +55,6 @@ public:
|
|||||||
virtual PTDB Clone(PTABS t);
|
virtual PTDB Clone(PTABS t);
|
||||||
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
|
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
|
||||||
virtual PCOL InsertSpecialColumn(PCOL colp);
|
virtual PCOL InsertSpecialColumn(PCOL colp);
|
||||||
virtual void SetFilter(PFIL fp);
|
|
||||||
virtual int RowNumber(PGLOBAL g, bool b = FALSE) {return N;}
|
virtual int RowNumber(PGLOBAL g, bool b = FALSE) {return N;}
|
||||||
|
|
||||||
// Database routines
|
// Database routines
|
||||||
@@ -146,35 +69,15 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool Init(PGLOBAL g);
|
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
|
// Members
|
||||||
PGLOBAL G; // Needed by SetFilter
|
CMgoConn *Cmgp; // Points to a C Mongo connection class
|
||||||
mongoc_uri_t *Uri;
|
CMGOPARM Pcg; // Parms passed to Cmgp
|
||||||
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
|
|
||||||
const Item *Cnd; // The first condition
|
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 Fpos; // The current row index
|
||||||
int N; // The current Rownum
|
int N; // The current Rownum
|
||||||
int B; // Array index base
|
int B; // Array index base
|
||||||
bool Done; // Init done
|
bool Done; // Init done
|
||||||
bool Pipe; // True for pipeline
|
|
||||||
}; // end of class TDBMGO
|
}; // end of class TDBMGO
|
||||||
|
|
||||||
/* --------------------------- MGOCOL class -------------------------- */
|
/* --------------------------- MGOCOL class -------------------------- */
|
||||||
@@ -191,26 +94,20 @@ public:
|
|||||||
MGOCOL(MGOCOL *colp, PTDB tdbp); // Constructor used in copy process
|
MGOCOL(MGOCOL *colp, PTDB tdbp); // Constructor used in copy process
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
virtual int GetAmType(void) { return Tmgp->GetAmType(); }
|
virtual int GetAmType(void) { return Tmgp->GetAmType(); }
|
||||||
|
|
||||||
// Methods
|
// 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 ReadColumn(PGLOBAL g);
|
||||||
virtual void WriteColumn(PGLOBAL g);
|
virtual void WriteColumn(PGLOBAL g);
|
||||||
bool AddValue(PGLOBAL g, bson_t *doc, char *key, bool upd);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Default constructor not to be used
|
// Default constructor not to be used
|
||||||
MGOCOL(void) {}
|
MGOCOL(void) {}
|
||||||
char *GetProjPath(PGLOBAL g);
|
|
||||||
char *Mini(PGLOBAL g, const bson_t *bson, bool b);
|
|
||||||
|
|
||||||
// Members
|
// Members
|
||||||
TDBMGO *Tmgp; // To the MGO table block
|
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 *Jpath; // The json path
|
||||||
char *Mbuf; // The Mini buffer
|
|
||||||
}; // end of class MGOCOL
|
}; // end of class MGOCOL
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -226,6 +123,7 @@ protected:
|
|||||||
virtual PQRYRES GetResult(PGLOBAL g);
|
virtual PQRYRES GetResult(PGLOBAL g);
|
||||||
|
|
||||||
// Members
|
// Members
|
||||||
PTOS Topt;
|
PTOS Topt;
|
||||||
char *Db;
|
PCSZ Uri;
|
||||||
|
PCSZ Db;
|
||||||
}; // end of class TDBGOL
|
}; // 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
|
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
|
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.
|
that is a connection with its personnal memory allocation.
|
||||||
|
|
||||||
@note
|
@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. */
|
/* 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();
|
uint worksize= GetWorkSize();
|
||||||
|
|
||||||
PlugCleanup(g, true);
|
PlugCleanup(g, true);
|
||||||
@@ -171,7 +171,7 @@ bool user_connect::CheckCleanup(void)
|
|||||||
g->Mrr = 0;
|
g->Mrr = 0;
|
||||||
last_query_id= thdp->query_id;
|
last_query_id= thdp->query_id;
|
||||||
|
|
||||||
if (trace)
|
if (trace && !force)
|
||||||
printf("=====> Begin new query %llu\n", last_query_id);
|
printf("=====> Begin new query %llu\n", last_query_id);
|
||||||
|
|
||||||
return true;
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
Declaration of the user_connect class.
|
Declaration of the user_connect class.
|
||||||
|
|
||||||
@note
|
@note
|
||||||
|
Author Olivier Bertrand
|
||||||
|
|
||||||
@see
|
@see
|
||||||
/sql/handler.h and /storage/connect/user_connect.cc
|
/sql/handler.h and /storage/connect/user_connect.cc
|
||||||
@@ -53,7 +54,7 @@ public:
|
|||||||
// Implementation
|
// Implementation
|
||||||
bool user_init();
|
bool user_init();
|
||||||
void SetHandler(ha_connect *hc);
|
void SetHandler(ha_connect *hc);
|
||||||
bool CheckCleanup(void);
|
bool CheckCleanup(bool force = false);
|
||||||
bool CheckQueryID(void) {return thdp->query_id > last_query_id;}
|
bool CheckQueryID(void) {return thdp->query_id > last_query_id;}
|
||||||
bool CheckQuery(query_id_t vid) {return last_query_id > vid;}
|
bool CheckQuery(query_id_t vid) {return last_query_id > vid;}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user