libdrizzle Developer Documentation

column.c
Go to the documentation of this file.
1 /*
2  * Drizzle Client & Protocol Library
3  *
4  * Copyright (C) 2008 Eric Day (eday@oddments.org)
5  * All rights reserved.
6  *
7  * Use and distribution licensed under the BSD license. See
8  * the COPYING file in this directory for full text.
9  */
10 
16 #include "common.h"
17 
18 /*
19  * Private variables.
20  */
21 
23 {
36 };
37 
39 {
50 
61 
72 
83 
94 
105 
116 
127 
138 
149 
160 
171 
182 
193 
204 
215 
226 
237 
248 
259 
270 
281 
292 
303 
314 
320  DRIZZLE_COLUMN_TYPE_DRIZZLE_MAX
321 };
322 
323 /*
324  * Common definitions
325  */
326 
328  drizzle_column_st *column)
329 {
330  if (column == NULL)
331  {
332  column= malloc(sizeof(drizzle_column_st));
333  if (column == NULL)
334  {
335  drizzle_set_error(result->con->drizzle, "drizzle_column_create",
336  "malloc");
337  return NULL;
338  }
339 
340  memset(column, 0, sizeof(drizzle_column_st));
342  }
343  else
344  memset(column, 0, sizeof(drizzle_column_st));
345 
346  column->result= result;
347 
348  if (result->column_list)
349  result->column_list->prev= column;
350  column->next= result->column_list;
351  result->column_list= column;
352 
353  return column;
354 }
355 
357 {
358  if (column->result->column_list == column)
359  column->result->column_list= column->next;
360  if (column->prev)
361  column->prev->next= column->next;
362  if (column->next)
363  column->next->prev= column->prev;
364 
365  if (column->options & DRIZZLE_COLUMN_ALLOCATED)
366  free(column);
367 }
368 
370 {
371  return column->result;
372 }
373 
375 {
376  return column->catalog;
377 }
378 
380 {
381  return column->db;
382 }
383 
385 {
386  return column->table;
387 }
388 
390 {
391  return column->orig_table;
392 }
393 
395 {
396  return column->name;
397 }
398 
400 {
401  return column->orig_name;
402 }
403 
405 {
406  return column->charset;
407 }
408 
410 {
411  return column->size;
412 }
413 
415 {
416  return column->max_size;
417 }
418 
420 {
421  column->max_size= size;
422 }
423 
425 {
426  return column->type;
427 }
428 
431 {
432  return _column_type_drizzle_map_from[column->type];
433 }
434 
436 {
437  return column->flags;
438 }
439 
441 {
442  return column->decimals;
443 }
444 
446  size_t *size)
447 {
448  *size= column->default_value_size;
449  return column->default_value;
450 }
451 
452 /*
453  * Client definitions
454  */
455 
457 {
458  if (drizzle_state_none(result->con))
459  {
461 
464  }
465 
466  return drizzle_state_loop(result->con);
467 }
468 
470  drizzle_column_st *column,
471  drizzle_return_t *ret_ptr)
472 {
473  if (drizzle_state_none(result->con))
474  {
475  result->column= column;
476 
479  }
480 
481  *ret_ptr= drizzle_state_loop(result->con);
482  return result->column;
483 }
484 
486 {
487  drizzle_return_t ret;
488 
489  if (result->column_buffer == NULL)
490  {
491  if (result->column_count == 0)
492  {
494  return DRIZZLE_RETURN_OK;
495  }
496 
497  result->column_buffer= malloc(sizeof(drizzle_column_st) *
498  result->column_count);
499  if (result->column_buffer == NULL)
500  {
501  drizzle_set_error(result->con->drizzle, "drizzle_column_buffer",
502  "malloc");
503  return DRIZZLE_RETURN_MEMORY;
504  }
505  }
506 
507  /* No while body, just keep calling to buffer columns. */
508  while (drizzle_column_read(result,
509  &(result->column_buffer[result->column_current]),
510  &ret) != NULL && ret == DRIZZLE_RETURN_OK);
511  if (ret == DRIZZLE_RETURN_OK)
512  {
513  result->column_current= 0;
515  }
516 
517  return ret;
518 }
519 
521 {
522  if (result->column_current == result->column_count)
523  return NULL;
524 
525  result->column_current++;
526  return &(result->column_buffer[result->column_current - 1]);
527 }
528 
530 {
531  if (result->column_current == 0)
532  return NULL;
533 
534  result->column_current--;
535  return &(result->column_buffer[result->column_current]);
536 }
537 
538 void drizzle_column_seek(drizzle_result_st *result, uint16_t column)
539 {
540  if (column <= result->column_count)
541  result->column_current= column;
542 }
543 
545  uint16_t column)
546 {
547  if (column >= result->column_count)
548  return NULL;
549 
550  return &(result->column_buffer[column]);
551 }
552 
554 {
555  return result->column_current;
556 }
557 
558 /*
559  * Server definitions
560  */
561 
563  drizzle_column_st *column)
564 {
565  if (drizzle_state_none(result->con))
566  {
567  result->column= column;
568 
570  }
571 
572  return drizzle_state_loop(result->con);
573 }
574 
575 void drizzle_column_set_catalog(drizzle_column_st *column, const char *catalog)
576 {
577  if (catalog == NULL)
578  column->catalog[0]= 0;
579  else
580  {
581  strncpy(column->catalog, catalog, DRIZZLE_MAX_CATALOG_SIZE);
582  column->catalog[DRIZZLE_MAX_CATALOG_SIZE - 1]= 0;
583  }
584 }
585 
586 void drizzle_column_set_db(drizzle_column_st *column, const char *db)
587 {
588  if (db == NULL)
589  column->db[0]= 0;
590  else
591  {
592  strncpy(column->db, db, DRIZZLE_MAX_DB_SIZE);
593  column->db[DRIZZLE_MAX_DB_SIZE - 1]= 0;
594  }
595 }
596 
597 void drizzle_column_set_table(drizzle_column_st *column, const char *table)
598 {
599  if (table == NULL)
600  column->table[0]= 0;
601  else
602  {
603  strncpy(column->table, table, DRIZZLE_MAX_TABLE_SIZE);
604  column->table[DRIZZLE_MAX_TABLE_SIZE - 1]= 0;
605  }
606 }
607 
609  const char *orig_table)
610 {
611  if (orig_table == NULL)
612  column->orig_table[0]= 0;
613  else
614  {
615  strncpy(column->orig_table, orig_table, DRIZZLE_MAX_TABLE_SIZE);
616  column->orig_table[DRIZZLE_MAX_TABLE_SIZE - 1]= 0;
617  }
618 }
619 
620 void drizzle_column_set_name(drizzle_column_st *column, const char *name)
621 {
622  if (name == NULL)
623  column->name[0]= 0;
624  else
625  {
626  strncpy(column->name, name, DRIZZLE_MAX_COLUMN_NAME_SIZE);
627  column->name[DRIZZLE_MAX_COLUMN_NAME_SIZE - 1]= 0;
628  }
629 }
630 
632  const char *orig_name)
633 {
634  if (orig_name == NULL)
635  column->orig_name[0]= 0;
636  else
637  {
638  strncpy(column->orig_name, orig_name, DRIZZLE_MAX_COLUMN_NAME_SIZE);
639  column->orig_name[DRIZZLE_MAX_COLUMN_NAME_SIZE - 1]= 0;
640  }
641 }
642 
644  drizzle_charset_t charset)
645 {
646  column->charset= charset;
647 }
648 
649 void drizzle_column_set_size(drizzle_column_st *column, uint32_t size)
650 {
651  column->size= size;
652 }
653 
656 {
657  column->type= type;
658 }
659 
662 {
663  column->flags= flags;
664 }
665 
666 void drizzle_column_set_decimals(drizzle_column_st *column, uint8_t decimals)
667 {
668  column->decimals= decimals;
669 }
670 
672  const uint8_t *default_value,
673  size_t size)
674 {
675  if (default_value == NULL)
676  column->default_value[0]= 0;
677  else
678  {
680  {
681  memcpy(column->default_value, default_value, size);
682  column->default_value[size]= 0;
683  column->default_value_size= size;
684  }
685  else
686  {
687  memcpy(column->default_value, default_value,
691  }
692  }
693 }
694 
695 /*
696  * Internal state functions.
697  */
698 
700 {
701  drizzle_column_st *column;
702  drizzle_column_type_drizzle_t drizzle_type;
703 
704  drizzle_log_debug(con->drizzle, "drizzle_state_column_read");
705 
706  /* Assume the entire column packet will fit in the buffer. */
707  if (con->buffer_size < con->packet_size)
708  {
710  return DRIZZLE_RETURN_OK;
711  }
712 
713  if (con->packet_size == 5 && con->buffer_ptr[0] == 254)
714  {
715  /* EOF packet marking end of columns. */
716  con->result->column= NULL;
718  con->status= drizzle_get_byte2(con->buffer_ptr + 3);
719  con->buffer_ptr+= 5;
720  con->buffer_size-= 5;
721 
722  drizzle_state_pop(con);
723  }
724  else if (con->result->options & DRIZZLE_RESULT_SKIP_COLUMN)
725  {
726  con->buffer_ptr+= con->packet_size;
727  con->buffer_size-= con->packet_size;
728  con->packet_size= 0;
729 
731  }
732  else
733  {
734  column= drizzle_column_create(con->result, con->result->column);
735  if (column == NULL)
736  return DRIZZLE_RETURN_MEMORY;
737 
738  con->result->column= column;
739 
740  /* These functions can only fail if they need to read data, but we know we
741  buffered the entire packet, so ignore returns. */
743  (void)drizzle_unpack_string(con, column->db, DRIZZLE_MAX_DB_SIZE);
745  (void)drizzle_unpack_string(con, column->orig_table,
747  (void)drizzle_unpack_string(con, column->name,
749  (void)drizzle_unpack_string(con, column->orig_name,
751 
752  /* Skip one filler byte. */
754  column->size= drizzle_get_byte4(con->buffer_ptr + 3);
755 
756  if (con->options & DRIZZLE_CON_MYSQL)
757  column->type= con->buffer_ptr[7];
758  else
759  {
760  drizzle_type= con->buffer_ptr[7];
761  if (drizzle_type >= DRIZZLE_COLUMN_TYPE_DRIZZLE_MAX)
762  drizzle_type= DRIZZLE_COLUMN_TYPE_DRIZZLE_MAX;
763  column->type= _column_type_drizzle_map_to[drizzle_type];
764  }
765 
766  column->flags= drizzle_get_byte2(con->buffer_ptr + 8);
767  if (column->type <= DRIZZLE_COLUMN_TYPE_INT24 &&
769  {
771  }
772 
773  column->decimals= con->buffer_ptr[10];
774  /* Skip two reserved bytes. */
775 
776  con->buffer_ptr+= 13;
777  con->buffer_size-= 13;
778  con->packet_size-= 13;
779 
780  if (con->packet_size > 0)
781  {
783  con->packet_size);
784 
785  con->buffer_ptr+= con->packet_size;
786  con->buffer_size-= con->packet_size;
787  }
788  else
789  column->default_value[0]= 0;
790 
791  con->result->column_current++;
792 
793  drizzle_state_pop(con);
794  }
795 
796  return DRIZZLE_RETURN_OK;
797 }
798 
800 {
801  uint8_t *start= con->buffer_ptr + con->buffer_size;
802  uint8_t *ptr;
803  drizzle_column_st *column= con->result->column;
804 
805  drizzle_log_debug(con->drizzle, "drizzle_state_column_write");
806 
807  /* Calculate max packet size. */
808  con->packet_size= 9 + strlen(column->catalog)
809  + 9 + strlen(column->db)
810  + 9 + strlen(column->table)
811  + 9 + strlen(column->orig_table)
812  + 9 + strlen(column->name)
813  + 9 + strlen(column->orig_name)
814  + 1 /* Unused */
815  + 2 /* Charset */
816  + 4 /* Size */
817  + 1 /* Type */
818  + 2 /* Flags */
819  + 1 /* Decimals */
820  + 2 /* Unused */
821  + column->default_value_size;
822 
823  /* Assume the entire column packet will fit in the buffer. */
824  if ((con->packet_size + 4) > DRIZZLE_MAX_BUFFER_SIZE)
825  {
826  drizzle_set_error(con->drizzle, "drizzle_state_column_write",
827  "buffer too small:%zu", con->packet_size + 4);
829  }
830 
831  /* Flush buffer if there is not enough room. */
832  if (((size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer)) <
833  con->packet_size)
834  {
836  return DRIZZLE_RETURN_OK;
837  }
838 
839  /* Store packet size at the end since it may change. */
840  ptr= start;
841  ptr[3]= con->packet_number;
842  con->packet_number++;
843  ptr+= 4;
844 
845  ptr= drizzle_pack_string(column->catalog, ptr);
846  ptr= drizzle_pack_string(column->db, ptr);
847  ptr= drizzle_pack_string(column->table, ptr);
848  ptr= drizzle_pack_string(column->orig_table, ptr);
849  ptr= drizzle_pack_string(column->name, ptr);
850  ptr= drizzle_pack_string(column->orig_name, ptr);
851 
852  /* This unused byte is set to 12 for some reason. */
853  ptr[0]= 12;
854  ptr++;
855 
856  drizzle_set_byte2(ptr, column->charset);
857  ptr+= 2;
858 
859  drizzle_set_byte4(ptr, column->size);
860  ptr+= 4;
861 
862  if (con->options & DRIZZLE_CON_MYSQL)
863  ptr[0]= column->type;
864  else
865  ptr[0]= _column_type_drizzle_map_from[column->type];
866  ptr++;
867 
868  drizzle_set_byte2(ptr, column->flags);
869  ptr+= 2;
870 
871  ptr[0]= column->decimals;
872  ptr++;
873 
874  memset(ptr, 0, 2);
875  ptr+= 2;
876 
877  if (column->default_value_size > 0)
878  {
879  memcpy(ptr, column->default_value, column->default_value_size);
880  ptr+= column->default_value_size;
881  }
882 
883  con->packet_size= ((size_t)(ptr - start) - 4);
884  con->buffer_size+= (4 + con->packet_size);
885 
886  /* Store packet size now. */
887  drizzle_set_byte3(start, con->packet_size);
888 
889  con->result->column_current++;
890 
891  drizzle_state_pop(con);
892 
893  return DRIZZLE_RETURN_OK;
894 }