BANNED
Join Date: Nov 2009
Location: 9`su 09`n0n7e`r0f76a
|
06-15-2010
, 18:06
Re: [ES][TUT] SQLx (Traduccion del tutorial de Hawk552)
|
#5
|
Quote:
Originally Posted by Ayudanding
Antes de comenzar, es importante entender que este tutorial asume que usted sabe lo básico acerca de Pawn (sintáctica y la aplicación de la misma en AMXX). Usted debe ser al menos un nivel intermedio y los conocimientos de SQL (en sí mismo) y quizás DBI (Le ha quedado muy poco de DBI Pero aun sigue funcionando con los controladores (drivers) de SQL que quedo en AMXX Hace ya bastante tiempo) Voy a hacer pequeñas secciones que explican el código SQL en sí, pero para la mayor parte usted debe saber lo básico.
SQLx es uno de los conjuntos de nuevos controladores de SQL y API que se incorporaron en AMXX 1.75 Y la gente ya lo tenia desde 1.70
Las nuevas características importantes incluyen la capacidad de las consultas de hilo (para guardar cuando se cae el server, las consultas(queryes) a la base de datos se envíen a un nuevo hilo y luego se hace una devolución de llamada cuando la consulta se ha completado o no), más la abstracción de la API (más fácil de crear complementos, más comprensible), conexión "tuples o truples" (un sistema utilizado para almacenar información sobre una base de datos pero no se conectan a él, muy útil para escribir API donde debe haber una conexión permite ser independientes de todo diferentes plugins), y la capacidad de carga de varios módulos (puede cargar MySQL, SQLite y cualquier otro controlador/driver).
Lo más importante de entender acerca de SQLx es que todo el sistema trabaja con "Handlers", que almacenan toda la información como una conexión, tupla(truple), resultado(result) y consulta(query) preparada. Esto hace que sea muy sencillo. (al tratar de conectar con resultados de una consulta(query), debido a la falta de diferenciación de marca, por ejemplo.), pero al mismo tiempo hace las cosas mucho más simples - por ejemplo, una conexión se interrumpe mediante la ejecución de SQL_FreeHandle, la native misma que se utiliza para liberar a un resultado (free result), sin una query preparada y sin una base de datos de tuple.
Veamos una comparación entre DBI y SQLx:
DBI:
PHP Code:
#include <amxmodx>
#include <amxmisc>
#include <dbi>
new Sql:g_SqlConexion
new g_Error[512]
public plugin_init()
{
register_plugin("DBI Demonstracion","1.0","Hawk552")
new Host[64],User[64],Pass[64],Db[64]
// Vamos a buscar las cvars que vamos a utilizar para conectar.
// No hagamos pcvars por que solo las vamos a utilizar 1 ves.
get_cvar_string("amx_sql_host",Host,63)
get_cvar_string("amx_sql_user",User,63)
get_cvar_string("amx_sql_pass",Pass,63)
get_cvar_string("amx_sql_db",Db,63)
// Esta bien, listo para conectarse.
g_SqlConexion = dbi_connect(Host,User,Pass,Db,g_Error,511)
// Indica que la conexion a fallado, Si falla (SQL_ERROR) Si anda bien (SQL_OK).
if(g_SqlConexion < SQL_OK)
// Paramos el plugin mediante un mensaje de error.
set_fail_state(g_Error)
new Result:Results[3]
// Ejecutamos algunas queryes..
if((Results[0] = dbi_query(g_SqlConexion,"CREATE TABLE IF NOT EXISTS zomg (you INT(11),are INT(11),a INT(11),noob INT(11))")) < RESULT_OK || (Results[1] = dbi_query(g_SqlConexion,"INSERT INTO zomg VALUES('1','2','3','4')")) < RESULT_OK || (Results[2] = dbi_query(g_SqlConexion,"INSERT INTO zomg VALUES('4','3','2','1')")) < RESULT_OK)
{
// Buscar cualquier error si tiene problemas
dbi_error(g_SqlConexion,g_Error,511)
// Paramos el plugin.
set_fail_state(g_Error)
}
// Free result Handler's.
for(new Count;Count < 3;Count++)
dbi_free_result(Results[Count])
}
public client_disconnect(id)
{
// Ejecutamos cualquier query.
new Result:QueryResult = dbi_query(g_SqlConexion,"SELECT * FROM zomg WHERE you='1' OR you='4'")
// La query Fallo, La base de datos esta cerrada.
if(!QueryResult)
{
dbi_error(g_SqlConexion,g_Error,511)
set_fail_state(g_Error)
}
new Data
// Nota: Aca corremos dbi_nextrow primero, una de las principales razones por las que no me gusta DBI.
// Debes hacer esto, nose iniciar desde la primera fila.
while(dbi_nextrow(Result))
{
// Tomamos la Fila
// Nota: Tambien podriamos usard dbi_result(Result,"usted")
Data = dbi_field(Result,1)
// Llamamos al server y escribimos en consola.
server_print("zomg, we have data: %d",Data)
}
}
public plugin_end()
// Cerramos la conexion
dbi_close(g_SqlConexion)
SQLx:
PHP Code:
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
new Handle:g_SqlTuple
new g_Error[512]
public plugin_init()
{
register_plugin("SQLx Demonstracion","1.0","Hawk552")
new Host[64],User[64],Pass[64],Db[64]
// Vamos a buscar las cvars que vamos a utilizar para conectar.
// No hagamos pcvars por que solo las vamos a utilizar 1 ves.
get_cvar_string("amx_sql_host",Host,63)
get_cvar_string("amx_sql_user",User,63)
get_cvar_string("amx_sql_pass",Pass,63)
get_cvar_string("amx_sql_db",Db,63)
// LLamamos a API, que es la informacion basica que conectaremos.
// Todabia no, basicamente es como guardar variables globales.
g_SqlTuple = SQL_MakeDbTuple(Host,User,Pass,Db)
// Ok, estamos listos para conectar.
new ErrorCode,Handle:SqlConnection = SQL_Connect(g_SqlTuple,ErrorCode,g_Error,511)
if(SqlConnection == Empty_Handle)
// Paramos el plugin mediante un mensaje de error.
set_fail_state(g_Error)
new Handle:Queries[3]
// Ahora preparamos algunaz queries al azar.
Queries[0] = SQL_PrepareQuery(SqlConnection,"CREATE TABLE IF NOT EXISTS zomg (you INT(11),are INT(11),a INT(11),noob INT(11))")
Queries[1] = SQL_PrepareQuery(SqlConnection,"INSERT INTO zomg VALUES('1','2','3','4')")
Queries[2] = SQL_PrepareQuery(SqlConnection,"INSERT INTO zomg VALUES('4','3','2','1')")
for(new Count;Count < 3;Count++)
{
// Ejecutamos las queryes y comprobamos que estan bien.
// Tene en cuenta que podes ejecutar la misma query varias veces.
// No estamos haciendo esto aca, pero verificamos si estan bien.
if(!SQL_Execute(Queries[Count]))
{
// Si hay algun problema...
SQL_QueryError(Queries[Count],g_Error,511)
set_fail_state(g_Error)
}
// Cerramos la "Handle"
SQL_FreeHandle(Queries[Count])
}
// you free everything with SQL_FreeHandle
SQL_FreeHandle(SqlConnection)
}
public client_disconnect(id)
{
// Ok, Listo para conectar.
new ErrorCode,Handle:SqlConnection = SQL_Connect(g_SqlTuple,ErrorCode,g_Error,511)
if(g_SqlTuple == Empty_Handle)
// Pausamos el plugin mediante un mensaje de error
set_fail_state(g_Error)
// Ejecutamos una query (random)
new Handle:Query = SQL_PrepareQuery(SqlConnection,"SELECT * FROM zomg WHERE you='1' OR you='4'")
// Ejecutamos la query
if(!SQL_Execute(Query))
{
// Si hay algun problema..
SQL_QueryError(Query,g_Error,511)
set_fail_state(g_Error)
}
// Comprobamos si hay mas resultados.
// Se inicia en la primera fila, en vez de "NULL".
new Data
while(SQL_MoreResults(Query))
{
// La columna comienza desde 0.
Data = SQL_ReadResult(Query,0)
server_print("Encontramos data: %d",Data)
SQL_NextRow(Query)
}
// Por supuesto, Liberamos la "query"
SQL_FreeHandle(Query)
// Tambien, por supuesto, Cerramos la conexion.
SQL_FreeHandle(SqlConnection)
}
public plugin_end()
// La truple "libre" - Nota: esto no cierra la conexion.
// Ya que no esta conectado xd!
SQL_FreeHandle(g_SqlTuple)
Como puede ver, no hay demasiadas diferencias cuando no se usa consulta rosca o.o? (threaded query), (que, en caso de que se lo pregunte, no he incluido en este ejemplo).
Por desgracia, nada de esto demuestra el verdadero poder de SQLx. Lo único que muestra es realmente el handle: SQL_FreeHandle y el sistema.
El verdadero poder está en consulta con rosca (threaded query). Roscado consulta (Threaded query) significa nada menos que una nueva versión de un plugin que todo está escrito con DBI, pero tiene enormes ventajas, especialmente en conexiones lentas. La idea de una consulta con rosca (threaded) es esencialmente un nuevo hilo (un sub-proceso) con el que su único objetivo es enviar, monitorear e informar de las cosas que le ocurren a una consulta. Debido a que está en un hilo separado, una consulta (query) que suele tener un segundo (y un segundo de la pérdida total de conexión para todos los clientes en el servidor) todavía tiene la misma cantidad de tiempo, pero no juega de interrupción.
¿Cuáles son las desventajas? Como he escrito, que significa básicamente una reescritura total, y un infierno de mucho más código. Cuando una consulta se completa con rosca (threaded), se llama a una función (que se declara en el prototipo de SQL_ThreadQuery) que controla el resultado de la consulta (query). Podría ser cualquier cantidad de tiempo después de esta consulta se envía, es decir, en eventos en tiempos sensibles sería casi imposible trabajar con él.
aca un ejemplo:
PHP Code:
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
new Handle:g_SqlTuple
new g_Cache[512]
public plugin_init()
{
register_plugin("SQLx Demonstration","1.0","Hawk552")
new Host[64],User[64],Pass[64],Db[64]
// Vamos a buscar las cvars que vamos a utilizar para conectar.
// No hagamos pcvars por que solo las vamos a utilizar 1 ves.
get_cvar_string("amx_sql_host",Host,63)
get_cvar_string("amx_sql_user",User,63)
get_cvar_string("amx_sql_pass",Pass,63)
get_cvar_string("amx_sql_db",Db,63)
// LLamamos a API, que es la informacion basica que conectaremos.
// Todabia no, basicamente es como guardar variables globales.
g_SqlTuple = SQL_MakeDbTuple(Host,User,Pass,Db)
copy(g_Cache,511,"CREATE TABLE IF NOT EXISTS zomg (you INT(11),are INT(11),a INT(11),noob INT(11))")
SQL_ThreadQuery(g_SqlTuple,"TableHandle",g_Cache)
}
public TableHandle(FailState,Handle:Query,Error[],Errcode,Data[],DataSize)
{
// Chequeamos una banda de errores.
if(FailState == TQUERY_CONNECT_FAILED)
return set_fail_state("Could not connect to SQL database.")
else if(FailState == TQUERY_QUERY_FAILED)
return set_fail_state("Query failed.")
if(Errcode)
return log_amx("Error on query: %s",Error)
SQL_ThreadQuery(g_SqlTuple,"QueryHandle","INSERT INTO zomg VALUES('1','2','3','4')")
SQL_ThreadQuery(g_SqlTuple,"QueryHandle","INSERT INTO zomg VALUES('4','3','2','1')")
// Avisa que no libera la query. - Usted no tiene que hacerlo.
return PLUGIN_CONTINUE
}
public QueryHandle(FailState,Handle:Query,Error[],Errcode,Data[],DataSize)
{
// Chequeamos una banda de errores.
if(FailState == TQUERY_CONNECT_FAILED)
return set_fail_state("Could not connect to SQL database.")
else if(FailState == TQUERY_QUERY_FAILED)
return set_fail_state("Query failed.")
if(Errcode)
return log_amx("Error on query: %s",Error)
return PLUGIN_CONTINUE
}
public client_disconnect(id)
SQL_ThreadQuery(g_SqlTuple,"SelectHandle","SELECT * FROM zomg WHERE you='1' OR you='4'")
public SelectHandle(FailState,Handle:Query,Error[],Errcode,Data[],DataSize)
{
if(FailState == TQUERY_CONNECT_FAILED)
return set_fail_state("Could not connect to SQL database.")
else if(FailState == TQUERY_QUERY_FAILED)
return set_fail_state("Query failed.")
if(Errcode)
return log_amx("Error on query: %s",Error)
new DataNum
while(SQL_MoreResults(Query))
{
DataNum = SQL_ReadResult(Query,0)
server_print("zomg, some data: %d",DataNum)
SQL_NextRow(Query)
}
return PLUGIN_CONTINUE
}
public plugin_end()
// La truple "libre" - Nota: esto no cierra la conexion.
// Ya que no esta conectado xd!
SQL_FreeHandle(g_SqlTuple)
No es tan dificil, especialmente si el resultado que se obtiene no importa.
Por último, varios módulos en ejecución puede llevarse a cabo mediante la ejecución de SQL_GetAffinity, comparándolo con el tipo de bases de datos que desean ejecutar, y se establece con SQL_SetAffinity. Un ejemplo de esto puede encontrarse en la cabecera sqlx.inc:
PHP Code:
new set_type[12]
get_cvar_string("amx_sql_type", set_type, 11)
SQL_GetAffinity(get_type, 12)
if (!equali(get_type, set_type))
{
if (!SQL_SetAffinity(set_type))
{
log_amx("Failed to set affinity from %s to %s.", get_type, set_type)
}
}
SQLx también es útil para hacerle frente a los plugins multiples, la tupla/truple y la handle, el sistema permite una fácil transferencia de información a través de territorio desconocido (específicamente addon's de plugins).
Aca un ejemplo:
PHP Code:
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
new Handle:g_SqlTuple
public plugin_init()
register_plugin("SQLx Demonstracion - Core","1.0","Hawk552")
public plugin_natives()
{
new Host[64],User[64],Pass[64],Db[64]
// Vamos a buscar las cvars que vamos a utilizar para conectar.
// No hagamos pcvars por que solo las vamos a utilizar 1 ves.
get_cvar_string("amx_sql_host",Host,63)
get_cvar_string("amx_sql_user",User,63)
get_cvar_string("amx_sql_pass",Pass,63)
get_cvar_string("amx_sql_db",Db,63)
// LLamamos a API, que es la informacion basica que conectaremos.
// Todabia no, basicamente es como guardar variables globales.
g_SqlTuple = SQL_MakeDbTuple(Host,User,Pass,Db)
register_native("sql_demo_get_handle","_sql_demo_get_handle")
}
public _sql_demo_get_handle()
return _:g_SqlTuple
public plugin_end()
// La truple "libre" - Nota: esto no cierra la conexion.
// Ya que no esta conectado xd!
SQL_FreeHandle(g_SqlTuple)
PHP Code:
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
native Handle:sql_demo_get_handle()
public plugin_init()
{
register_plugin("SQLx Demonstracion - Attachment","1.0","Hawk552")
SQL_ThreadQuery(sql_demo_get_handle(),"QueryHandle","CREATE TABLE IF NOT EXISTS zomg (rofl INT(11))")
}
public QueryHandle(FailState,Handle:Query,Error[],Errcode,Data[],DataSize)
{
if(FailState == TQUERY_CONNECT_FAILED)
return set_fail_state("Could not connect to SQL database.")
else if(FailState == TQUERY_QUERY_FAILED)
return set_fail_state("Query failed.")
if(Errcode)
return log_amx("Error on query: %s",Error)
server_print("zomg, table made")
}
Lograr esto en DBI no es difícil, pero una conexión constante tendría que quedar abierta, algo que no SQLx demanda.
Recuerde que contienen todos los módulos SQLx soporte a DBI también, y muchas personas se sienten más cómodos con ello, DBI tiene sus puntos débiles sin embargo, y SQLx fue diseñado para superarlos.
Traducido por mi y un toque de ayuda de google traductor.
si algo esta mal explicado posteen. xd
|
Jajajajajajaj hiciste un google translate negro. Mira lo que sale en google translate:
Antes de comenzar, es importante entender que este tutorial asume que usted sabe lo básico acerca de Peón (sintáctica y la aplicación de la misma en AMXX). Usted debe ser al menos un guionista nivel intermedio, y los conocimientos de SQL (el lenguaje en sí mismo) y quizás DBI (la ha quedado desfasado y obsoleto, aunque sigue funcionando controlador de SQL que se utilizó en AMXX por un tiempo). Voy a hacer pequeñas secciones que explican el código SQL en sí, pero para la mayor parte usted debe saber lo básico.
SQLx es uno de los conjuntos de nuevo controlador de SQL y las API que se incorporaron en AMXX 1,75 (?) Y accesible al público poco después de la liberación de AMXX 1,70. Las nuevas características importantes incluyen la capacidad de las consultas de hilo (para salvar la interrupción del juego, las consultas a la base de datos se envíen a un nuevo hilo y luego se hace una devolución de llamada cuando la consulta se ha completado o no), más la abstracción de la API (más fácil de crear complementos con y más comprensible), conexión "tuplas" (un sistema utilizado para almacenar información sobre una base de datos pero no se conectan a él - muy útil para escribir API donde debe haber una conexión permite ser independientes de toda dife plugins), y la capacidad de carga varios módulos (puede cargar MySQL, SQLite y cualquier otro controlador).
Lo más importante de entender acerca de SQLx es que todo el sistema trabaja con "Mangos", que almacenan toda la información como una conexión, tupla, resultado y consulta preparada. Esto hace que sea muy sencillo tanto a la pata (al tratar de conectar con resultados de una consulta, debido a la falta de diferenciación de marca, por ejemplo), pero al mismo tiempo hace las cosas mucho más simples - por ejemplo, una conexión se interrumpe mediante la ejecución de SQL_FreeHandle, el nativo mismo que se utiliza para liberar a un resultado, sin una consulta preparada y sin una base de datos de tupla.
Veamos una comparación entre DBI y SQLx:
Como puede ver, no hay demasiadas diferencias cuando no se usa consulta rosca (que, en caso de que se lo pregunte, no he incluido en este ejemplo).
Por desgracia, nada de esto demuestra el verdadero poder de SQLx. Lo único que muestra es realmente el mango: SQL_FreeHandle y el sistema.
El verdadero poder está en consulta con rosca. Roscado consulta significa nada menos que una nueva versión de un plugin que todo está escrito con DBI, pero tiene enormes ventajas, especialmente en conexiones lentas. La idea de una consulta con rosca es esencialmente un nuevo hilo (un sub-proceso) con el que su único objetivo es enviar, monitorear e informar de las cosas que le ocurren a una consulta. Debido a que está en un hilo separado, una consulta que suele tener un segundo (y un segundo de la pérdida total de conexión para todos los clientes en el servidor) todavía tiene la misma cantidad de tiempo, pero no juego de interrupción.
¿Cuáles son las desventajas? Como he escrito, que significa básicamente una reescritura total, y un infierno de mucho más código. Cuando una consulta se completa con rosca, se llama a una función (que se declara en el prototipo de SQL_ThreadQuery) que controla el resultado de la consulta. Podría ser cualquier cantidad de tiempo después de esta consulta se envía, es decir, eventos en tiempo sensible sería casi imposible trabajar con él.
He aquí un ejemplo en acción:
ETC
|
|