void MADB_CopyMadbTimestamp(MYSQL_TIME *tm, MADB_Desc *Ard, MADB_DescRecord *ArdRecord, int Type, unsigned long RowNumber) { void *DataPtr= GetBindOffset(Ard, ArdRecord, ArdRecord->DataPtr, RowNumber, ArdRecord->OctetLength); switch(Type) { case SQL_C_TIMESTAMP: case SQL_C_TYPE_TIMESTAMP: { SQL_TIMESTAMP_STRUCT *ts= (SQL_TIMESTAMP_STRUCT *)DataPtr; /* if (!tm->year) { time_t sec_time; struct tm * cur_tm; sec_time= time(NULL); cur_tm= localtime(&sec_time); ts->year= 1900 + cur_tm->tm_year; ts->month= cur_tm->tm_mon + 1; ts->day= cur_tm->tm_mday; } else */ { ts->year= tm->year; ts->month= tm->month; ts->day= tm->day; } ts->hour= tm->hour; ts->minute= tm->minute; ts->second= tm->second; ts->fraction= tm->second_part * 1000; if (ts->year + ts->month + ts->day + ts->hour + ts->minute + ts->fraction + ts->second == 0) if (ArdRecord->IndicatorPtr) *ArdRecord->IndicatorPtr= SQL_NULL_DATA; } break; case SQL_C_TIME: case SQL_TYPE_TIME: { SQL_TIME_STRUCT *ts= (SQL_TIME_STRUCT *)DataPtr; ts->hour= tm->hour; ts->minute= tm->minute; ts->second= tm->second; if (ts->hour + ts->minute + ts->second == 0) if (ArdRecord->IndicatorPtr) *ArdRecord->IndicatorPtr= SQL_NULL_DATA; } break; case SQL_C_DATE: case SQL_TYPE_DATE: { SQL_DATE_STRUCT *ts= (SQL_DATE_STRUCT *)DataPtr; ts->year= tm->year; ts->month= tm->month; ts->day= tm->day; if (ts->year + ts->month + ts->day == 0) if (ArdRecord->IndicatorPtr) *ArdRecord->IndicatorPtr= SQL_NULL_DATA; } break; } }
void MADB_CleanBulkOperData(MADB_Stmt *Stmt, unsigned int ParamOffset) { if (MADB_DOING_BULK_OPER(Stmt)) { MADB_DescRecord *CRec; void *DataPtr= NULL; MYSQL_BIND *MaBind= NULL; int i; for (i= ParamOffset; i < MADB_STMT_PARAM_COUNT(Stmt); ++i) { if (CRec= MADB_DescGetInternalRecord(Stmt->Apd, i, MADB_DESC_READ)) { MaBind= &Stmt->params[i - ParamOffset]; DataPtr= GetBindOffset(Stmt->Apd, CRec, CRec->DataPtr, 0, CRec->OctetLength); if (MaBind->buffer != DataPtr) { switch (CRec->ConciseType) { case DATETIME_TYPES: if (CanUseStructArrForDatetime(Stmt) == FALSE) { MADB_FREE(MaBind->buffer); break; } /* Otherwise falling through and do the same as for others */ case SQL_C_WCHAR: case SQL_C_NUMERIC: { unsigned int i; for (i= 0; i < Stmt->Bulk.ArraySize; ++i) { MADB_FREE(((char**)MaBind->buffer)[i]); } } /* falling through */ default: MADB_FREE(MaBind->buffer); } } MADB_FREE(MaBind->length); MADB_FREE(MaBind->u.indicator); } } Stmt->Bulk.ArraySize= 0; Stmt->Bulk.HasRowsToSkip= 0; } }
/* Checking if column ignored in all bound rows. Should hel*/ BOOL MADB_ColumnIgnoredInAllRows(MADB_Desc *Desc, MADB_DescRecord *Rec) { SQLULEN row; SQLLEN *IndicatorPtr; for (row= 0; row < Desc->Header.ArraySize; ++row) { IndicatorPtr= (SQLLEN *)GetBindOffset(Desc, Rec, Rec->IndicatorPtr, row, sizeof(SQLLEN)); if (IndicatorPtr == NULL || *IndicatorPtr != SQL_COLUMN_IGNORE) { return FALSE; } } return TRUE; }
int MADB_FindNextDaeParam(MADB_Desc *Desc, int InitialParam, SQLSMALLINT RowNumber) { int i; MADB_DescRecord *Record; for (i= InitialParam > -1 ? InitialParam + 1 : 0; i < Desc->Header.Count; i++) { if ((Record= MADB_DescGetInternalRecord(Desc, i, MADB_DESC_READ))) { if (Record->OctetLengthPtr) { /* Stmt->DaeRowNumber is 1 based */ SQLLEN *OctetLength = (SQLLEN *)GetBindOffset(Desc, Record, Record->OctetLengthPtr, RowNumber > 1 ? RowNumber - 1 : 0, sizeof(SQLLEN)); if (PARAM_IS_DAE(OctetLength)) { return i; } } } } return MADB_NOPARAM; }
/* {{{ MADB_CharToSQLNumeric */ int MADB_CharToSQLNumeric(char *buffer, MADB_Desc *Ard, MADB_DescRecord *ArdRecord, unsigned long RowNumber) { char *p; SQL_NUMERIC_STRUCT *number= (SQL_NUMERIC_STRUCT *)GetBindOffset(Ard, ArdRecord, ArdRecord->DataPtr, RowNumber, ArdRecord->OctetLength); int ret= 0; if (!buffer || !number) return ret; p= trim(buffer); MADB_NumericInit(number, ArdRecord); if (!(number->sign= (*p=='-') ? 0 : 1)) p++; if (!*p) return FALSE; if (number->precision == 0) { number->precision= MADB_DEFAULT_PRECISION; } while (*p=='0') p++; if (*p) { int i; int bit, hval, tv, dig, sta, olen; int tmp_digit= 0; int leading_zeros= 0; char *dot= strchr(p, '.'); char digits[100]; short digits_count= 0; /* Overflow check */ if (number->precision > 0 && (dot - p) > number->precision) return MADB_ERR_22003; if (dot && number->scale > 0) { short digits_total= 0, digits_significant= 0; digits_count= dot - p; memcpy(digits, p, digits_count); p= dot + 1; while (*p) { /* ignore non numbers */ if (!isdigit(*p)) break; digits_total++; /* ignore trailing zeros */ if (*p != '0') digits_significant= digits_total; p++; } /* check possible overflow */ digits_significant= MIN(digits_significant,number->scale); if (digits_count + digits_significant > number->precision) { int i; /* if digits are zero there is no overflow */ for (i=1; i <= digits_significant; i++) { p= dot + i; if (*p != '0') return MADB_ERR_22003; } } memcpy(digits + digits_count, dot + 1, digits_significant); digits_count+= digits_significant; } else { char *start= p; while (*p && isdigit(*p)) p++; /* check overflow */ if (p - start > number->precision) { return MADB_ERR_22003; } digits_count= p - start; memcpy(digits, start, digits_count); number->scale= ArdRecord->Scale ? ArdRecord->Scale : 0; } /* Rounding */ if (number->scale < 0) { int64_t OldVal, Val; int64_t RoundNumber= (int64_t)pow(10.0, -number->scale); digits[number->precision]= 0; Val= _atoi64(digits); OldVal= Val; Val= (Val + RoundNumber / 2) / RoundNumber * RoundNumber; if (OldVal != Val) return MADB_ERR_22003; _i64toa(Val, digits, 10); digits_count= strlen(digits); if (digits_count > number->precision) return MADB_ERR_22003; } digits_count= MIN(digits_count, 38); for (hval = 0, bit = 1L, sta = 0, olen = 0; sta < digits_count;) { for (dig = 0, i = sta; i < digits_count; i++) { tv = dig * 10 + digits[i] - '0'; dig = tv % 2; digits[i] = tv / 2 + '0'; if (i == sta && tv < 2) sta++; } if (dig > 0) hval |= bit; bit <<= 1; if (bit >= (1L << 8)) { number->val[olen++] = hval; hval = 0; bit = 1L; if (olen >= SQL_MAX_NUMERIC_LEN - 1) { //number->scale = sta - number->precision; //ret= MADB_ERR_22003; break; } } } if (hval && olen < SQL_MAX_NUMERIC_LEN - 1) number->val[olen++] = hval; } return ret; }
/* Assuming that bulk insert can't go with DAE(and that unlikely ever changes). And that it has been checked before this call, and we can't have DAE here */ SQLRETURN MADB_ExecuteBulk(MADB_Stmt *Stmt, unsigned int ParamOffset) { unsigned int i, IndIdx= -1; unsigned long Dummy; for (i= ParamOffset; i < ParamOffset + MADB_STMT_PARAM_COUNT(Stmt); ++i) { MADB_DescRecord *CRec, *SqlRec; SQLLEN *IndicatorPtr= NULL; SQLLEN *OctetLengthPtr= NULL; void *DataPtr= NULL; MYSQL_BIND *MaBind= &Stmt->params[i - ParamOffset]; SQLULEN row, Start= Stmt->ArrayOffset; if ((CRec= MADB_DescGetInternalRecord(Stmt->Apd, i, MADB_DESC_READ)) && (SqlRec= MADB_DescGetInternalRecord(Stmt->Ipd, i, MADB_DESC_READ))) { /* check if parameter was bound */ if (!CRec->inUse) { return MADB_SetError(&Stmt->Error, MADB_ERR_07002, NULL, 0); } if (MADB_ConversionSupported(CRec, SqlRec) == FALSE) { return MADB_SetError(&Stmt->Error, MADB_ERR_07006, NULL, 0); } MaBind->length= NULL; IndicatorPtr= (SQLLEN *)GetBindOffset(Stmt->Apd, CRec, CRec->IndicatorPtr, 0, sizeof(SQLLEN)); OctetLengthPtr= (SQLLEN *)GetBindOffset(Stmt->Apd, CRec, CRec->OctetLengthPtr, 0, sizeof(SQLLEN)); DataPtr= GetBindOffset(Stmt->Apd, CRec, CRec->DataPtr, 0, CRec->OctetLength); /* If these are the same pointers, setting indicator to NULL to simplify things a bit */ if (IndicatorPtr == OctetLengthPtr) { IndicatorPtr= NULL; } /* Well, specs kinda say, that both values and lenghts arrays should be set(in instruction to param array operations) But there is no error/sqlstate for the case if any of those pointers is not set. Thus we assume that is possible */ if (DataPtr == NULL) { /* Special case - DataPtr is not set, we treat it as all values are NULL. Setting indicators and moving on next param */ RETURN_ERROR_OR_CONTINUE(MADB_InitIndicatorArray(Stmt, MaBind, MADB_MapIndicatorValue(SQL_NULL_DATA))); continue; } /* Sets Stmt->Bulk.HasRowsToSkip if needed, since it traverses and checks status array anyway */ RETURN_ERROR_OR_CONTINUE(MADB_InitBulkOperBuffers(Stmt, CRec, DataPtr, OctetLengthPtr, IndicatorPtr, SqlRec->ConciseType, MaBind)); if (MaBind->u.indicator != NULL && IndIdx == (unsigned int)-1) { IndIdx= i - ParamOffset; } /* Doing it on last parameter - just to do do this once, and to use already allocated indicator array. Little stupid optimization. But it's actually even a bit simpler this way */ if (i == ParamOffset + MADB_STMT_PARAM_COUNT(Stmt) - 1 && Stmt->Bulk.HasRowsToSkip) { if (IndIdx == (unsigned int)-1) { IndIdx= 0; } for (row= Start; row < Start + Stmt->Apd->Header.ArraySize; ++row) { if (Stmt->Apd->Header.ArrayStatusPtr[row] == SQL_PARAM_IGNORE) { MADB_SetIndicatorValue(Stmt, &Stmt->params[IndIdx], (unsigned int)row, SQL_PARAM_IGNORE); } } } if (MADB_AppBufferCanBeUsed(CRec->ConciseType, SqlRec->ConciseType)) { /* Everything has been done for such column already */ continue; } /* We either have skipped rows or need to convert parameter values/convert array */ for (row= Start; row < Start + Stmt->Apd->Header.ArraySize; ++row, DataPtr= (char*)DataPtr + CRec->OctetLength) { void *Buffer= (char*)MaBind->buffer + row*MaBind->buffer_length; void **BufferPtr= (void**)Buffer; /* For the case when Buffer points to the pointer already */ if (Stmt->Apd->Header.ArrayStatusPtr != NULL && Stmt->Apd->Header.ArrayStatusPtr[row] == SQL_PARAM_IGNORE) { continue; } if (MaBind->u.indicator && MaBind->u.indicator[row] > STMT_INDICATOR_NONE) { continue; } switch (CRec->ConciseType) { case SQL_C_CHAR: if (SqlRec->ConciseType != SQL_BIT) { break; } case DATETIME_TYPES: if (CanUseStructArrForDatetime(Stmt)) { BufferPtr= &Buffer; } } /* Need &Dummy here as a length ptr, since NULL is not good here. It would make MADB_ConvertC2Sql to use MaBind->buffer_length by default */ if (!SQL_SUCCEEDED(MADB_ConvertC2Sql(Stmt, CRec, DataPtr, MaBind->length != NULL ? MaBind->length[row] : 0, SqlRec, MaBind, BufferPtr, MaBind->length != NULL ? MaBind->length + row : &Dummy))) { /* Perhaps it's better to move to Clean function */ CRec->InternalBuffer= NULL; return Stmt->Error.ReturnValue; } CRec->InternalBuffer= NULL; } } } return MADB_DoExecute(Stmt, FALSE); }