Merge joreland@bk-internal.mysql.com:/home/bk/mysql-5.0-ndb

into mysql.com:/home/jonas/src/mysql-5.0-ndb
This commit is contained in:
unknown 2005-01-09 05:03:33 +01:00
commit 79192c2335
35 changed files with 878 additions and 414 deletions

View File

@ -79,7 +79,8 @@ int completion_hash_update(HashTable *ht, char *arKey, uint nKeyLength,
if (!memcmp(p->arKey, arKey, nKeyLength)) {
entry *n;
n = (entry *) alloc_root(&ht->mem_root,sizeof(entry));
if (!(n = (entry *) alloc_root(&ht->mem_root,sizeof(entry))))
return FAILURE;
n->pNext = p->pData;
n->str = str;
p->pData = n;

View File

@ -1502,7 +1502,10 @@ You can turn off this feature to get a quicker startup with -A\n\n");
if (!(field_names[i] = (char **) alloc_root(&hash_mem_root,
sizeof(char *) *
(num_fields*2+1))))
break;
{
mysql_free_result(fields);
break;
}
field_names[i][num_fields*2]= '\0';
j=0;
while ((sql_field=mysql_fetch_field(fields)))
@ -2077,10 +2080,10 @@ print_table_data_html(MYSQL_RES *result)
}
while ((cur = mysql_fetch_row(result)))
{
ulong *lengths=mysql_fetch_lengths(result);
(void) tee_fputs("<TR>", PAGER);
for (uint i=0; i < mysql_num_fields(result); i++)
{
ulong *lengths=mysql_fetch_lengths(result);
(void) tee_fputs("<TD>", PAGER);
safe_put_field(cur[i],lengths[i]);
(void) tee_fputs("</TD>", PAGER);
@ -2106,10 +2109,10 @@ print_table_data_xml(MYSQL_RES *result)
fields = mysql_fetch_fields(result);
while ((cur = mysql_fetch_row(result)))
{
ulong *lengths=mysql_fetch_lengths(result);
(void) tee_fputs("\n <row>\n", PAGER);
for (uint i=0; i < mysql_num_fields(result); i++)
{
ulong *lengths=mysql_fetch_lengths(result);
tee_fprintf(PAGER, "\t<%s>", (fields[i].name ?
(fields[i].name[0] ? fields[i].name :
" &nbsp; ") : "NULL"));

View File

@ -145,7 +145,7 @@ case $FLAG in
#
-fh)
cat $FILES | $AWK '/el_action_t/ { print $3 }' | \
sort | tr '[a-z]' '[A-Z]' | $AWK '
sort | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n");

View File

@ -87,7 +87,8 @@ parse_line(EditLine *el, const char *line)
int argc;
Tokenizer *tok;
tok = tok_init(NULL);
if (!(tok = tok_init(NULL)))
return -1;
tok_line(tok, line, &argc, &argv);
argc = el_parse(el, argc, argv);
tok_end(tok);

View File

@ -419,3 +419,113 @@ SubscrID SbclID
3 NULL
drop table test1;
drop table test2;
create table t1 (
pk int primary key,
dt datetime not null,
da date not null,
ye year not null,
ti time not null,
ts timestamp not null,
index(dt),
index(da),
index(ye),
index(ti),
index(ts)
) engine=ndb;
insert into t1 (pk,dt,da,ye,ti) values
(1, '1901-05-05 23:00:59', '1901-05-05', '1901', '23:00:59'),
(2, '1912-09-05 13:00:59', '1912-09-05', '1912', '13:00:59'),
(3, '1945-12-31 00:00:00', '1945-12-31', '1945', '00:00:00'),
(4, '1955-12-31 00:00:00', '1955-12-31', '1955', '00:00:00'),
(5, '1963-06-06 06:06:06', '1963-06-06', '1963', '06:06:06'),
(6, '1993-06-06 06:06:06', '1993-06-06', '1993', '06:06:06'),
(7, '2001-01-01 10:11:10', '2001-01-01', '2001', '10:11:10'),
(8, '2001-01-01 10:11:11', '2001-01-01', '2001', '10:11:11'),
(9, '2005-01-31 23:59:59', '2005-01-31', '2005', '23:59:59');
select count(*)-9 from t1 use index (dt) where dt > '1900-01-01 00:00:00';
count(*)-9
0
select count(*)-6 from t1 use index (dt) where dt >= '1955-12-31 00:00:00';
count(*)-6
0
select count(*)-5 from t1 use index (dt) where dt > '1955-12-31 00:00:00';
count(*)-5
0
select count(*)-5 from t1 use index (dt) where dt < '1970-03-03 22:22:22';
count(*)-5
0
select count(*)-7 from t1 use index (dt) where dt < '2001-01-01 10:11:11';
count(*)-7
0
select count(*)-8 from t1 use index (dt) where dt <= '2001-01-01 10:11:11';
count(*)-8
0
select count(*)-9 from t1 use index (dt) where dt <= '2055-01-01 00:00:00';
count(*)-9
0
select count(*)-9 from t1 use index (da) where da > '1900-01-01';
count(*)-9
0
select count(*)-6 from t1 use index (da) where da >= '1955-12-31';
count(*)-6
0
select count(*)-5 from t1 use index (da) where da > '1955-12-31';
count(*)-5
0
select count(*)-5 from t1 use index (da) where da < '1970-03-03';
count(*)-5
0
select count(*)-6 from t1 use index (da) where da < '2001-01-01';
count(*)-6
0
select count(*)-8 from t1 use index (da) where da <= '2001-01-02';
count(*)-8
0
select count(*)-9 from t1 use index (da) where da <= '2055-01-01';
count(*)-9
0
select count(*)-9 from t1 use index (ye) where ye > '1900';
count(*)-9
0
select count(*)-6 from t1 use index (ye) where ye >= '1955';
count(*)-6
0
select count(*)-5 from t1 use index (ye) where ye > '1955';
count(*)-5
0
select count(*)-5 from t1 use index (ye) where ye < '1970';
count(*)-5
0
select count(*)-6 from t1 use index (ye) where ye < '2001';
count(*)-6
0
select count(*)-8 from t1 use index (ye) where ye <= '2001';
count(*)-8
0
select count(*)-9 from t1 use index (ye) where ye <= '2055';
count(*)-9
0
select count(*)-9 from t1 use index (ti) where ti >= '00:00:00';
count(*)-9
0
select count(*)-7 from t1 use index (ti) where ti > '00:00:00';
count(*)-7
0
select count(*)-7 from t1 use index (ti) where ti > '05:05:05';
count(*)-7
0
select count(*)-5 from t1 use index (ti) where ti > '06:06:06';
count(*)-5
0
select count(*)-5 from t1 use index (ti) where ti < '10:11:11';
count(*)-5
0
select count(*)-6 from t1 use index (ti) where ti <= '10:11:11';
count(*)-6
0
select count(*)-8 from t1 use index (ti) where ti < '23:59:59';
count(*)-8
0
select count(*)-9 from t1 use index (ti) where ti <= '23:59:59';
count(*)-9
0

View File

@ -143,3 +143,39 @@ drop table t1;
create table t1 (f float(54));
ERROR 42000: Incorrect column specifier for column 'f'
drop table if exists t1;
create table t1 (f float(4,3));
insert into t1 values (-11.0),(-11),("-11"),(11.0),(11),("11");
Warnings:
Warning 1264 Out of range value adjusted for column 'f' at row 1
Warning 1264 Out of range value adjusted for column 'f' at row 2
Warning 1264 Out of range value adjusted for column 'f' at row 3
Warning 1264 Out of range value adjusted for column 'f' at row 4
Warning 1264 Out of range value adjusted for column 'f' at row 5
Warning 1264 Out of range value adjusted for column 'f' at row 6
select * from t1;
f
-9.999
-9.999
-9.999
9.999
9.999
9.999
drop table if exists t1;
create table t1 (f double(4,3));
insert into t1 values (-11.0),(-11),("-11"),(11.0),(11),("11");
Warnings:
Warning 1264 Out of range value adjusted for column 'f' at row 1
Warning 1264 Out of range value adjusted for column 'f' at row 2
Warning 1264 Out of range value adjusted for column 'f' at row 3
Warning 1264 Out of range value adjusted for column 'f' at row 4
Warning 1264 Out of range value adjusted for column 'f' at row 5
Warning 1264 Out of range value adjusted for column 'f' at row 6
select * from t1;
f
-9.999
-9.999
-9.999
9.999
9.999
9.999
drop table if exists t1;

View File

@ -15,8 +15,8 @@ f1 float NULL YES NULL
f2 double NULL YES NULL
insert into t1 values(10,10),(1e+5,1e+5),(1234567890,1234567890),(1e+10,1e+10),(1e+15,1e+15),(1e+20,1e+20),(1e+50,1e+50),(1e+150,1e+150);
Warnings:
Warning 1264 Data truncated; out of range for column 'f1' at row 7
Warning 1264 Data truncated; out of range for column 'f1' at row 8
Warning 1264 Out of range value adjusted for column 'f1' at row 7
Warning 1264 Out of range value adjusted for column 'f1' at row 8
insert into t1 values(-10,-10),(1e-5,1e-5),(1e-10,1e-10),(1e-15,1e-15),(1e-20,1e-20),(1e-50,1e-50),(1e-150,1e-150);
select * from t1;
f1 f2
@ -143,3 +143,39 @@ drop table t1;
create table t1 (f float(54));
ERROR 42000: Incorrect column specifier for column 'f'
drop table if exists t1;
create table t1 (f float(4,3));
insert into t1 values (-11.0),(-11),("-11"),(11.0),(11),("11");
Warnings:
Warning 1264 Out of range value adjusted for column 'f' at row 1
Warning 1264 Out of range value adjusted for column 'f' at row 2
Warning 1264 Out of range value adjusted for column 'f' at row 3
Warning 1264 Out of range value adjusted for column 'f' at row 4
Warning 1264 Out of range value adjusted for column 'f' at row 5
Warning 1264 Out of range value adjusted for column 'f' at row 6
select * from t1;
f
-9.999
-9.999
-9.999
9.999
9.999
9.999
drop table if exists t1;
create table t1 (f double(4,3));
insert into t1 values (-11.0),(-11),("-11"),(11.0),(11),("11");
Warnings:
Warning 1264 Out of range value adjusted for column 'f' at row 1
Warning 1264 Out of range value adjusted for column 'f' at row 2
Warning 1264 Out of range value adjusted for column 'f' at row 3
Warning 1264 Out of range value adjusted for column 'f' at row 4
Warning 1264 Out of range value adjusted for column 'f' at row 5
Warning 1264 Out of range value adjusted for column 'f' at row 6
select * from t1;
f
-9.999
-9.999
-9.999
9.999
9.999
9.999
drop table if exists t1;

View File

@ -203,3 +203,67 @@ SELECT s.SubscrID,l.SbclID FROM test1 s left JOIN test2 l ON
l.SbcrID=s.SubscrID WHERE s.UsrID=224 order by 1, 2;
drop table test1;
drop table test2;
# bug#7424 + bug#7725
create table t1 (
pk int primary key,
dt datetime not null,
da date not null,
ye year not null,
ti time not null,
ts timestamp not null,
index(dt),
index(da),
index(ye),
index(ti),
index(ts)
) engine=ndb;
insert into t1 (pk,dt,da,ye,ti) values
(1, '1901-05-05 23:00:59', '1901-05-05', '1901', '23:00:59'),
(2, '1912-09-05 13:00:59', '1912-09-05', '1912', '13:00:59'),
(3, '1945-12-31 00:00:00', '1945-12-31', '1945', '00:00:00'),
(4, '1955-12-31 00:00:00', '1955-12-31', '1955', '00:00:00'),
(5, '1963-06-06 06:06:06', '1963-06-06', '1963', '06:06:06'),
(6, '1993-06-06 06:06:06', '1993-06-06', '1993', '06:06:06'),
(7, '2001-01-01 10:11:10', '2001-01-01', '2001', '10:11:10'),
(8, '2001-01-01 10:11:11', '2001-01-01', '2001', '10:11:11'),
(9, '2005-01-31 23:59:59', '2005-01-31', '2005', '23:59:59');
# datetime
select count(*)-9 from t1 use index (dt) where dt > '1900-01-01 00:00:00';
select count(*)-6 from t1 use index (dt) where dt >= '1955-12-31 00:00:00';
select count(*)-5 from t1 use index (dt) where dt > '1955-12-31 00:00:00';
select count(*)-5 from t1 use index (dt) where dt < '1970-03-03 22:22:22';
select count(*)-7 from t1 use index (dt) where dt < '2001-01-01 10:11:11';
select count(*)-8 from t1 use index (dt) where dt <= '2001-01-01 10:11:11';
select count(*)-9 from t1 use index (dt) where dt <= '2055-01-01 00:00:00';
# date
select count(*)-9 from t1 use index (da) where da > '1900-01-01';
select count(*)-6 from t1 use index (da) where da >= '1955-12-31';
select count(*)-5 from t1 use index (da) where da > '1955-12-31';
select count(*)-5 from t1 use index (da) where da < '1970-03-03';
select count(*)-6 from t1 use index (da) where da < '2001-01-01';
select count(*)-8 from t1 use index (da) where da <= '2001-01-02';
select count(*)-9 from t1 use index (da) where da <= '2055-01-01';
# year
select count(*)-9 from t1 use index (ye) where ye > '1900';
select count(*)-6 from t1 use index (ye) where ye >= '1955';
select count(*)-5 from t1 use index (ye) where ye > '1955';
select count(*)-5 from t1 use index (ye) where ye < '1970';
select count(*)-6 from t1 use index (ye) where ye < '2001';
select count(*)-8 from t1 use index (ye) where ye <= '2001';
select count(*)-9 from t1 use index (ye) where ye <= '2055';
# time
select count(*)-9 from t1 use index (ti) where ti >= '00:00:00';
select count(*)-7 from t1 use index (ti) where ti > '00:00:00';
select count(*)-7 from t1 use index (ti) where ti > '05:05:05';
select count(*)-5 from t1 use index (ti) where ti > '06:06:06';
select count(*)-5 from t1 use index (ti) where ti < '10:11:11';
select count(*)-6 from t1 use index (ti) where ti <= '10:11:11';
select count(*)-8 from t1 use index (ti) where ti < '23:59:59';
select count(*)-9 from t1 use index (ti) where ti <= '23:59:59';

View File

@ -93,3 +93,13 @@ create table t1 (f float(54)); # Should give an error
drop table if exists t1;
--enable_warnings
# Ensure that maximum values as the result of number of decimals
# being specified in table schema are enforced (Bug #7361)
create table t1 (f float(4,3));
insert into t1 values (-11.0),(-11),("-11"),(11.0),(11),("11");
select * from t1;
drop table if exists t1;
create table t1 (f double(4,3));
insert into t1 values (-11.0),(-11),("-11"),(11.0),(11),("11");
select * from t1;
drop table if exists t1;

View File

@ -266,12 +266,13 @@ public:
ExtBinary = NdbSqlUtil::Type::Binary,
ExtVarbinary = NdbSqlUtil::Type::Varbinary,
ExtDatetime = NdbSqlUtil::Type::Datetime,
ExtTimespec = NdbSqlUtil::Type::Timespec,
ExtDate = NdbSqlUtil::Type::Date,
ExtBlob = NdbSqlUtil::Type::Blob,
ExtText = NdbSqlUtil::Type::Text,
ExtBit = NdbSqlUtil::Type::Bit,
ExtLongvarchar = NdbSqlUtil::Type::Longvarchar,
ExtLongvarbinary = NdbSqlUtil::Type::Longvarbinary
ExtLongvarbinary = NdbSqlUtil::Type::Longvarbinary,
ExtTime = NdbSqlUtil::Type::Time
};
// Attribute data interpretation
@ -358,10 +359,10 @@ public:
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize = 8 * AttributeExtLength;
break;
case DictTabInfo::ExtTimespec:
case DictTabInfo::ExtDate:
// to fix
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize = 12 * AttributeExtLength;
AttributeArraySize = 3 * AttributeExtLength;
break;
case DictTabInfo::ExtBlob:
case DictTabInfo::ExtText:
@ -380,6 +381,10 @@ public:
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize = AttributeExtLength + 2;
break;
case DictTabInfo::ExtTime:
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize = 3 * AttributeExtLength;
break;
default:
return false;
};

View File

@ -22,7 +22,7 @@
*
* The NDB Cluster Management API (MGM API) is a C API
* that is used to:
* - Start and stop database nodes (DB nodes)
* - Start and stop database nodes (ndbd processes)
* - Start and stop NDB Cluster backups
* - Control the NDB Cluster log
* - Perform other administrative tasks
@ -30,18 +30,23 @@
* @section General Concepts
*
* Each MGM API function needs a management server handle
* of type Mgm_C_Api::NdbMgmHandle.
* of type @ref NdbMgmHandle.
* This handle is initally created by calling the
* function ndb_mgm_create_handle().
* function ndb_mgm_create_handle() and freed by calling
* ndb_mgm_destroy_handle().
*
* A function can return:
* -# An integer value.
* A value of <b>-1</b> indicates an error.
* -# A pointer value. A <var>NULL</var> value indicates an error;
* otherwise, the return value must be freed by the user of the MGM API.
* -# A non-const pointer value. A <var>NULL</var> value indicates an error;
* otherwise, the return value must be freed
* by the user of the MGM API
* -# A const pointer value. A <var>NULL</var> value indicates an error.
* Returned value should not be freed.
*
* Error conditions can be identified by using the appropriate
* error-reporting functions.
* error-reporting functions ndb_mgm_get_latest_error() and
* @ref ndb_mgm_error.
*/
/** @addtogroup MGM_C_API
@ -64,32 +69,54 @@ extern "C" {
* NDB Cluster node types
*/
enum ndb_mgm_node_type {
NDB_MGM_NODE_TYPE_UNKNOWN = -1, /*< Node type not known*/
NDB_MGM_NODE_TYPE_API = NODE_TYPE_API,/*< An application node (API)*/
NDB_MGM_NODE_TYPE_NDB = NODE_TYPE_DB, /*< A database node (DB)*/
NDB_MGM_NODE_TYPE_MGM = NODE_TYPE_MGM,/*< A mgmt server node (MGM)*/
NDB_MGM_NODE_TYPE_REP = NODE_TYPE_REP,/*< A replication node */
NDB_MGM_NODE_TYPE_MIN = 0, /*< Min valid value*/
NDB_MGM_NODE_TYPE_MAX = 3 /*< Max valid value*/
NDB_MGM_NODE_TYPE_UNKNOWN = -1 /** Node type not known*/
,NDB_MGM_NODE_TYPE_API /** An application node (API) */
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
= NODE_TYPE_API
#endif
,NDB_MGM_NODE_TYPE_NDB /** A database node (DB) */
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
= NODE_TYPE_DB
#endif
,NDB_MGM_NODE_TYPE_MGM /** A mgmt server node (MGM)*/
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
= NODE_TYPE_MGM
#endif
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
,NDB_MGM_NODE_TYPE_REP = NODE_TYPE_REP /** A replication node */
,NDB_MGM_NODE_TYPE_MIN = 0 /** Min valid value*/
,NDB_MGM_NODE_TYPE_MAX = 3 /** Max valid value*/
#endif
};
/**
* Database node status
*/
enum ndb_mgm_node_status {
NDB_MGM_NODE_STATUS_UNKNOWN = 0, /*< Node status not known*/
NDB_MGM_NODE_STATUS_NO_CONTACT = 1, /*< No contact with node*/
NDB_MGM_NODE_STATUS_NOT_STARTED = 2, /*< Has not run starting protocol*/
NDB_MGM_NODE_STATUS_STARTING = 3, /*< Is running starting protocol*/
NDB_MGM_NODE_STATUS_STARTED = 4, /*< Running*/
NDB_MGM_NODE_STATUS_SHUTTING_DOWN = 5, /*< Is shutting down*/
NDB_MGM_NODE_STATUS_RESTARTING = 6, /*< Is restarting*/
NDB_MGM_NODE_STATUS_SINGLEUSER = 7, /*< Maintenance mode*/
NDB_MGM_NODE_STATUS_RESUME = 8, /*< Resume mode*/
NDB_MGM_NODE_STATUS_MIN = 0, /*< Min valid value*/
NDB_MGM_NODE_STATUS_MAX = 6 /*< Max valid value*/
/** Node status not known*/
NDB_MGM_NODE_STATUS_UNKNOWN = 0,
/** No contact with node*/
NDB_MGM_NODE_STATUS_NO_CONTACT = 1,
/** Has not run starting protocol*/
NDB_MGM_NODE_STATUS_NOT_STARTED = 2,
/** Is running starting protocol*/
NDB_MGM_NODE_STATUS_STARTING = 3,
/** Running*/
NDB_MGM_NODE_STATUS_STARTED = 4,
/** Is shutting down*/
NDB_MGM_NODE_STATUS_SHUTTING_DOWN = 5,
/** Is restarting*/
NDB_MGM_NODE_STATUS_RESTARTING = 6,
/** Maintenance mode*/
NDB_MGM_NODE_STATUS_SINGLEUSER = 7,
/** Resume mode*/
NDB_MGM_NODE_STATUS_RESUME = 8,
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/** Min valid value*/
NDB_MGM_NODE_STATUS_MIN = 0,
/** Max valid value*/
NDB_MGM_NODE_STATUS_MAX = 8
#endif
};
/**
@ -128,14 +155,15 @@ extern "C" {
NDB_MGM_USAGE_ERROR = 5001
};
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
struct Ndb_Mgm_Error_Msg {
enum ndb_mgm_error code;
const char * msg;
};
const struct Ndb_Mgm_Error_Msg ndb_mgm_error_msgs[] = {
{ NDB_MGM_NO_ERROR, "No error" },
/* Request for service errors */
{ NDB_MGM_ILLEGAL_CONNECT_STRING, "Illegal connect string" },
{ NDB_MGM_ILLEGAL_PORT_NUMBER, "Illegal port number" },
{ NDB_MGM_ILLEGAL_SOCKET, "Illegal socket" },
@ -167,66 +195,86 @@ extern "C" {
{ NDB_MGM_USAGE_ERROR,
"Usage error" }
};
const int ndb_mgm_noOfErrorMsgs =
sizeof(ndb_mgm_error_msgs)/sizeof(struct Ndb_Mgm_Error_Msg);
#endif
/**
* Structure returned by ndb_mgm_get_status
* Status of a node in the cluster
*
* Sub-structure in enum ndb_mgm_cluster_state
* returned by ndb_mgm_get_status()
*/
struct ndb_mgm_node_state {
int node_id; /*< NDB Cluster node id*/
enum ndb_mgm_node_type node_type; /*< Type of NDB Cluster node*/
enum ndb_mgm_node_status node_status; /*< State of node*/
int start_phase; /*< Start phase.
*< @note Start phase is only
*< valid if
*< node_type is
*< NDB_MGM_NODE_TYPE_NDB and
*< node_status is
*< NDB_MGM_NODE_STATUS_STARTING
*/
int dynamic_id; /*< Id for heartbeats and
*< master take-over
*< (only valid for DB nodes)
*/
int node_group; /*< Node group of node
*< (only valid for DB nodes)*/
int version; /*< Internal version number*/
int connect_count; /*< Number of times node has connected
*< or disconnected to the mgm srv
*/
char connect_address[sizeof("000.000.000.000")+1];
/** NDB Cluster node id*/
int node_id;
/** Type of NDB Cluster node*/
enum ndb_mgm_node_type node_type;
/** State of node*/
enum ndb_mgm_node_status node_status;
/** Start phase.
*
* @note Start phase is only valid if node_type is
* NDB_MGM_NODE_TYPE_NDB and node_status is
* NDB_MGM_NODE_STATUS_STARTING
*/
int start_phase;
/** Id for heartbeats and master take-over (only valid for DB nodes)
*/
int dynamic_id;
/** Node group of node (only valid for DB nodes)*/
int node_group;
/** Internal version number*/
int version;
/** Number of times node has connected or disconnected to the
* management server
*/
int connect_count;
/** Ip adress of node when it connected to the management server.
* @note it will be empty if the management server has restarted
* after the node connected.
*/
char connect_address[
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
sizeof("000.000.000.000")+1
#endif
];
};
/**
* Cluster status
* State of all nodes in the cluster returned from
* ndb_mgm_get_status()
*/
struct ndb_mgm_cluster_state {
int no_of_nodes; /*< No of entries in the
*< node_states array
*/
struct ndb_mgm_node_state /*< An array with node_states*/
node_states[1];
const char *hostname;
/** No of entries in the node_states array */
int no_of_nodes;
/** An array with node_states*/
struct ndb_mgm_node_state node_states[
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
1
#endif
];
};
/**
* Default reply from the server
* Default reply from the server (for future use, not used today)
*/
struct ndb_mgm_reply {
int return_code; /*< 0 if successful,
*< otherwise error code.
*/
char message[256]; /*< Error or reply message.*/
/** 0 if successful, otherwise error code. */
int return_code;
/** Error or reply message.*/
char message[256];
};
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* Default information types
*/
enum ndb_mgm_info {
NDB_MGM_INFO_CLUSTER, /*< ?*/
NDB_MGM_INFO_CLUSTERLOG /*< Cluster log*/
/** ?*/
NDB_MGM_INFO_CLUSTER,
/** Cluster log*/
NDB_MGM_INFO_CLUSTERLOG
};
/**
@ -234,11 +282,16 @@ extern "C" {
* (Used only in the development of NDB Cluster.)
*/
enum ndb_mgm_signal_log_mode {
NDB_MGM_SIGNAL_LOG_MODE_IN, /*< Log receiving signals */
NDB_MGM_SIGNAL_LOG_MODE_OUT, /*< Log sending signals*/
NDB_MGM_SIGNAL_LOG_MODE_INOUT, /*< Log both sending/receiving*/
NDB_MGM_SIGNAL_LOG_MODE_OFF /*< Log off*/
/** Log receiving signals */
NDB_MGM_SIGNAL_LOG_MODE_IN,
/** Log sending signals*/
NDB_MGM_SIGNAL_LOG_MODE_OUT,
/** Log both sending/receiving*/
NDB_MGM_SIGNAL_LOG_MODE_INOUT,
/** Log off*/
NDB_MGM_SIGNAL_LOG_MODE_OFF
};
#endif
/**
* Log severities (used to filter the cluster log)
@ -246,32 +299,31 @@ extern "C" {
enum ndb_mgm_clusterlog_level {
NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL = -1,
/* must range from 0 and up, indexes into an array */
NDB_MGM_CLUSTERLOG_ON = 0, /*< Cluster log on*/
NDB_MGM_CLUSTERLOG_DEBUG = 1, /*< Used in NDB Cluster
*< developement
*/
NDB_MGM_CLUSTERLOG_INFO = 2, /*< Informational messages*/
NDB_MGM_CLUSTERLOG_WARNING = 3, /*< Conditions that are not
*< error condition, but
*< might require handling
*/
NDB_MGM_CLUSTERLOG_ERROR = 4, /*< Conditions that should be
*< corrected
*/
NDB_MGM_CLUSTERLOG_CRITICAL = 5, /*< Critical conditions, like
*< device errors or out of
*< resources
*/
NDB_MGM_CLUSTERLOG_ALERT = 6, /*< A condition that should be
*< corrected immediately,
*< such as a corrupted system
*/
/** Cluster log on*/
NDB_MGM_CLUSTERLOG_ON = 0,
/** Used in NDB Cluster developement */
NDB_MGM_CLUSTERLOG_DEBUG = 1,
/** Informational messages*/
NDB_MGM_CLUSTERLOG_INFO = 2,
/** Conditions that are not error condition, but might require handling
*/
NDB_MGM_CLUSTERLOG_WARNING = 3,
/** Conditions that should be corrected */
NDB_MGM_CLUSTERLOG_ERROR = 4,
/** Critical conditions, like device errors or out of resources */
NDB_MGM_CLUSTERLOG_CRITICAL = 5,
/** A condition that should be corrected immediately,
* such as a corrupted system
*/
NDB_MGM_CLUSTERLOG_ALERT = 6,
/* must be next number, works as bound in loop */
NDB_MGM_CLUSTERLOG_ALL = 7 /*< All severities */
/** All severities */
NDB_MGM_CLUSTERLOG_ALL = 7
};
/**
* Log categories
* Log categories, used to set filter on the clusterlog using
* ndb_mgm_set_loglevel_clusterlog()
*/
enum ndb_mgm_event_category {
/**
@ -282,28 +334,56 @@ extern "C" {
* Events during all kinds of startups
*/
NDB_MGM_EVENT_CATEGORY_STARTUP = CFG_LOGLEVEL_STARTUP,
/**
* Events during shutdown
*/
NDB_MGM_EVENT_CATEGORY_SHUTDOWN = CFG_LOGLEVEL_SHUTDOWN,
/**
* Transaction statistics (Job level, TCP/IP speed)
*/
NDB_MGM_EVENT_CATEGORY_STATISTIC = CFG_LOGLEVEL_STATISTICS,
/**
* Events regarding checkpoints
*/
NDB_MGM_EVENT_CATEGORY_CHECKPOINT = CFG_LOGLEVEL_CHECKPOINT,
/**
* Events during node restart
*/
NDB_MGM_EVENT_CATEGORY_NODE_RESTART = CFG_LOGLEVEL_NODERESTART,
/**
* Events on connection between cluster nodes
*/
NDB_MGM_EVENT_CATEGORY_CONNECTION = CFG_LOGLEVEL_CONNECTION,
NDB_MGM_EVENT_CATEGORY_DEBUG = CFG_LOGLEVEL_DEBUG,
NDB_MGM_EVENT_CATEGORY_INFO = CFG_LOGLEVEL_INFO,
NDB_MGM_EVENT_CATEGORY_WARNING = CFG_LOGLEVEL_WARNING,
NDB_MGM_EVENT_CATEGORY_ERROR = CFG_LOGLEVEL_ERROR,
NDB_MGM_EVENT_CATEGORY_GREP = CFG_LOGLEVEL_GREP,
/**
* Backup events
*/
NDB_MGM_EVENT_CATEGORY_BACKUP = CFG_LOGLEVEL_BACKUP,
/**
* Loglevel debug
*/
NDB_MGM_EVENT_CATEGORY_DEBUG = CFG_LOGLEVEL_DEBUG,
/**
* Loglevel info
*/
NDB_MGM_EVENT_CATEGORY_INFO = CFG_LOGLEVEL_INFO,
/**
* Loglevel warning
*/
NDB_MGM_EVENT_CATEGORY_WARNING = CFG_LOGLEVEL_WARNING,
/**
* Loglevel error
*/
NDB_MGM_EVENT_CATEGORY_ERROR = CFG_LOGLEVEL_ERROR,
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
*
*/
NDB_MGM_EVENT_CATEGORY_GREP = CFG_LOGLEVEL_GREP,
#endif
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
NDB_MGM_MIN_EVENT_CATEGORY = CFG_MIN_LOGLEVEL,
NDB_MGM_MAX_EVENT_CATEGORY = CFG_MAX_LOGLEVEL
#endif
};
/***************************************************************************/
@ -384,6 +464,15 @@ extern "C" {
* @param connect_string Connect string to the management server,
*
* @return -1 on error.
*
* @code
* <connectstring> := [<nodeid-specification>,]<host-specification>[,<host-specification>]
* <nodeid-specification> := nodeid=<id>
* <host-specification> := <host>[:<port>]
* <id> is an integer larger than 1 identifying a node in config.ini
* <port> is an integer referring to a regular unix port
* <host> is a string which is a valid Internet host address
* @endcode
*/
int ndb_mgm_set_connectstring(NdbMgmHandle handle,
const char *connect_string);
@ -391,8 +480,8 @@ extern "C" {
/**
* Get connectstring used for connection
*
* @note returns what the connectstring defaults to if the above call has
* not been performed
* @note returns what the connectstring defaults to if the
* ndb_mgm_set_connectstring() call has not been performed
*
* @param handle Management handle
*
@ -401,7 +490,8 @@ extern "C" {
const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz);
/**
* Connect to a management server
* Connect to a management server. Coonect string is set by
* ndb_mgm_set_connectstring().
*
* @param handle Management handle.
* @return -1 on error.
@ -422,7 +512,8 @@ extern "C" {
*
* @param handle Management handle
*
* @return node id
* @return node id, 0 indicated that no nodeid has been
* specified
*/
int ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle);
@ -444,6 +535,7 @@ extern "C" {
*/
const char *ndb_mgm_get_connected_host(NdbMgmHandle handle);
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/** @} *********************************************************************/
/**
* @name Functions: Convert between different data formats
@ -492,7 +584,6 @@ extern "C" {
const char * ndb_mgm_get_node_status_string(enum ndb_mgm_node_status status);
const char * ndb_mgm_get_clusterlog_level_string(enum ndb_mgm_clusterlog_level);
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
ndb_mgm_event_category ndb_mgm_match_event_category(const char *);
const char * ndb_mgm_get_event_category_string(enum ndb_mgm_event_category);
#endif
@ -618,7 +709,7 @@ extern "C" {
/** @} *********************************************************************/
/**
* @name Functions: Logging and Statistics
* @name Functions: Logging
* @{
*/
@ -670,6 +761,17 @@ extern "C" {
enum ndb_mgm_event_category category,
int level,
struct ndb_mgm_reply* reply);
/**
* Listen to log events
*
* @param filter pairs of { level, ndb_mgm_event_category } that will be
* pushed to fd, level=0 ends lists
*
* @return fd which events will be pushed to
*/
int ndb_mgm_listen_event(NdbMgmHandle handle, int filter[]);
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* Set log category and levels for the Node
@ -708,9 +810,9 @@ extern "C" {
* Start backup
*
* @param handle NDB management handle.
* @param wait_completed 0=don't wait for confirmation
1=wait for backup started
2=wait for backup completed
* @param wait_completed 0=don't wait for confirmation,
* 1=wait for backup started,
* 2=wait for backup completed
* @param backup_id Backup id is returned from function.
* @param reply Reply message.
* @return -1 on error.
@ -760,25 +862,21 @@ extern "C" {
int ndb_mgm_exit_single_user(NdbMgmHandle handle,
struct ndb_mgm_reply* reply);
/** @} *********************************************************************/
/**
* Listen event
*
* @param filter pairs of { level, category } that will be
* pushed to fd, level=0 ends lists
*
* @return fd which events will be pushed to
* @name Configuration handling
* @{
*/
int ndb_mgm_listen_event(NdbMgmHandle handle, int filter[]);
/**
* Get configuration
* @param handle NDB management handle.
* @param version Version of configuration, 0 means latest
* @see MAKE_VERSION
* (which is the only supported input at this point)
*
* @return configuration
*
* @note the caller must call ndb_mgm_detroy_configuration
* @note the caller must call ndb_mgm_destroy_configuration()
*/
struct ndb_mgm_configuration * ndb_mgm_get_configuration(NdbMgmHandle handle,
unsigned version);

View File

@ -53,14 +53,15 @@
#define NDB_TYPE_VARCHAR 15
#define NDB_TYPE_BINARY 16
#define NDB_TYPE_VARBINARY 17
#define NDB_TYPE_DATETIME 18 // need to fix
#define NDB_TYPE_TIMESPEC 19 // need to fix
#define NDB_TYPE_DATETIME 18
#define NDB_TYPE_DATE 19
#define NDB_TYPE_BLOB 20
#define NDB_TYPE_TEXT 21
#define NDB_TYPE_BIT 22
#define NDB_TYPE_LONG_VARCHAR 23
#define NDB_TYPE_LONG_VARBINARY 24
#define NDB_TYPE_TIME 25
#define NDB_TYPE_MAX 25
#define NDB_TYPE_MAX 26
#endif

View File

@ -21,7 +21,7 @@
on http://dev.mysql.com/doc/mysql/en/NDBCluster.html .
Some of the fundamental ones are also described in section @ref secConcepts.
The <em>NDB API</em> is a MySQL Cluster application interface
The NDB API is a MySQL Cluster application interface
that implements transactions.
The NDB API consists of the following fundamental classes:
- Ndb_cluster_connection, representing a connection to a cluster,
@ -36,39 +36,38 @@
- NdbDictionary represents meta information about tables and attributes.
- NdbError contains the specification for an error.
It is also possible to receive "events" on changed data in the database.
It is also possible to receive "events" triggered when data in the database in changed.
This is done through the NdbEventOperation class.
There are also some auxiliary classes.
There are also some auxiliary classes, which are listed in the class hierarchy.
The main structure of an application program is as follows:
-# Construct and connect to a cluster using the Ndb_cluster_connection
-# Connect to a cluster using the Ndb_cluster_connection
object.
-# Construct and initialize Ndb object(s) to connect to a database.
-# Define and execute transactions using NdbTransaction.
-# Initiate a database connection by constructing and initialising one or more Ndb objects.
-# Define and execute transactions using the NdbTransaction class.
-# Delete Ndb objects.
-# Delete cluster connection.
-# Terminate the connection to the cluster (terminate instance of Ndb_cluster_connection).
The main structure of a transaction is as follows:
-# Start transaction (an NdbTransaction)
-# Add and define operations associated with the transaction using
NdbOperation, NdbScanOperation, NdbIndexOperation, NdbIndexScanOperation
The procedure for using transactions is as follows:
-# Start transaction (instantiate an NdbTransaction object)
-# Add and define operations associated with the transaction using the
NdbOperation, NdbScanOperation, NdbIndexOperation, and NdbIndexScanOperation classes.
-# Execute transaction
The execution can be of two different types,
<var>Commit</var> or <var>NoCommit</var>.
If the execution is of type <var>NoCommit</var>,
then the application program executes part of a transaction,
but without committing the transaction.
but without actually committing the transaction.
After executing a <var>NoCommit</var> transaction, the program can continue
to add and define more operations to the transaction
for later execution.
If the execute is of type <var>Commit</var>, then the transaction is
committed. The transaction <em>must</em> be closed after it has been
immediately committed. The transaction <em>must</em> be closed after it has been
commited (event if commit fails), and no further addition or definition of
operations is allowed.
operations for this transaction is allowed.
@section secSync Synchronous Transactions
@ -94,12 +93,12 @@
To execute several parallel synchronous transactions, one can either
use multiple Ndb objects in several threads, or start multiple
applications programs.
application programs.
@section secNdbOperations Operations
Each NdbTransaction consists of a list of operations which are represented
by instances of NdbOperation, NdbScanOperation, NdbIndexOperation, and/or
A NdbTransaction consists of a list of operations, each of which is represented
by an instance of NdbOperation, NdbScanOperation, NdbIndexOperation, or
NdbIndexScanOperation.
<h3>Single row operations</h3>
@ -111,7 +110,7 @@
-# Specify attribute actions, using NdbOperation::getValue()
Here are two brief examples illustrating this process. For the sake of
brevity, we omit error-handling.
brevity, we omit error handling.
This first example uses an NdbOperation:
@code
@ -150,17 +149,17 @@
creation and use of synchronous transactions.
<h4>Step 1: Define single row operation type</h4>
The following types of operations exist:
-# NdbOperation::insertTuple :
The following operation types are supported:
-# NdbOperation::insertTuple() :
inserts a non-existing tuple
-# NdbOperation::writeTuple :
-# NdbOperation::writeTuple() :
updates an existing tuple if is exists,
otherwise inserts a new tuple
-# NdbOperation::updateTuple :
-# NdbOperation::updateTuple() :
updates an existing tuple
-# NdbOperation::deleteTuple :
-# NdbOperation::deleteTuple() :
deletes an existing tuple
-# NdbOperation::readTuple :
-# NdbOperation::readTuple() :
reads an existing tuple with specified lock mode
All of these operations operate on the unique tuple key.
@ -172,20 +171,22 @@
NdbTransaction::getNdbIndexOperation() for each operation.
<h4>Step 2: Specify Search Conditions</h4>
The search condition is used to select tuples using NdbOperation::equal()
The search condition is used to select tuples. Search conditions are set using NdbOperation::equal().
<h4>Step 3: Specify Attribute Actions</h4>
Now it is time to define which attributes should be read or updated.
Deletes can neither read nor set values, read can only read values and
updates can only set values.
Normally the attribute is defined by its name but it is
also possible to use the attribute identity to define the
Next, it is necessary to determine which attributes should be read or updated.
It is important to remember that:
- Deletes can neither read nor set values, but only delete them
- Reads can only read values
- Updates can only set values
Normally the attribute is identified by name, but it is
also possible to use the attribute's identity to determine the
attribute.
NdbOperation::getValue() returns an NdbRecAttr object
containing the read value.
To get the value, there is actually two methods.
The application can either
To obtain the actual value, one of two methods can be used;
the application can either
- use its own memory (passed through a pointer aValue) to
NdbOperation::getValue(), or
- receive the attribute value in an NdbRecAttr object allocated
@ -193,39 +194,40 @@
The NdbRecAttr object is released when Ndb::closeTransaction()
is called.
Thus, the application can not reference this object after
Ndb::closeTransaction() have been called.
The result of reading data from an NdbRecAttr object before
calling NdbTransaction::execute() is undefined.
Thus, the application cannot reference this object following
any subsequent call to Ndb::closeTransaction().
Attempting to read data from an NdbRecAttr object before
calling NdbTransaction::execute() yields an undefined result.
@subsection secScan Scan Operations
Scans are roughly the equivalent of SQL cursors.
Scans are roughly the equivalent of SQL cursors, providing a means to
preform high-speed row processing. A scan can be performed
on either a table (using @ref NdbScanOperation) or
an ordered index (by means of an @ref NdbIndexScanOperation).
Scans can either be performed on a table (@ref NdbScanOperation) or
on an ordered index (@ref NdbIndexScanOperation).
Scan operation are characteriesed by the following:
- They can only perform reads (shared, exclusive or dirty)
Scan operations are characterised by the following:
- They can perform only reads (shared, exclusive or dirty)
- They can potentially work with multiple rows
- They can be used to update or delete multiple rows
- They can operate on several nodes in parallell
- They can operate on several nodes in parallel
After the operation is created using NdbTransaction::getNdbScanOperation()
(or NdbTransaction::getNdbIndexScanOperation()),
it is defined in the following three steps:
it is carried out in the following three steps:
-# Define the standard operation type, using NdbScanOperation::readTuples()
-# Specify search conditions, using @ref NdbScanFilter and/or
@ref NdbIndexScanOperation::setBound()
-# Specify attribute actions, using NdbOperation::getValue()
-# Executing the transaction, using NdbTransaction::execute()
-# Iterating through the result set using NdbScanOperation::nextResult()
-# Traversing the result set by means of succssive calls to
NdbScanOperation::nextResult()
Here are two brief examples illustrating this process. For the sake of
brevity, we omit error-handling.
Here are two brief examples illustrating this process. Once again, in order
to keep things relatively short and simple, we will forego any error handling.
This first example uses an NdbScanOperation:
This first example performs a table scan, using an NdbScanOperation:
@code
// 1. Create
MyOperation= MyTransaction->getNdbScanOperation("MYTABLENAME");
@ -244,7 +246,7 @@
MyRecAttr= MyOperation->getValue("ATTR2", NULL);
@endcode
The second example uses an NdbIndexScanOperation:
Our second example uses an NdbIndexScanOperation to perform an index scan:
@code
// 1. Create
MyOperation= MyTransaction->getNdbIndexScanOperation("MYORDEREDINDEX", "MYTABLENAME");
@ -261,98 +263,87 @@
MyRecAttr = MyOperation->getValue("ATTR2", NULL);
@endcode
<h4>Step 1: Define scan operation operation type</h4>
Scan operations only support 1 operation,
@ref NdbScanOperation::readTuples()
or @ref NdbIndexScanOperation::readTuples()
Some additional discussion of each step required to perform a scan follows:
<h4>Step 1: Define Scan Operation Type</h4>
It is important to remember that only a single operation is supported for each scan operation
(@ref NdbScanOperation::readTuples() or @ref NdbIndexScanOperation::readTuples()).
@note If you want to define multiple scan operations within the same
transaction, then you need to call
NdbTransaction::getNdbScanOperation() or
NdbTransaction::getNdbIndexScanOperation() for each operation.
NdbTransaction::getNdbIndexScanOperation() separately for <b>each</b> operation.
<h4>Step 2: Specify Search Conditions</h4>
The search condition is used to select tuples.
If no search condition is specified, the scan will return all rows
in the table.
Search condition can be @ref NdbScanFilter which can be used on both
@ref NdbScanOperation and @ref NdbIndexScanOperation or bounds which
can only be used on index scans, @ref NdbIndexScanOperation::setBound.
An index scan can have both NdbScanFilter and bounds
The search condition can be an @ref NdbScanFilter (which can be used on both
@ref NdbScanOperation and @ref NdbIndexScanOperation) or bounds which
can only be used on index scans (@ref NdbIndexScanOperation::setBound()).
An index scan can use both NdbScanFilter and bounds.
@note When NdbScanFilter is used each row is examined but maybe not
returned. But when using bounds, only rows within bounds will be examined.
@note When NdbScanFilter is used, each row is examined, whether or not it is
actually returned. However, when using bounds, only rows within the bounds will be examined.
<h4>Step 3: Specify Attribute Actions</h4>
Now it is time to define which attributes should be read.
Normally the attribute is defined by its name but it is
also possible to use the attribute identity to define the
attribute.
Next, it is necessary to define which attributes should be read.
As with transaction attributes, scan attributes are defined by name but it is
also possible to use the attributes' identities to define attributes.
NdbOperation::getValue() returns an NdbRecAttr object
containing the read value.
To get the value, there is actually two methods.
The application can either
- use its own memory (passed through a pointer aValue) to
NdbOperation::getValue(), or
- receive the attribute value in an NdbRecAttr object allocated
by the NDB API.
As previously discussed (see @ref secSync), the value read is returned as
an NdbRecAttr object by the NdbOperation::getValue() method.
The NdbRecAttr object is released when Ndb::closeTransaction()
is called. Thus, the application can not reference this object after
Ndb::closeTransaction() have been called.
The result of reading data from an NdbRecAttr object before
calling NdbTransaction::execute() is undefined.
<h3> Using Scan to update/delete </h3>
Scanning can also be used to update/delete rows.
<h3>Using Scan to Update/Delete</h3>
Scanning can also be used to update or delete rows.
This is performed by
-# Scan using exclusive locks, NdbOperation::LM_Exclusive
-# When iterating through the result set, for each row optionally call
-# Scanning using exclusive locks (using NdbOperation::LM_Exclusive)
-# When iterating through the result set, for each row optionally calling
either NdbScanOperation::updateCurrentTuple() or
NdbScanOperation::deleteCurrentTuple()
-# If performing NdbScanOperation::updateCurrentTuple(),
set new values on record using ordinary @ref NdbOperation::setValue().
NdbOperation::equal() should <em>not</em> be called as the primary
key is retreived from the scan.
-# (If performing NdbScanOperation::updateCurrentTuple():)
Setting new values for records simply by using @ref NdbOperation::setValue().
NdbOperation::equal() should <em>not</em> be called in such cases, as the primary
key is retrieved from the scan.
@note that the actual update/delete will not be performed until next
NdbTransaction::execute (as with single row operations),
NdbTransaction::execute needs to be called before locks are released,
see @ref secScanLocks
@note The actual update or delete will not be performed until the next
call to NdbTransaction::execute(), just as with single row operations.
NdbTransaction::execute() also must be called before any locks are released;
see @ref secScanLocks for more information.
<h4> Index scans specific features </h4>
The following features are available when performing an index scan
- Scan subset of table using @ref NdbIndexScanOperation::setBound()
- Ordering result set ascending or descending,
@ref NdbIndexScanOperation::readTuples()
- When using NdbIndexScanOperation::BoundEQ on partition key
only fragments containing rows will be scanned.
<h4>Features Specific to Index Scans</h4>
Rows are returned unordered unless sorted is set to true.
@note When performing sorted scan, parameter parallelism to
NdbIndexScanOperation::readTuples() will
be ignored and max parallelism will be used instead.
When performing an index scan, it is possible to
scan only a subset of a table using @ref NdbIndexScanOperation::setBound().
In addition, result sets can be sorted in either ascending or descending order, using
@ref NdbIndexScanOperation::readTuples(). Note that rows are returned unordered
by default, that is, unless <var>sorted</var> is set to <b>true</b>.
It is also important to note that, when using NdbIndexScanOperation::BoundEQ
on a partition key, only fragments containing rows will actually be scanned.
@note When performing a sorted scan, any value passed as the
NdbIndexScanOperation::readTuples() method's <code>parallel</code> argument
will be ignored and maximum parallelism will be used instead. In other words, all
fragments which it is possible to scan will be scanned simultaneously and in parallel
in such cases.
@subsection secScanLocks Lock handling with scans
When scanning a table or an index potentially
a lot of records will be returned.
But Ndb will only lock a batch of rows per fragment at a time.
Performing scans on either a tables or an index has the potential
return a great many records; however, Ndb will lock only a predetermined
number of rows per fragment at a time.
How many rows will be locked per fragment is controlled by the
batch parameter to NdbScanOperation::readTuples().
<var>batch</var> parameter passed to NdbScanOperation::readTuples().
To let the application handle how locks are released
NdbScanOperation::nextResult() have a parameter fetch_allow.
If NdbScanOperation::nextResult() is called with fetch_allow = false, no
locks may be released as result of the function call. Otherwise the locks
for the current batch may be released.
In order to allow the application to handle how locks are released,
NdbScanOperation::nextResult() has a Boolean parameter <var>fetch_allow</var>.
If NdbScanOperation::nextResult() is called with <var>fetch_allow</var> equal to
<b>false</b>, then no locks may be released as result of the function call.
Otherwise the locks for the current batch may be released.
This example shows scan delete, handling locks in an efficient manner.
This next example shows a scan delete that handle locks in an efficient manner.
For the sake of brevity, we omit error-handling.
@code
int check;
@ -364,40 +355,31 @@
{
// Inner loop for each row within batch
MyScanOperation->deleteCurrentTuple();
} while((check = MyScanOperation->nextResult(false) == 0));
} while((check = MyScanOperation->nextResult(false)) == 0);
// When no more rows in batch, exeute all defined deletes
MyTransaction->execute(NoCommit);
}
@endcode
See @ref ndbapi_scan.cpp for full example of scan.
See @ref ndbapi_scan.cpp for a more complete example of a scan.
@section secError Error Handling
Errors can occur when
-# operations are being defined, or when the
-# transaction is being executed.
Errors can occur either when operations making up a transaction are being
defined, or when the transaction is actually being executed. Catching and
handling either sort of error requires testing the value returned by
NdbTransaction::execute(), and then, if an error is indicated (that is,
if this value is equal to -1), using the following two methods in order to
identify the error's type and location:
One recommended way to handle a transaction failure
(i.e. an error is reported) is to:
-# Rollback transaction (NdbTransaction::execute() with a special parameter)
-# Close transaction
-# Restart transaction (if the error was temporary)
@note Transactions are not automatically closed when an error occur. Call
Ndb::closeTransaction() to close.
Several errors can occur when a transaction holds multiple
operations which are simultaneously executed.
In this case the application has to go through the operation
objects and query for their NdbError objects to find out what really
happened.
NdbTransaction::getNdbErrorOperation() returns a reference to the
operation causing the latest error.
NdbTransaction::getNdbErrorLine() delivers the method number of the
erroneous method in the operation.
- NdbTransaction::getNdbErrorOperation() returns a reference to the
operation causing the most recent error.
- NdbTransaction::getNdbErrorLine() yields the method number of the
erroneous method in the operation.
This short example illustrates how to detect an error and to use these
two methods to identify it:
@code
theTransaction = theNdb->startTransaction();
@ -405,26 +387,43 @@
if (theOperation == NULL) goto error;
theOperation->readTuple(NdbOperation::LM_Read);
theOperation->setValue("ATTR_1", at1);
theOperation->setValue("ATTR_2", at1); //Here an error occurs
theOperation->setValue("ATTR_2", at1); // Error occurs here
theOperation->setValue("ATTR_3", at1);
theOperation->setValue("ATTR_4", at1);
if (theTransaction->execute(Commit) == -1) {
errorLine = theTransaction->getNdbErrorLine();
errorOperation = theTransaction->getNdbErrorOperation();
}
@endcode
Here errorLine will be 3 as the error occurred in the third method
on the operation object.
Getting errorLine == 0 means that the error occurred when executing the
operations.
Here errorOperation will be a pointer to the theOperation object.
NdbTransaction::getNdbError() will return the NdbError object
including holding information about the error.
Here <code>errorLine</code> will be 3, as the error occurred in the
third method called on the NdbOperation object (in this case,
<code>theOperation</code>); if the result of
NdbTransaction::getNdbErrorLine() is 0, this means that the error
occurred when the operations were executed. In this example,
<code>errorOperation</code> will be a pointer to the <code>theOperation</code>
object. The NdbTransaction::getNdbError() method returns an NdbError
object providing information about the error.
Since errors could have occurred even when a commit was reported,
there is also a special method, NdbTransaction::commitStatus(),
to check the commit status of the transaction.
@note Transactions are <b>not</b> automatically closed when an error occurs. Call
Ndb::closeTransaction() to close the transaction.
One recommended way to handle a transaction failure
(i.e. an error is reported) is to:
-# Rollback transaction (call NdbTransaction::execute() with a special parameter)
-# Close transaction (call NdbTransaction::closeTransaction())
-# If the error was temporary, attempt to restart the transaction
Several errors can occur when a transaction contains multiple
operations which are simultaneously executed.
In this case the application has to go through all operations
and query their NdbError objects to find out what really happened.
It is also important to note that errors can occur even when a commit is
reported as successful. In order to handle such situations, the NDB API
provides an additional NdbTransaction::commitStatus() method to check the
transactions's commit status.
******************************************************************************/
@ -434,6 +433,10 @@
*/
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* @page ndbapi_async.cpp ndbapi_async.cpp
* @include ndbapi_async.cpp
*/
/**
* @page ndbapi_async1.cpp ndbapi_async1.cpp
* @include ndbapi_async1.cpp
@ -455,6 +458,11 @@
* @include ndbapi_scan.cpp
*/
/**
* @page ndbapi_event.cpp ndbapi_event.cpp
* @include ndbapi_event.cpp
*/
/**
@page secAdapt Adaptive Send Algorithm

View File

@ -52,6 +52,7 @@ typedef struct charset_info_st CHARSET_INFO;
* -# Dropping secondary indexes (Dictionary::dropIndex)
*
* NdbDictionary has several help (inner) classes to support this:
* -# NdbDictionary::Dictionary the dictionary handling dictionary objects
* -# NdbDictionary::Table for creating tables
* -# NdbDictionary::Column for creating table columns
* -# NdbDictionary::Index for creating secondary indexes
@ -189,12 +190,13 @@ public:
Binary = NDB_TYPE_BINARY, ///< Len
Varbinary = NDB_TYPE_VARBINARY, ///< Length bytes: 1, Max: 255
Datetime = NDB_TYPE_DATETIME, ///< Precision down to 1 sec (sizeof(Datetime) == 8 bytes )
Timespec = NDB_TYPE_TIMESPEC, ///< Precision down to 1 nsec(sizeof(Datetime) == 12 bytes )
Date = NDB_TYPE_DATE, ///< Precision down to 1 day(sizeof(Date) == 4 bytes )
Blob = NDB_TYPE_BLOB, ///< Binary large object (see NdbBlob)
Text = NDB_TYPE_TEXT, ///< Text blob
Bit = NDB_TYPE_BIT, ///< Bit, length specifies no of bits
Longvarchar = NDB_TYPE_LONG_VARCHAR, ///< Length bytes: 2, little-endian
Longvarbinary = NDB_TYPE_LONG_VARBINARY ///< Length bytes: 2, little-endian
Longvarbinary = NDB_TYPE_LONG_VARBINARY, ///< Length bytes: 2, little-endian
Time = NDB_TYPE_TIME ///< Time without date
};
/**
@ -909,6 +911,9 @@ public:
*/
class Event : public Object {
public:
/**
* Specifies the type of database operations an Event listens to
*/
enum TableEvent {
TE_INSERT=1, ///< Insert event on table
TE_DELETE=2, ///< Delete event on table
@ -916,6 +921,10 @@ public:
TE_ALL=7 ///< Any/all event on table (not relevant when
///< events are received)
};
/**
* Specifies the durability of an event
* (future version may supply other types)
*/
enum EventDurability {
ED_UNDEFINED
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
@ -930,8 +939,8 @@ public:
// All API's can use it,
// But's its removed when ndb is restarted
#endif
,ED_PERMANENT ///< All API's can use it,
///< It's still defined after a restart
,ED_PERMANENT ///< All API's can use it.
///< It's still defined after a cluster system restart
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
= 3
#endif
@ -950,9 +959,12 @@ public:
Event(const char *name, const NdbDictionary::Table& table);
virtual ~Event();
/**
* Set/get unique identifier for the event
* Set unique identifier for the event
*/
void setName(const char *name);
/**
* Get unique identifier for the event
*/
const char *getName() const;
/**
* Define table on which events should be detected
@ -967,7 +979,7 @@ public:
/**
* Set table for which events should be detected
*
* @note preferred way is using setTable(const NdbDictionary::Table)
* @note preferred way is using setTable(const NdbDictionary::Table&)
* or constructor with table object parameter
*/
void setTable(const char *tableName);
@ -1224,9 +1236,12 @@ public:
#endif
/**
* Remove table/index from local cache
* Remove table from local cache
*/
void removeCachedTable(const char * table);
/**
* Remove index from local cache
*/
void removeCachedIndex(const char * index, const char * table);

View File

@ -24,73 +24,79 @@ class NdbEventOperationImpl;
* @class NdbEventOperation
* @brief Class of operations for getting change events from database.
*
* An NdbEventOperation object is instantiated by
* Ndb::createEventOperation
* Brief description on how to work with events:
*
* Prior to that an event must have been created in the Database through
* NdbDictionary::createEvent
*
* The instance is removed by Ndb::dropEventOperation
* - An event, represented by an NdbDictionary::Event, i created in the
* Database through
* NdbDictionary::Dictionary::createEvent() (note that this can be done
* by any application or thread and not necessarily by the "listener")
* - To listen to events, an NdbEventOperation object is instantiated by
* Ndb::createEventOperation()
* - execute() starts the event flow. Use Ndb::pollEvents() to wait
* for an event to occur. Use next() to iterate
* through the events that have occured.
* - The instance is removed by Ndb::dropEventOperation()
*
* For more info see:
* @ref ndbapi_event.cpp
*
* Known limitations:
*
* Maximum number of active NdbEventOperations are now set at compile time.
* - Maximum number of active NdbEventOperations are now set at compile time.
* Today 100. This will become a configuration parameter later.
*
* Maximum number of NdbEventOperations tied to same event are maximum 16
* - Maximum number of NdbEventOperations tied to same event are maximum 16
* per process.
*
* Known issues:
*
* When several NdbEventOperation's are tied to the same event in the same
* - When several NdbEventOperation's are tied to the same event in the same
* process they will share the circular buffer. The BufferLength will then
* be the same for all and decided by the first NdbEventOperation
* instantiation. Just make sure to instantiate the "largest" one first.
*
* Today all events INSERT/DELETE/UPDATE and all changed attributes are
* - Today all events INSERT/DELETE/UPDATE and all changed attributes are
* sent to the API, even if only specific attributes have been specified.
* These are however hidden from the user and only relevant data is shown
* after next().
* However false exits from Ndb::pollEvents() may occur and thus
* - "False" exits from Ndb::pollEvents() may occur and thus
* the subsequent next() will return zero,
* since there was no available data. Just do Ndb::pollEvents() again.
*
* Event code does not check table schema version. Make sure to drop events
* - Event code does not check table schema version. Make sure to drop events
* after table is dropped. Will be fixed in later
* versions.
*
* If a node failure has occured not all events will be recieved
* - If a node failure has occured not all events will be recieved
* anymore. Drop NdbEventOperation and Create again after nodes are up
* again. Will be fixed in later versions.
*
* Test status:
* Tests have been run on 1-node and 2-node systems
*
* Known bugs:
*
* None, except if we can call some of the "issues" above bugs
* - Tests have been run on 1-node and 2-node systems
*
* Useful API programs:
*
* ndb_select_all -d sys 'NDB$EVENTS_0'
* Will show contents in the system table containing created events.
* - ndb_select_all -d sys 'NDB$EVENTS_0'
* shows contents in the system table containing created events.
*
* @note this is an inteface to viewing events that is subject to change
*/
class NdbEventOperation {
public:
/**
* State of the NdbEventOperation object
*/
enum State {
EO_CREATED, ///< Created but execute() not called
EO_EXECUTING, ///< execute() called
EO_ERROR ///< An error has occurred. Object unusable.
};
/**
* Retrieve current state of the NdbEventOperation object
*/
enum State {CREATED,EXECUTING,ERROR};
State getState();
/**
* Activates the NdbEventOperation to start receiving events. The
* changed attribute values may be retrieved after next() has returned
* a value greater than zero. The getValue() methods below must be called
* a value greater than zero. The getValue() methods must be called
* prior to execute().
*
* @return 0 if successful otherwise -1.
@ -112,21 +118,21 @@ public:
* aligned appropriately. The buffer is used directly
* (avoiding a copy penalty) only if it is aligned on a
* 4-byte boundary and the attribute size in bytes
* (i.e. NdbRecAttr::attrSize times NdbRecAttr::arraySize is
* (i.e. NdbRecAttr::attrSize() times NdbRecAttr::arraySize() is
* a multiple of 4).
*
* @note There are two versions, NdbOperation::getValue and
* NdbOperation::getPreValue for retrieving the current and
* @note There are two versions, getValue() and
* getPreValue() for retrieving the current and
* previous value repectively.
*
* @note This method does not fetch the attribute value from
* the database! The NdbRecAttr object returned by this method
* is <em>not</em> readable/printable before the
* NdbEventConnection::execute has been made and
* NdbEventConnection::next has returned a value greater than
* execute() has been made and
* next() has returned a value greater than
* zero. If a specific attribute has not changed the corresponding
* NdbRecAttr will be in state UNDEFINED. This is checked by
* NdbRecAttr::isNull which then returns -1.
* NdbRecAttr::isNull() which then returns -1.
*
* @param anAttrName Attribute name
* @param aValue If this is non-NULL, then the attribute value
@ -143,11 +149,11 @@ public:
/**
* Retrieves event resultset if available, inserted into the NdbRecAttrs
* specified in getValue() and getPreValue(). To avoid polling for
* a resultset, one can use Ndb::pollEvents
* a resultset, one can use Ndb::pollEvents()
* which will wait on a mutex until an event occurs or the specified
* timeout occurs.
*
* @return >=0 if successful otherwise -1. Return value inicates number
* @return >=0 if successful otherwise -1. Return value indicates number
* of available events. By sending pOverRun one may query for buffer
* overflow and *pOverRun will indicate the number of events that have
* overwritten.

View File

@ -86,12 +86,13 @@ public:
Binary = NDB_TYPE_BINARY,
Varbinary = NDB_TYPE_VARBINARY,
Datetime = NDB_TYPE_DATETIME,
Timespec = NDB_TYPE_TIMESPEC,
Date = NDB_TYPE_DATE,
Blob = NDB_TYPE_BLOB,
Text = NDB_TYPE_TEXT,
Bit = NDB_TYPE_BIT,
Longvarchar = NDB_TYPE_LONG_VARCHAR,
Longvarbinary = NDB_TYPE_LONG_VARBINARY
Longvarbinary = NDB_TYPE_LONG_VARBINARY,
Time = NDB_TYPE_TIME
};
Enum m_typeId; // redundant
Cmp* m_cmp; // comparison method
@ -153,12 +154,13 @@ private:
static Cmp cmpBinary;
static Cmp cmpVarbinary;
static Cmp cmpDatetime;
static Cmp cmpTimespec;
static Cmp cmpDate;
static Cmp cmpBlob;
static Cmp cmpText;
static Cmp cmpBit;
static Cmp cmpLongvarchar;
static Cmp cmpLongvarbinary;
static Cmp cmpTime;
};
#endif

View File

@ -153,8 +153,8 @@ NdbSqlUtil::m_typeList[] = {
cmpDatetime
},
{
Type::Timespec,
NULL // cmpTimespec
Type::Date,
cmpDate
},
{
Type::Blob,
@ -175,6 +175,10 @@ NdbSqlUtil::m_typeList[] = {
{
Type::Longvarbinary,
cmpLongvarbinary
},
{
Type::Time,
cmpTime
}
};
@ -507,19 +511,57 @@ NdbSqlUtil::cmpVarbinary(const void* info, const void* p1, unsigned n1, const vo
return CmpUnknown;
}
// allowed but ordering is wrong before wl-1442 done
int
NdbSqlUtil::cmpDatetime(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
return cmpBinary(info, p1, n1, p2, n2, full);
if (n2 >= sizeof(Int64)) {
Int64 v1, v2;
memcpy(&v1, p1, sizeof(Int64));
memcpy(&v2, p2, sizeof(Int64));
if (v1 < v2)
return -1;
if (v1 > v2)
return +1;
return 0;
}
assert(! full);
return CmpUnknown;
}
// not used by MySQL or NDB
int
NdbSqlUtil::cmpTimespec(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
NdbSqlUtil::cmpDate(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
assert(false);
return 0;
#ifdef ndb_date_is_4_byte_native_int
if (n2 >= sizeof(Int32)) {
Int32 v1, v2;
memcpy(&v1, p1, sizeof(Int32));
memcpy(&v2, p2, sizeof(Int32));
if (v1 < v2)
return -1;
if (v1 > v2)
return +1;
return 0;
}
assert(! full);
return CmpUnknown;
#else
if (n2 >= 4) { // may access 4-th byte
const uchar* v1 = (const uchar*)p1;
const uchar* v2 = (const uchar*)p2;
// from Field_newdate::val_int
Uint64 j1 = uint3korr(v1);
Uint64 j2 = uint3korr(v2);
j1 = (j1 % 32L)+(j1 / 32L % 16L)*100L + (j1/(16L*32L))*10000L;
j2 = (j2 % 32L)+(j2 / 32L % 16L)*100L + (j2/(16L*32L))*10000L;
if (j1 < j2)
return -1;
if (j1 > j2)
return +1;
return 0;
}
assert(! full);
return CmpUnknown;
#endif
}
// not supported
@ -538,6 +580,25 @@ NdbSqlUtil::cmpText(const void* info, const void* p1, unsigned n1, const void* p
return 0;
}
int
NdbSqlUtil::cmpTime(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
if (n2 >= 4) { // may access 4-th byte
const uchar* v1 = (const uchar*)p1;
const uchar* v2 = (const uchar*)p2;
// from Field_time::val_int
Int32 j1 = sint3korr(v1);
Int32 j2 = sint3korr(v2);
if (j1 < j2)
return -1;
if (j1 > j2)
return +1;
return 0;
}
assert(! full);
return CmpUnknown;
}
// not yet
int
NdbSqlUtil::cmpBit(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)

View File

@ -2364,7 +2364,8 @@ Dbtc::handle_special_hash(Uint32 dstHash[4], Uint32* src, Uint32 srcLen,
*/
Uint32 dstLen = xmul * (srcBytes - lb);
ndbrequire(dstLen <= ((dstSize - dstPos) << 2));
uint n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
ndbrequire(n != -1);
while ((n & 3) != 0) {
dstPtr[n++] = 0;
}

View File

@ -629,7 +629,6 @@ ndb_mgm_get_status(NdbMgmHandle handle)
malloc(sizeof(ndb_mgm_cluster_state)+
noOfNodes*(sizeof(ndb_mgm_node_state)+sizeof("000.000.000.000#")));
state->hostname= 0;
state->no_of_nodes= noOfNodes;
ndb_mgm_node_state * ptr = &state->node_states[0];
int nodeId = 0;
@ -1046,6 +1045,7 @@ struct ndb_mgm_event_categories
{ "CHECKPOINT", NDB_MGM_EVENT_CATEGORY_CHECKPOINT },
{ "DEBUG", NDB_MGM_EVENT_CATEGORY_DEBUG },
{ "INFO", NDB_MGM_EVENT_CATEGORY_INFO },
{ "WARNING", NDB_MGM_EVENT_CATEGORY_WARNING },
{ "ERROR", NDB_MGM_EVENT_CATEGORY_ERROR },
{ "GREP", NDB_MGM_EVENT_CATEGORY_GREP },
{ "BACKUP", NDB_MGM_EVENT_CATEGORY_BACKUP },

View File

@ -1177,7 +1177,14 @@ NdbEventOperation* Ndb::createEventOperation(const char* eventName,
tOp = new NdbEventOperation(this, eventName, bufferLength);
if (tOp->getState() != NdbEventOperation::CREATED) {
if (tOp == 0)
{
theError.code= 4000;
return NULL;
}
if (tOp->getState() != NdbEventOperation::EO_CREATED) {
theError.code= tOp->getNdbError().code;
delete tOp;
tOp = NULL;
}

View File

@ -956,8 +956,8 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col)
case NdbDictionary::Column::Datetime:
out << "Datetime";
break;
case NdbDictionary::Column::Timespec:
out << "Timespec";
case NdbDictionary::Column::Date:
out << "Date";
break;
case NdbDictionary::Column::Blob:
out << "Blob(" << col.getInlineSize() << "," << col.getPartSize()
@ -967,6 +967,9 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col)
out << "Text(" << col.getInlineSize() << "," << col.getPartSize()
<< ";" << col.getStripeSize() << ";" << csname << ")";
break;
case NdbDictionary::Column::Time:
out << "Time";
break;
case NdbDictionary::Column::Undefined:
out << "Undefined";
break;

View File

@ -125,7 +125,7 @@ NdbColumnImpl::init(Type t)
case Binary:
case Varbinary:
case Datetime:
case Timespec:
case Date:
m_precision = 0;
m_scale = 0;
m_length = 1;
@ -143,6 +143,12 @@ NdbColumnImpl::init(Type t)
m_length = 4;
m_cs = default_cs;
break;
case Time:
m_precision = 0;
m_scale = 0;
m_length = 1;
m_cs = NULL;
break;
case Bit:
m_precision = 0;
m_scale = 0;

View File

@ -55,9 +55,8 @@ NdbEventOperationImpl::NdbEventOperationImpl(NdbEventOperation &N,
const char* eventName,
const int bufferLength)
: NdbEventOperation(*this), m_ndb(theNdb),
m_state(ERROR), m_bufferL(bufferLength)
m_state(EO_ERROR), m_bufferL(bufferLength)
{
m_eventId = 0;
theFirstRecAttrs[0] = NULL;
theCurrentRecAttrs[0] = NULL;
@ -71,16 +70,15 @@ NdbEventOperationImpl::NdbEventOperationImpl(NdbEventOperation &N,
// we should lookup id in Dictionary, TODO
// also make sure we only have one listener on each event
if (!m_ndb) { ndbout_c("m_ndb=NULL"); return; }
if (!m_ndb) abort();
NdbDictionary::Dictionary *myDict = m_ndb->getDictionary();
if (!myDict) { ndbout_c("getDictionary=NULL"); return; }
if (!myDict) { m_error.code= m_ndb->getNdbError().code; return; }
const NdbDictionary::Event *myEvnt = myDict->getEvent(eventName);
if (!myEvnt) { ndbout_c("getEvent()=NULL"); return; }
if (!myEvnt) { m_error.code= myDict->getNdbError().code; return; }
m_eventImpl = &myEvnt->m_impl;
if (!m_eventImpl) { ndbout_c("m_impl=NULL"); return; }
m_bufferHandle = m_ndb->getGlobalEventBufferHandle();
if (m_bufferHandle->m_bufferL > 0)
@ -88,7 +86,7 @@ NdbEventOperationImpl::NdbEventOperationImpl(NdbEventOperation &N,
else
m_bufferHandle->m_bufferL = m_bufferL;
m_state = CREATED;
m_state = EO_CREATED;
}
NdbEventOperationImpl::~NdbEventOperationImpl()
@ -106,7 +104,7 @@ NdbEventOperationImpl::~NdbEventOperationImpl()
p = p_next;
}
}
if (m_state == NdbEventOperation::EXECUTING) {
if (m_state == EO_EXECUTING) {
stop();
// m_bufferHandle->dropSubscribeEvent(m_bufferId);
; // We should send stop signal here
@ -122,7 +120,7 @@ NdbEventOperationImpl::getState()
NdbRecAttr*
NdbEventOperationImpl::getValue(const char *colName, char *aValue, int n)
{
if (m_state != NdbEventOperation::CREATED) {
if (m_state != EO_CREATED) {
ndbout_c("NdbEventOperationImpl::getValue may only be called between instantiation and execute()");
return NULL;
}
@ -211,8 +209,8 @@ NdbEventOperationImpl::execute()
{
NdbDictionary::Dictionary *myDict = m_ndb->getDictionary();
if (!myDict) {
ndbout_c("NdbEventOperation::execute(): getDictionary=NULL");
return 0;
m_error.code= m_ndb->getNdbError().code;
return -1;
}
if (theFirstRecAttrs[0] == NULL) { // defaults to get all
@ -245,14 +243,14 @@ NdbEventOperationImpl::execute()
if (r) {
//Error
m_bufferHandle->unprepareAddSubscribeEvent(m_bufferId);
m_state = NdbEventOperation::ERROR;
m_state = EO_ERROR;
} else {
m_bufferHandle->addSubscribeEvent(m_bufferId, this);
m_state = NdbEventOperation::EXECUTING;
m_state = EO_EXECUTING;
}
} else {
//Error
m_state = NdbEventOperation::ERROR;
m_state = EO_ERROR;
}
return r;
}
@ -261,14 +259,14 @@ int
NdbEventOperationImpl::stop()
{
DBUG_ENTER("NdbEventOperationImpl::stop");
if (m_state != NdbEventOperation::EXECUTING)
if (m_state != EO_EXECUTING)
DBUG_RETURN(-1);
// ndbout_c("NdbEventOperation::stopping()");
NdbDictionary::Dictionary *myDict = m_ndb->getDictionary();
if (!myDict) {
ndbout_c("NdbEventOperation::stop(): getDictionary=NULL");
m_error.code= m_ndb->getNdbError().code;
DBUG_RETURN(-1);
}
@ -299,13 +297,13 @@ NdbEventOperationImpl::stop()
//Error
m_bufferHandle->unprepareDropSubscribeEvent(m_bufferId);
m_error.code= myDictImpl.m_error.code;
m_state = NdbEventOperation::ERROR;
m_state = EO_ERROR;
} else {
#ifdef EVENT_DEBUG
ndbout_c("NdbEventOperation::dropping()");
#endif
m_bufferHandle->dropSubscribeEvent(m_bufferId);
m_state = NdbEventOperation::CREATED;
m_state = EO_CREATED;
}
DBUG_RETURN(r);

View File

@ -576,7 +576,8 @@ convertColumnTypeToAttrType(NdbDictionary::Column::Type _type)
case NdbDictionary::Column::Varbinary:
return String;
case NdbDictionary::Column::Datetime:
case NdbDictionary::Column::Timespec:
case NdbDictionary::Column::Date:
case NdbDictionary::Column::Time:
case NdbDictionary::Column::Undefined:
default:
return NoAttrTypeDef;

View File

@ -1978,7 +1978,7 @@ Val::cmpchars(Par par, const unsigned char* buf1, unsigned len1, const unsigned
unsigned len = maxxmulsize * col.m_bytelength;
int n1 = NdbSqlUtil::strnxfrm_bug7284(cs, x1, chs->m_xmul * len, buf1, len1);
int n2 = NdbSqlUtil::strnxfrm_bug7284(cs, x2, chs->m_xmul * len, buf2, len2);
assert(n1 == n2);
assert(n1 != -1 && n1 == n2);
k = memcmp(x1, x2, n1);
} else {
k = (*cs->coll->strnncollsp)(cs, buf1, len1, buf2, len2, false);

View File

@ -71,7 +71,10 @@ BackupConsumer::create_table_string(const TableS & table,
case NdbDictionary::Column::Datetime:
pos += sprintf(buf+pos, "%s", "datetime");
break;
case NdbDictionary::Column::Timespec:
case NdbDictionary::Column::Date:
pos += sprintf(buf+pos, "%s", "date");
break;
case NdbDictionary::Column::Time:
pos += sprintf(buf+pos, "%s", "time");
break;
case NdbDictionary::Column::Undefined:

View File

@ -1663,7 +1663,7 @@ pr_tag_type (p, name, id, kind)
{
struct pr_handle *info = (struct pr_handle *) p;
const char *t, *tag;
char idbuf[20];
char idbuf[30];
switch (kind)
{

View File

@ -93,10 +93,10 @@ CREATE TABLE IF NOT EXISTS tables_priv (
CREATE TABLE IF NOT EXISTS columns_priv (
Host char(60) DEFAULT '' NOT NULL,
Db char(60) DEFAULT '' NOT NULL,
Db char(64) DEFAULT '' NOT NULL,
User char(16) DEFAULT '' NOT NULL,
Table_name char(60) DEFAULT '' NOT NULL,
Column_name char(59) DEFAULT '' NOT NULL,
Table_name char(64) DEFAULT '' NOT NULL,
Column_name char(64) DEFAULT '' NOT NULL,
Timestamp timestamp(14),
Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL,
PRIMARY KEY (Host,Db,User,Table_name,Column_name)

View File

@ -2440,23 +2440,7 @@ int Field_float::store(double nr)
int Field_float::store(longlong nr)
{
int error= 0;
float j= (float) nr;
if (unsigned_flag && j < 0)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
j=0;
error= 1;
}
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
float4store(ptr,j);
}
else
#endif
memcpy_fixed(ptr,(byte*) &j,sizeof(j));
return error;
return store((double)nr);
}
@ -2738,23 +2722,7 @@ int Field_double::store(double nr)
int Field_double::store(longlong nr)
{
double j= (double) nr;
int error= 0;
if (unsigned_flag && j < 0)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
j=0;
}
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
float8store(ptr,j);
}
else
#endif
doublestore(ptr,j);
return error;
return store((double)nr);
}

View File

@ -3907,7 +3907,7 @@ ha_innobase::create(
error = create_table_def(trx, form, norm_name,
create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
!(form->s->db_options_in_use & HA_OPTION_PACK_RECORD));
form->s->row_type != ROW_TYPE_REDUNDANT);
if (error) {
innobase_commit_low(trx);

View File

@ -2393,13 +2393,15 @@ void ha_ndbcluster::print_results()
break;
}
case NdbDictionary::Column::Datetime: {
// todo
my_snprintf(buf, sizeof(buf), "Datetime ?");
my_snprintf(buf, sizeof(buf), "Datetime ?"); // fix-me
break;
}
case NdbDictionary::Column::Timespec: {
// todo
my_snprintf(buf, sizeof(buf), "Timespec ?");
case NdbDictionary::Column::Date: {
my_snprintf(buf, sizeof(buf), "Date ?"); // fix-me
break;
}
case NdbDictionary::Column::Time: {
my_snprintf(buf, sizeof(buf), "Time ?"); // fix-me
break;
}
case NdbDictionary::Column::Blob: {
@ -3420,6 +3422,9 @@ int ndbcluster_rollback(THD *thd, void *ndb_transaction)
Define NDB column based on Field.
Returns 0 or mysql error code.
Not member of ha_ndbcluster because NDBCOL cannot be declared.
MySQL text types with character set "binary" are mapped to true
NDB binary types without a character set. This may change.
*/
static int create_ndb_column(NDBCOL &col,
@ -3495,9 +3500,15 @@ static int create_ndb_column(NDBCOL &col,
col.setType(NDBCOL::Datetime);
col.setLength(1);
break;
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_NEWDATE:
col.setType(NDBCOL::Date);
col.setLength(1);
break;
case MYSQL_TYPE_TIME:
col.setType(NDBCOL::Time);
col.setLength(1);
break;
case MYSQL_TYPE_DATE: // ?
case MYSQL_TYPE_YEAR:
col.setType(NDBCOL::Char);
col.setLength(field->pack_length());
@ -3509,7 +3520,7 @@ static int create_ndb_column(NDBCOL &col,
col.setType(NDBCOL::Bit);
col.setLength(1);
}
else if (field->flags & BINARY_FLAG)
else if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
{
col.setType(NDBCOL::Binary);
col.setLength(field->pack_length());
@ -3527,7 +3538,7 @@ static int create_ndb_column(NDBCOL &col,
Field_varstring* f= (Field_varstring*)field;
if (f->length_bytes == 1)
{
if (field->flags & BINARY_FLAG)
if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
col.setType(NDBCOL::Varbinary);
else {
col.setType(NDBCOL::Varchar);
@ -3536,7 +3547,7 @@ static int create_ndb_column(NDBCOL &col,
}
else if (f->length_bytes == 2)
{
if (field->flags & BINARY_FLAG)
if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
col.setType(NDBCOL::Longvarbinary);
else {
col.setType(NDBCOL::Longvarchar);
@ -3553,7 +3564,7 @@ static int create_ndb_column(NDBCOL &col,
// Blob types (all come in as MYSQL_TYPE_BLOB)
mysql_type_tiny_blob:
case MYSQL_TYPE_TINY_BLOB:
if (field->flags & BINARY_FLAG)
if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
col.setType(NDBCOL::Blob);
else {
col.setType(NDBCOL::Text);
@ -3566,7 +3577,7 @@ static int create_ndb_column(NDBCOL &col,
break;
//mysql_type_blob:
case MYSQL_TYPE_BLOB:
if (field->flags & BINARY_FLAG)
if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
col.setType(NDBCOL::Blob);
else {
col.setType(NDBCOL::Text);
@ -3588,7 +3599,7 @@ static int create_ndb_column(NDBCOL &col,
break;
mysql_type_medium_blob:
case MYSQL_TYPE_MEDIUM_BLOB:
if (field->flags & BINARY_FLAG)
if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
col.setType(NDBCOL::Blob);
else {
col.setType(NDBCOL::Text);
@ -3600,7 +3611,7 @@ static int create_ndb_column(NDBCOL &col,
break;
mysql_type_long_blob:
case MYSQL_TYPE_LONG_BLOB:
if (field->flags & BINARY_FLAG)
if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
col.setType(NDBCOL::Blob);
else {
col.setType(NDBCOL::Text);

View File

@ -101,7 +101,7 @@ struct show_table_type_st sys_table_types[]=
};
const char *ha_row_type[] = {
"", "FIXED", "DYNAMIC", "COMPRESSED","?","?","?"
"", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "?","?","?"
};
const char *tx_isolation_names[] =

View File

@ -167,7 +167,8 @@ struct show_table_type_st {
};
enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
ROW_TYPE_DYNAMIC, ROW_TYPE_COMPRESSED};
ROW_TYPE_DYNAMIC, ROW_TYPE_COMPRESSED,
ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT };
/* struct to hold information about the table that should be created */

View File

@ -116,6 +116,7 @@ static SYMBOL symbols[] = {
{ "COMMENT", SYM(COMMENT_SYM)},
{ "COMMIT", SYM(COMMIT_SYM)},
{ "COMMITTED", SYM(COMMITTED_SYM)},
{ "COMPACT", SYM(COMPACT_SYM)},
{ "COMPRESSED", SYM(COMPRESSED_SYM)},
{ "CONCURRENT", SYM(CONCURRENT)},
{ "CONDITION", SYM(CONDITION_SYM)},
@ -378,6 +379,7 @@ static SYMBOL symbols[] = {
{ "READ", SYM(READ_SYM)},
{ "READS", SYM(READS_SYM)},
{ "REAL", SYM(REAL)},
{ "REDUNDANT", SYM(REDUNDANT_SYM)},
{ "REFERENCES", SYM(REFERENCES)},
{ "REGEXP", SYM(REGEXP)},
{ "RELAY_LOG_FILE", SYM(RELAY_LOG_FILE_SYM)},

View File

@ -227,6 +227,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token COLLATION_SYM
%token COLUMNS
%token COLUMN_SYM
%token COMPACT_SYM
%token CONCURRENT
%token CONDITION_SYM
%token CONNECTION_SYM
@ -381,6 +382,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token READ_SYM
%token READS_SYM
%token REAL_NUM
%token REDUNDANT_SYM
%token REFERENCES
%token REGEXP
%token RELOAD
@ -2628,7 +2630,9 @@ row_types:
DEFAULT { $$= ROW_TYPE_DEFAULT; }
| FIXED_SYM { $$= ROW_TYPE_FIXED; }
| DYNAMIC_SYM { $$= ROW_TYPE_DYNAMIC; }
| COMPRESSED_SYM { $$= ROW_TYPE_COMPRESSED; };
| COMPRESSED_SYM { $$= ROW_TYPE_COMPRESSED; }
| REDUNDANT_SYM { $$= ROW_TYPE_REDUNDANT; }
| COMPACT_SYM { $$= ROW_TYPE_COMPACT; };
raid_types:
RAID_STRIPED_SYM { $$= RAID_TYPE_0; }
@ -6915,6 +6919,7 @@ keyword:
| COMMENT_SYM {}
| COMMITTED_SYM {}
| COMMIT_SYM {}
| COMPACT_SYM {}
| COMPRESSED_SYM {}
| CONCURRENT {}
| CONSISTENT_SYM {}
@ -7046,6 +7051,7 @@ keyword:
| RAID_CHUNKSIZE {}
| RAID_STRIPED_SYM {}
| RAID_TYPE {}
| REDUNDANT_SYM {}
| RELAY_LOG_FILE_SYM {}
| RELAY_LOG_POS_SYM {}
| RELOAD {}