int subtractDoubleFromNumericVector(MYSQL * sqlConn, rdbVector * result, rdbVector *input1, double y) { /* Both inputs must either be integers or doubles or logic */ if( input1->sxp_type != SXP_TYPE_INTEGER && input1->sxp_type != SXP_TYPE_DOUBLE && input1->sxp_type != SXP_TYPE_LOGIC ) return 0; /* Build the sql string */ int length = strlen(sqlTemplateSimpleNumericBinary) + strlen(MINUS_SIGN) + strlen(input1->tableName) + MAX_DOUBLE_LENGTH + 1; char *sqlString = malloc( length * sizeof(char) ); sprintf(sqlString, sqlTemplateSimpleNumericBinary, MINUS_SIGN, y, input1->tableName); /* Create the results view */ initRDBVector(&result, 1, 0); result->size = input1->size; int success = 0; success = createNewDoubleVectorView(sqlConn, result, sqlString); free(sqlString); /* Create the view references */ if( success ) createVectorViewReferences(sqlConn, result, input1, input1); else result->size = 0; return success; }
int internalHandleNumericBinOp(MYSQL * sqlConn, rdbVector * result, rdbVector * input1, rdbVector * input2, char * sign, int forceDouble) { /* Both inputs must either be integers or doubles or logic */ if( input1->sxp_type != SXP_TYPE_INTEGER && input1->sxp_type != SXP_TYPE_DOUBLE && input1->sxp_type != SXP_TYPE_LOGIC ) return 0; if( input2->sxp_type != SXP_TYPE_INTEGER && input2->sxp_type != SXP_TYPE_DOUBLE && input2->sxp_type != SXP_TYPE_LOGIC ) return 0; /* Build the sql string and create the view */ char * sqlString; buildNumericBinaryOpsSQL(input1, input2, sign, &sqlString); initRDBVector(&result, 1, 0); result->size = (input1->size > input2->size)? input1->size : input2->size; int success = 0; if( (input1->sxp_type == SXP_TYPE_INTEGER || input1->sxp_type == SXP_TYPE_LOGIC ) && (input2->sxp_type == SXP_TYPE_INTEGER || input2->sxp_type == SXP_TYPE_LOGIC ) && !forceDouble) { success = createNewIntegerVectorView(sqlConn, result, sqlString); } else { success = createNewDoubleVectorView(sqlConn, result, sqlString); } free(sqlString); if( success ) createVectorViewReferences(sqlConn, result, input1, input2); else result->size = 0; return success; }
SEXP duplicateOrConvert(SEXP orig, int (*func)(MYSQL*,rdbVector*,rdbVector*), MYSQL *sqlconn, int needConvert) { SEXP x, tname; rdbVector *info; rdbVector *origInfo = getInfo(orig); /* if this dbvector is shared by more than one variable we should copy before set */ if (origInfo->sxp_spare > 1 || needConvert) { PROTECT(x = duplicate(orig)); Rprintf("new address %p \n",x); SEXP s = R_do_slot(x,install("info")); info = (rdbVector*)RAW(s); initRDBVector(info); info->sxp_spare = 0; func(sqlconn, origInfo, info); Rprintf("duplicated into table %s\n",info->tableName); /* set tablename slot */ PROTECT(tname = ScalarString(mkChar(info->tableName))); R_do_slot_assign(x, install("tablename"), tname); free(info->tableName); /* register finalizer for the new duplicate */ rdbVector *ptr = malloc(sizeof(rdbVector)); *ptr = *info; SEXP rptr; R_do_slot_assign(x, install("ext"), (rptr=R_MakeExternalPtr(ptr, R_NilValue, R_NilValue))); R_RegisterCFinalizerEx(rptr, rdbVectorFinalizer, TRUE); origInfo->sxp_spare--; UNPROTECT(2); } else { x = orig; /* set ref counter to 0 because it'll be incremented when the result is bound to a name */ origInfo->sxp_spare = 0; /* rdbVector oldInfo = *origInfo; origInfo->tableName = calloc(MAX_TABLE_NAME, sizeof(char)); func(sqlconn, &oldInfo, origInfo); */ /* save new table name */ /* PROTECT(tname = ScalarString(mkChar(origInfo->tableName))); R_do_slot_assign(x, install("tablename"), tname); UNPROTECT(1); */ /* update finalizer */ /* SEXP rptr = R_do_slot(x, install("ext")); rdbVector *ptr = R_ExternalPtrAddr(rptr); rdbVector *ptr = malloc(sizeof(rdbVector)); *ptr = *info; rep->tableName = calloc(MAX_TABLE_NAME, sizeof(char)); strcpy(ptr->tableName, info->tableName); SEXP rptr; R_do_slot_assign(x, install("ext"), (rptr=R_MakeExternalPtr(ptr, R_NilValue, R_NilValue))); R_RegisterCFinalizerEx(rptr, rdbvectorFinalizer, TRUE); */ } return x; }
SEXP math_dbvector(SEXP x, SEXP op) { SEXP ans, rinfo, rtablename, rptr; rdbVector *xinfo = getInfo(x); MYSQL *sqlconn = NULL; int success = connectToLocalDB(&sqlconn); if(!success || sqlconn == NULL) { error("cannot connect to local db\n"); return R_NilValue; } PROTECT(ans = R_do_new_object(R_getClassDef("dbvector"))); PROTECT(rinfo = allocVector(RAWSXP,sizeof(rdbVector))); rdbVector *vec = (rdbVector*)RAW(rinfo); vec->tableName = malloc(MAX_TABLE_NAME*sizeof(char)); initRDBVector(&vec, 0, 0); if (strcmp(CHAR(asChar(op)), "sin") == 0) { switch(xinfo->sxp_type) { case INTSXP: case REALSXP: performNumericSin(sqlconn, xinfo, vec); break; case CPLXSXP: performComplexSin(sqlconn, xinfo, vec); break; default: free(vec->tableName); mysql_close(sqlconn); UNPROTECT(2); error("wrong type"); } } else if (strcmp(CHAR(asChar(op)), "cos") == 0) { switch(xinfo->sxp_type) { case INTSXP: case REALSXP: performNumericCos(sqlconn, xinfo, vec); break; case CPLXSXP: performComplexCos(sqlconn, xinfo, vec); break; default: free(vec->tableName); mysql_close(sqlconn); UNPROTECT(2); error("wrong type"); } } else { free(vec->tableName); mysql_close(sqlconn); UNPROTECT(2); error("wrong type"); } PROTECT(rtablename= allocVector(STRSXP, 1)); SET_STRING_ELT(rtablename, 0, mkChar(vec->tableName)); R_do_slot_assign(ans, install("tablename"), rtablename); R_do_slot_assign(ans, install("info"), rinfo); /* register finalizer */ rdbVector *ptr = malloc(sizeof(rdbVector)); *ptr = *vec; PROTECT(rptr = R_MakeExternalPtr(ptr, R_NilValue, R_NilValue)); R_do_slot_assign(ans, install("ext"), rptr); R_RegisterCFinalizerEx(rptr, rdbVectorFinalizer, TRUE); UNPROTECT(4); return ans; }
int internalHandleComplexBinOp(MYSQL * sqlConn, rdbVector * result, rdbVector * input1, rdbVector * input2, int op) { /* Create some temporary rdbVector objects */ rdbVector * cInput1; rdbVector * cInput2; if( input1->sxp_type == SXP_TYPE_INTEGER || input1->sxp_type == SXP_TYPE_DOUBLE || input1->sxp_type == SXP_TYPE_LOGIC ) { initRDBVector(&cInput1, input1->isView, 1); if( !convertNumericToComplex(sqlConn, input1, cInput1) ) { clearRDBVector(&cInput1); return 0; } } else if( input1->sxp_type == SXP_TYPE_COMPLEX ) { copyRDBVector(&cInput1, input1, 1); } else { return 0; } if( input2->sxp_type == SXP_TYPE_INTEGER || input2->sxp_type == SXP_TYPE_DOUBLE || input2->sxp_type == SXP_TYPE_LOGIC ) { initRDBVector(&cInput2, input2->isView, 1); if( !convertNumericToComplex(sqlConn, input2, cInput2) ) { clearRDBVector(&cInput1); clearRDBVector(&cInput2); return 0; } } else if( input2->sxp_type == SXP_TYPE_COMPLEX ) { copyRDBVector(&cInput2, input2, 1); } else { clearRDBVector(&cInput1); return 0; } /* Build the sql string */ char * sqlString; switch( op ) { case PLUS_OP: buildComplexAddSubSQL(cInput1, cInput2, PLUS_SIGN, &sqlString); break; case MINUS_OP: buildComplexAddSubSQL(cInput1, cInput2, MINUS_SIGN, &sqlString); break; case MULT_OP: buildComplexMultDivSQL(cInput1, cInput2, sqlTemplateComplexMultiply_EQ, sqlTemplateComplexMultiply_NE, &sqlString); break; case DIV_OP: buildComplexMultDivSQL(cInput1, cInput2, sqlTemplateComplexDivide_EQ, sqlTemplateComplexDivide_NE, &sqlString); break; default: clearRDBVector(&cInput1); clearRDBVector(&cInput2); return 0; } initRDBVector(&result, 1, 0); result->size = (cInput1->size > cInput2->size)? cInput1->size : cInput2->size; /* Create the view */ int success = createNewComplexVectorView(sqlConn, result, sqlString); if( success ) createVectorViewReferences(sqlConn, result, cInput1, cInput2); else result->size = 0; /* Clean up */ free(sqlString); clearRDBVector(&cInput1); clearRDBVector(&cInput2); return success; }