Chat global

Chat
Loading the chat ...
Conexão World - SQL...
 
Notifications
Clear all

Conexão World - SQL Errors

4 Posts
2 Usuários
5 Reactions
120 Visualizações
NatsuBr
(@natsubr)
Posts: 13
Mentor Respeitado
Topic starter
 

@EDIT 

QUERO DEIXA O AGRADECIMENTO AO ViGo PORME DAR UMA LUZ DE ONDE COMEÇAR A ACHAR OS PROBLEMAS E POR COMPARTILHAR TBM O RESTANTE DOS AJUSTES.

 

GOSTO DE SER JUSTO E REALMENTE ELE HAVIA DITO O QUE ERA O PROBLEMA, (MAIS N DISSE AONDE KK)  

Pessoal esta tendo algumas dificuldades em fazer a Source do world funcionar e eu consegui então vou passar o que consegui fazer para ajustar e fazer ela funcionar.

Sim uso IA para me ajudar, e quem é iniciante tbm deveria pois evitaria desgastes com certas coisas, pessoal ajuda sim, mais também precisamos aprender a nos virar as vezes, sou novato e peço ajuda mais as vezes eu entendo que nem tudo da pra vir de graça e de mão beijada.

IA te ajuda a encontrar os problemas mais na maioria das vezes pode te gerar outros então teste antes de fazer e sempre faça backup.

Vamos la 😀

erro:
Message: [Microsoft][ODBC SQL Server Driver]Invalid precision value
SQLSTATE: HY104

O erro [Microsoft][ODBC SQL Server Driver]Invalid precision value (SQLSTATE: HY104) geralmente ocorre quando um parâmetro passado para uma query SQL espera um tipo numérico com precisão (como decimal(p,s) ou numeric(p,s)), mas recebe um valor ou tipo incompatível, ou a configuração do parâmetro está incorreta.

exemplo:

void LogRoleta(char PlayerID[32], char PlayerName[32], char ItemCode[32], char MonsterName[32])
 {
 auto db = SQLConnection::GetConnection(DATABASEID_LogDB);

 if (db && db->Open())
 {

 // o "erro" esta aqui
 const char* const query = "INSERT INTO Roleta VALUES (?,?,?,?,GETDATE())";

 if (db->Prepare(query))
 {
 db->BindInputParameter(PlayerID, 1, PARAMTYPE_String);
 db->BindInputParameter(PlayerName, 2, PARAMTYPE_String);
 db->BindInputParameter(ItemCode, 3, PARAMTYPE_String);
 db->BindInputParameter(MonsterName, 4, PARAMTYPE_String);

 db->Execute();
 }

 db->Close();
 }
 }

Aplicação correta :

// Especifique os nomes das colunas
const char* const query = "INSERT INTO Roleta (PlayerID, PlayerName, ItemCode, MonsterName, Data) VALUES (?,?,?,?,GETDATE())";

Existe outra questão também na SQLConnection.cpp:

 BOOL SQLConnection::BindInputParameter(void* pParameter, int iPosition, EDatabaseDataType eDataType)
 {
 int iType = 0;
 int iSQLType = 0;
 SQLLEN cbColDef = 0; // tamanho declarado da coluna (precision/length)
 SQLLEN cbValueMax = 0; // tamanho do buffer do parâmetro (em bytes)

 switch (eDataType)
 {
 case PARAMTYPE_Integer:
 iType = SQL_C_LONG;
 iSQLType = SQL_INTEGER;
 cbColDef = 0;
 cbValueMax = 0;
 break;
 case PARAMTYPE_String:
 iType = SQL_C_CHAR;
 iSQLType = SQL_VARCHAR;
 // cbColDef deve ser a precisão/length; cbValueMax é o tamanho do buffer passado
 if (pParameter)
 {
 cbColDef = static_cast<SQLLEN>(lstrlenA((char*)pParameter));
 if (cbColDef <= 0) cbColDef = 1;
 cbValueMax = cbColDef + 1; // inclui terminador
 }
 else
 {
 cbColDef = 1;
 cbValueMax = 1;
 }
 break;
 case PARAMTYPE_Float:
 iType = SQL_C_FLOAT;
 iSQLType = SQL_REAL;
 cbColDef = 0;
 cbValueMax = 0;
 break;
 case PARAMTYPE_Int64:
 iType = SQL_C_SBIGINT;
 iSQLType = SQL_BIGINT;
 cbColDef = 0;
 cbValueMax = 0;
 break;
 case PARAMTYPE_Time:
 iType = SQL_C_TIMESTAMP;
 iSQLType = SQL_TYPE_TIMESTAMP;
 cbColDef = 0;
 cbValueMax = 0;
 break;
 default:
 break;
 }

 // Use cbValueMax != 0 para tipos string; pcbValuePtr NULL é aceitável para parâmetros de entrada
 if (SQLBindParameter(hStatement, static_cast<SQLUSMALLINT>(iPosition), SQL_PARAM_INPUT,
 static_cast<SQLSMALLINT>(iType), static_cast<SQLSMALLINT>(iSQLType),
 cbColDef, 0, pParameter, cbValueMax, NULL) == SQL_ERROR)
 {
 show_errorSQL(SQL_HANDLE_STMT, hStatement);
 return FALSE;
 }
 return TRUE;
 }

O que mudei e por quê:

• Antes: SQLBindParameter estava sendo chamado com iLen (só usado como cbColDef) e cbValueMax = 0 — isso pode levar o driver a aceitar uma precisão inválida (0) e gerar o erro HY104.

• Agora: para strings calculo cbColDef (comprimento da string) e cbValueMax (comprimento do buffer + terminador). Para outros tipos mantenho 0. Isso evita passar um cbValueMax = 0 para strings e reduz chance do driver reclamar de precisão inválida.


Este tópico foi modificado 3 semanas atrás by NatsuBr
 
Postado : 26/12/2025 3:28 am
panda90 reacted
ViGo
 ViGo
(@vigo)
Posts: 106
Guia Valioso
 

Te passei a lógica no discord, mas é mais fácil dar o crédito pra ia do que pro amigo, eu amo a comunidade.

parabéns, você corrigiu 10% do problema, agora deixa eu desempenhar o meu papel de 🤡 e terminar de mastigar a correção pra você e os demais.

já sabemos que HY104 se trata de querys não é mesmo? 

temos duas funções no SQLCONNECTION que lidam com a preparação e execução delas:

SQLConnection::Prepare

SQLConnection::Execute

se eu pedir pro nosso amigo chatgpt criar uma função auxiliar de logs, logando o máximo que dá. ele talvez crie algo semelhante a:

bool SQLConnection::show_errorSQL(unsigned int handletype, const SQLHANDLE& handle)
{
SQLCHAR sqlstateSqlError[1024] = { 0 };
SQLCHAR messageSqlError[1024] = { 0 };
char szBufSQLError[4096] = { 0 };
 
if (SQL_SUCCESS == SQLGetDiagRecA(handletype, handle, 1,
sqlstateSqlError, NULL,
messageSqlError, 1024, NULL))
{
// monta mensagem com a última query salva em szQuery
STRINGFORMAT(szBufSQLError,
"Message: %s\nSQLSTATE: %s\nQuery: %s\n",
messageSqlError, sqlstateSqlError, szQuery);
 
// log no sistema atual
Utils_Log(LOG_SERVER, szBufSQLError);
std::cerr << szBufSQLError << std::endl;
 
// grava em arquivo .txt
std::ofstream logFile("error_log.txt", std::ios::app); // append
if (logFile.is_open())
{
std::time_t t = std::time(nullptr);
char timeBuf[64];
std::strftime(timeBuf, sizeof(timeBuf),
"%Y-%m-%d %H:%M:%S",
std::localtime(&t));
 
logFile << "=============================\n";
logFile << "Timestamp: " << timeBuf << "\n";
logFile << "Message  : " << messageSqlError << "\n";
logFile << "SQLSTATE : " << sqlstateSqlError << "\n";
logFile << "Query    : " << szQuery << "\n";
logFile << "=============================\n\n";
}
 
return true;
}
return false;
}
então podemos pedir pra ele utilizar essa função de log nas funções que preparam e executam as querys:
BOOL SQLConnection::Prepare(const char* pszQuery)
{
// Copy Query
strcpy_s(szQuery, pszQuery);
 
// Check SQLI
for (int i = 0; i < 2048; i++)
{
// End string? break it
if (szQuery[i] == 0)
break;
 
// Have quote mark? SQLI, return error
if (szQuery[i] == 0x27)
{
// Query Not secure
 
return FALSE;
}
}
 
// Free Statement
SQLFreeStmt(hStatement, SQL_CLOSE);
 
// Prepare Query error? return
if (SQLPrepareA(hStatement, (SQLCHAR*)szQuery, SQL_NTS) == SQL_ERROR)
{
Utils_Log(LOG_SQL, "Error Prepare() - Query: %s", pszQuery);
show_errorSQL(SQL_HANDLE_STMT, hStatement);
return FALSE;
}
// Success
return TRUE;
}
 
BOOL SQLConnection::Execute(BOOL bFetch)
{
// Try Execute query
if (SQLExecute(hStatement) == SQL_ERROR)
{
Utils_Log(LOG_SQL, "Error Execute() - Query: %s", szQuery);
show_errorSQL(SQL_HANDLE_STMT, hStatement);
return FALSE;
}
if (bFetch)
{
if (!NextRow())
return FALSE;
}
return TRUE;
}
dessa forma, toda query que tiver problema, ele vai nos dizer exatamente qual a query e o que ela está tentando incrementar ou ler no nosso banco de dados.
 
 
ao ter acesso as querys problemáticas, quase 100% delas é por estar tentando incrementar valores vazios no banco, recomendo você entender o fluxo de chamada da query pra realmente corrigir os dados vazios que estão sendo passados para os binds, algumas você simplesmente pode negar a execução da query se tiver com dados vazios, outras você corrige, outras você pode moocar dados, pois algumas dessas query vão ser lidas no futuro por outros sistemas, e se ler dados vazios, vai dar crash no server e você não vai saber da onde vem, então faça bem feito desde o começo para não se tornar algo mais difícil no futuro, acredite.
 
agora faz sentido pra você doutor @NatsuBR o pq da gente ficar descrente em ajudar e muito menos de passar solução pronta pra vocês? no final vocês querem tudo na mão, e tudo que aprendem através do esforço do próximo, banalizam e querem ganhar algo em cima disso, isso não é legal pra nenhuma das partes.
 
agora faz o favor pra gente, termina de postar a verdade, apenas as DB's que o tacola postou e disse que corrigiria o erro, resolveu? 
 
vi que você tinha abandonado a source que apresentou esse problema, e começou a utilizar a source que o tacola também disponibilizou, o erro voltou a persistir nessa source? 
 
existem algumas versões dessa source do world, umas com o problema e outras sem, talvez alguns tiverem o privilégio de ter acesso a source corrigida, e ficam chutando correções com intuito de descredibilizar o colega, ops o 🤡 que perde meses procurando problema e posta a solução de graça, de qualquer forma, está aí o caminho para corrigir, se mais um cidadão postar alguma dúvida relacionada a isso, merece realmente ser ignorado 🤣 
 
 

1 por amor, 2 por dinheiro

https://www.youtube.com/@ViGo_Priston

 
Postado : 26/12/2025 4:56 pm
Luk, panda90 and NatsuBr reacted
NatsuBr
(@natsubr)
Posts: 13
Mentor Respeitado
Topic starter
 

Postado por: @vigo

Te passei a lógica no discord, mas é mais fácil dar o crédito pra ia do que pro amigo, eu amo a comunidade.

parabéns, você corrigiu 10% do problema, agora deixa eu desempenhar o meu papel de 🤡 e terminar de mastigar a correção pra você e os demais.

já sabemos que HY104 se trata de querys não é mesmo? 

temos duas funções no SQLCONNECTION que lidam com a preparação e execução delas:

SQLConnection::Prepare

SQLConnection::Execute

se eu pedir pro nosso amigo chatgpt criar uma função auxiliar de logs, logando o máximo que dá. ele talvez crie algo semelhante a:

bool SQLConnection::show_errorSQL(unsigned int handletype, const SQLHANDLE& handle)
{
SQLCHAR sqlstateSqlError[1024] = { 0 };
SQLCHAR messageSqlError[1024] = { 0 };
char szBufSQLError[4096] = { 0 };
 
if (SQL_SUCCESS == SQLGetDiagRecA(handletype, handle, 1,
sqlstateSqlError, NULL,
messageSqlError, 1024, NULL))
{
// monta mensagem com a última query salva em szQuery
STRINGFORMAT(szBufSQLError,
"Message: %s\nSQLSTATE: %s\nQuery: %s\n",
messageSqlError, sqlstateSqlError, szQuery);
 
// log no sistema atual
Utils_Log(LOG_SERVER, szBufSQLError);
std::cerr << szBufSQLError << std::endl;
 
// grava em arquivo .txt
std::ofstream logFile("error_log.txt", std::ios::app); // append
if (logFile.is_open())
{
std::time_t t = std::time(nullptr);
char timeBuf[64];
std::strftime(timeBuf, sizeof(timeBuf),
"%Y-%m-%d %H:%M:%S",
std::localtime(&t));
 
logFile << "=============================\n";
logFile << "Timestamp: " << timeBuf << "\n";
logFile << "Message  : " << messageSqlError << "\n";
logFile << "SQLSTATE : " << sqlstateSqlError << "\n";
logFile << "Query    : " << szQuery << "\n";
logFile << "=============================\n\n";
}
 
return true;
}
return false;
}
então podemos pedir pra ele utilizar essa função de log nas funções que preparam e executam as querys:
BOOL SQLConnection::Prepare(const char* pszQuery)
{
// Copy Query
strcpy_s(szQuery, pszQuery);
 
// Check SQLI
for (int i = 0; i < 2048; i++)
{
// End string? break it
if (szQuery[i] == 0)
break;
 
// Have quote mark? SQLI, return error
if (szQuery[i] == 0x27)
{
// Query Not secure
 
return FALSE;
}
}
 
// Free Statement
SQLFreeStmt(hStatement, SQL_CLOSE);
 
// Prepare Query error? return
if (SQLPrepareA(hStatement, (SQLCHAR*)szQuery, SQL_NTS) == SQL_ERROR)
{
Utils_Log(LOG_SQL, "Error Prepare() - Query: %s", pszQuery);
show_errorSQL(SQL_HANDLE_STMT, hStatement);
return FALSE;
}
// Success
return TRUE;
}
 
