/***********************************************************************/ /* Make and allocate the alias list. */ /***********************************************************************/ constchar *CONDFIL::Chk(constchar *fln, bool *h)
{ for (PAL pal = Alist; pal; pal = pal->Next) if (!stricmp(fln, pal->Alias)) {
*h = pal->Having; return pal->Name;
} // endif fln
*h = false; return fln;
} // end of Chk
/* --------------------------- Class EXTDEF -------------------------- */
/***********************************************************************/ /* DefineAM: define specific AM block values from XDB file. */ /***********************************************************************/ bool EXTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{ if (g->Createas) {
safe_strcpy(g->Message, sizeof(g->Message), "Multiple-table UPDATE/DELETE commands are not supported"); returntrue;
} // endif multi
/******************************************************************/ /* Convert an UTF-8 string to latin characters. */ /******************************************************************/ int TDBEXT::Decode(PCSZ txt, char *buf, size_t n)
{
uint dummy_errors;
uint32 len = copy_and_convert(buf, n, &my_charset_latin1,
txt, strlen(txt),
&my_charset_utf8mb3_general_ci,
&dummy_errors);
buf[len] = '\0'; return0;
} // end of Decode
/* Countnumberof%splaceholdersinstring. Returns-1ifothersprintfplaceholdersarefound,.g%d
*/ staticint count_placeholders(constchar *fmt)
{ int cnt= 0; for (constchar *p=fmt; *p; p++)
{ if (*p == '%')
{ switch (p[1])
{ case's': /* %s found */
cnt++;
p++; break; case'%': /* masking char for % found */
p++; break; default: /* some other placeholder found */ return -1;
}
}
} return cnt;
}
/***********************************************************************/ /* MakeSrcdef: make the SQL statement from SRDEF option. */ /***********************************************************************/ bool TDBEXT::MakeSrcdef(PGLOBAL g)
{ char *catp = strstr(Srcdef, "%s");
/***********************************************************************/ /* MakeSQL: make the SQL statement use with remote connection. */ /* TODO: when implementing remote filtering, column only used in */ /* local filter should be removed from column list. */ /***********************************************************************/ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt)
{
PCSZ schmp = NULL; char *catp = NULL, buf[NAM_LEN * 3]; int len; bool first = true;
PCOL colp; char *res= NULL, *my_schema_table= NULL;
size_t my_len= 0;
if (Srcdef) return MakeSrcdef(g);
// Allocate the string used to contain the Query
Query = new(g)STRING(g, 1023, "SELECT ");
if (!cnt) { if (Columns) { // Normal SQL statement to retrieve results for (colp = Columns; colp; colp = colp->GetNext()) if (!colp->IsSpecial()) { if (!first)
Query->Append(", "); else
first = false;
// Column name can be encoded in UTF-8
Decode(colp->GetName(), buf, sizeof(buf));
if (Quote) { // Put column name between identifier quotes in case in contains blanks
Query->Append(Quote);
Query->Append(buf);
Query->Append(Quote);
} else
Query->Append(buf);
((PEXTCOL)colp)->SetRank(++Ncol);
} // endif colp
} else // !Columns can occur for queries such that sql count(*) from... // for which we will count the rows from sql * from...
Query->Append('*');
} else // SQL statement used to retrieve the size of the result
Query->Append("count(*)");
// Table name can be encoded in UTF-8
Decode(TableName, buf, sizeof(buf));
if (Quote) { // Tabname can have both database and table identifiers, we need to parse if ((res= strstr(buf, ".")))
{ // Parse schema
my_len= res - buf + 1;
my_schema_table= (char *) malloc(my_len);
memcpy(my_schema_table, buf, my_len - 1);
my_schema_table[my_len - 1] = 0;
Query->Append(Quote);
Query->Append(my_schema_table);
Query->Append(Quote);
free(my_schema_table);
Query->Append("."); // Parse table
my_len= strlen(buf) - my_len + 1;
my_schema_table= (char *) malloc(my_len + 1);
memcpy(my_schema_table, ++res, my_len);
my_schema_table[my_len] = 0;
Query->Append(Quote);
Query->Append(my_schema_table);
Query->Append(Quote);
free(my_schema_table);
} else
{ // Put table name between identifier quotes in case in contains blanks
Query->Append(Quote);
Query->Append(buf);
Query->Append(Quote);
}
} else
Query->Append(buf);
len = Query->GetLength();
if (To_CondFil) { if (Mode == MODE_READ) {
Query->Append(" WHERE ");
Query->Append(To_CondFil->Body);
len = Query->GetLength() + 1;
} else
len += (strlen(To_CondFil->Body) + 256);
} else
len += ((Mode == MODE_READX) ? 256 : 1);
if (Query->IsTruncated()) {
safe_strcpy(g->Message, sizeof(g->Message), "MakeSQL: Out of memory"); returntrue;
} else
Query->Resize(len);
if (trace(33))
htrc("Query=%s\n", Query->GetStr());
returnfalse;
} // end of MakeSQL
/***********************************************************************/ /* Remove the NAME_CONST functions that are added by procedures. */ /***********************************************************************/ void TDBEXT::RemoveConst(PGLOBAL g, char *stmt)
{ char *p, *p2; char val[1025], nval[1025]; int n, nc;
while ((p = strstr(stmt, "NAME_CONST")))
{ if ((n = sscanf(p, "%*[^,],%1024[^)])%n", val, &nc))) { if (trace(33))
htrc("p=%s\nn=%d val=%s nc=%d\n", p, n, val, nc);
*p = 0;
if ((p2 = strstr(val, "'"))) { if ((n = sscanf(p2, "%*['\\]%1024[^'\\]", nval))) { if (trace(33))
htrc("p2=%s\nn=%d nval=%s\n", p2, n, nval);
strcat(strcat(strcat(strcat(stmt, "'"), nval), "'"), p + nc);
} else break;
} else
strcat(strcat(strcat(strcat(stmt, "("), val), ")"), p + nc);
if (trace(33))
htrc("stmt=%s\n", stmt);
} else break;
} return;
} // end of RemoveConst
/***********************************************************************/ /* MakeCommand: make the Update or Delete statement to send to the */ /* MySQL server. Limited to remote values and filtering. */ /***********************************************************************/ bool TDBEXT::MakeCommand(PGLOBAL g)
{
PCSZ schmp = NULL; char *p, *stmt, name[132], *body = NULL; char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1); bool qtd = Quoted > 0; char q = qtd ? *Quote : ' '; int i = 0, k = 0;
size_t stmt_sz = 0;
// Make a lower case copy of the originale query and change // back ticks to the data source identifier quoting character do {
qrystr[i] = (Qrystr[i] == '`') ? q : tolower(Qrystr[i]);
} while (Qrystr[i++]);
// Check whether the table name is equal to a keyword // If so, it must be quoted in the original query
snprintf(name, sizeof(name), " %s ", Name);
strlwr(name);
if (strstr(" update delete low_priority ignore quick from ", name)) { if (Quote) {
snprintf(name, sizeof(name), "%s%s%s", Quote, Name, Quote);
strlwr(name);
k += 2;
} else {
safe_strcpy(g->Message, sizeof(g->Message), "Quoted must be specified"); returntrue;
} // endif Quote
} else {
safe_strcpy(name, sizeof(name), Name); // Not a keyword
strlwr(name);
}
if ((p = strstr(qrystr, name))) { for (i = 0; i < p - qrystr; i++)
stmt[i] = (Qrystr[i] == '`') ? q : Qrystr[i];
stmt[i] = 0;
k += i + (int)strlen(Name);
if (Schema && *Schema)
schmp = Schema;
if (qtd && *(p - 1) == ' ') { if (schmp) {
safe_strcat(stmt, stmt_sz, schmp);
safe_strcat(stmt, stmt_sz, ".");
}
do {
stmt[i++] = (Qrystr[k] == '`') ? q : Qrystr[k];
} while (Qrystr[k++]);
RemoveConst(g, stmt);
if (body)
safe_strcat(stmt, stmt_sz, body);
} else {
snprintf(g->Message, sizeof(g->Message), "Cannot use this %s command",
(Mode == MODE_UPDATE) ? "UPDATE" : "DELETE"); returntrue;
} // endif p
if (trace(33))
htrc("Command=%s\n", stmt);
Query = new(g)STRING(g, 0, stmt); return (!Query->GetSize());
} // end of MakeCommand
/***********************************************************************/ /* GetRecpos: return the position of last read record. */ /***********************************************************************/ int TDBEXT::GetRecpos(void)
{ return Fpos;
} // end of GetRecpos
/***********************************************************************/ /* ODBC GetMaxSize: returns table size estimate in number of lines. */ /***********************************************************************/ int TDBEXT::GetMaxSize(PGLOBAL g)
{ if (MaxSize < 0) { if (Mode == MODE_DELETE) // Return 0 in mode DELETE in case of delete all.
MaxSize = 0; elseif (!Cardinality(NULL))
MaxSize = 10; // To make MySQL happy elseif ((MaxSize = Cardinality(g)) < 0)
MaxSize = 12; // So we can see an error occurred
} // endif MaxSize
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/ /* Return max size value. */ /***********************************************************************/ int TDBEXT::GetProgMax(PGLOBAL g)
{ return GetMaxSize(g);
} // end of GetProgMax
/* ---------------------------EXTCOL class --------------------------- */
/***********************************************************************/ /* EXTCOL public constructor. */ /***********************************************************************/
EXTCOL::EXTCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
: COLBLK(cdp, tdbp, i)
{ if (cprec) {
Next = cprec->GetNext();
cprec->SetNext(this);
} else {
Next = tdbp->GetColumns();
tdbp->SetColumns(this);
} // endif cprec
if (trace(1))
htrc(" making new %sCOL C%d %s at %p\n", am, Index, Name, this);
// Set additional remote access method information for column.
Crp = NULL; Long = Precision;
To_Val = NULL;
Bufp = NULL;
Blkp = NULL;
Rank = 0; // Not known yet
} // end of JDBCCOL constructor
/***********************************************************************/ /* EXTCOL private constructor. */ /***********************************************************************/
EXTCOL::EXTCOL(void) : COLBLK()
{
Crp = NULL;
Buf_Type = TYPE_INT; // This is a count(*) column
// Set additional Dos access method information for column. Long = sizeof(int);
To_Val = NULL;
Bufp = NULL;
Blkp = NULL;
Rank = 1;
} // end of EXTCOL constructor
/***********************************************************************/ /* EXTCOL constructor used for copying columns. */ /* tdbp is the pointer to the new table descriptor. */ /***********************************************************************/
EXTCOL::EXTCOL(PEXTCOL col1, PTDB tdbp) : COLBLK(col1, tdbp)
{
Crp = col1->Crp; Long = col1->Long;
To_Val = col1->To_Val;
Bufp = col1->Bufp;
Blkp = col1->Blkp;
Rank = col1->Rank;
} // end of JDBCCOL copy constructor
/***********************************************************************/ /* SetBuffer: prepare a column block for write operation. */ /***********************************************************************/ bool EXTCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
{ if (!(To_Val = value)) {
snprintf(g->Message, sizeof(g->Message), MSG(VALUE_ERROR), Name); returntrue;
} elseif (Buf_Type == value->GetType()) { // Values are of the (good) column type if (Buf_Type == TYPE_DATE) { // If any of the date values is formatted // output format must be set for the receiving table if (GetDomain() || ((DTVAL *)value)->IsFormatted()) goto newval; // This will make a new value;
} elseif (Buf_Type == TYPE_DOUBLE) // Float values must be written with the correct (column) precision // Note: maybe this should be forced by ShowValue instead of this ?
value->SetPrec(GetScale());
Value = value; // Directly access the external value
} else { // Values are not of the (good) column type if (check) {
snprintf(g->Message, sizeof(g->Message), MSG(TYPE_VALUE_ERR), Name,
GetTypeName(Buf_Type), GetTypeName(value->GetType())); returntrue;
} // endif check
newval: if (InitValue(g)) // Allocate the matching value block returntrue;
} // endif's Value, Buf_Type
// Because Colblk's have been made from a copy of the original TDB in // case of Update, we must reset them to point to the original one. if (To_Tdb->GetOrig())
To_Tdb = (PTDB)To_Tdb->GetOrig();
// Set the Column
Status = (ok) ? BUF_EMPTY : BUF_NO; returnfalse;
} // end of SetBuffer
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.3 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.