~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libmysql/libmysql.c

  • Committer: Brian Aker
  • Date: 2008-07-02 20:56:30 UTC
  • Revision ID: brian@tangent.org-20080702205630-go36gbsrq1zbjyvg
Second pass on removing PS from client library

Show diffs side-by-side

added added

removed removed

Lines of Context:
437
437
 
438
438
  rc= (*mysql->methods->read_change_user_result)(mysql, buff, passwd);
439
439
 
440
 
  /*
441
 
    The server will close all statements no matter was the attempt
442
 
    to change user successful or not.
443
 
  */
444
 
  mysql_detach_stmt_list(&mysql->stmts, "mysql_change_user");
445
440
  if (rc == 0)
446
441
  {
447
442
    /* Free old connect information */
1270
1265
 'emb_' reside in libmysqld/lib_sql.cc.
1271
1266
*********************************************************************/
1272
1267
 
1273
 
/******************* Declarations ***********************************/
1274
 
 
1275
 
/* Default number of rows fetched per one COM_STMT_FETCH command. */
1276
 
 
1277
 
#define DEFAULT_PREFETCH_ROWS (ulong) 1
1278
 
 
1279
 
/*
1280
 
  These functions are called by function pointer MYSQL_STMT::read_row_func.
1281
 
  Each function corresponds to one of the read methods:
1282
 
  - mysql_stmt_fetch without prior mysql_stmt_store_result,
1283
 
  - mysql_stmt_fetch when result is stored,
1284
 
  - mysql_stmt_fetch when there are no rows (always returns MYSQL_NO_DATA)
1285
 
*/
1286
 
 
1287
 
/*
1288
 
  This function is used in mysql_stmt_store_result if
1289
 
  STMT_ATTR_UPDATE_MAX_LENGTH attribute is set.
1290
 
*/
1291
 
static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data);
1292
 
 
1293
 
/* Auxilary function used to reset statement handle. */
1294
 
 
1295
 
#define RESET_SERVER_SIDE 1
1296
 
#define RESET_LONG_DATA 2
1297
 
#define RESET_STORE_RESULT 4
1298
 
 
1299
 
/*
1300
 
  Maximum sizes of MYSQL_TYPE_DATE, MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME
1301
 
  values stored in network buffer.
1302
 
*/
1303
 
 
1304
 
/* 1 (length) + 2 (year) + 1 (month) + 1 (day) */
1305
 
#define MAX_DATE_REP_LENGTH 5
1306
 
 
1307
 
/*
1308
 
  1 (length) + 1 (is negative) + 4 (day count) + 1 (hour)
1309
 
  + 1 (minute) + 1 (seconds) + 4 (microseconds)
1310
 
*/
1311
 
#define MAX_TIME_REP_LENGTH 13
1312
 
 
1313
 
/*
1314
 
  1 (length) + 2 (year) + 1 (month) + 1 (day) +
1315
 
  1 (hour) + 1 (minute) + 1 (second) + 4 (microseconds)
1316
 
*/
1317
 
#define MAX_DATETIME_REP_LENGTH 12
1318
 
 
1319
 
#define MAX_DOUBLE_STRING_REP_LENGTH 331
1320
 
 
1321
 
/* A macro to check truncation errors */
1322
 
 
1323
 
#define IS_TRUNCATED(value, is_unsigned, min, max, umax) \
1324
 
        ((is_unsigned) ? (((value) > (umax) || (value) < 0) ? 1 : 0) : \
1325
 
                         (((value) > (max)  || (value) < (min)) ? 1 : 0))
1326
 
 
1327
 
#define BIND_RESULT_DONE 1
1328
 
/*
1329
 
  We report truncations only if at least one of MYSQL_BIND::error
1330
 
  pointers is set. In this case stmt->bind_result_done |-ed with
1331
 
  this flag.
1332
 
*/
1333
 
#define REPORT_DATA_TRUNCATION 2
1334
 
 
1335
 
/**************** Misc utility functions ****************************/
1336
 
 
1337
 
/*
1338
 
  Reallocate the NET package to have at least length bytes available.
1339
 
 
1340
 
  SYNPOSIS
1341
 
    my_realloc_str()
1342
 
    net                 The NET structure to modify.
1343
 
    length              Ensure that net->buff has space for at least
1344
 
                        this number of bytes.
1345
 
 
1346
 
  RETURN VALUES
1347
 
    0   Success.
1348
 
    1   Error, i.e. out of memory or requested packet size is bigger
1349
 
        than max_allowed_packet. The error code is stored in net->last_errno.
1350
 
*/
1351
 
 
1352
 
static my_bool my_realloc_str(NET *net, ulong length)
1353
 
{
1354
 
  ulong buf_length= (ulong) (net->write_pos - net->buff);
1355
 
  my_bool res=0;
1356
 
  DBUG_ENTER("my_realloc_str");
1357
 
  if (buf_length + length > net->max_packet)
1358
 
  {
1359
 
    res= net_realloc(net, buf_length + length);
1360
 
    if (res)
1361
 
    {
1362
 
      strmov(net->sqlstate, unknown_sqlstate);
1363
 
      strmov(net->last_error, ER(net->last_errno));
1364
 
    }
1365
 
    net->write_pos= net->buff+ buf_length;
1366
 
  }
1367
 
  DBUG_RETURN(res);
1368
 
}
1369
 
 
1370
 
 
1371
 
static void stmt_clear_error(MYSQL_STMT *stmt)
1372
 
{
1373
 
  if (stmt->last_errno)
1374
 
  {
1375
 
    stmt->last_errno= 0;
1376
 
    stmt->last_error[0]= '\0';
1377
 
    strmov(stmt->sqlstate, not_error_sqlstate);
1378
 
  }
1379
 
}
1380
 
 
1381
 
/**
1382
 
  Set statement error code, sqlstate, and error message
1383
 
  from given errcode and sqlstate.
1384
 
*/
1385
 
 
1386
 
void set_stmt_error(MYSQL_STMT * stmt, int errcode,
1387
 
                    const char *sqlstate, const char *err)
1388
 
{
1389
 
  DBUG_ENTER("set_stmt_error");
1390
 
  DBUG_PRINT("enter", ("error: %d '%s'", errcode, ER(errcode)));
1391
 
  DBUG_ASSERT(stmt != 0);
1392
 
 
1393
 
  if (err == 0)
1394
 
    err= ER(errcode);
1395
 
 
1396
 
  stmt->last_errno= errcode;
1397
 
  strmov(stmt->last_error, ER(errcode));
1398
 
  strmov(stmt->sqlstate, sqlstate);
1399
 
 
1400
 
  DBUG_VOID_RETURN;
1401
 
}
1402
 
 
1403
 
 
1404
 
/**
1405
 
  Set statement error code, sqlstate, and error message from NET.
1406
 
 
1407
 
  @param stmt  a statement handle. Copy the error here.
1408
 
  @param net   mysql->net. Source of the error.
1409
 
*/
1410
 
 
1411
 
void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net)
1412
 
{
1413
 
  DBUG_ENTER("set_stmt_errmsg");
1414
 
  DBUG_PRINT("enter", ("error: %d/%s '%s'",
1415
 
                       net->last_errno,
1416
 
                       net->sqlstate,
1417
 
                       net->last_error));
1418
 
  DBUG_ASSERT(stmt != 0);
1419
 
 
1420
 
  stmt->last_errno= net->last_errno;
1421
 
  if (net->last_error && net->last_error[0])
1422
 
    strmov(stmt->last_error, net->last_error);
1423
 
  strmov(stmt->sqlstate, net->sqlstate);
1424
 
 
1425
 
  DBUG_VOID_RETURN;
1426
 
}
1427
 
 
1428
 
/*
1429
 
  Read and unpack server reply to COM_STMT_PREPARE command (sent from
1430
 
  mysql_stmt_prepare).
1431
 
 
1432
 
  SYNOPSIS
1433
 
    cli_read_prepare_result()
1434
 
    mysql   connection handle
1435
 
    stmt    statement handle
1436
 
 
1437
 
  RETURN VALUES
1438
 
    0   ok
1439
 
    1   error
1440
 
*/
1441
 
 
1442
 
my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
1443
 
{
1444
 
  uchar *pos;
1445
 
  uint field_count, param_count;
1446
 
  ulong packet_length;
1447
 
  MYSQL_DATA *fields_data;
1448
 
  DBUG_ENTER("cli_read_prepare_result");
1449
 
 
1450
 
  if ((packet_length= cli_safe_read(mysql)) == packet_error)
1451
 
    DBUG_RETURN(1);
1452
 
  mysql->warning_count= 0;
1453
 
 
1454
 
  pos= (uchar*) mysql->net.read_pos;
1455
 
  stmt->stmt_id= uint4korr(pos+1); pos+= 5;
1456
 
  /* Number of columns in result set */
1457
 
  field_count=   uint2korr(pos);   pos+= 2;
1458
 
  /* Number of placeholders in the statement */
1459
 
  param_count=   uint2korr(pos);   pos+= 2;
1460
 
  if (packet_length >= 12)
1461
 
    mysql->warning_count= uint2korr(pos+1);
1462
 
 
1463
 
  if (param_count != 0)
1464
 
  {
1465
 
    MYSQL_DATA *param_data;
1466
 
 
1467
 
    /* skip parameters data: we don't support it yet */
1468
 
    if (!(param_data= (*mysql->methods->read_rows)(mysql, (MYSQL_FIELD*)0, 7)))
1469
 
      DBUG_RETURN(1);
1470
 
    free_rows(param_data);
1471
 
  }
1472
 
 
1473
 
  if (field_count != 0)
1474
 
  {
1475
 
    if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
1476
 
      mysql->server_status|= SERVER_STATUS_IN_TRANS;
1477
 
 
1478
 
    if (!(fields_data= (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*)0,7)))
1479
 
      DBUG_RETURN(1);
1480
 
    if (!(stmt->fields= unpack_fields(fields_data,&stmt->mem_root,
1481
 
                                      field_count,0,
1482
 
                                      mysql->server_capabilities)))
1483
 
      DBUG_RETURN(1);
1484
 
  }
1485
 
  stmt->field_count=  field_count;
1486
 
  stmt->param_count=  (ulong) param_count;
1487
 
  DBUG_PRINT("exit",("field_count: %u  param_count: %u  warning_count: %u",
1488
 
                     field_count, param_count, (uint) mysql->warning_count));
1489
 
 
1490
 
  DBUG_RETURN(0);
1491
 
}
1492
 
 
1493
 
static void net_store_datetime(NET *net, MYSQL_TIME *tm)
1494
 
{
1495
 
  char buff[MAX_DATETIME_REP_LENGTH], *pos;
1496
 
  uint length;
1497
 
 
1498
 
  pos= buff+1;
1499
 
 
1500
 
  int2store(pos, tm->year);
1501
 
  pos[2]= (uchar) tm->month;
1502
 
  pos[3]= (uchar) tm->day;
1503
 
  pos[4]= (uchar) tm->hour;
1504
 
  pos[5]= (uchar) tm->minute;
1505
 
  pos[6]= (uchar) tm->second;
1506
 
  int4store(pos+7, tm->second_part);
1507
 
  if (tm->second_part)
1508
 
    length= 11;
1509
 
  else if (tm->hour || tm->minute || tm->second)
1510
 
    length= 7;
1511
 
  else if (tm->year || tm->month || tm->day)
1512
 
    length= 4;
1513
 
  else
1514
 
    length= 0;
1515
 
  buff[0]= (char) length++;
1516
 
  memcpy((char *)net->write_pos, buff, length);
1517
 
  net->write_pos+= length;
1518
 
}
1519
 
 
1520
 
/*
1521
 
  Read one row from network: unbuffered non-cursor fetch.
1522
 
  If last row was read, or error occured, erase this statement
1523
 
  from record pointing to object unbuffered fetch is performed from.
1524
 
 
1525
 
  SYNOPSIS
1526
 
    stmt_read_row_unbuffered()
1527
 
    stmt  statement handle
1528
 
    row   pointer to write pointer to row data;
1529
 
 
1530
 
  RETURN VALUE
1531
 
    0           - success; *row contains valid address of a row;
1532
 
                  row data is stored in network buffer
1533
 
    1           - error; error code is written to
1534
 
                  stmt->last_{errno,error}; *row is not changed
1535
 
  MYSQL_NO_DATA - end of file was read from network;
1536
 
                  *row is set to NULL
1537
 
*/
1538
 
 
1539
 
static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row)
1540
 
{
1541
 
  int rc= 1;
1542
 
  MYSQL *mysql= stmt->mysql;
1543
 
  /*
1544
 
    This function won't be called if stmt->field_count is zero
1545
 
    or execution wasn't done: this is ensured by mysql_stmt_execute.
1546
 
  */
1547
 
  if (!mysql)
1548
 
  {
1549
 
    set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
1550
 
    return 1;
1551
 
  }
1552
 
  if (mysql->status != MYSQL_STATUS_GET_RESULT)
1553
 
  {
1554
 
    set_stmt_error(stmt, stmt->unbuffered_fetch_cancelled ?
1555
 
                   CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
1556
 
                   unknown_sqlstate, NULL);
1557
 
    goto error;
1558
 
  }
1559
 
  if ((*mysql->methods->unbuffered_fetch)(mysql, (char**) row))
1560
 
  {
1561
 
    set_stmt_errmsg(stmt, &mysql->net);
1562
 
    /*
1563
 
      If there was an error, there are no more pending rows:
1564
 
      reset statement status to not hang up in following
1565
 
      mysql_stmt_close (it will try to flush result set before
1566
 
      closing the statement).
1567
 
    */
1568
 
    mysql->status= MYSQL_STATUS_READY;
1569
 
    goto error;
1570
 
  }
1571
 
  if (!*row)
1572
 
  {
1573
 
    mysql->status= MYSQL_STATUS_READY;
1574
 
    rc= MYSQL_NO_DATA;
1575
 
    goto error;
1576
 
  }
1577
 
  return 0;
1578
 
error:
1579
 
  if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
1580
 
    mysql->unbuffered_fetch_owner= 0;
1581
 
  return rc;
1582
 
}
1583
 
 
1584
 
 
1585
 
/*
1586
 
  Default read row function to not SIGSEGV in client in
1587
 
  case of wrong sequence of API calls.
1588
 
*/
1589
 
 
1590
 
static int
1591
 
stmt_read_row_no_data(MYSQL_STMT *stmt  __attribute__((unused)),
1592
 
                      unsigned char **row  __attribute__((unused)))
1593
 
{
1594
 
  return MYSQL_NO_DATA;
1595
 
}
1596
 
 
1597
 
static int
1598
 
stmt_read_row_no_result_set(MYSQL_STMT *stmt  __attribute__((unused)),
1599
 
                      unsigned char **row  __attribute__((unused)))
1600
 
{
1601
 
  set_stmt_error(stmt, CR_NO_RESULT_SET, unknown_sqlstate, NULL);
1602
 
  return 1;
1603
 
}
1604
 
 
1605
1268
 
1606
1269
static my_bool int_is_null_true= 1;             /* Used for MYSQL_TYPE_NULL */
1607
1270
static my_bool int_is_null_false= 0;
1767
1430
  return 0;
1768
1431
}
1769
1432
 
1770
 
 
1771
 
/*
1772
 
  Read all rows of data from server  (binary format)
1773
 
*/
1774
 
 
1775
 
int cli_read_binary_rows(MYSQL_STMT *stmt)
1776
 
{
1777
 
  ulong      pkt_len;
1778
 
  uchar      *cp;
1779
 
  MYSQL      *mysql= stmt->mysql;
1780
 
  MYSQL_DATA *result= &stmt->result;
1781
 
  MYSQL_ROWS *cur, **prev_ptr= &result->data;
1782
 
  NET        *net;
1783
 
 
1784
 
  DBUG_ENTER("cli_read_binary_rows");
1785
 
 
1786
 
  if (!mysql)
1787
 
  {
1788
 
    set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
1789
 
    DBUG_RETURN(1);
1790
 
  }
1791
 
 
1792
 
  net = &mysql->net;
1793
 
 
1794
 
  while ((pkt_len= cli_safe_read(mysql)) != packet_error)
1795
 
  {
1796
 
    cp= net->read_pos;
1797
 
    if (cp[0] != 254 || pkt_len >= 8)
1798
 
    {
1799
 
      if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
1800
 
                                          sizeof(MYSQL_ROWS) + pkt_len - 1)))
1801
 
      {
1802
 
        set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
1803
 
        goto err;
1804
 
      }
1805
 
      cur->data= (MYSQL_ROW) (cur+1);
1806
 
      *prev_ptr= cur;
1807
 
      prev_ptr= &cur->next;
1808
 
      memcpy((char *) cur->data, (char *) cp+1, pkt_len-1);
1809
 
      cur->length= pkt_len;             /* To allow us to do sanity checks */
1810
 
      result->rows++;
1811
 
    }
1812
 
    else
1813
 
    {
1814
 
      /* end of data */
1815
 
      *prev_ptr= 0;
1816
 
      mysql->warning_count= uint2korr(cp+1);
1817
 
      mysql->server_status= uint2korr(cp+3);
1818
 
      DBUG_PRINT("info",("status: %u  warning_count: %u",
1819
 
                         mysql->server_status, mysql->warning_count));
1820
 
      DBUG_RETURN(0);
1821
 
    }
1822
 
  }
1823
 
  set_stmt_errmsg(stmt, net);
1824
 
 
1825
 
err:
1826
 
  DBUG_RETURN(1);
1827
 
}
1828
 
 
1829
1433
/********************************************************************
1830
1434
 Transactional APIs
1831
1435
*********************************************************************/