~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table.cc

  • Committer: Brian Aker
  • Date: 2009-06-01 02:14:08 UTC
  • mfrom: (1039.1.17 merge)
  • Revision ID: brian@gaz-20090601021408-ejp1tjf3m5fm7mzv
Merge of Brian

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
 
50
50
void open_table_error(TableShare *share, int error, int db_errno,
51
51
                      myf errortype, int errarg);
52
 
static void fix_type_pointers(const char ***array, TYPELIB *point_to_type,
53
 
                              uint32_t types, char **names);
54
52
 
55
53
/*************************************************************************/
56
54
 
72
70
 
73
71
  DESCRIPTION
74
72
    Checks file name part starting with the rightmost '.' character,
75
 
    and returns it if it is equal to '.frm'.
 
73
    and returns it if it is equal to '.dfe'.
76
74
 
77
75
  TODO
78
76
    It is a good idea to get rid of this function modifying the code
285
283
    share->storage_engine= ha_resolve_by_name(session, &engine_name);
286
284
  }
287
285
 
288
 
  share->mysql_version= DRIZZLE_VERSION_ID; // TODO: remove
289
 
 
290
286
  drizzled::message::Table::TableOptions table_options;
291
287
 
292
288
  if (table.has_options())
1531
1527
  return (error);
1532
1528
}
1533
1529
 
1534
 
/* close_temporary_tables' internal, 4 is due to uint4korr definition */
1535
 
uint32_t  Table::tmpkeyval()
1536
 
{
1537
 
  return uint4korr(s->table_cache_key.str + s->table_cache_key.length - 4);
1538
 
}
1539
 
 
1540
1530
/*
1541
1531
  Free information allocated by openfrm
1542
1532
 
1565
1555
  if (free_share)
1566
1556
  {
1567
1557
    if (s->tmp_table == NO_TMP_TABLE)
1568
 
      release_table_share(s, RELEASE_NORMAL);
 
1558
      release_table_share(s);
1569
1559
    else
1570
1560
      s->free_table_share();
1571
1561
  }
1587
1577
}
1588
1578
 
1589
1579
 
1590
 
        /* Find where a form starts */
1591
 
        /* if formname is NULL then only formnames is read */
1592
 
 
1593
 
ulong get_form_pos(File file, unsigned char *head, TYPELIB *save_names)
1594
 
{
1595
 
  uint32_t a_length,names,length;
1596
 
  unsigned char *pos,*buf;
1597
 
  ulong ret_value=0;
1598
 
 
1599
 
  names=uint2korr(head+8);
1600
 
  a_length=(names+2)*sizeof(char *);            /* Room for two extra */
1601
 
 
1602
 
  if (!save_names)
1603
 
    a_length=0;
1604
 
  else
1605
 
    save_names->type_names=0;                   /* Clear if error */
1606
 
 
1607
 
  if (names)
1608
 
  {
1609
 
    length=uint2korr(head+4);
1610
 
    lseek(file,64,SEEK_SET);
1611
 
    if (!(buf= (unsigned char*) malloc(length+a_length+names*4)) ||
1612
 
        my_read(file, buf+a_length, (size_t) (length+names*4),
1613
 
                MYF(MY_NABP)))
1614
 
    {                                           /* purecov: inspected */
1615
 
      if (buf)
1616
 
        free(buf);
1617
 
      return(0L);                               /* purecov: inspected */
1618
 
    }
1619
 
    pos= buf+a_length+length;
1620
 
    ret_value=uint4korr(pos);
1621
 
  }
1622
 
  if (! save_names)
1623
 
  {
1624
 
    if (names)
1625
 
      free((unsigned char*) buf);
1626
 
  }
1627
 
  else if (!names)
1628
 
    memset(save_names, 0, sizeof(save_names));
1629
 
  else
1630
 
  {
1631
 
    char *str;
1632
 
    str=(char *) (buf+a_length);
1633
 
    fix_type_pointers((const char ***) &buf,save_names,1,&str);
1634
 
  }
1635
 
  return(ret_value);
1636
 
}
1637
 
 
1638
 
 
1639
 
/*
1640
 
  Read string from a file with malloc
1641
 
 
1642
 
  NOTES:
1643
 
    We add an \0 at end of the read string to make reading of C strings easier
1644
 
*/
1645
 
 
1646
 
int read_string(File file, unsigned char**to, size_t length)
1647
 
