📄 jnicli.cpp
字号:
#define _JNI_IMPLEMENTATION_ 1#include <jni.h>#include "fastdb.h"#include "localcli.h"static cli_var_type const cliTypeMap[] = { cli_oid, cli_bool, // TP_BOOL cli_int2, // TP_CHAR cli_int1, // TP_INT1 cli_int2, // TP_INT2 cli_int4, // TP_INT4 cli_int8, // TP_INT8 cli_real4, // TP_REAL4 cli_real8, // TP_REAL8 cli_asciiz, // TP_STRING cli_int8, // TP_DATE cli_array_of_bool, // TP_BOOL_ARRAY cli_array_of_int2, // TP_CHAR_ARRAY cli_array_of_int1, // TP_INT1_ARRAY cli_array_of_int2, // TP_INT2_ARRAY cli_array_of_int4, // TP_INT4_ARRAY cli_array_of_int8, // TP_INT8_ARRAY cli_array_of_real4, // TP_REAL4_ARRAY cli_array_of_real8, // TP_REAL8_ARRAY cli_array_of_string, // TP_STRING_ARRAY};inline char const* getStringBody(JNIEnv* env, jstring str) { return env->GetStringUTFChars(str, 0);}inline void releaseStringBody(JNIEnv* env, jstring str, char const* body) { env->ReleaseStringUTFChars(str, body);}inline int getStringLength(JNIEnv* env, jstring str) { return env->GetStringUTFLength(str);}inline jstring newString(JNIEnv* env, char const* body) { return env->NewStringUTF(body);}class ClassDescriptor { public: int nColumns; cli_field_descriptor* columns; char* names; ~ClassDescriptor() { delete[] columns; delete[] names; }};const size_t VARYING_BLOCK_SIZE = 1024;struct VaryingBlock { VaryingBlock* next; char data[1];};class ObjectBuffer { dbSmallBuffer fixedPart; VaryingBlock* varyingPart; size_t fixedPos; size_t varyingPos; public: void* base() { return fixedPart.base(); } ObjectBuffer() { fixedPos = 0; varyingPos = 0; varyingPart = NULL; } ~ObjectBuffer() { VaryingBlock *curr, *next; for (curr = varyingPart; curr != NULL; curr = next) { next = curr->next; dbFree(curr); } } void* appendFixed(size_t size) { return appendFixed(size, size); } void* appendFixed(size_t size, size_t alignment) { fixedPos = DOALIGN(fixedPos, alignment); fixedPart.put(fixedPos + size); void* ptr = fixedPart.base() + fixedPos; fixedPos += size; return ptr; } void* appendVarying(size_t nElems, size_t elemSize) { varyingPos = DOALIGN(varyingPos, elemSize); size_t size = nElems*elemSize; void* ptr; if (varyingPart != NULL && varyingPos + size <= VARYING_BLOCK_SIZE) { ptr = &varyingPart->data[varyingPos]; varyingPos += size; } else { VaryingBlock* blk = (VaryingBlock*) dbMalloc(sizeof(VaryingBlock*) + (size < VARYING_BLOCK_SIZE ? VARYING_BLOCK_SIZE : size)); blk->next = varyingPart; varyingPart = blk; ptr = varyingPart->data; varyingPos = size; } return ptr; }};class JniResultSet { public: byte* record; size_t pos; dbAnyCursor cursor; bool first; JniResultSet(dbTableDescriptor* desc) : record(new byte[desc->size()]), pos(0), cursor(*desc, dbCursorViewOnly, record), first(true) { memset(record, 0, desc->size()); cursor.reset(); } int size() { return cursor.getNumberOfRecords(); } oid_t next() { pos = 0; if (first) { if (cursor.isEmpty()) { delete this; return 0; } first = false; } else if (!cursor.gotoNext()) { delete this; return 0; } cursor.fetch(); return cursor.currId; } jbyte nextByte() { return (jbyte)record[pos++]; } jshort nextShort() { pos = DOALIGN(pos, sizeof(jshort)); jshort val = *(jshort*)(record + pos); pos += sizeof(jshort); return val; } jint nextInt() { pos = DOALIGN(pos, sizeof(jint)); jint val = *(jint*)(record + pos); pos += sizeof(jint); return val; } jlong nextLong() { pos = DOALIGN(pos, sizeof(jlong)); jlong val = *(jlong*)(record + pos); pos += sizeof(jlong); return val; } jstring nextString(JNIEnv* env) { pos = DOALIGN(pos, sizeof(char*)); jstring val = newString(env, *(char**)(record + pos)); pos += sizeof(char*); return val; } jbooleanArray nextBoolArray(JNIEnv* env) { pos = DOALIGN(pos, sizeof(void*)); cli_array_t* arr = (cli_array_t*)(record + pos); jbooleanArray val = env->NewBooleanArray(arr->size); env->SetBooleanArrayRegion(val, 0, arr->size, (jboolean*)arr->data); pos += sizeof(cli_array_t); return val; } jcharArray nextCharArray(JNIEnv* env) { pos = DOALIGN(pos, sizeof(void*)); cli_array_t* arr = (cli_array_t*)(record + pos); jcharArray val = env->NewCharArray(arr->size); env->SetCharArrayRegion(val, 0, arr->size, (jchar*)arr->data); pos += sizeof(cli_array_t); return val; } jbyteArray nextByteArray(JNIEnv* env) { pos = DOALIGN(pos, sizeof(void*)); cli_array_t* arr = (cli_array_t*)(record + pos); jbyteArray val = env->NewByteArray(arr->size); env->SetByteArrayRegion(val, 0, arr->size, (jbyte*)arr->data); pos += sizeof(cli_array_t); return val; } jshortArray nextShortArray(JNIEnv* env) { pos = DOALIGN(pos, sizeof(void*)); cli_array_t* arr = (cli_array_t*)(record + pos); jshortArray val = env->NewShortArray(arr->size); env->SetShortArrayRegion(val, 0, arr->size, (jshort*)arr->data); pos += sizeof(cli_array_t); return val; } jintArray nextIntArray(JNIEnv* env) { pos = DOALIGN(pos, sizeof(void*)); cli_array_t* arr = (cli_array_t*)(record + pos); jintArray val = env->NewIntArray(arr->size); env->SetIntArrayRegion(val, 0, arr->size, (jint*)arr->data); pos += sizeof(cli_array_t); return val; } jlongArray nextLongArray(JNIEnv* env) { pos = DOALIGN(pos, sizeof(void*)); cli_array_t* arr = (cli_array_t*)(record + pos); jlongArray val = env->NewLongArray(arr->size); env->SetLongArrayRegion(val, 0, arr->size, (jlong*)arr->data); pos += sizeof(cli_array_t); return val; } jfloatArray nextFloatArray(JNIEnv* env) { pos = DOALIGN(pos, sizeof(void*)); cli_array_t* arr = (cli_array_t*)(record + pos); jfloatArray val = env->NewFloatArray(arr->size); env->SetFloatArrayRegion(val, 0, arr->size, (jfloat*)arr->data); pos += sizeof(cli_array_t); return val; } jdoubleArray nextDoubleArray(JNIEnv* env) { pos = DOALIGN(pos, sizeof(void*)); cli_array_t* arr = (cli_array_t*)(record + pos); jdoubleArray val = env->NewDoubleArray(arr->size); env->SetDoubleArrayRegion(val, 0, arr->size, (jdouble*)arr->data); pos += sizeof(cli_array_t); return val; } jobjectArray nextStringArray(JNIEnv* env) { pos = DOALIGN(pos, sizeof(void*)); cli_array_t* arr = (cli_array_t*)(record + pos); int size = (int)arr->size; jobjectArray val = env->NewObjectArray(size, env->FindClass("java/lang/String"), NULL); char** spp = (char**)arr->data; for (int i = 0; i < size; i++) { env->SetObjectArrayElement(val, i, newString(env, spp[i])); } pos += sizeof(cli_array_t); return val; } ~JniResultSet() { delete[] record; }};class JniDatabase : public dbDatabase { private: oid_t tableId; oid_t nextTableId; JNIEnv* env; public: JniDatabase(JNIEnv* env, dbAccessType type, size_t poolSize) : dbDatabase(type, poolSize) { this->env = env; } virtual void handleError(dbErrorClass error, char const* msg, int arg = 0) { jclass cls = env->FindClass("jnicli/CliException"); if (cls != NULL) { env->ThrowNew(cls, msg); } } void open(char const* databaseName, char const* databasePath, int transactionCommitDelay) { if (!dbDatabase::open(databaseName, databasePath, transactionCommitDelay)) { handleError(dbDatabase::DatabaseOpenError, "Failed to open database"); return; } dbTable* table = (dbTable*)getRow(dbMetaTableId); dbTableDescriptor* metatable = new dbTableDescriptor(table); linkTable(metatable, dbMetaTableId); oid_t tid = table->firstRow; nextTableId = tid; while (tid != 0) { table = (dbTable*)getRow(tid); dbTableDescriptor* desc = new dbTableDescriptor(table); linkTable(desc, tid); desc->setFlags(); tid = table->next; } } jstring nextTable() { tableId = nextTableId; if (tableId == 0) { if (!completeDescriptorsInitialization()) { close(); handleError(dbDatabase::DatabaseOpenError, "Referenced table not found"); } return NULL; } dbTable* table = (dbTable*)getRow(tableId); jstring name = newString(env, (char*)((byte*)table + table->name.offs)); nextTableId = table->next; return name; } dbTableDescriptor* createTable(char const* name, ClassDescriptor* clsDesc) { beginTransaction(dbExclusiveLock); dbTableDescriptor* tableDesc = NULL; int rc = dbCLI::create_table(this, name, clsDesc->nColumns, clsDesc->columns); if (rc == cli_unsupported_type) { handleError(dbDatabase::DatabaseOpenError, "Unsupported table field type"); return NULL; } return findTableByName(name); } dbTableDescriptor* updateTable(char const* name, ClassDescriptor* clsDesc) { beginTransaction(dbExclusiveLock); int rc = dbCLI::alter_table(this, name, clsDesc->nColumns, clsDesc->columns); if (rc == cli_unsupported_type) { handleError(dbDatabase::DatabaseOpenError, "Unsupported table field type"); return NULL; } return findTableByName(name); } oid_t insert(dbTableDescriptor* desc, ObjectBuffer* buf) { dbAnyReference ref; char** ptr = (char**)buf->base(); insertRecord(desc, &ref, buf->base()); return ref.getOid(); } JniResultSet* select(dbTableDescriptor* desc, char const* query) { JniResultSet* rs = new JniResultSet(desc); rs->cursor.select(query, dbCursorViewOnly, NULL); return rs; } void update(oid_t oid, dbTableDescriptor* desc, ObjectBuffer* buf) { dbDatabase::update(oid, desc, buf->base()); } int remove(dbTableDescriptor* desc, char const* query) { JniResultSet rs(desc); int result = rs.cursor.select(query, dbCursorForUpdate, NULL); rs.cursor.removeAllSelected(); return result; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -