mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
e94b4ebf2b
Give warning if we are using non transactional tables and do ROLLBACK Porting of crash-me and benchmarks to FrontBase Docs/manual.texi: Updates for 3.23.29 include/mysqld_error.h: New error messages sql-bench/Data/ATIS/fconnection.txt: Name change because 'connection' was a reserved word in FrontBase sql-bench/bench-init.pl.sh: Port to FrontBase sql-bench/crash-me.sh: Port to FrontBase sql-bench/server-cfg.sh: Port to FrontBase sql-bench/test-ATIS.sh: Port to FrontBase sql-bench/test-alter-table.sh: Port to FrontBase sql-bench/test-big-tables.sh: Port to FrontBase sql-bench/test-connect.sh: Port to FrontBase sql-bench/test-create.sh: Port to FrontBase sql-bench/test-insert.sh: Port to FrontBase sql-bench/test-select.sh: Port to FrontBase sql-bench/test-wisconsin.sh: Port to FrontBase sql/ha_berkeley.cc: All statements are now run in a sub transaction sql/ha_berkeley.h: All statements are now run in a sub transaction sql/handler.cc: All statements are now run in a sub transaction sql/handler.h: All statements are now run in a sub transaction sql/mysql_priv.h: Moved QUERY_NO.. flags to unique numbers sql/mysqld.cc: All statements are now run in a sub transaction sql/net_pkg.cc: Added send_warning sql/share/czech/errmsg.sys: New error messages sql/share/czech/errmsg.txt: New error messages sql/share/danish/errmsg.sys: New error messages sql/share/danish/errmsg.txt: New error messages sql/share/dutch/errmsg.sys: New error messages sql/share/dutch/errmsg.txt: New error messages sql/share/english/errmsg.sys: New error messages sql/share/english/errmsg.txt: New error messages sql/share/estonian/errmsg.sys: New error messages sql/share/estonian/errmsg.txt: New error messages sql/share/french/errmsg.sys: New error messages sql/share/french/errmsg.txt: New error messages sql/share/german/errmsg.sys: New error messages sql/share/german/errmsg.txt: New error messages sql/share/greek/errmsg.sys: New error messages sql/share/greek/errmsg.txt: New error messages sql/share/hungarian/errmsg.sys: New error messages sql/share/hungarian/errmsg.txt: New error messages sql/share/italian/errmsg.sys: New error messages sql/share/italian/errmsg.txt: New error messages sql/share/japanese/errmsg.sys: New error messages sql/share/japanese/errmsg.txt: New error messages sql/share/korean/errmsg.sys: New error messages sql/share/korean/errmsg.txt: New error messages sql/share/norwegian-ny/errmsg.txt: New error messages sql/share/norwegian/errmsg.txt: New error messages sql/share/polish/errmsg.sys: New error messages sql/share/polish/errmsg.txt: New error messages sql/share/portuguese/errmsg.sys: New error messages sql/share/portuguese/errmsg.txt: New error messages sql/share/romanian/errmsg.txt: New error messages sql/share/russian/errmsg.sys: New error messages sql/share/russian/errmsg.txt: New error messages sql/share/slovak/errmsg.sys: New error messages sql/share/slovak/errmsg.txt: New error messages sql/share/spanish/errmsg.sys: New error messages sql/share/spanish/errmsg.txt: New error messages sql/share/swedish/errmsg.OLD: New error messages sql/share/swedish/errmsg.sys: New error messages sql/share/swedish/errmsg.txt: New error messages sql/slave.cc: All statements are now run in a sub transaction sql/sql_class.cc: All statements are now run in a sub transaction sql/sql_class.h: All statements are now run in a sub transaction sql/sql_delete.cc: Remember if we are using a non transactional table sql/sql_insert.cc: Remember if we are using a non transactional table sql/sql_load.cc: Remember if we are using a non transactional table sql/sql_parse.cc: All statements are now run in a sub transaction sql/sql_select.cc: Remember if we are using a non transactional table sql/sql_table.cc: All statements are now run in a sub transaction sql/sql_update.cc: All statements are now run in a sub transaction sql/sql_yacc.yy: All statements are now run in a sub transaction
341 lines
8.1 KiB
C++
341 lines
8.1 KiB
C++
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
|
|
#include "mysql_priv.h"
|
|
#include <stdarg.h>
|
|
|
|
/* Send a error string to client */
|
|
|
|
void send_error(NET *net, uint sql_errno, const char *err)
|
|
{
|
|
uint length;
|
|
char buff[MYSQL_ERRMSG_SIZE+2];
|
|
THD *thd=current_thd;
|
|
DBUG_ENTER("send_error");
|
|
DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno,
|
|
err ? err : net->last_error[0] ?
|
|
net->last_error : "NULL"));
|
|
|
|
if (thd)
|
|
thd->query_error = 1; // needed to catch query errors during replication
|
|
if (!err)
|
|
{
|
|
if (sql_errno)
|
|
err=ER(sql_errno);
|
|
else if (!err)
|
|
{
|
|
if ((err=net->last_error)[0])
|
|
sql_errno=net->last_errno;
|
|
else
|
|
{
|
|
sql_errno=ER_UNKNOWN_ERROR;
|
|
err=ER(sql_errno); /* purecov: inspected */
|
|
}
|
|
}
|
|
}
|
|
if (net->vio == 0)
|
|
{
|
|
if (thd && thd->bootstrap)
|
|
{
|
|
fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
|
|
}
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
if (net->return_errno)
|
|
{ // new client code; Add errno before message
|
|
int2store(buff,sql_errno);
|
|
length= (uint) (strmake(buff+2,err,MYSQL_ERRMSG_SIZE-1) - buff);
|
|
err=buff;
|
|
}
|
|
else
|
|
{
|
|
length=(uint) strlen(err);
|
|
set_if_smaller(length,MYSQL_ERRMSG_SIZE);
|
|
}
|
|
VOID(net_write_command(net,(uchar) 255,(char*) err,length));
|
|
if (thd)
|
|
thd->fatal_error=0; // Error message is given
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
/*
|
|
At some point we need to be able to distinguish between warnings and
|
|
errors; The following function will help make this easier.
|
|
*/
|
|
|
|
void send_warning(NET *net, uint sql_errno, const char *err)
|
|
{
|
|
DBUG_ENTER("send_warning");
|
|
send_error(net,sql_errno,err);
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
/**
|
|
** write error package and flush to client
|
|
** It's a little too low level, but I don't want to allow another buffer
|
|
*/
|
|
/* VARARGS3 */
|
|
|
|
void
|
|
net_printf(NET *net, uint errcode, ...)
|
|
{
|
|
va_list args;
|
|
uint length,offset;
|
|
const char *format,*text_pos;
|
|
int head_length= NET_HEADER_SIZE;
|
|
THD *thd=current_thd;
|
|
DBUG_ENTER("net_printf");
|
|
DBUG_PRINT("enter",("message: %u",errcode));
|
|
|
|
if(thd) thd->query_error = 1;
|
|
// if we are here, something is wrong :-)
|
|
|
|
va_start(args,errcode);
|
|
format=ER(errcode);
|
|
offset= net->return_errno ? 2 : 0;
|
|
text_pos=(char*) net->buff+head_length+offset+1;
|
|
(void) vsprintf(my_const_cast(char*) (text_pos),format,args);
|
|
length=(uint) strlen((char*) text_pos);
|
|
if (length >= sizeof(net->last_error))
|
|
length=sizeof(net->last_error)-1; /* purecov: inspected */
|
|
va_end(args);
|
|
|
|
if (net->vio == 0)
|
|
{
|
|
if (thd && thd->bootstrap)
|
|
{
|
|
fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos);
|
|
thd->fatal_error=1;
|
|
}
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
int3store(net->buff,length+1+offset);
|
|
net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
|
|
net->buff[head_length]=(uchar) 255; // Error package
|
|
if (offset)
|
|
int2store(text_pos-2, errcode);
|
|
VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset));
|
|
if (thd)
|
|
thd->fatal_error=0; // Error message is given
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
|
|
void
|
|
send_ok(NET *net,ha_rows affected_rows,ulonglong id,const char *message)
|
|
{
|
|
if(net->no_send_ok)
|
|
return;
|
|
|
|
char buff[MYSQL_ERRMSG_SIZE+10],*pos;
|
|
DBUG_ENTER("send_ok");
|
|
buff[0]=0; // No fields
|
|
pos=net_store_length(buff+1,(ulonglong) affected_rows);
|
|
pos=net_store_length(pos, (ulonglong) id);
|
|
if (net->return_status)
|
|
{
|
|
int2store(pos,*net->return_status);
|
|
pos+=2;
|
|
}
|
|
if (message)
|
|
pos=net_store_data((char*) pos,message);
|
|
if (net->vio != 0)
|
|
{
|
|
VOID(my_net_write(net,buff,(uint) (pos-buff)));
|
|
VOID(net_flush(net));
|
|
}
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
void
|
|
send_eof(NET *net,bool no_flush)
|
|
{
|
|
static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
|
|
DBUG_ENTER("send_eof");
|
|
if (net->vio != 0)
|
|
{
|
|
VOID(my_net_write(net,eof_buff,1));
|
|
if (!no_flush)
|
|
VOID(net_flush(net));
|
|
}
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
** Store a field length in logical packet
|
|
****************************************************************************/
|
|
|
|
char *
|
|
net_store_length(char *pkg, ulonglong length)
|
|
{
|
|
uchar *packet=(uchar*) pkg;
|
|
if (length < LL(251))
|
|
{
|
|
*packet=(uchar) length;
|
|
return (char*) packet+1;
|
|
}
|
|
/* 251 is reserved for NULL */
|
|
if (length < LL(65536))
|
|
{
|
|
*packet++=252;
|
|
int2store(packet,(uint) length);
|
|
return (char*) packet+2;
|
|
}
|
|
if (length < LL(16777216))
|
|
{
|
|
*packet++=253;
|
|
int3store(packet,(ulong) length);
|
|
return (char*) packet+3;
|
|
}
|
|
*packet++=254;
|
|
int8store(packet,length);
|
|
return (char*) packet+9;
|
|
}
|
|
|
|
char *
|
|
net_store_length(char *pkg, uint length)
|
|
{
|
|
uchar *packet=(uchar*) pkg;
|
|
if (length < 251)
|
|
{
|
|
*packet=(uchar) length;
|
|
return (char*) packet+1;
|
|
}
|
|
*packet++=252;
|
|
int2store(packet,(uint) length);
|
|
return (char*) packet+2;
|
|
}
|
|
|
|
/* The following will only be used for short strings < 65K */
|
|
char *
|
|
net_store_data(char *to,const char *from)
|
|
{
|
|
uint length=(uint) strlen(from);
|
|
to=net_store_length(to,length);
|
|
memcpy(to,from,length);
|
|
return to+length;
|
|
}
|
|
|
|
|
|
char *
|
|
net_store_data(char *to,int32 from)
|
|
{
|
|
char buff[20];
|
|
uint length=(uint) (int10_to_str(from,buff,10)-buff);
|
|
to=net_store_length(to,length);
|
|
memcpy(to,buff,length);
|
|
return to+length;
|
|
}
|
|
|
|
char *
|
|
net_store_data(char *to,longlong from)
|
|
{
|
|
char buff[22];
|
|
uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
|
|
to=net_store_length(to,length);
|
|
memcpy(to,buff,length);
|
|
return to+length;
|
|
}
|
|
|
|
|
|
bool net_store_null(String *packet)
|
|
{
|
|
return packet->append((char) 251);
|
|
}
|
|
|
|
bool
|
|
net_store_data(String *packet,const char *from,uint length)
|
|
{
|
|
ulong packet_length=packet->length();
|
|
if (packet_length+5+length > packet->alloced_length() &&
|
|
packet->realloc(packet_length+5+length))
|
|
return 1;
|
|
char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
|
|
(ulonglong) length);
|
|
memcpy(to,from,length);
|
|
packet->length((uint) (to+length-packet->ptr()));
|
|
return 0;
|
|
}
|
|
|
|
/* The following is only used at short, null terminated data */
|
|
|
|
bool
|
|
net_store_data(String *packet,const char *from)
|
|
{
|
|
uint length=(uint) strlen(from);
|
|
uint packet_length=packet->length();
|
|
if (packet_length+5+length > packet->alloced_length() &&
|
|
packet->realloc(packet_length+5+length))
|
|
return 1;
|
|
char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
|
|
length);
|
|
memcpy(to,from,length);
|
|
packet->length((uint) (to+length-packet->ptr()));
|
|
return 0;
|
|
}
|
|
|
|
|
|
bool
|
|
net_store_data(String *packet,uint32 from)
|
|
{
|
|
char buff[20];
|
|
return net_store_data(packet,(char*) buff,
|
|
(uint) (int10_to_str(from,buff,10)-buff));
|
|
}
|
|
|
|
bool
|
|
net_store_data(String *packet, longlong from)
|
|
{
|
|
char buff[22];
|
|
return net_store_data(packet,(char*) buff,
|
|
(uint) (longlong10_to_str(from,buff,10)-buff));
|
|
}
|
|
|
|
bool
|
|
net_store_data(String *packet,struct tm *tmp)
|
|
{
|
|
char buff[20];
|
|
sprintf(buff,"%04d-%02d-%02d %02d:%02d:%02d",
|
|
((int) (tmp->tm_year+1900)) % 10000,
|
|
(int) tmp->tm_mon+1,
|
|
(int) tmp->tm_mday,
|
|
(int) tmp->tm_hour,
|
|
(int) tmp->tm_min,
|
|
(int) tmp->tm_sec);
|
|
return net_store_data(packet,(char*) buff,19);
|
|
}
|
|
|
|
bool net_store_data(String* packet, I_List<i_string>* str_list)
|
|
{
|
|
char buf[256];
|
|
String tmp(buf, sizeof(buf));
|
|
tmp.length(0);
|
|
I_List_iterator<i_string> it(*str_list);
|
|
i_string* s;
|
|
|
|
while((s=it++))
|
|
{
|
|
if(tmp.length())
|
|
tmp.append(',');
|
|
tmp.append(s->ptr);
|
|
}
|
|
|
|
return net_store_data(packet, (char*)tmp.ptr(), tmp.length());
|
|
}
|