{
1648
 
 
1649
 
  if (*to)
1650
 
    free(*to);
1651
 
  if (!(*to= (unsigned char*) malloc(length+1)) ||
1652
 
      my_read(file, *to, length,MYF(MY_NABP)))
1653
 
  {
1654
 
    if (*to)
1655
 
      free(*to);
1656
 
    *to= NULL;
1657
 
    return(1);                           /* purecov: inspected */
1658
 
  }
1659
 
  *((char*) *to+length)= '\0';
1660
 
  return (0);
1661
 
} /* read_string */
1662
 
 
1663
 
 
1664
 
        /* Add a new form to a form file */
1665
 
 
1666
 
off_t make_new_entry(File file, unsigned char *fileinfo, TYPELIB *formnames,
1667
 
                     const char *newname)
1668
 
{
1669
 
  uint32_t i,bufflength,maxlength,n_length,length,names;
1670
 
  off_t endpos,newpos;
1671
 
  unsigned char buff[IO_SIZE];
1672
 
  unsigned char *pos;
1673
 
 
1674
 
  length=(uint32_t) strlen(newname)+1;
1675
 
  n_length=uint2korr(fileinfo+4);
1676
 
  maxlength=uint2korr(fileinfo+6);
1677
 
  names=uint2korr(fileinfo+8);
1678
 
  newpos=uint4korr(fileinfo+10);
1679
 
 
1680
 
  if (64+length+n_length+(names+1)*4 > maxlength)
1681
 
  {                                             /* Expand file */
1682
 
    newpos+=IO_SIZE;
1683
 
    int4store(fileinfo+10,newpos);
1684
 
    endpos= lseek(file,0,SEEK_END);/* Copy from file-end */
1685
 
    bufflength= (uint32_t) (endpos & (IO_SIZE-1));      /* IO_SIZE is a power of 2 */
1686
 
 
1687
 
    while (endpos > maxlength)
1688
 
    {
1689
 
      lseek(file,(off_t) (endpos-bufflength),SEEK_SET);
1690
 
      if (my_read(file, buff, bufflength, MYF(MY_NABP+MY_WME)))
1691
 
        return(0L);
1692
 
      lseek(file,(off_t) (endpos-bufflength+IO_SIZE),SEEK_SET);
1693
 
      if ((my_write(file, buff,bufflength,MYF(MY_NABP+MY_WME))))
1694
 
        return(0);
1695
 
      endpos-=bufflength; bufflength=IO_SIZE;
1696
 
    }
1697
 
    memset(buff, 0, IO_SIZE);                   /* Null new block */
1698
 
    lseek(file,(ulong) maxlength,SEEK_SET);
1699
 
    if (my_write(file,buff,bufflength,MYF(MY_NABP+MY_WME)))
1700
 
      return(0L);
1701
 
    maxlength+=IO_SIZE;                         /* Fix old ref */
1702
 
    int2store(fileinfo+6,maxlength);
1703
 
    for (i=names, pos= (unsigned char*) *formnames->type_names+n_length-1; i--;
1704
 
         pos+=4)
1705
 
    {
1706
 
      endpos=uint4korr(pos)+IO_SIZE;
1707
 
      int4store(pos,endpos);
1708
 
    }
1709
 
  }
1710
 
 
1711
 
  if (n_length == 1 )
1712
 
  {                                             /* First name */
1713
 
    length++;
1714
 
    sprintf((char*)buff,"/%s/",newname);
1715
 
  }
1716
 
  else
1717
 
    sprintf((char*)buff,"%s/",newname); /* purecov: inspected */
1718
 
  lseek(file, 63 + n_length,SEEK_SET);
1719
 
  if (my_write(file, buff, (size_t) length+1,MYF(MY_NABP+MY_WME)) ||
1720
 
      (names && my_write(file,(unsigned char*) (*formnames->type_names+n_length-1),
1721
 
                         names*4, MYF(MY_NABP+MY_WME))) ||
1722
 
      my_write(file, fileinfo+10, 4,MYF(MY_NABP+MY_WME)))
1723
 
    return(0L); /* purecov: inspected */
1724
 
 
1725
 
  int2store(fileinfo+8,names+1);
1726
 
  int2store(fileinfo+4,n_length+length);
1727
 
  assert(ftruncate(file, newpos)==0);/* Append file with '\0' */
1728
 
  return(newpos);
1729
 
} /* make_new_entry */
1730
 
 
1731
 
 
1732
1580
        /* error message when opening a form file */
1733
1581
 
1734
1582
void TableShare::open_table_error(int pass_error, int db_errno, int pass_errarg)
1803
1651
} /* open_table_error */
1804
1652
 
1805
1653
 
1806
 
        /*
1807
 
        ** fix a str_type to a array type
1808
 
        ** typeparts separated with some char. differents types are separated
1809
 
        ** with a '\0'
1810
 
        */
1811
 
 
1812
 
static void
1813
 
fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint32_t types,
1814
 
                  char **names)
1815
 
{
1816
 
  char *type_name, *ptr;
1817
 
  char chr;
1818
 
 
1819
 
  ptr= *names;
1820
 
  while (types--)
1821
 
  {
1822
 
    point_to_type->name=0;
1823
 
    point_to_type->type_names= *array;
1824
 
 
1825
 
    if ((chr= *ptr))                    /* Test if empty type */
1826
 
    {
1827
 
      while ((type_name=strchr(ptr+1,chr)) != NULL)
1828
 
      {
1829
 
        *((*array)++) = ptr+1;
1830
 
        *type_name= '\0';               /* End string */
1831
 
        ptr=type_name;
1832
 
      }
1833
 
      ptr+=2;                           /* Skip end mark and last 0 */
1834
 
    }
1835
 
    else
1836
 
      ptr++;
1837
 
    point_to_type->count= (uint32_t) (*array - point_to_type->type_names);
1838
 
    point_to_type++;
1839
 
    *((*array)++)= NULL;                /* End of type */
1840
 
  }
1841
 
  *names=ptr;                           /* Update end */
1842
 
  return;
1843
 
} /* fix_type_pointers */
1844
 
 
1845
 
 
1846
1654
TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings)
1847
1655
{
1848
1656
  TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
2002
1810
  return (my_rename(from_s.c_str(),to_s.c_str(),MYF(MY_WME)));
2003
1811
}
2004
1812
 
2005
 
 
2006
 
/*
2007
 
  Allocate string field in MEM_ROOT and return it as String
2008
 
 
2009
 
  SYNOPSIS
2010
 
    get_field()
2011
 
    mem         MEM_ROOT for allocating
2012
 
    field       Field for retrieving of string
2013
 
    res         result String
2014
 
 
2015
 
  RETURN VALUES
2016
 
    1   string is empty
2017
 
    0   all ok
2018
 
*/
2019
 
 
2020
 
bool get_field(MEM_ROOT *mem, Field *field, String *res)
2021
 
{
2022
 
  char buff[MAX_FIELD_WIDTH], *to;
2023
 
  String str(buff,sizeof(buff),&my_charset_bin);
2024
 
  uint32_t length;
2025
 
 
2026
 
  field->val_str(&str);
2027
 
  if (!(length= str.length()))
2028
 
  {
2029
 
    res->length(0);
2030
 
    return 1;
2031
 
  }
2032
 
  if (!(to= strmake_root(mem, str.ptr(), length)))
2033
 
    length= 0;                                  // Safety fix
2034
 
  res->set(to, length, ((Field_str*)field)->charset());
2035
 
  return 0;
2036
 
}
2037
 
 
2038
 
 
2039
 
/*
2040
 
  Allocate string field in MEM_ROOT and return it as NULL-terminated string
2041
 
 
2042
 
  SYNOPSIS
2043
 
    get_field()
2044
 
    mem         MEM_ROOT for allocating
2045
 
    field       Field for retrieving of string
2046
 
 
2047
 
  RETURN VALUES
2048
 
    NULL  string is empty
2049
 
    #      pointer to NULL-terminated string value of field
2050
 
*/
2051
 
 
2052
 
char *get_field(MEM_ROOT *mem, Field *field)
2053
 
{
2054
 
  char buff[MAX_FIELD_WIDTH], *to;
2055
 
  String str(buff,sizeof(buff),&my_charset_bin);
2056
 
  uint32_t length;
2057
 
 
2058
 
  field->val_str(&str);
2059
 
  length= str.length();
2060
 
  if (!length || !(to= (char*) alloc_root(mem,length+1)))
2061
 
    return NULL;
2062
 
  memcpy(to,str.ptr(),(uint32_t) length);
2063
 
  to[length]=0;
2064
 
  return to;
2065
 
}
2066
 
 
2067
1813
/*
2068
1814
  DESCRIPTION
2069
1815
    given a buffer with a key value, and a map of keyparts
2178
1924
}
2179
1925
 
2180
1926
 
2181
 
/**
2182
 
  Checks whether a table is intact. Should be done *just* after the table has
2183
 
  been opened.
2184
 
 
2185
 
  @param[in] table             The table to check
2186
 
  @param[in] table_f_count     Expected number of columns in the table
2187
 
  @param[in] table_def         Expected structure of the table (column name
2188
 
                               and type)
2189
 
 
2190
 
  @retval  false  OK
2191
 
  @retval  TRUE   There was an error. An error message is output
2192
 
                  to the error log.  We do not push an error
2193
 
                  message into the error stack because this
2194
 
                  function is currently only called at start up,
2195
 
                  and such errors never reach the user.
2196
 
*/
2197
 
 
2198
 
bool
2199
 
Table::table_check_intact(const uint32_t table_f_count,
2200
 
                          const TABLE_FIELD_W_TYPE *table_def)
2201
 
{
2202
 
  uint32_t i;
2203
 
  bool error= false;
2204
 
  bool fields_diff_count;
2205
 
 
2206
 
  fields_diff_count= (s->fields != table_f_count);
2207
 
  if (fields_diff_count)
2208
 
  {
2209
 
 
2210
 
    /* previous MySQL version */
2211
 
    if (DRIZZLE_VERSION_ID > s->mysql_version)
2212
 
    {
2213
 
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE),
2214
 
                      alias, table_f_count, s->fields,
2215
 
                      s->mysql_version, DRIZZLE_VERSION_ID);
2216
 
      return(true);
2217
 
    }
2218
 
    else if (DRIZZLE_VERSION_ID == s->mysql_version)
2219
 
    {
2220
 
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), alias,
2221
 
                      table_f_count, s->fields);
2222
 
      return(true);
2223
 
    }
2224
 
    /*
2225
 
      Something has definitely changed, but we're running an older
2226
 
      version of MySQL with new system tables.
2227
 
      Let's check column definitions. If a column was added at
2228
 
      the end of the table, then we don't care much since such change
2229
 
      is backward compatible.
2230
 
    */
2231
 
  }
2232
 
  char buffer[STRING_BUFFER_USUAL_SIZE];
2233
 
  for (i=0 ; i < table_f_count; i++, table_def++)
2234
 
  {
2235
 
    String sql_type(buffer, sizeof(buffer), system_charset_info);
2236
 
    sql_type.length(0);
2237
 
    if (i < s->fields)
2238
 
    {
2239
 
      Field *cur_field= this->field[i];
2240
 
 
2241
 
      if (strncmp(cur_field->field_name, table_def->name.str,
2242
 
                  table_def->name.length))
2243
 
      {
2244
 
        /*
2245
 
          Name changes are not fatal, we use ordinal numbers to access columns.
2246
 
          Still this can be a sign of a tampered table, output an error
2247
 
          to the error log.
2248
 
        */
2249
 
        errmsg_printf(ERRMSG_LVL_ERROR, _("Incorrect definition of table %s.%s: "
2250
 
                        "expected column '%s' at position %d, found '%s'."),
2251
 
                        s->db.str, alias, table_def->name.str, i,
2252
 
                        cur_field->field_name);
2253
 
      }
2254
 
      cur_field->sql_type(sql_type);
2255
 
      /*
2256
 
        Generally, if column types don't match, then something is
2257
 
        wrong.
2258
 
 
2259
 
        However, we only compare column definitions up to the
2260
 
        length of the original definition, since we consider the
2261
 
        following definitions compatible:
2262
 
 
2263
 
        1. DATETIME and DATETIM
2264
 
        2. INT(11) and INT(11
2265
 
        3. SET('one', 'two') and SET('one', 'two', 'more')
2266
 
 
2267
 
        For SETs or ENUMs, if the same prefix is there it's OK to
2268
 
        add more elements - they will get higher ordinal numbers and
2269
 
        the new table definition is backward compatible with the
2270
 
        original one.
2271
 
       */
2272
 
      if (strncmp(sql_type.c_ptr_safe(), table_def->type.str,
2273
 
                  table_def->type.length - 1))
2274
 
      {
2275
 
        errmsg_printf(ERRMSG_LVL_ERROR,
2276
 
                      _("Incorrect definition of table %s.%s: "
2277
 
                        "expected column '%s' at position %d to have type "
2278
 
                        "%s, found type %s."),
2279
 
                      s->db.str, alias,
2280
 
                      table_def->name.str, i, table_def->type.str,
2281
 
                      sql_type.c_ptr_safe());
2282
 
        error= true;
2283
 
      }
2284
 
      else if (table_def->cset.str && !cur_field->has_charset())
2285
 
      {
2286
 
        errmsg_printf(ERRMSG_LVL_ERROR,
2287
 
                      _("Incorrect definition of table %s.%s: "
2288
 
                        "expected the type of column '%s' at position %d "
2289
 
                        "to have character set '%s' but the type has no "
2290
 
                        "character set."),
2291
 
                      s->db.str, alias,
2292
 
                      table_def->name.str, i, table_def->cset.str);
2293
 
        error= true;
2294
 
      }
2295
 
      else if (table_def->cset.str &&
2296
 
               strcmp(cur_field->charset()->csname, table_def->cset.str))
2297
 
      {
2298
 
        errmsg_printf(ERRMSG_LVL_ERROR,
2299
 
                      _("Incorrect definition of table %s.%s: "
2300
 
                        "expected the type of column '%s' at position %d "
2301
 
                        "to have character set '%s' but found "
2302
 
                        "character set '%s'."),
2303
 
                      s->db.str, alias,
2304
 
                      table_def->name.str, i, table_def->cset.str,
2305
 
                      cur_field->charset()->csname);
2306
 
        error= true;
2307
 
      }
2308
 
    }
2309
 
    else
2310
 
    {
2311
 
      errmsg_printf(ERRMSG_LVL_ERROR,
2312
 
                    _("Incorrect definition of table %s.%s: "
2313
 
                      "expected column '%s' at position %d to have type %s "
2314
 
                      " but the column is not found."),
2315
 
                    s->db.str, alias,
2316
 
                    table_def->name.str, i, table_def->type.str);
2317
 
      error= true;
2318
 
    }
2319
 
  }
2320
 
  return(error);
2321
 
}
2322
 
 
2323
 
 
2324
1927
/*
2325
1928
  Create Item_field for each column in the table.
2326
1929
 
2353
1956
  return false;
2354
1957
}
2355
1958
 
2356
 
/*
2357
 
  Reset an existing list of Item_field items to point to the
2358
 
  Fields of this table.
2359
 
 
2360
 
  SYNPOSIS
2361
 
    Table::fill_item_list()
2362
 
      item_list          a non-empty list with Item_fields
2363
 
 
2364
 
  DESCRIPTION
2365
 
    This is a counterpart of fill_item_list used to redirect
2366
 
    Item_fields to the fields of a newly created table.
2367
 
    The caller must ensure that number of items in the item_list
2368
 
    is the same as the number of columns in the table.
2369
 
*/
2370
 
 
2371
 
void Table::reset_item_list(List<Item> *item_list) const
2372
 
{
2373
 
  List_iterator_fast<Item> it(*item_list);
2374
 
  for (Field **ptr= field; *ptr; ptr++)
2375
 
  {
2376
 
    Item_field *item_field= (Item_field*) it++;
2377
 
    assert(item_field != 0);
2378
 
    item_field->reset_field(*ptr);
2379
 
  }
2380
 
}
2381
 
 
2382
1959
 
2383
1960
/*
2384
1961
  Find underlying base tables (TableList) which represent given
2807
2384
    mark_auto_increment_column();
2808
2385
}
2809
2386
 
2810
 
 
2811
 
/*
2812
 
  Cleanup this table for re-execution.
2813
 
 
2814
 
  SYNOPSIS
2815
 
    TableList::reinit_before_use()
2816
 
*/
2817
 
 
2818
 
void TableList::reinit_before_use(Session *session)
2819
 
{
2820
 
  /*
2821
 
    Reset old pointers to TABLEs: they are not valid since the tables
2822
 
    were closed in the end of previous prepare or execute call.
2823
 
  */
2824
 
  table= 0;
2825
 
  /* Reset is_schema_table_processed value(needed for I_S tables */
2826
 
  schema_table_state= NOT_PROCESSED;
2827
 
 
2828
 
  TableList *embedded; /* The table at the current level of nesting. */
2829
 
  TableList *parent_embedding= this; /* The parent nested table reference. */
2830
 
  do
2831
 
  {
2832
 
    embedded= parent_embedding;
2833
 
    if (embedded->prep_on_expr)
2834
 
      embedded->on_expr= embedded->prep_on_expr->copy_andor_structure(session);
2835
 
    parent_embedding= embedded->embedding;
2836
 
  }
2837
 
  while (parent_embedding &&
2838
 
         parent_embedding->nested_join->join_list.head() == embedded);
2839
 
}
2840
 
 
2841
2387
/*
2842
2388
  Return subselect that contains the FROM list this table is taken from
2843
2389