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:
commit
79192c2335
@ -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;
|
||||
|
@ -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))))
|
||||
{
|
||||
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 :
|
||||
" ") : "NULL"));
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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';
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
/** 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 dynamic_id; /*< Id for heartbeats and
|
||||
*< master take-over
|
||||
*< (only valid for DB nodes)
|
||||
int start_phase;
|
||||
/** 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
|
||||
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
|
||||
*/
|
||||
char connect_address[sizeof("000.000.000.000")+1];
|
||||
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
|
||||
/** 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_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
|
||||
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);
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
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 sorted scan, parameter parallelism to
|
||||
NdbIndexScanOperation::readTuples() will
|
||||
be ignored and max parallelism will be used instead.
|
||||
@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,67 +355,75 @@
|
||||
{
|
||||
// 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
|
||||
- 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();
|
||||
theOperation = theTransaction->getNdbOperation("TEST_TABLE");
|
||||
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
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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,20 +511,58 @@ 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);
|
||||
#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
|
||||
int
|
||||
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 },
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
36
sql/field.cc
36
sql/field.cc
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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[] =
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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)},
|
||||
|
@ -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 {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user