BOOL SQLConnection::Execute(BOOL bFetch)
{
// Try Execute query
if (SQLExecute(hStatement) == SQL_ERROR)
{
Utils_Log(LOG_SQL, "Error Execute() - Query: %s", szQuery);
show_errorSQL(SQL_HANDLE_STMT, hStatement);
return FALSE;
}
if (bFetch)
{
if (!NextRow())
return FALSE;
}
return TRUE;
}
dessa forma, toda query que tiver problema, ele vai nos dizer exatamente qual a query e o que ela está tentando incrementar ou ler no nosso banco de dados.
 
 
ao ter acesso as querys problemáticas, quase 100% delas é por estar tentando incrementar valores vazios no banco, recomendo você entender o fluxo de chamada da query pra realmente corrigir os dados vazios que estão sendo passados para os binds, algumas você simplesmente pode negar a execução da query se tiver com dados vazios, outras você corrige, outras você pode moocar dados, pois algumas dessas query vão ser lidas no futuro por outros sistemas, e se ler dados vazios, vai dar crash no server e você não vai saber da onde vem, então faça bem feito desde o começo para não se tornar algo mais difícil no futuro, acredite.
 
agora faz sentido pra você doutor @NatsuBR o pq da gente ficar descrente em ajudar e muito menos de passar solução pronta pra vocês? no final vocês querem tudo na mão, e tudo que aprendem através do esforço do próximo, banalizam e querem ganhar algo em cima disso, isso não é legal pra nenhuma das partes.
 
agora faz o favor pra gente, termina de postar a verdade, apenas as DB's que o tacola postou e disse que corrigiria o erro, resolveu? 
 
vi que você tinha abandonado a source que apresentou esse problema, e começou a utilizar a source que o tacola também disponibilizou, o erro voltou a persistir nessa source? 
 
existem algumas versões dessa source do world, umas com o problema e outras sem, talvez alguns tiverem o privilégio de ter acesso a source corrigida, e ficam chutando correções com intuito de descredibilizar o colega, ops o 🤡 que perde meses procurando problema e posta a solução de graça, de qualquer forma, está aí o caminho para corrigir, se mais um cidadão postar alguma dúvida relacionada a isso, merece realmente ser ignorado 🤣 
 
 

 

Obrigado pela ajuda, e já retribui os créditos a vc pela dica de onde procurar os problemas 😀 

@EDIT
E EU ME ESQUECI DEVIDO A IMPOLGAÇÃO DE DAR OS CREDITOS, MAIS SOU HUMILDE EM RECONHECER ISSO E INCETIVAR O CRESCIMENTO DA COMUNIDADE, COMO NÃO SOU PROGRAMADOR E AINDA ESTOU COMEÇANDO OS ESTUDO, CERTAS COISAS POR MAIS BOBAS QUE SEJAM PODE NOS ALEGRAR, INCENTIVAR O CRESCIMENTO E FAZER A SUA PARTE EM AJUDAR A COMUNIDADE A CRESCER, EU NÃO GOSTO DE PEDIR O COD PRONTO, E SIM DE AONDE POSSO COMEÇAR A PROCURAR E IR AVANTE.

 


Este post foi modificado 3 semanas atrás por NatsuBr
 
Postado : 26/12/2025 5:12 pm
ViGo
 ViGo
(@vigo)
Posts: 106
Guia Valioso
 

@natsubr 

GOSTO DE SER JUSTO E REALMENTE ELE HAVIA DITO O QUE ERA O PROBLEMA, (MAIS N DISSE AONDE KK)  

Porque não existe esse onde, apenas existem diversas querys problemáticas no código, e esses erros travam o servidor, literalmente travam...

na minha source eu precisei ajustar várias, para alguns clientes foram poucas, outros mais outros menos, mas todos menos que na minha, então é isso, não existe esse aonde, o que existe é botar o juízo pra funcionar, entender o problema e partir pra cima dele.

 


1 por amor, 2 por dinheiro

https://www.youtube.com/@ViGo_Priston

 
Postado : 26/12/2025 5:23 pm
NatsuBr reacted
Compartilhar:

Anúncio