Raised This Month: $32 Target: $400
 8% 

[ES][TUT] SQLx (Traduccion del tutorial de Hawk552)


  
 
 
Thread Tools Display Modes
Author Message
Ayudanding
BANNED
Join Date: Jun 2010
Old 06-15-2010 , 17:48   [ES][TUT] SQLx (Traduccion del tutorial de Hawk552)
#1

[IMG]http://img214.**************/img214/7079/5180537378a9794389erq7.jpg[/IMG]

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_type11)

SQL_GetAffinity(get_type12)

if (!
equali(get_typeset_type))
{
    if (!
SQL_SetAffinity(set_type))
    {
        
log_amx("Failed to set affinity from %s to %s."get_typeset_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

Last edited by Ayudanding; 06-15-2010 at 18:06.
Ayudanding is offline
01101101
BANNED
Join Date: Nov 2009
Location: 9`su 09`n0n7e`r0f76a
Old 06-15-2010 , 17:55   Re: [ES][TUT] SQLx (Traduccion del tutorial de Hawk552)
#2

Quote:
Originally Posted by Ayudanding View Post
Fail, SQLx sirve para MySQL, o SQLite, pero no para MSSQL (el de la imagen)

Igual no te esforzaste, nada mas lo tradujiste, y que, en realidad mucho no sirve ese tutorial, porque te muestra mas que nada la diferencia entre DBI y SQLx (Y, en realidad si no sabes SQL saber usar las natives no te sirve de nada)

Last edited by 01101101; 06-15-2010 at 18:02.
01101101 is offline
Frizze!
Senior Member
Join Date: Jun 2010
Location: Interested?
Old 06-15-2010 , 17:56   Re: [ES][TUT] SQLx (Traduccion del tutorial de Hawk552)
#3

Muy bueno, gracias R!
Frizze! is offline
Send a message via MSN to Frizze!
Ayudanding
BANNED
Join Date: Jun 2010
Old 06-15-2010 , 17:57   Re: [ES][TUT] SQLx (Traduccion del tutorial de Hawk552)
#4

Ahi la removi, no quoties todo el post HDP, solo queria darle "style" al post.
Ayudanding is offline
01101101
BANNED
Join Date: Nov 2009
Location: 9`su 09`n0n7e`r0f76a
Old 06-15-2010 , 18:06   Re: [ES][TUT] SQLx (Traduccion del tutorial de Hawk552)
#5

Quote:
Originally Posted by Ayudanding View Post
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_type11)

SQL_GetAffinity(get_type12)

if (!
equali(get_typeset_type))
{
    if (!
SQL_SetAffinity(set_type))
    {
        
log_amx("Failed to set affinity from %s to %s."get_typeset_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
01101101 is offline
Alucard^
AMXX Moderator: Others
Join Date: Sep 2007
Location: Street
Old 06-15-2010 , 19:06   Re: [ES][TUT] SQLx (Traduccion del tutorial de Hawk552)
#6

Usuario baneado, google traductor usado, closed.
__________________
Approved Plugins - Steam Profile

Public non-terminated projects:
All Admins Menu, HLTV parameters, Subnick,
Second Password (cool style), InfoZone,
Binary C4 plant/defuse, and more...

Private projects:
NoSpec (+menu), NV Surf Management,
PM Adanved System, KZ longjump2, and more...
Alucard^ is offline
Send a message via Skype™ to Alucard^
 



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 18:49.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode