Skip to content

Commit b002d9d

Browse files
committed
Refactored code around index search for positional operations
The class for that has been moved to cppmini. The code is much cleaner now. Maybe tiny bit faster and Stmt handle is a tiny bit smaller in base case.
1 parent 5c60284 commit b002d9d

File tree

11 files changed

+216
-419
lines changed

11 files changed

+216
-419
lines changed

driver/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ SET(MARIADB_CPPMINI_FILES
6363
cppmini/class/ResultSetMetaData.cpp
6464
cppmini/class/Parameter.cpp
6565
cppmini/class/Protocol.cpp
66+
cppmini/class/unique_key.cpp
6667
cppmini/interface/PreparedStatement.cpp
6768
cppmini/interface/Row.cpp
6869
cppmini/interface/ResultSet.cpp
@@ -82,6 +83,7 @@ SET(MARIADB_CPPMINI_HEADERS
8283
cppmini/class/ClientSidePreparedStatement.h
8384
cppmini/class/ServerSidePreparedStatement.h
8485
cppmini/class/SSPSDirectExec.h
86+
cppmini/class/unique_key.h
8587
cppmini/class/ClientPrepareResult.h
8688
cppmini/class/ServerPrepareResult.h
8789
cppmini/class/CmdInformationSingle.h

driver/ma_helper.cpp

Lines changed: 22 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "ma_odbc.h"
2020
#include <stdint.h>
2121
#include "class/ResultSetMetaData.h"
22+
#include "class/unique_key.h"
2223
#include "interface/PreparedStatement.h"
2324
#include "Protocol.h"
2425

@@ -73,48 +74,6 @@ int MADB_GetWCharType(int Type)
7374
}
7475
}
7576

76-
/* Returns total number of columns, and columns count in the primary key and in the unique key
77-
TODO: if there are >1 of unique keys, this will go wrong */
78-
int MADB_KeyTypeCount(MADB_Dbc *Connection, char *TableName, int *PrimaryKeysCount, int *UniqueKeysCount)
79-
{
80-
int Count= -1;
81-
int i;
82-
char StmtStr[512];
83-
char *p= StmtStr;
84-
char Database[68]= {'\0'};
85-
MYSQL_RES *Res;
86-
MYSQL_FIELD *Field;
87-
88-
// It shouldn't be current but the one from the query
89-
Connection->GetAttr(SQL_ATTR_CURRENT_CATALOG, Database, sizeof(Database), NULL, FALSE);
90-
p+= _snprintf(p, sizeof(StmtStr), "SELECT * FROM ");
91-
if (Database[0] != '\0')
92-
{
93-
p+= _snprintf(p, sizeof(StmtStr) - (p - StmtStr), "`%s`.", Database);
94-
}
95-
p+= _snprintf(p, sizeof(StmtStr) - (p - StmtStr), "%s LIMIT 0", TableName);
96-
std::lock_guard<std::mutex> localScopeLock(Connection->guard->getLock());
97-
Connection->guard->safeRealQuery({StmtStr, (std::size_t)(p - StmtStr)});
98-
if ((Res= mysql_store_result(Connection->mariadb)) != nullptr)
99-
{
100-
Count= mysql_field_count(Connection->mariadb);
101-
for (i= 0; i < Count; ++i)
102-
{
103-
Field= mysql_fetch_field_direct(Res, i);
104-
if (Field->flags & PRI_KEY_FLAG)
105-
{
106-
++*PrimaryKeysCount;
107-
}
108-
if (Field->flags & UNIQUE_KEY_FLAG)
109-
{
110-
++*UniqueKeysCount;
111-
}
112-
}
113-
mysql_free_result(Res);
114-
}
115-
return Count;
116-
}
117-
11877

