void tmDecode(short type, void * src, std::tm * dst) { switch (type & ~1) { case SQL_TIMESTAMP: isc_decode_timestamp(static_cast<ISC_TIMESTAMP*>(src), dst); break; case SQL_TYPE_TIME: isc_decode_sql_time(static_cast<ISC_TIME*>(src), dst); break; case SQL_TYPE_DATE: isc_decode_sql_date(static_cast<ISC_DATE*>(src), dst); break; default: std::ostringstream msg; msg << "Unexpected type of date/time field (" << type << ")"; throw soci_error(msg.str()); } }
static void call_php(char *name, PARAMDSC *r, int argc, PARAMDSC **argv) { do { zval callback, args[4], *argp[4], return_value; PARAMVARY *res = (PARAMVARY*)r->dsc_address; int i; INIT_ZVAL(callback); ZVAL_STRING(&callback,name,0); LOCK(); /* check if the requested function exists */ if (!zend_is_callable(&callback, 0, NULL TSRMLS_CC)) { break; } UNLOCK(); /* create the argument array */ for (i = 0; i < argc; ++i) { INIT_ZVAL(args[i]); argp[i] = &args[i]; /* test arg for null */ if (argv[i]->dsc_flags & DSC_null) { ZVAL_NULL(argp[i]); continue; } switch (argv[i]->dsc_dtype) { ISC_INT64 l; struct tm t; char const *fmt; char d[64]; case dtype_cstring: ZVAL_STRING(argp[i], (char*)argv[i]->dsc_address,0); break; case dtype_text: ZVAL_STRINGL(argp[i], (char*)argv[i]->dsc_address, argv[i]->dsc_length,0); break; case dtype_varying: ZVAL_STRINGL(argp[i], ((PARAMVARY*)argv[i]->dsc_address)->vary_string, ((PARAMVARY*)argv[i]->dsc_address)->vary_length,0); break; case dtype_short: if (argv[i]->dsc_scale == 0) { ZVAL_LONG(argp[i], *(short*)argv[i]->dsc_address); } else { ZVAL_DOUBLE(argp[i], ((double)*(short*)argv[i]->dsc_address)/scales[-argv[i]->dsc_scale]); } break; case dtype_long: if (argv[i]->dsc_scale == 0) { ZVAL_LONG(argp[i], *(ISC_LONG*)argv[i]->dsc_address); } else { ZVAL_DOUBLE(argp[i], ((double)*(ISC_LONG*)argv[i]->dsc_address)/scales[-argv[i]->dsc_scale]); } break; case dtype_int64: l = *(ISC_INT64*)argv[i]->dsc_address; if (argv[i]->dsc_scale == 0 && l <= LONG_MAX && l >= LONG_MIN) { ZVAL_LONG(argp[i], (long)l); } else { ZVAL_DOUBLE(argp[i], ((double)l)/scales[-argv[i]->dsc_scale]); } break; case dtype_real: ZVAL_DOUBLE(argp[i], *(float*)argv[i]->dsc_address); break; case dtype_double: ZVAL_DOUBLE(argp[i], *(double*)argv[i]->dsc_address); break; case dtype_sql_date: isc_decode_sql_date((ISC_DATE*)argv[i]->dsc_address, &t); ZVAL_STRINGL(argp[i], d, strftime(d, sizeof(d), INI_STR("ibase.dateformat"), &t),1); break; case dtype_sql_time: isc_decode_sql_time((ISC_TIME*)argv[i]->dsc_address, &t); ZVAL_STRINGL(argp[i], d, strftime(d, sizeof(d), INI_STR("ibase.timeformat"), &t),1); break; case dtype_timestamp: isc_decode_timestamp((ISC_TIMESTAMP*)argv[i]->dsc_address, &t); ZVAL_STRINGL(argp[i], d, strftime(d, sizeof(d), INI_STR("ibase.timestampformat"), &t),1); break; } } LOCK(); /* now call the function */ if (FAILURE == call_user_function(EG(function_table), NULL, &callback, &return_value, argc, argp TSRMLS_CC)) { UNLOCK(); break; } UNLOCK(); for (i = 0; i < argc; ++i) { switch (argv[i]->dsc_dtype) { case dtype_sql_date: case dtype_sql_time: case dtype_timestamp: zval_dtor(argp[i]); } } /* return whatever type we got back from the callback: let DB handle conversion */ switch (Z_TYPE(return_value)) { case IS_LONG: r->dsc_dtype = dtype_long; *(long*)r->dsc_address = Z_LVAL(return_value); r->dsc_length = sizeof(long); break; case IS_DOUBLE: r->dsc_dtype = dtype_double; *(double*)r->dsc_address = Z_DVAL(return_value); r->dsc_length = sizeof(double); break; case IS_NULL: r->dsc_flags |= DSC_null; break; default: convert_to_string(&return_value); case IS_STRING: r->dsc_dtype = dtype_varying; memcpy(res->vary_string, Z_STRVAL(return_value), (res->vary_length = min(r->dsc_length-2,Z_STRLEN(return_value)))); r->dsc_length = res->vary_length+2; break; } zval_dtor(&return_value); return; } while (0); /** * If we end up here, we should report an error back to the DB engine, but * that's not possible. We can however report it back to PHP. */ LOCK(); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error calling function '%s' from database", name); UNLOCK(); }
//function fb_store_row based on fiebird's apifull example void fb_store_row(rlm_sql_firebird_conn_t *conn) { int dtype; struct tm times; ISC_QUAD bid; int i; XSQLVAR *var; VARY * vary; /* assumed: id, username, attribute, value, op */ if (conn->row_fcount<conn->sqlda_out->sqld) { i = conn->row_fcount; conn->row_fcount = conn->sqlda_out->sqld; conn->row = (char **) realloc(conn->row, conn->row_fcount * sizeof(char *)); conn->row_sizes = (int *) realloc(conn->row_sizes, conn->row_fcount * sizeof(int)); while( i <conn->row_fcount) { conn->row[i] = 0; conn->row_sizes[i++] = 0; } } for (i = 0, var = conn->sqlda_out->sqlvar; i < conn->sqlda_out->sqld; var++, i++) { /* * Initial buffer size to store field's data is 256 bytes */ if (conn->row_sizes[i]<256) { conn->row[i] = (char *) realloc(conn->row[i], 256); conn->row_sizes[i] = 256; } if (IS_NULL(var)) { strcpy(conn->row[i], "NULL"); continue; } dtype = var->sqltype & ~1; switch (dtype) { case SQL_TEXT: if (conn->row_sizes[i]<= var->sqllen) { conn->row_sizes[i] = var->sqllen + 1; conn->row[i] = realloc(conn->row[i], conn->row_sizes[i]); } memmove(conn->row[i], var->sqldata, var->sqllen); conn->row[i][var->sqllen] = 0; break; case SQL_VARYING: vary = (VARY*) var->sqldata; if (conn->row_sizes[i] <= vary->vary_length) { conn->row_sizes[i] = vary->vary_length + 1; conn->row[i] = realloc(conn->row[i], conn->row_sizes[i]); } memmove(conn->row[i], vary->vary_string, vary->vary_length); conn->row[i][vary->vary_length] = 0; break; case SQL_FLOAT: snprintf(conn->row[i], conn->row_sizes[i], "%15g", *(float ISC_FAR *) (var->sqldata)); break; case SQL_SHORT: case SQL_LONG: case SQL_INT64: { ISC_INT64 value = 0; short field_width = 0; short dscale = 0; char *p; p = conn->row[i]; switch (dtype) { case SQL_SHORT: value = (ISC_INT64) *(short *)var->sqldata; field_width = 6; break; case SQL_LONG: value = (ISC_INT64) *(int *)var->sqldata; field_width = 11; break; case SQL_INT64: value = (ISC_INT64) *(ISC_INT64 *)var->sqldata; field_width = 21; break; } dscale = var->sqlscale; if (dscale < 0) { ISC_INT64 tens; short j; tens = 1; for (j = 0; j > dscale; j--) { tens *= 10; } if (value >= 0) { sprintf(p, "%*lld.%0*lld", field_width - 1 + dscale, (ISC_INT64) value / tens, -dscale, (ISC_INT64) value % tens); } else if ((value / tens) != 0) { sprintf (p, "%*lld.%0*lld", field_width - 1 + dscale, (ISC_INT64) (value / tens), -dscale, (ISC_INT64) -(value % tens)); } else { sprintf(p, "%*s.%0*lld", field_width - 1 + dscale, "-0", -dscale, (ISC_INT64) - (value % tens)); } } else if (dscale) { sprintf(p, "%*lld%0*d", field_width, (ISC_INT64) value, dscale, 0); } else { sprintf(p, "%*lld", field_width, (ISC_INT64) value); } } break; case SQL_D_FLOAT: case SQL_DOUBLE: snprintf(conn->row[i], conn->row_sizes[i], "%24f", *(double ISC_FAR *) (var->sqldata)); break; case SQL_TIMESTAMP: isc_decode_timestamp((ISC_TIMESTAMP ISC_FAR *)var->sqldata, ×); snprintf(conn->row[i], conn->row_sizes[i], "%04d-%02d-%02d %02d:%02d:%02d.%04d", times.tm_year + 1900, times.tm_mon + 1, times.tm_mday, times.tm_hour, times.tm_min, times.tm_sec, ((ISC_TIMESTAMP *)var->sqldata)->timestamp_time % 10000); break; case SQL_TYPE_DATE: isc_decode_sql_date((ISC_DATE ISC_FAR *)var->sqldata, ×); snprintf(conn->row[i], conn->row_sizes[i], "%04d-%02d-%02d", times.tm_year + 1900, times.tm_mon + 1, times.tm_mday); break; case SQL_TYPE_TIME: isc_decode_sql_time((ISC_TIME ISC_FAR *)var->sqldata, ×); snprintf(conn->row[i], conn->row_sizes[i], "%02d:%02d:%02d.%04d", times.tm_hour, times.tm_min, times.tm_sec, (*((ISC_TIME *)var->sqldata)) % 10000); break; case SQL_BLOB: case SQL_ARRAY: /* Print the blob id on blobs or arrays */ bid = *(ISC_QUAD ISC_FAR *) var->sqldata; snprintf(conn->row[i], conn->row_sizes[i], "%08" ISC_LONG_FMT "x:%08" ISC_LONG_FMT "x", bid.gds_quad_high, bid.gds_quad_low); break; } } }
/* ** Pushes the indexed value onto the lua stack */ static void push_column(lua_State *L, int i, cur_data *cur) { int varcharlen; struct tm timevar; char timestr[256]; ISC_STATUS blob_stat; isc_blob_handle blob_handle = NULL; ISC_QUAD blob_id; luaL_Buffer b; char *buffer; unsigned short actual_seg_len; if( (cur->out_sqlda->sqlvar[i].sqlind != NULL) && (*(cur->out_sqlda->sqlvar[i].sqlind) != 0) ) { /* a null field? */ lua_pushnil(L); } else { switch(cur->out_sqlda->sqlvar[i].sqltype & ~1) { case SQL_VARYING: varcharlen = (int)isc_vax_integer(cur->out_sqlda->sqlvar[i].sqldata, 2); lua_pushlstring(L, cur->out_sqlda->sqlvar[i].sqldata+2, varcharlen); break; case SQL_TEXT: lua_pushlstring(L, cur->out_sqlda->sqlvar[i].sqldata, cur->out_sqlda->sqlvar[i].sqllen); break; case SQL_SHORT: lua_pushnumber(L, *(short*)(cur->out_sqlda->sqlvar[i].sqldata)); break; case SQL_LONG: lua_pushnumber(L, *(long*)(cur->out_sqlda->sqlvar[i].sqldata)); break; case SQL_INT64: lua_pushnumber(L, (lua_Number)*(ISC_INT64*)(cur->out_sqlda->sqlvar[i].sqldata)); break; case SQL_FLOAT: lua_pushnumber(L, *(float*)(cur->out_sqlda->sqlvar[i].sqldata)); break; case SQL_DOUBLE: lua_pushnumber(L, *(double*)(cur->out_sqlda->sqlvar[i].sqldata)); break; case SQL_TYPE_TIME: isc_decode_sql_time((ISC_TIME*)(cur->out_sqlda->sqlvar[i].sqldata), &timevar); strftime(timestr, 255, "%X", &timevar); lua_pushstring(L, timestr); break; case SQL_TYPE_DATE: isc_decode_sql_date((ISC_DATE*)(cur->out_sqlda->sqlvar[i].sqldata), &timevar); strftime(timestr, 255, "%x", &timevar); lua_pushstring(L, timestr); break; case SQL_TIMESTAMP: isc_decode_timestamp((ISC_TIMESTAMP*)(cur->out_sqlda->sqlvar[i].sqldata), &timevar); strftime(timestr, 255, "%x %X", &timevar); lua_pushstring(L, timestr); break; case SQL_BLOB: /* get the BLOB ID and open it */ memcpy(&blob_id, cur->out_sqlda->sqlvar[i].sqldata, sizeof(ISC_QUAD)); isc_open_blob2( cur->env->status_vector, &cur->conn->db, &cur->conn->transaction, &blob_handle, &blob_id, 0, NULL ); /* fetch the blob data */ luaL_buffinit(L, &b); buffer = luaL_prepbuffer(&b); blob_stat = isc_get_segment( cur->env->status_vector, &blob_handle, &actual_seg_len, LUAL_BUFFERSIZE, buffer ); while(blob_stat == 0 || cur->env->status_vector[1] == isc_segment) { luaL_addsize(&b, actual_seg_len); buffer = luaL_prepbuffer(&b); blob_stat = isc_get_segment( cur->env->status_vector, &blob_handle, &actual_seg_len, LUAL_BUFFERSIZE, buffer ); } /* finnished, close the BLOB */ isc_close_blob(cur->env->status_vector, &blob_handle); blob_handle = NULL; luaL_pushresult(&b); break; default: lua_pushstring(L, "<unsupported data type>"); break; } } }
char * getdata( int pos ) { short dtype; char data[ MAX_BUFFER ], * p; char blob_s[ 20 ], date_s[ 25 ]; short len; long status[ 20 ]; struct tm times; ISC_QUAD bid; XSQLVAR * var; if( ( pos + 1 ) > sqlda->sqln ) return "error"; var = sqlda->sqlvar; var += pos; dtype = var->sqltype & ~1; p = data; if( ( var->sqltype & 1 ) && ( *var->sqlind < 0 ) ) { switch( dtype ) { case SQL_TEXT: case SQL_VARYING: len = var->sqllen; break; case SQL_SHORT: len = 6; if( var->sqlscale > 0 ) len += var->sqlscale; break; case SQL_LONG: len = 11; if( var->sqlscale > 0 ) len += var->sqlscale; break; case SQL_INT64: len = 21; if( var->sqlscale > 0 ) len += var->sqlscale; break; case SQL_FLOAT: len = 15; break; case SQL_DOUBLE: len = 24; break; case SQL_TIMESTAMP: len = 24; break; case SQL_TYPE_DATE: len = 10; break; case SQL_TYPE_TIME: len = 13; break; case SQL_BLOB: case SQL_ARRAY: default: len = 17; break; } if( ( dtype == SQL_TEXT ) || ( dtype == SQL_VARYING ) ) sprintf( p, "%-*s ", len, "NULL" ); else sprintf( p, "%*s ", len, "NULL" ); } else { switch( dtype ) { case SQL_TEXT: sprintf( p, "%.*s ", var->sqllen, var->sqldata ); break; case SQL_VARYING: sprintf( p, "%.*s ", var->sqllen, var->sqldata ); break; case SQL_SHORT: case SQL_LONG: case SQL_INT64: { ISC_INT64 value = 0; short field_width = 0; short dscale; switch( dtype ) { case SQL_SHORT: value = ( ISC_INT64 ) *( short ISC_FAR * ) var->sqldata; field_width = 6; break; case SQL_LONG: value = ( ISC_INT64 ) *( long ISC_FAR * ) var->sqldata; field_width = 11; break; case SQL_INT64: value = ( ISC_INT64 ) *( ISC_INT64 ISC_FAR * ) var->sqldata; field_width = 21; break; } dscale = var->sqlscale; if( dscale < 0 ) { ISC_INT64 tens; short i; tens = 1; for( i = 0; i > dscale; i-- ) { tens *= 10; if( value >= 0 ) { sprintf( p, "%*" ISC_INT64_FORMAT "d.%0*" ISC_INT64_FORMAT "d", field_width - 1 + dscale, ( ISC_INT64 ) ( value / tens ), -dscale, ( ISC_INT64 ) ( value % tens ) ); } else if( ( value / tens ) != 0 ) { sprintf( p, "%*" ISC_INT64_FORMAT "d.%0*" ISC_INT64_FORMAT "d", field_width - 1 + dscale, ( ISC_INT64 ) ( value / tens ), -dscale, ( ISC_INT64 ) -( value % tens ) ); } else { sprintf( p, "%*s.%0*" ISC_INT64_FORMAT "d", field_width - 1 + dscale, "-0", -dscale, ( ISC_INT64 ) -( value % tens ) ); } } } else if( dscale ) { sprintf( p, "%*" ISC_INT64_FORMAT "d%0*d", field_width, ( ISC_INT64 ) value, dscale, 0 ); } else { sprintf( p, "%*" ISC_INT64_FORMAT "d", field_width, ( ISC_INT64 ) value ); } }; break; case SQL_FLOAT: sprintf( p, "%15g ", *( float ISC_FAR * ) ( var->sqldata ) ); break; case SQL_DOUBLE: sprintf( p, "%24f ", *( double ISC_FAR * ) ( var->sqldata ) ); break; case SQL_TIMESTAMP: isc_decode_timestamp( ( ISC_TIMESTAMP ISC_FAR * ) var->sqldata, × ); sprintf( date_s, "%04d-%02d-%02d %02d:%02d:%02d.%04lui", times.tm_year + 1900, times.tm_mon + 1, times.tm_mday, times.tm_hour, times.tm_min, times.tm_sec, ( ( ISC_TIMESTAMP * ) var->sqldata )->timestamp_time % 10000 ); sprintf( p, "%*s ", 24, date_s ); break; case SQL_TYPE_DATE: isc_decode_sql_date( ( ISC_DATE ISC_FAR * ) var->sqldata, × ); sprintf( date_s, "%04d-%02d-%02d", times.tm_year + 1900, times.tm_mon + 1, times.tm_mday ); sprintf( p, "%*s ", 10, date_s ); break; case SQL_TYPE_TIME: isc_decode_sql_time( ( ISC_TIME ISC_FAR * ) var->sqldata, × ); sprintf( date_s, "%02d:%02d:%02d.%04lui", times.tm_hour, times.tm_min, times.tm_sec, ( *( ( ISC_TIME * ) var->sqldata ) ) % 10000 ); sprintf( p, "%*s ", 13, date_s ); break; case SQL_BLOB: case SQL_ARRAY: /* Print the blob id on blobs or arrays */ bid = *( ISC_QUAD ISC_FAR * ) var->sqldata; sprintf( blob_s, "%08x:%08x", ( unsigned int ) bid.gds_quad_high, ( unsigned int ) bid.gds_quad_low ); sprintf( p, "%17s ", blob_s ); break; default: break; } } return p; }
int _get_row_data(dbi_result_t *result, dbi_row_t *row, unsigned long long rowidx) { unsigned int curfield = 0; XSQLVAR var; long fetch_stat = 0, blob_stat = 0; ISC_QUAD bid; isc_blob_handle blob_handle = NULL; /* Blob handle. */ char blob_segment[80]; unsigned short actual_seg_len; struct tm times; char date_s[25]; unsigned int sizeattrib; dbi_data_t *data = NULL; ibase_stmt_t *istmt = (ibase_stmt_t *)result->result_handle; ibase_conn_t *iconn = (ibase_conn_t *)result->conn->connection; fetch_stat = isc_dsql_fetch(iconn->status_vector, &(istmt->stmt), SQL_DIALECT_V6, istmt->osqlda); if (fetch_stat != 0) { result->numrows_matched--; return 0; } while (curfield < result->numfields) { var = istmt->osqlda->sqlvar[curfield]; data = &row->field_values[curfield]; /** * If the column holds a NULL value mark it as NULL */ if ( (var.sqltype & 1) && ( *var.sqlind < 0)) { _set_field_flag( row, curfield, DBI_VALUE_NULL, 1); curfield++; continue; } switch ( result->field_types[curfield] ) { case DBI_TYPE_STRING: if(result->field_attribs[curfield] & DBI_STRING_FIXEDSIZE) { data->d_string = strdup(var.sqldata); row->field_sizes[curfield] = (unsigned long long) var.sqllen; } else { vary_t *vary = NULL; vary = (vary_t *) var.sqldata; data->d_string = malloc(vary->vary_length+1); memcpy(data->d_string, vary->vary_string, vary->vary_length); data->d_string[vary->vary_length] = '\0'; row->field_sizes[curfield] = (unsigned long long) vary->vary_length; } break; case DBI_TYPE_INTEGER: sizeattrib = _isolate_attrib(result->field_attribs[curfield], DBI_INTEGER_SIZE1, DBI_INTEGER_SIZE8); switch (sizeattrib) { case DBI_INTEGER_SIZE1: case DBI_INTEGER_SIZE2: data->d_short = *(short *) var.sqldata; break; case DBI_INTEGER_SIZE3: case DBI_INTEGER_SIZE4: data->d_long = *(int *) var.sqldata; break; case DBI_INTEGER_SIZE8: data->d_longlong = *(ISC_INT64 *) var.sqldata; break; default: break; } break; case DBI_TYPE_DECIMAL: sizeattrib = _isolate_attrib(result->field_attribs[curfield], DBI_DECIMAL_SIZE4, DBI_DECIMAL_SIZE8); switch (sizeattrib) { case DBI_DECIMAL_SIZE4: data->d_float = *(float *) (var.sqldata); break; case DBI_DECIMAL_SIZE8: data->d_double = *(double *) (var.sqldata); break; default: break; } break; case DBI_TYPE_DATETIME: sizeattrib = _isolate_attrib(result->field_attribs[curfield], DBI_DATETIME_DATE, DBI_DATETIME_TIME); if (sizeattrib&DBI_DATETIME_TIME && sizeattrib&DBI_DATETIME_DATE) { isc_decode_timestamp((ISC_TIMESTAMP *)var.sqldata, ×); sprintf(date_s, "%04d-%02d-%02d %02d:%02d:%02d", times.tm_year + 1900, times.tm_mon+1, times.tm_mday, times.tm_hour, times.tm_min, times.tm_sec); } else if (sizeattrib&DBI_DATETIME_TIME) { isc_decode_sql_time((ISC_TIME *)var.sqldata, ×); sprintf(date_s, "%02d:%02d:%02d", times.tm_hour, times.tm_min, times.tm_sec); } else { isc_decode_sql_date((ISC_DATE *)var.sqldata, ×); sprintf(date_s, "%04d-%02d-%02d", times.tm_year + 1900, times.tm_mon+1, times.tm_mday); } data->d_datetime = _dbd_parse_datetime(date_s, sizeattrib); break; case DBI_TYPE_BINARY: bid = *(ISC_QUAD *) var.sqldata; isc_open_blob2( iconn->status_vector, &(iconn->db), &(iconn->trans), &blob_handle, &bid, 0, NULL ); blob_stat = isc_get_segment( iconn->status_vector, &blob_handle, &actual_seg_len, sizeof(blob_segment), blob_segment ); data->d_string = malloc(sizeof(actual_seg_len)); memcpy(data->d_string, blob_segment, actual_seg_len); row->field_sizes[curfield] = actual_seg_len; while (blob_stat == 0 || iconn->status_vector[1] == isc_segment) { blob_stat = isc_get_segment(iconn->status_vector, &blob_handle, &actual_seg_len, sizeof(blob_segment), blob_segment); data->d_string = realloc(data->d_string, row->field_sizes[curfield] + actual_seg_len); memcpy(data->d_string+row->field_sizes[curfield], blob_segment, actual_seg_len); row->field_sizes[curfield] += actual_seg_len; } isc_close_blob(iconn->status_vector, &blob_handle); row->field_sizes[curfield] = _dbd_decode_binary(data->d_string, data->d_string); break; default: break; } curfield++; } if( fetch_stat != 100L ) { result->rows = realloc(result->rows, (sizeof(dbi_row_t *) * (result->numrows_matched+1))); result->numrows_matched++; } return result->numrows_matched; }