Chat global
Conexão World - SQL Errors
@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.
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 szQuerySTRINGFORMAT(szBufSQLError,"Message: %s\nSQLSTATE: %s\nQuery: %s\n",messageSqlError, sqlstateSqlError, szQuery);// log no sistema atualUtils_Log(LOG_SERVER, szBufSQLError);std::cerr << szBufSQLError << std::endl;// grava em arquivo .txtstd::ofstream logFile("error_log.txt", std::ios::app); // appendif (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;}
BOOL SQLConnection::Prepare(const char* pszQuery){// Copy Querystrcpy_s(szQuery, pszQuery);// Check SQLIfor (int i = 0; i < 2048; i++){// End string? break itif (szQuery[i] == 0)break;// Have quote mark? SQLI, return errorif (szQuery[i] == 0x27){// Query Not securereturn FALSE;}}// Free StatementSQLFreeStmt(hStatement, SQL_CLOSE);// Prepare Query error? returnif (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;}// Successreturn TRUE;}BOOL SQLConnection::Execute(BOOL bFetch){// Try Execute queryif (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;}
1 por amor, 2 por dinheiro
Postado por: @vigoTe 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 szQuerySTRINGFORMAT(szBufSQLError,"Message: %s\nSQLSTATE: %s\nQuery: %s\n",messageSqlError, sqlstateSqlError, szQuery);// log no sistema atualUtils_Log(LOG_SERVER, szBufSQLError);std::cerr << szBufSQLError << std::endl;// grava em arquivo .txtstd::ofstream logFile("error_log.txt", std::ios::app); // appendif (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 Querystrcpy_s(szQuery, pszQuery);// Check SQLIfor (int i = 0; i < 2048; i++){// End string? break itif (szQuery[i] == 0)break;// Have quote mark? SQLI, return errorif (szQuery[i] == 0x27){// Query Not securereturn FALSE;}}// Free StatementSQLFreeStmt(hStatement, SQL_CLOSE);// Prepare Query error? returnif (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;}// Successreturn TRUE;}BOOL SQLConnection::Execute(BOOL bFetch){// Try Execute queryif (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.
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
- 21 Fóruns
- 290 Tópicos
- 1,726 Posts
- 10 Online
- 316 Membros