11978
/* {{{ MADB_CheckODBCType */
12079
BOOL MADB_CheckODBCType(SQLSMALLINT Type)
@@ -1135,8 +1094,6 @@ size_t MADB_GetHexString(char *BinaryBuffer, size_t BinaryLength,
11351094

11361095
SQLRETURN MADB_DaeStmt(MADB_Stmt *Stmt, SQLUSMALLINT Operation)
11371096
{
1138-
char *TableName= MADB_GetTableName(Stmt);
1139-
char *CatalogName= MADB_GetCatalogName(Stmt);
11401097
SQLString Query;
11411098

11421099
MADB_CLEAR_ERROR(&Stmt->Error);
@@ -1151,30 +1108,43 @@ SQLRETURN MADB_DaeStmt(MADB_Stmt *Stmt, SQLUSMALLINT Operation)
11511108
return MADB_CopyError(&Stmt->Error, &Stmt->Connection->Error);
11521109
}
11531110

1154-
Query.reserve(1024);
1155-
switch(Operation)
1156-
{
1111+
if (Operation != SQL_ADD && !Stmt->UniqueIndex) {
1112+
// For SQL_ADD we don't need index, and reading index means additional query(ies) to the server, i.e. rather expensive
1113+
Stmt->UniqueIndex.reset(new mariadb::unique_key(Stmt->Connection->guard.get(), Stmt->metadata));
1114+
}
1115+
Query.reserve(8192);
1116+
1117+
switch(Operation) {
1118+
11571119
case SQL_ADD:
1120+
{
1121+
// This constructor does not read index info but only verifies that only one table is used
1122+
mariadb::unique_key tableInfo(Stmt->metadata);
11581123
// Should it really be CatalogName
1159-
Query.assign("INSERT INTO `").append(CatalogName).append("`.`").append(TableName).append(1,'`');
1124+
Query.assign("INSERT INTO `").append(tableInfo.getSchema()).append("`.`").append(tableInfo.getTable()).append(1, '`');
11601125
if (MADB_DynStrUpdateSet(Stmt, Query))
11611126
{
11621127
return Stmt->Error.ReturnValue;
11631128
}
11641129
Stmt->DataExecutionType= MADB_DAE_ADD;
1130+
}
11651131
break;
1132+
11661133
case SQL_DELETE:
1167-
Query.assign("DELETE FROM `").append(CatalogName).append("`.`").append(TableName).append(1, '`');
1168-
if (MADB_DynStrGetWhere(Stmt, Query, TableName, false))
1134+
Query.assign("DELETE FROM `").append(Stmt->UniqueIndex->getSchema()).append("`.`").
1135+
append(Stmt->UniqueIndex->getTable()).append(1, '`');
1136+
if (MADB_DynStrGetWhere(Stmt, Query, false))
11691137
{
11701138
return Stmt->Error.ReturnValue;
11711139
}
11721140

11731141
Stmt->DataExecutionType= MADB_DAE_DELETE;
11741142
break;
1143+
11751144
case SQL_UPDATE:
1176-
Query.assign("UPDATE `").append(CatalogName).append("`.`").append(TableName).append(1, '`');
1177-
if (MADB_DynStrUpdateSet(Stmt, Query) || MADB_DynStrGetWhere(Stmt, Query, TableName, false))
1145+
Query.assign("UPDATE `").append(Stmt->UniqueIndex->getSchema()).append("`.`").
1146+
append(Stmt->UniqueIndex->getTable()).append(1, '`');
1147+
if (MADB_DynStrUpdateSet(Stmt, Query) || MADB_DynStrGetWhere(Stmt, Query, false))
11781148
{
11791149
return Stmt->Error.ReturnValue;
11801150
}

driver/ma_helper.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
void CloseMultiStatements(MADB_Stmt *Stmt);
2323
bool QueryIsPossiblyMultistmt(MADB_QUERY *Query);
2424
int SqlRtrim(char *StmtStr, int Length);
25-
int MADB_KeyTypeCount(MADB_Dbc *Connection, char *TableName, int *PrimaryKeysCount, int *UniqueKeysCount);
2625
MYSQL_RES* MADB_ReadDefaultValues(MADB_Dbc *Dbc, const char *Catalog, const char *TableName);
2726
int MADB_GetDefaultType(int SQLDataType);
2827
void MADB_CopyOdbcTsToMadbTime(SQL_TIMESTAMP_STRUCT *Src, MYSQL_TIME *Dst);

driver/ma_legacy_helpers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ bool MADB_DynstrRealloc(MADB_DynString *str, size_t additional_size)
195195

196196
bool MADB_DynstrAppend(MADB_DynString *str, const char *append)
197197
{
198-
return MADB_DynstrAppendMem(str,append,strlen(append));
198+
return MADB_DynstrAppendMem(str, append, strlen(append));
199199
}
200200

201201

driver/ma_odbc.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ struct MADB_Env {
287287
// Stmt has to know few things about connection and descriptor
288288
#include "ma_connection.h"
289289
#include "ma_desc.h"
290-
#define xxx sizeof(std::mutex)
290+
291291
struct MADB_Stmt
292292
{
293293
MADB_QUERY Query;
@@ -312,8 +312,6 @@ struct MADB_Stmt
312312
MYSQL_BIND *params= nullptr;
313313
unsigned long *CharOffset= nullptr;
314314
unsigned long *Lengths= nullptr;
315-
char *TableName= nullptr;
316-
char *CatalogName= nullptr;
317315
MADB_ShortTypeInfo *ColsTypeFixArr= nullptr;
318316
/* Application Descriptors */
319317
MADB_Desc *Apd= nullptr;
@@ -326,7 +324,8 @@ struct MADB_Stmt
326324
MADB_Desc *IIrd;
327325
MADB_Desc *IIpd;
328326

329-
unsigned short *UniqueIndex= nullptr; /* Insdexes of columns that make best available unique identifier */
327+
Unique::key UniqueIndex; /* Insdexes of columns that make best available unique identifier
328+
for positional operations */
330329
SQLSETPOSIROW DaeRowNumber= 0;
331330
int32_t ArrayOffset= 0;
332331
uint32_t MultiStmtNr= 0;
@@ -340,9 +339,6 @@ struct MADB_Stmt
340339
bool PositionedCommand= false;
341340
bool RebindParams= false;
342341
bool bind_done= false;
343-
char IndexType= 0; /* For positional operation - the type of index in the UniqueIndex(value of the
344-
unique or pri flag) or > 0 if all columns in the table(UniqueIndex==NULL).
345-
0 - no info, <0 - can't build index */
346342

347343
MADB_Stmt(MADB_Dbc *Connection);
348344
SQLRETURN Prepare(const char* StatementText, SQLINTEGER TextLength, bool ServerSide= true, bool DirectExecution= false);

driver/ma_statement.cpp

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "ResultSetMetaData.h"
2525
#include "interface/Exception.h"
2626
#include "Protocol.h"
27+
#include "class/unique_key.h"
2728

2829
#include "ma_odbc.h"
2930

@@ -110,9 +111,6 @@ void MADB_DropStmt(MADB_Stmt *Stmt, bool external= true)
110111
MADB_FREE(Stmt->params);
111112
MADB_FREE(Stmt->result);
112113
MADB_FREE(Stmt->Cursor.Name);
113-
MADB_FREE(Stmt->CatalogName);
114-
MADB_FREE(Stmt->TableName);
115-
MADB_FREE(Stmt->UniqueIndex);
116114
/* For explicit descriptors we only remove reference to the stmt*/
117115
if (Stmt->Apd->AppType)
118116
{
@@ -277,6 +275,8 @@ MADB_Stmt *MADB_FindCursor(MADB_Stmt *Stmt, const char *CursorName)
277275
ResultSetMetaData* FetchMetadata(MADB_Stmt *Stmt, bool early)
278276
{
279277
delete Stmt->metadata;
278+
// unique_key references metadata. TODO: Need to do smth about this
279+
Stmt->UniqueIndex.reset();
280280
/* TODO early probably is not needed here at all */
281281
if (early)
282282
{
@@ -324,9 +324,7 @@ SQLRETURN MADB_StmtReset(MADB_Stmt* Stmt)
324324
Stmt->PositionedCommand= 0;
325325
Stmt->State= MADB_SS_INITED;
326326
MADB_CLEAR_ERROR(&Stmt->Error);
327-
MADB_FREE(Stmt->UniqueIndex);
328-
Stmt->IndexType= 0;
329-
MADB_FREE(Stmt->TableName);
327+
Stmt->UniqueIndex.reset();
330328
}
331329
return SQL_SUCCESS;
332330
}
@@ -569,7 +567,6 @@ SQLRETURN MADB_Stmt::Prepare(const char *StatementText, SQLINTEGER TextLength, b
569567
*/
570568
if ((CursorName= MADB_ParseCursorName(&Query, &WhereOffset)))
571569
{
572-
char *TableName;
573570
/* Make sure we have a delete or update statement
574571
MADB_QUERY_DELETE and MADB_QUERY_UPDATE defined in the enum to have the same value
575572
as SQL_UPDATE and SQL_DELETE, respectively */
@@ -589,10 +586,9 @@ SQLRETURN MADB_Stmt::Prepare(const char *StatementText, SQLINTEGER TextLength, b
589586
goto cleanandexit;
590587
}
591588

592-
TableName= MADB_GetTableName(PositionedCursor);
593-
SQLString StmtStr(Query.RefinedText.c_str(),WhereOffset);
589+
SQLString StmtStr(Query.RefinedText.c_str(), WhereOffset);
594590
StmtStr.reserve(8192);
595-
if (MADB_DynStrGetWhere(PositionedCursor, StmtStr, TableName, true))
591+
if (MADB_DynStrGetWhere(PositionedCursor, StmtStr, true))
596592
{
597593
goto cleanandexit;
598594
}
@@ -834,8 +830,11 @@ SQLRETURN MADB_ExecutePositionedUpdate(MADB_Stmt *Stmt, bool ExecDirect)
834830

835831
for (j= 1; j < MADB_STMT_COLUMN_COUNT(Stmt->PositionedCursor) + 1; ++j)
836832
{
837-
if (Stmt->PositionedCursor->UniqueIndex == nullptr ||
838-
(Stmt->PositionedCursor->UniqueIndex[0] != 0 && IndexIdx <= Stmt->PositionedCursor->UniqueIndex[0] && j == Stmt->PositionedCursor->UniqueIndex[IndexIdx] + 1))
833+
// unique_key methods use 0 based indexes
834+
if (!Stmt->PositionedCursor->UniqueIndex ||
835+
(Stmt->PositionedCursor->UniqueIndex->exists() &&
836+
IndexIdx <= static_cast<SQLSMALLINT>(Stmt->PositionedCursor->UniqueIndex->fieldCount()) &&
837+
j == Stmt->PositionedCursor->UniqueIndex->fieldIndex(IndexIdx - 1) + 1))
839838
{
840839
SQLLEN Length;
841840
MADB_DescRecord* Rec= MADB_DescGetInternalRecord(Stmt->PositionedCursor->Ard, j, MADB_DESC_READ);
@@ -845,7 +844,7 @@ SQLRETURN MADB_ExecutePositionedUpdate(MADB_Stmt *Stmt, bool ExecDirect)
845844
if (Stmt->PositionedCursor->UniqueIndex != nullptr)
846845
{
847846
ParamNumber= /* Param ordnum in pos.cursor condition */IndexIdx +
848-
/* Num of params in main stmt */(Stmt->ParamCount - Stmt->PositionedCursor->UniqueIndex[0]);
847+
/* Num of params in main stmt */(Stmt->ParamCount - Stmt->PositionedCursor->UniqueIndex->fieldCount());
849848
++IndexIdx;
850849
}
851850
else
@@ -3628,20 +3627,18 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT
36283627
/* Nothing else to do (at least for now) in this 2 cases */
36293628
return SQL_SUCCESS;
36303629
};
3631-
3632-
char* TableName= MADB_GetTableName(Stmt);
3633-
if (!TableName)
3634-
{
3635-
return MADB_SetError(&Stmt->Error, MADB_ERR_IM001, "Updatable Cursors with multiple tables are not supported", 0);
3630+
/*SQL_ADD does not need to know the index */
3631+
if (Operation != SQL_ADD && !Stmt->UniqueIndex) {
3632+
Stmt->UniqueIndex.reset(new mariadb::unique_key(Stmt->Connection->guard.get(), Stmt->metadata));
36363633
}
3637-
char* CatalogName= MADB_GetCatalogName(Stmt);
3638-
36393634
switch (Operation) {
36403635
case SQL_ADD:
36413636
{
36423637
MADB_DynString DynStmt;
36433638
SQLRETURN ret;
36443639
int column, param= 0;
3640+
// This constructor does not read index info but only verifies that only one table is used
3641+
mariadb::unique_key tableInfo(Stmt->metadata);
36453642

36463643
Stmt->DaeRowNumber= RowNumber;
36473644

@@ -3654,9 +3651,9 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT
36543651
MADB_StmtInit(Stmt->Connection, (SQLHANDLE *)&Stmt->DaeStmt, false);
36553652

36563653
if (MADB_InitDynamicString(&DynStmt, "INSERT INTO ", 8192, 1024) ||
3657-
MADB_DynStrAppendQuoted(&DynStmt, CatalogName) ||
3654+
MADB_DynStrAppendQuoted(&DynStmt, tableInfo.getSchema().c_str()) ||
36583655
MADB_DynstrAppend(&DynStmt, ".") ||
3659-
MADB_DynStrAppendQuoted(&DynStmt, TableName)||
3656+
MADB_DynStrAppendQuoted(&DynStmt, tableInfo.getTable().c_str()) ||
36603657
MADB_DynStrInsertSet(Stmt, &DynStmt))
36613658
{
36623659
MADB_DynstrFree(&DynStmt);
@@ -3852,7 +3849,7 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT
38523849
case SQL_DELETE:
38533850
{
38543851
SQLRETURN result = SQL_INVALID_HANDLE; /* Just smth we cannot normally get */
3855-
SQLString DynamicStmt("DELETE FROM ");
3852+
SQLString DynamicStmt;
38563853
std::size_t baseStmtLen;
38573854
SQLULEN SaveArraySize= Stmt->Ard->Header.ArraySize;
38583855
my_ulonglong Start= 0,
@@ -3869,14 +3866,15 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT
38693866
{
38703867
End= Start;
38713868
}
3872-
DynamicStmt.reserve(8182);
3873-
DynamicStmt.append(TableName);
3869+
DynamicStmt.reserve(8192);
3870+
DynamicStmt.append("DELETE FROM `", 13).append(Stmt->UniqueIndex->getSchema()).append("`.`", 3).
3871+
append(Stmt->UniqueIndex->getTable()).append("`", 1);
38743872
baseStmtLen= DynamicStmt.length();
38753873
while (Start <= End)
38763874
{
38773875
MADB_StmtDataSeek(Stmt, Start);
38783876

3879-
if (MADB_DynStrGetWhere(Stmt, DynamicStmt, TableName, false))
3877+
if (MADB_DynStrGetWhere(Stmt, DynamicStmt, false))
38803878
{
38813879
MADB_SETPOS_AGG_RESULT(result, Stmt->Error.ReturnValue);
38823880
/* Continuing to next row. If there is no key - we will get it for all rows and as aggregated result.

driver/ma_statement.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ void MADB_CloseCursor (MADB_Stmt *Stmt);
113113
#define MADB_RESET_COLUMT_COUNT(aStmt) (aStmt)->Ird->Header.Count= 0
114114
#define MADB_STMT_PARAM_COUNT(aStmt) (aStmt)->ParamCount
115115
#define MADB_POSITIONED_COMMAND(aStmt) ((aStmt)->PositionedCommand && (aStmt)->PositionedCursor)
116-
#define MADB_STMT_HAS_UNIQUE_IDX(aStmt) (aStmt->UniqueIndex != NULL && aStmt->UniqueIndex[0] > 0)
117-
#define MADB_POS_COMM_IDX_FIELD_COUNT(aStmt) (MADB_STMT_HAS_UNIQUE_IDX((aStmt)->PositionedCursor)?(aStmt)->PositionedCursor->UniqueIndex[0]:MADB_STMT_COLUMN_COUNT((aStmt)->PositionedCursor))
116+
#define MADB_STMT_HAS_UNIQUE_IDX(aStmt) (aStmt->UniqueIndex && aStmt->UniqueIndex->isIndex())
117+
#define MADB_POS_COMM_IDX_FIELD_COUNT(aStmt) (MADB_STMT_HAS_UNIQUE_IDX((aStmt)->PositionedCursor)?(aStmt)->PositionedCursor->UniqueIndex->exists():MADB_STMT_COLUMN_COUNT((aStmt)->PositionedCursor))
118118
#define MADB_STMT_FORGET_NEXT_POS(aStmt) (aStmt)->Cursor.Next= -1
119119
#define MADB_STMT_RESET_CURSOR(aStmt) (aStmt)->Cursor.Position= 0; MADB_STMT_FORGET_NEXT_POS(aStmt)
120120
#define MADB_STMT_CLOSE_STMT(aStmt) (aStmt)->stmt.reset()

0 commit comments

Comments
 (0)