Beispiel #1
0
/* {{{ ps_fetch_time */
static
void ps_fetch_time(zval *zv, const MYSQLND_FIELD * const field,
				   unsigned int pack_len, zend_uchar **row,
				   zend_bool as_unicode TSRMLS_DC)
{
	struct st_mysqlnd_time t;
	unsigned int length; /* First byte encodes the length*/
	char *to;
	DBG_ENTER("ps_fetch_time");

	if ((length = php_mysqlnd_net_field_length(row))) {
		zend_uchar *to= *row;

		t.time_type = MYSQLND_TIMESTAMP_TIME;
		t.neg			= (zend_bool) to[0];

		t.day			= (unsigned long) sint4korr(to+1);
		t.hour			= (unsigned int) to[5];
		t.minute		= (unsigned int) to[6];
		t.second		= (unsigned int) to[7];
		t.second_part	= (length > 8) ? (unsigned long) sint4korr(to+8) : 0;
		t.year			= t.month= 0;
		if (t.day) {
			/* Convert days to hours at once */
			t.hour += t.day*24;
			t.day	= 0;
		}

		(*row) += length;
	} else {
		memset(&t, 0, sizeof(t));
		t.time_type = MYSQLND_TIMESTAMP_TIME;
 	}

	/*
	  QQ : How to make this unicode without copying two times the buffer -
	  Unicode equivalent of spprintf?
	*/
	length = spprintf(&to, 0, "%s%02u:%02u:%02u",
					 (t.neg ? "-" : ""), t.hour, t.minute, t.second);

	DBG_INF_FMT("%s", to);
#if PHP_MAJOR_VERSION >= 6
	if (!as_unicode) {
#endif
		ZVAL_STRINGL(zv, to, length, 1);
		efree(to);  /* allocated by spprintf */
#if PHP_MAJOR_VERSION >= 6
	} else {
		ZVAL_UTF8_STRINGL(zv, to, length, ZSTR_AUTOFREE);	
	}
#endif
	DBG_VOID_RETURN;
}
static void convert_to_datetime(MYSQL_TIME *t, unsigned char **row, uint len, enum enum_field_types type)
{
  memset(t, 0, sizeof(MYSQL_TIME));

  /* binary protocol for datetime:
     4-bytes:  DATE
     7-bytes:  DATE + TIME
     >7 bytes: DATE + TIME with second_part
  */
  if (len)
  {
    unsigned char *to= *row;
    int has_date= 0;
    uint offset= 7;
    
    if (type == MYSQL_TYPE_TIME)
    {
      t->neg= to[0];
      t->day= (ulong) sint4korr(to + 1);
      t->time_type= MYSQL_TIMESTAMP_TIME;
      offset= 8;
      to++;
    } else
    {
      t->year= (uint) sint2korr(to);
      t->month= (uint) to[2];
      t->day= (uint) to[3];
      t->time_type= MYSQL_TIMESTAMP_DATE;
      if (type == MYSQL_TYPE_DATE)
        return;
      has_date= 1;
    }

    if (len > 4)
    {
      t->hour= (uint) to[4];
      if (type == MYSQL_TYPE_TIME)
        t->hour+= t->day * 24;
      t->minute= (uint) to[5];
      t->second= (uint) to[6];
      if (has_date)
        t->time_type= MYSQL_TIMESTAMP_DATETIME;
    }
    if (len > offset)
    {
      t->second_part= (ulong)sint4korr(to+7);
    }
  }
}
Beispiel #3
0
/* {{{ ps_fetch_time */
static
void ps_fetch_time(zval *zv, const MYSQLND_FIELD * const field,
				   unsigned int pack_len, zend_uchar **row,
				   zend_bool as_unicode TSRMLS_DC)
{
	struct st_mysqlnd_time t;
	unsigned int length; /* First byte encodes the length*/
	char * value;
	DBG_ENTER("ps_fetch_time");

	if ((length = php_mysqlnd_net_field_length(row))) {
		zend_uchar *to= *row;

		t.time_type = MYSQLND_TIMESTAMP_TIME;
		t.neg			= (zend_bool) to[0];

		t.day			= (unsigned long) sint4korr(to+1);
		t.hour			= (unsigned int) to[5];
		t.minute		= (unsigned int) to[6];
		t.second		= (unsigned int) to[7];
		t.second_part	= (length > 8) ? (unsigned long) sint4korr(to+8) : 0;
		t.year			= t.month= 0;
		if (t.day) {
			/* Convert days to hours at once */
			t.hour += t.day*24;
			t.day	= 0;
		}

		(*row) += length;
	} else {
		memset(&t, 0, sizeof(t));
		t.time_type = MYSQLND_TIMESTAMP_TIME;
	}

	length = mnd_sprintf(&value, 0, "%s%02u:%02u:%02u", (t.neg ? "-" : ""), t.hour, t.minute, t.second);

	DBG_INF_FMT("%s", value);
#if MYSQLND_UNICODE
	if (!as_unicode) {
#endif
		ZVAL_STRINGL(zv, value, length, 1);
		mnd_sprintf_free(value);
#if MYSQLND_UNICODE
	} else {
		ZVAL_UTF8_STRINGL(zv, value, length, ZSTR_AUTOFREE);
	}
#endif
	DBG_VOID_RETURN;
}
/* {{{ ps_fetch_from_1_to_8_bytes */
void ps_fetch_from_1_to_8_bytes(MYSQL_BIND *r_param, const MYSQL_FIELD * const field,
                unsigned char **row, unsigned int byte_count)
{
  my_bool is_unsigned= test(field->flags & UNSIGNED_FLAG);
  r_param->buffer_length= byte_count;
  switch (byte_count) {
    case 1:
      *(uchar *)r_param->buffer= **row;
      *r_param->error= is_unsigned != r_param->is_unsigned && *(uchar *)r_param->buffer > INT_MAX8;
      break;
    case 2:
      shortstore(r_param->buffer, ((ushort) sint2korr(*row)));
      *r_param->error= is_unsigned != r_param->is_unsigned && *(ushort *)r_param->buffer > INT_MAX16;
      break;
    case 4:
    {
      longstore(r_param->buffer, ((uint32)sint4korr(*row)));
      *r_param->error= is_unsigned != r_param->is_unsigned && *(uint32 *)r_param->buffer > INT_MAX32;
    }
    break;
    case 8:
      {
        ulonglong val= (ulonglong)sint8korr(*row);
        longlongstore(r_param->buffer, val);
        *r_param->error= is_unsigned != r_param->is_unsigned && val > LONGLONG_MAX ;
      }
      break;
    default:
      r_param->buffer_length= 0;
      break;
  }
  (*row)+= byte_count;
}
/* {{{ ps_fetch_int32 */
static
void ps_fetch_int32(MYSQL_BIND *r_param, const MYSQL_FIELD * const field,
           unsigned char **row)
{
  switch (r_param->buffer_type) {
/*    case MYSQL_TYPE_TINY:
      ps_fetch_from_1_to_8_bytes(r_param, field, row, 1);
      break;
    case MYSQL_TYPE_YEAR:
    case MYSQL_TYPE_SHORT:
      ps_fetch_from_1_to_8_bytes(r_param, field, row, 2);
      break; */
    case MYSQL_TYPE_INT24:
    case MYSQL_TYPE_LONG:
      ps_fetch_from_1_to_8_bytes(r_param, field, row, 4);
    break; 
    default:
    {
      int32 sval= sint4korr(*row);
      longlong lval= field->flags & UNSIGNED_FLAG ? (longlong)(uint32) sval : (longlong)sval;
      convert_from_long(r_param, field, lval, field->flags & UNSIGNED_FLAG);
      (*row) += 4;
    }
    break;
  }
}
Beispiel #6
0
/* {{{ ps_fetch_datetime */
static
void ps_fetch_datetime(zval *zv, const MYSQLND_FIELD * const field,
					   unsigned int pack_len, zend_uchar **row,
					   zend_bool as_unicode TSRMLS_DC)
{
	struct st_mysqlnd_time t;
	unsigned int length; /* First byte encodes the length*/
	char * value;
	DBG_ENTER("ps_fetch_datetime");

	if ((length = php_mysqlnd_net_field_length(row))) {
		zend_uchar *to= *row;

		t.time_type = MYSQLND_TIMESTAMP_DATETIME;
		t.neg	 = 0;

		t.year	 = (unsigned int) sint2korr(to);
		t.month = (unsigned int) to[2];
		t.day	 = (unsigned int) to[3];

		if (length > 4) {
			t.hour	 = (unsigned int) to[4];
			t.minute = (unsigned int) to[5];
			t.second = (unsigned int) to[6];
		} else {
			t.hour = t.minute = t.second= 0;
		}
		t.second_part = (length > 7) ? (unsigned long) sint4korr(to+7) : 0;

		(*row)+= length;
	} else {
		memset(&t, 0, sizeof(t));
		t.time_type = MYSQLND_TIMESTAMP_DATETIME;
	}

	/*
	  QQ : How to make this unicode without copying two times the buffer -
	  Unicode equivalent of spprintf?
	*/
	length = spprintf(&value, 0, "%04u-%02u-%02u %02u:%02u:%02u",
					  t.year, t.month, t.day, t.hour, t.minute, t.second);

	DBG_INF_FMT("%s", value);
#if MYSQLND_UNICODE
	if (!as_unicode) {
#endif
		ZVAL_STRINGL(zv, value, length, 1);
		efree(value); /* allocated by spprintf */
#if MYSQLND_UNICODE
	} else {
		ZVAL_UTF8_STRINGL(zv, to, length, ZSTR_AUTOFREE);
	}
#endif
	DBG_VOID_RETURN;
}
Beispiel #7
0
/* {{{ ps_fetch_datetime */
static void
ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
{
	struct st_mysqlnd_time t;
	zend_ulong length; /* First byte encodes the length*/
	char * value;
	DBG_ENTER("ps_fetch_datetime");

	if ((length = php_mysqlnd_net_field_length(row))) {
		zend_uchar * to = *row;

		t.time_type = MYSQLND_TIMESTAMP_DATETIME;
		t.neg	 = 0;

		t.year	 = (unsigned int) sint2korr(to);
		t.month = (unsigned int) to[2];
		t.day	 = (unsigned int) to[3];

		if (length > 4) {
			t.hour	 = (unsigned int) to[4];
			t.minute = (unsigned int) to[5];
			t.second = (unsigned int) to[6];
		} else {
			t.hour = t.minute = t.second= 0;
		}
		t.second_part = (length > 7) ? (zend_ulong) sint4korr(to+7) : 0;

		(*row)+= length;
	} else {
		memset(&t, 0, sizeof(t));
		t.time_type = MYSQLND_TIMESTAMP_DATETIME;
	}

	length = mnd_sprintf(&value, 0, "%04u-%02u-%02u %02u:%02u:%02u", t.year, t.month, t.day, t.hour, t.minute, t.second);

	DBG_INF_FMT("%s", value);
	ZVAL_STRINGL(zv, value, length);
	mnd_sprintf_free(value);
	DBG_VOID_RETURN;
}
Beispiel #8
0
/* {{{ ps_fetch_from_1_to_8_bytes */
void ps_fetch_from_1_to_8_bytes(zval *zv, const MYSQLND_FIELD * const field,
								unsigned int pack_len, zend_uchar **row, zend_bool as_unicode,
								unsigned int byte_count TSRMLS_DC)
{
	char tmp[22];
	size_t tmp_len = 0;
	zend_bool is_bit = field->type == MYSQL_TYPE_BIT;
	DBG_ENTER("ps_fetch_from_1_to_8_bytes");
	DBG_INF_FMT("zv=%p byte_count=%d", zv, byte_count);
	if (field->flags & UNSIGNED_FLAG) {
		uint64_t uval = 0;

		switch (byte_count) {
			case 8:uval = is_bit? (uint64_t) bit_uint8korr(*row):(uint64_t) uint8korr(*row);break;
			case 7:uval = bit_uint7korr(*row);break;
			case 6:uval = bit_uint6korr(*row);break;
			case 5:uval = bit_uint5korr(*row);break;
			case 4:uval = is_bit? (uint64_t) bit_uint4korr(*row):(uint64_t) uint4korr(*row);break;
			case 3:uval = is_bit? (uint64_t) bit_uint3korr(*row):(uint64_t) uint3korr(*row);break;
			case 2:uval = is_bit? (uint64_t) bit_uint2korr(*row):(uint64_t) uint2korr(*row);break;
			case 1:uval = (uint64_t) uint1korr(*row);break;
		}

#if SIZEOF_LONG==4
		if (uval > INT_MAX) {
			DBG_INF("stringify");
			tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval);
		} else 
#endif /* #if SIZEOF_LONG==4 */
		{
			if (byte_count < 8 || uval <= L64(9223372036854775807)) {
				ZVAL_LONG(zv, uval);
			} else {
				DBG_INF("stringify");
				tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval);
			}
		}
	} else {
		/* SIGNED */
		int64_t lval = 0;
		switch (byte_count) {
			case 8:lval = (int64_t) sint8korr(*row);break;
			/*
			  7, 6 and 5 are not possible.
			  BIT is only unsigned, thus only uint5|6|7 macroses exist
			*/
			case 4:lval = (int64_t) sint4korr(*row);break;
			case 3:lval = (int64_t) sint3korr(*row);break;
			case 2:lval = (int64_t) sint2korr(*row);break;
			case 1:lval = (int64_t) *(int8_t*)*row;break;
		}

#if SIZEOF_LONG==4
	    if ((L64(2147483647) < (int64_t) lval) || (L64(-2147483648) > (int64_t) lval)) {
			DBG_INF("stringify");
			tmp_len = sprintf((char *)&tmp, MYSQLND_LL_SPEC, lval);
		} else 
#endif /* SIZEOF */
		{
			ZVAL_LONG(zv, lval);
		}
	}

	if (tmp_len) {
#if PHP_MAJOR_VERSION >= 6
		if (as_unicode) {
			DBG_INF("stringify");
			ZVAL_UTF8_STRINGL(zv, tmp, tmp_len, ZSTR_DUPLICATE);
		} else
#endif
		{
			DBG_INF("stringify");
			ZVAL_STRINGL(zv, tmp, tmp_len, 1);
		}			
	}
	(*row)+= byte_count;
	DBG_VOID_RETURN;
}
/**************************************************

   read data in binary type 

**************************************************/ 
int mysac_decode_binary_row(char *buf, int packet_len,
                            MYSAC_RES *res, MYSAC_ROWS *row) {
	int j;
	int i;
	char nul;
	unsigned long len;
	int tmp_len;
	char *wh;
	char _null_ptr[16];
	char *null_ptr;
	unsigned char bit;

	wh = buf;
	null_ptr = _null_ptr;
	bit = 4; /* first 2 bits are reserved */

	/* first bit is unused */
	i = 1;

	/* skip null bits */
	tmp_len = ( (res->nb_cols + 9) / 8 );
	if (i + tmp_len > packet_len)
		return -1;

	memcpy(_null_ptr, &buf[i], tmp_len);
	i += tmp_len;

	for (j = 0; j < res->nb_cols; j++) {

		/*
		   We should set both row_ptr and is_null to be able to see
		   nulls in mysql_stmt_fetch_column. This is because is_null may point
		   to user data which can be overwritten between mysql_stmt_fetch and
		   mysql_stmt_fetch_column, and in this case nullness of column will be
		   lost. See mysql_stmt_fetch_column for details.
		 */
		if ( (*null_ptr & bit) != 0 ) {
			/* do nothing */
		}

		else {
			switch (res->cols[j].type) {
	
			/* read null */
			case MYSQL_TYPE_NULL:
				row->data[j].blob = NULL;
	
			/* read blob */
			case MYSQL_TYPE_TINY_BLOB:
			case MYSQL_TYPE_MEDIUM_BLOB:
			case MYSQL_TYPE_LONG_BLOB:
			case MYSQL_TYPE_BLOB:
			/* decimal ? maybe for very big num ... crypto key ? */
			case MYSQL_TYPE_DECIMAL:
			case MYSQL_TYPE_NEWDECIMAL:
			/* .... */
			case MYSQL_TYPE_BIT:
			/* read text */
			case MYSQL_TYPE_STRING:
			case MYSQL_TYPE_VAR_STRING:
			case MYSQL_TYPE_VARCHAR:
			/* read date */
			case MYSQL_TYPE_NEWDATE:
				tmp_len = my_lcb(&buf[i], &len, &nul, packet_len-i);
				if (tmp_len == -1)
					return -1;
				i += tmp_len;
				if (i + len > (unsigned int)packet_len)
					return -1;
				if (nul == 1)
					row->data[j].blob = NULL;
				else {
					memmove(wh, &buf[i], len);
					row->data[j].blob = wh;
					row->data[j].blob[len] = '\0';
					i += len;
					wh += len + 1;
				}
				row->lengths[j] = len;
				break;
	
			case MYSQL_TYPE_TINY:
				if (i > packet_len - 1)
					return -1;
				row->data[j].stiny = buf[i];
				i++;
				break;
	
			case MYSQL_TYPE_SHORT:
				if (i > packet_len - 2)
					return -1;
				row->data[j].ssmall = sint2korr(&buf[i]);
				i += 2;
				break;
	
			case MYSQL_TYPE_INT24:
			case MYSQL_TYPE_LONG:
				if (i > packet_len - 4)
					return -1;
				row->data[j].sint = sint4korr(&buf[i]);
				i += 4;
				break;
	
			case MYSQL_TYPE_LONGLONG:
				if (i > packet_len - 8)
					return -1;
				row->data[j].sbigint = sint8korr(&buf[i]);
				i += 8;
				break;
	
			case MYSQL_TYPE_FLOAT:
				if (i > packet_len - 4)
					return -1;
				float4get(row->data[j].mfloat, &buf[i]);
				i += 4;
				break;
	
			case MYSQL_TYPE_DOUBLE:
				if (i > packet_len - 8)
					return -1;
				float8get(row->data[j].mdouble, &buf[i]);
				i += 8;
				break;
	
			/* libmysql/libmysql.c:3370
			 * static void read_binary_time(MYSQL_TIME *tm, uchar **pos) */
			case MYSQL_TYPE_TIME:
				tmp_len = my_lcb(&buf[i], &len, &nul, packet_len-i);
				if (tmp_len == -1)
					return -1;
				i += tmp_len;
				if (i + len > (unsigned int)packet_len)
					return -1;
				if (nul == 1)
					row->data[j].blob = NULL;
	
				if (len > 0) {
					row->data[j].tv.tv_sec = 
					              ( uint4korr(&buf[i+1]) * 86400 ) +
					              ( buf[i+5] * 3600 ) +
					              ( buf[i+6] * 60 ) +
					                buf[i+7];
					if (buf[i] != 0)
						row->data[j].tv.tv_sec = - row->data[j].tv.tv_sec;
					if (len > 8)
						row->data[j].tv.tv_usec = uint4korr(&buf[i+8]);
					else
						row->data[j].tv.tv_usec = 0;
				}
				i += len;
				break;
	
			case MYSQL_TYPE_YEAR:
				row->data[j].tm->tm_year = uint2korr(&buf[i]) - 1900;
				row->data[j].tm->tm_mday = 1;
				i += 2;
				break;
	
			/* libmysql/libmysql.c:3400
			 * static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos) */
			case MYSQL_TYPE_TIMESTAMP:
			case MYSQL_TYPE_DATETIME:
				tmp_len = my_lcb(&buf[i], &len, &nul, packet_len-i);
				if (tmp_len == -1)
					return -1;
				i += tmp_len;
				if (i + len > (unsigned int)packet_len)
					return -1;
				if (nul == 1)
					row->data[j].blob = NULL;
	
				row->data[j].tm->tm_year = uint2korr(&buf[i+0]) - 1900;
				row->data[j].tm->tm_mon  = buf[i+2] - 1;
				row->data[j].tm->tm_mday = buf[i+3];
				if (len > 4) {
					row->data[j].tm->tm_hour = buf[i+4];
					row->data[j].tm->tm_min  = buf[i+5];
					row->data[j].tm->tm_sec  = buf[i+6];
				}
				if (len > 7) {
					/* les microsecondes ... */
				}
				i += len;
				break;
	
			/* libmysql/libmysql.c:3430
			 * static void read_binary_date(MYSQL_TIME *tm, uchar **pos) */
			case MYSQL_TYPE_DATE:
				tmp_len = my_lcb(&buf[i], &len, &nul, packet_len-i);
				if (tmp_len == -1)
					return -1;
				i += tmp_len;
				if (i + len > (unsigned int)packet_len)
					return -1;
				if (nul == 1)
					row->data[j].blob = NULL;
	
				row->data[j].tm->tm_year = uint2korr(&buf[i+0]) - 1900;
				row->data[j].tm->tm_mon  = buf[i+2] - 1;
				row->data[j].tm->tm_mday = buf[i+3];
				i += len;
				break;
	
			case MYSQL_TYPE_ENUM:
			case MYSQL_TYPE_SET:
			case MYSQL_TYPE_GEOMETRY:
				break;
			}
		}

		/* To next bit */
		bit <<= 1;

		/* To next byte */
		if ( (bit & 255) == 0 ) {
			bit = 1;
			null_ptr++;
		}
	}
	return wh - buf;
}