Raised This Month: $51 Target: $400
 12% 

Database ORM (MySQL Data Wrapper) v1.1


Post New Thread Reply   
 
Thread Tools Display Modes
Plugin Info:     Modification:   ALL        Category:   Technical/Development       
Backstabnoob
Veteran Member
Join Date: Feb 2009
Location: Iwotadai Dorm
Old 06-25-2014 , 12:52   Database ORM (MySQL Data Wrapper) v1.1
Reply With Quote #1

Database ORM v1.1
Version 1.1 released on 23rd of July, 2014



Table of Contents

Description top
Database ORM is a complex API designed to give 3rd party plugins easy access to the database, while making sure nothing goes wrong by using wrong and exhausting queries. This is typically good for servers with very high load on the MySQL database and for people who don't know much about MySQL. The intelligent query divider system inserts/updates as many rows as possible while minimizing the amount of queries.

The usage, however, can be challenging in some cases and requires intermediate knowledge in Pawn. Please refer to the examples in the topic to make sure you really know what you're doing, as while being very powerful, this can also be a devastating tool if used incorrectly.

WARNING: Please note that this is a beta release and it probably contains some bugs. I tested it as much as I could by myself, but that's a little hard without real-time simulation. With this, I'd also like to ask you guys if you could try testing this as much as you can and give me any feedback.

Possibilities top
This system can be useful in a lot of ways, but there are some things it really isn't designed to be used for.

This should be used for:
  • Inventories
  • Player XP
  • Player stats
  • Banks
  • Server variables (zones, global bank account,...)
  • Etc.

This shouldn't be used for:
  • Things that can be replaced by a simple config or cvars
  • Other things I can't think of right now
Simply put: Use common sense please. Don't use this for things that would be overkill.

Requirements top
There are only two requirements in particular:
  • Latest 1.8.3 snapshot from here: http://www.amxmodx.org/snapshots.php. I used git3921.
    This might not be needed, but is HIGHLY recommended, especially for Linux as 1.8.2 was giving me segmentation faults. It seems that cellvectors had problems in 1.8.2 which they don't in 1.8.3 PLEASE USE THIS VERSION.
  • MySQL server reachable with AMXX.
  • STEAM! This only works with STEAM_0:0:XXX and STEAM_0:1:XXX Steam IDs.

Installation, configuration top
To install:
Simply download the .sma file, compile it and put it into your plugins folder on the server. Add database_orm.amxx at the end of plugins.ini. Then download the orm_config.ini file and put into the configs folder.

To configure:
Open orm_config.ini. You will see the following values:
  • orm_hostname - the hostname to connect to. This is usually 'localhost' or '127.0.0.1'.
  • orm_username - the username for the MySQL server. This is usually 'root'.
  • orm_password - the password for the MySQL server. This is usually blank for local servers.
  • orm_database - the database of the MySQL server. There is no default one, you need to create it unless you already have it.
  • orm_saveperiod - this is how often you want to save the data in seconds. Notice: Data is also being saved automatically on player's disconnect and on plugin change. This is a very intensive process with lots of plugins using the core, so I highly recommend setting this to 0.0 to completely disable it if your server has short map times (20-30 minutes). This feature should be used only on servers which are either highly unstable or are running the same map without mapchange 24/7. In that case, I recommend setting this to 20 minutes (1200.0 seconds).
  • orm_preparedquery - this is a complex variable which decides what "tasks" or "events" should be saved with prepared queries rather than threaded queries. The difference between those two is that threaded queries take much longer to process, but don't lag the server at all, while prepared queries will be quickly done but they always wait for response, so there is a noticeable lag (with huge amount of data this can be in seconds). This setting only works for saving, not for loading. It's a flag value and the possible flags are:
    • a - Single player save (such as on their disconnect)
    • b - All players save (happens only during the save cycle, if it's 0 this is never called)
    • c - On static save (static classes have nothing to do with players and they reside in the memory since the server load, more on that later in the API section), this is called only during the save cycle, same as 'b'
    • d - On item delete - whenever an item is deleted with the CSRP_Delete{Player/Static}ClassItem( ) native
    • e - On plugin end - when the map is changing (saves all players and all static classes), recommended, although the difference is noticeable only on high load because plugin_end dispatches all threaded queries instantly as far as I know
    • f - On class nuke - When a class is nuked with the CSRP_Nuke{Player/Static}Class( ) native
  • orm_showsavemsg - shows a progress via print_center during saving cycles. The value doesn't matter if orm_saveperiod is 0, as the save never happens, only on the plugin end where this is unnecessary.

API (Natives and forwards) top
I'll put the .inc file here, the natives and forwards should be explained in it. It won't tell you anything when it comes to writing down the actual plugins, you should look at the examples for that kind of stuff.

There's one BIG thing to know before making a plugin, though, and that is the difference between Player and Static classes.

What are the player classes?
Player classes hold data for players.They are "three-dimensional" classes, with the first dimension being the player index, second dimension being the item itself and third dimension being the item values. The data is being automatically loaded on player connect and unloaded on player disconnect.

The structure for a class with the columns item_index(VARCHAR 32) and item_amount(INT 11) looks something like this:
Spoiler
What are static classes?
Static classes hold the data for the server itself and are loaded into the memory at the plugin start and unloaded on mapchange/exit/restart (plugin end). They are "two-dimensional" classes with the first dimension being the item itself and the second dimension being the item values.

The structure for a class with the columns property_owner(INT 11) and property_name(VARCHAR 32) looks something like this:
Spoiler
It is very simple once you get it down. Please ask if you're unsure about something.

The .INC file itself:
PHP Code:
// I don't really know what this does.
#pragma library "database_orm"

/**************************************************
 ************ API ENUMS AND STRUCTURES ************
 *************************************************/

enum ClassColumnType
{
    
Column_Varchar,
    
Column_Int
};

// Usage: new Array:Columns = ArrayCreate(ClassColumnStruct, Number_Of_Columns)
enum _ClassColumnStruct
{
    
_ColumnName[16],            // name of the column
    
ClassColumnType_Column,    // either Column_Varchar or Column_Int
    
_MaxLen                        // maxlen of the field. Use 11 for ints.
};

enum Class
{
    
Invalid_Class 0
};

/****************************************
 ************ PLAYER CLASSES ************
 ***************************************/

/* CSRP_CreatePlayerClass(): Creates a Player class.

 * @param (String) ClassName: name of the class (= table name in the database), must be unique
 * @param (Array) Columns: must contain the columns of the database. The array cannot ever be deleted! See examples.
 * @param (Int) CompositeKey: if -1, the player index will be unique (meaning only one row per player in the table),
        otherwise it's a combination of two columns (such as player index and item index).
 * @param (String) ClassCallback: function to call on class initialization.
 
 * @return: (Class) handle of the class.
*/
native Class:CSRP_CreatePlayerClass(const ClassName[], Array:ColumnsCompositeKey = -1, const ClassCallback[]);

/* CSRP_GetPlayerClassData(): Retrieves all of the data for player object in the class.
 
 * @param (Class) hClass: The class handler
 * @param (Int) Player: index of the player
 
 * @return: (Array) Dynamic array with all of the data ready to be looped. Use ArraySize(Array) for the amount of items.
*/
native Array:CSRP_GetPlayerClassData(Class:hClassPlayer);

/* CSRP_FindInPlayerClassString(): Finds an entry in the class for player by a string of the composite key. Composite key required.

 * @param (Class) hClass: The class handler
 * @param (Int) Player: index of the player
 * @param (String) Find: the string to look for
 * @param-byref (Int) ItemIndex: Optionally returns the index of the element in the array
 
 * @return: (Array) item handler if found, Invalid_Array if nothing exists or an error occured
*/
native Array:CSRP_FindInPlayerClassString(Class:hClassPlayerFind[], &ItemIndex=-1);

/* CSRP_FindInPlayerClassCell(): Finds an entry in the class for player by a cell of the composite key. Composite key required.

 * @param (Class) hClass: The class handler
 * @param (Int) Player: index of the player
 * @param (Any) Find: the cell to look for
 * @param-byref (Int) ItemIndex: Optionally returns the index of the element in the array
 
 * @return: (Array) item handler if found, Invalid_Array if nothing exists or an error occured
*/
native Array:CSRP_FindInPlayerClassCell(Class:hClassPlayerany:Find, &ItemIndex=-1);

/* CSRP_FindInPlayerClassUnique(): Finds an entry in the class for a player. The class must not have a composite key.

 * @param (Class) hClass: The class handler
 * @param (Int) Player: index of the player
 
 * @return: (Array) item handler if found, Invalid_Array if nothing exists or an error occured
*/
native Array:CSRP_FindInPlayerClassUnique(Class:hClassPlayer);

/* CSRP_PushPlayerClassItem(): Pushes an item to the class for player. The array must have the exact same amount of elements
    as there are columns in the class.

 * @param (Class) hClass: The class handler
 * @param (Int) Player: index of the player
 * @param (Array) Item: handler of the array with the item. Must not be destroyed!
 
 * @return: (Int) index of the item usable within CSRP_{Get/Delete}PlayerClassItem
*/
native CSRP_PushPlayerClassItem(Class:hClassPlayer, Array:Item);

/* CSRP_GetPlayerClassItem(): Retrieves an item handle for player by its index.

 * @param (Class) hClass: The class handler
 * @param (Int) Player: index of the player
 * @param (Int) ItemIndex: The array index to find.
 
 * @return: (Array) item handler if found, Invalid_Array if nothing exists or an error occured
*/
native Array:CSRP_GetPlayerClassItem(Class:hClassPlayerItemIndex);

/* CSRP_DeletePlayerClassItem(): Deletes an item from the player object in the player class by index.

 * @param (Class) hClass: The class handler
 * @param (Int) Player: index of the player
 * @param (Int) ItemIndex: the item to delete
 
 * @return: (Int) 1 on success, 0 on failure
*/
native CSRP_DeletePlayerClassItem(Class:hClassPlayerItemIndex);

/* CSRP_SavePlayerClass(): Saves the class, either for one player or for all players.
    This should be used in the CSRP_OnSave() forward.

 * @param (Class) hClass: The class handler
 * @param (Int) Player: index of the player. If 0, all players are saved.

 * @return: (Int) 1 on success, 0 on failure
*/
native CSRP_SavePlayerClass(Class:hClassPlayer 0);

/* CSRP_ClearPlayerClass(): Clears the content of a player's object in the player class.

 * @param (Class) hClass: The class handler
 * @param (Int) Player: index of the player
 
 * @return: (Int) 1 on success, 0 on failure
*/
native CSRP_ClearPlayerClass(Class:hClassPlayer);

/* CSRP_DestroyPlayerClass(): Completely empties the class and destroys its handle, rendering it unusable until mapchange.

 * @param-byref (Class) hClass: The class handler. Changed to Invalid_Class after usage.
 
 * @return: (Int) 1 on success, 0 on failure
*/
native CSRP_DestroyPlayerClass(&Class:hClass);

/* CSRP_NukePlayerClass(): The same as CSRP_DestroyPlayerClass, except this also removes the table from the database.
    The plugin needs to be paused/disabled after using this native, or the class will be re-created on next mapchange.
    
 * @param-byref (Class) hClass: The class handler. Changed to Invalid_Class after usage.
 
 * @return: (Int) 1 on success, 0 on failure
*/
native CSRP_NukePlayerClass(&Class:hClass);


/****************************************
 ************ STATIC CLASSES ************
 ***************************************/

 /* CSRP_CreateStaticClass(): Creates a Static class.

 * @param (String) ClassName: name of the class (= table name in the database), must be unique
 * @param (Array) aColumns: must contain the columns of the database. The array cannot ever be deleted! See examples.
 * @param (Int) UniqueKey: Similar to player classes, except static classes don't support composite keys. 
    Only one column can be unique and it is required.
 * @param (String) ClassCallback: function to call on class initialization.
 
 * @return: (Class) handle of the class.
*/
native Class:CSRP_CreateStaticClass(const ClassName[], Array:aColumnsUniqueKey, const ClassCallback[]);

/* CSRP_GetStaticClassData(): Retrieves all of the data in the class.
 
 * @param (Class) hClass: The class handler
 
 * @return: (Array) Dynamic array with all of the data ready to be looped. Use ArraySize(Array) for the amount of items.
*/
native Array:CSRP_GetStaticClassData(Class:hClass);

/* CSRP_FindInStaticClassString(): Finds an entry in the class by a string of the unique key.

 * @param (Class) hClass: The class handler
 * @param (String) Find: the string to look for
 * @param-byref (Int) ItemIndex: Optionally returns the index of the element in the array
 
 * @return: (Array) item handler if found, Invalid_Array if nothing exists or an error occured
*/
native Array:CSRP_FindInStaticClassString(Class:hClassFind[], &ItemIndex=-1);

/* CSRP_FindInStaticClassCell(): Finds an entry in the class by a cell of the unique key.

 * @param (Class) hClass: The class handler
 * @param (Any) Find: the cell to look for
 * @param-byref (Int) ItemIndex: Optionally returns the index of the element in the array
 
 * @return: (Array) item handler if found, Invalid_Array if nothing exists or an error occured
*/
native Array:CSRP_FindInStaticClassCell(Class:hClassany:Find, &ItemIndex=-1);

/* CSRP_PushStaticClassItem(): Pushes an item to the class. The array must have the exact same amount of elements
    as there are columns in the class.

 * @param (Class) hClass: The class handler
 * @param (Array) Item: handler of the array with the item. Must not be destroyed!
 
 * @return: (Int) index of the item usable within CSRP_{Get/Delete}StaticClassItem
*/
native CSRP_PushStaticClassItem(Class:hClass, Array:Item);

/* CSRP_GetStaticClassItem(): Retrieves an item handle by its index.

 * @param (Class) hClass: The class handler
 * @param (Int) ItemIndex: The array index to find.
 
 * @return: (Array) item handler if found, Invalid_Array if nothing exists or an error occured
*/
native Array:CSRP_GetStaticClassItem(Class:hClassItemIndex);

/* CSRP_DeleteStaticClassItem(): Deletes an item from the class by index.

 * @param (Class) hClass: The class handler
 * @param (Int) ItemIndex: the item to delete
 
 * @return: (Int) 1 on success, 0 on failure
*/
native CSRP_DeleteStaticClassItem(Class:hClassItemIndex);

/* CSRP_SaveStaticClass(): Saves the class.
    This should be used in the CSRP_OnSave() forward.

 * @param (Class) hClass: The class handler

 * @return: (Int) 1 on success, 0 on failure
*/
native CSRP_SaveStaticClass(Class:hClass);

/* CSRP_ClearStaticClass(): Clears the content of the class.

 * @param (Class) hClass: The class handler
 
 * @return: (Int) 1 on success, 0 on failure
*/
native CSRP_ClearStaticClass(Class:hClass);

/* CSRP_DestroyPlayerClass(): Completely empties the class and destroys its handle, rendering it unusable until mapchange.

 * @param-byref (Class) hClass: The class handler. Changed to Invalid_Class after usage.
 
 * @return: (Int) 1 on success, 0 on failure
*/
native CSRP_DestroyStaticClass(&Class:hClass);

/* CSRP_NukeStaticClass(): The same as CSRP_DestroyStaticClass, except this also removes the table from the database.
    The plugin needs to be paused/disabled after using this native, or the class will be re-created on next mapchange.
    
 * @param-byref (Class) hClass: The class handler. Changed to Invalid_Class after usage.
 
 * @return: (Int) 1 on success, 0 on failure
*/
native CSRP_NukeStaticClass(&Class:hClass);


/*****************************************
 ************ MISC, UTILITIES ************
 ****************************************/

/* CSRP_ShareSQLHandle(): Retrieves the SQLx tuple handler of the core plugin. This should be used only in extreme situations
    where you need to use complex queries to achieve your goal. This is identical to SQL_MakeDbTuple(), except ours uses the same
    handle as the core.

 * @return: (Handle) SQLx MySQL tuple handler.
*/
native HandleCSRP_ShareSQLHandle();

/**********************************
 ************ FORWARDS ************
 *********************************/

/* CSRP_OnSave(): Called whenever a save cycle is started. The period is defined in the orm_config.ini file. 
    Use CSRP_Save{Player/Static}Class() natives here, so everything is saved at once.
*/
forward CSRP_OnSave();

/* CSRP_OnPlayerLoad(): Called when a player is completely loaded. Make sure the player whenever
    you use any of the player class natives!
 
 @param (Int) Player: index of the loaded player.
*/
forward CSRP_OnPlayerLoad(Player);

/* CSRP_OnServerLoad(): Called when all static and player classes are initialized and they're ready to work with.
*/
forward CSRP_OnServerLoad(); 
Credits top
  • Hawk552 - Original idea, help with a lot of stuff, the comment block layout, encouragement.
  • Black Rose - Discussion, ideas, overall help when necessary, encouragement.
  • Kia - for taking the time to actually test this in the real world.
Attached Files
File Type: ini orm_config.ini (350 Bytes, 403 views)
File Type: sma Get Plugin or Get Source (database_orm.sma - 1135 views - 69.7 KB)
File Type: inc database_orm.inc (11.4 KB, 384 views)
__________________
Currently busy working on a very large scale anime database project.

Last edited by Backstabnoob; 07-23-2014 at 07:36.
Backstabnoob is offline
Backstabnoob
Veteran Member
Join Date: Feb 2009
Location: Iwotadai Dorm
Old 06-25-2014 , 12:52   Re: Database ORM (MySQL Data Wrapper) v1.0b
Reply With Quote #2

Changelog top
  • v1.1
    • Changed my coding style
    • Fixed a variety of bugs and overally improved the code
    • CSRP_FindXXX natives now also pass the array index by reference
    • Release date: 23 Jul, 2014 (23 downloads reset)
  • v1.0.1b
    • Changed client_connect to client_putinserver for now
    • Fixed a bug where UTIL_FindInX would cause errors in some cases
    • Release date: 27 Jun, 2014 (25 downloads reset)
  • v1.0b
    • Initial release
    • Release date: 25 Jun, 2014
__________________
Currently busy working on a very large scale anime database project.

Last edited by Backstabnoob; 07-22-2014 at 21:37.
Backstabnoob is offline
Backstabnoob
Veteran Member
Join Date: Feb 2009
Location: Iwotadai Dorm
Old 06-25-2014 , 12:52   Re: Database ORM (MySQL Data Wrapper) v1.0b
Reply With Quote #3

Questions and Answers top

Question: I am a simple server admin. How will this plugin benefit me?
Answer: Alone, this plugin doesn't do anything. This is a tool that other plugins should use, so the answer is: By itself, it won't benefit you at all.

Question: Does this improve performance of plugins using this?
Answer: Yes and no. If you compare two plugins side by side, where one uses this and the other one isn't, if they're both well written then the performance boost won't be noticable unless you move a lot of data. This API is meant to give authors easier control over MySQL while they can remain sure that the MySQL performance is optimized.

Question: I know MySQL very well. Should I still consider using this?
Answer: Absolutely. Combined with other plugins, the performance should be better, since both have centralized saving system that is optimized for handling more data.

Question: What is up with the CSRP_ prefix of the natives and forwards?
Answer: This plugin is made as a base for my upcoming Roleplaying mod. I want to keep the native names the same, so it's easier to port existing plugins in the future.

Question: Why are classes divided into Player and Static classes? Can't they be generalized into one type?
Answer: They sure can be, but let's get real - this is Counter-Strike and AMXX. It is way easier for me to do it this way and it probably performs slightly better than if it was the other way. 95% people will only use the Player classes, so there's really no reason to generalize something people will only use one part of.

Question: Due to your decision, the code for Static and Player classes is nearly the same. Why copy paste everything?
Answer: Because it doesn't matter. It's my decision, and while not being the best thing to maintain (yet it's still easy), I prefer being free to change whatever I want for a specific type rather than having to find workarounds and create wrappers all the time. The code is not THAT similar either, because the data structure for each is different.
__________________
Currently busy working on a very large scale anime database project.

Last edited by Backstabnoob; 06-25-2014 at 15:54.
Backstabnoob is offline
Backstabnoob
Veteran Member
Join Date: Feb 2009
Location: Iwotadai Dorm
Old 06-25-2014 , 12:53   Re: Database ORM (MySQL Data Wrapper) v1.0b
Reply With Quote #4

Examples top
Example #1: Simple bank system (Tested, works)
PHP Code:
#include < amxmodx >
#include < database_orm >
#include < cstrike >

// our class handler
new Class: g_hBank

// we cache whether or not are players ready
new boolg_bReady33 ]

// our database columns, we use an enum for easier indexing
enum _DatabaseColumns
{
    
Bank_Money,            // this holds the total amount of money
    
Bank_CreationDate    // timestamp of when the bank account was opened
}

// this is the column info, which we'll turn into a dynamic array
new g_DatabaseColumnsDatabaseColumns ][ ClassColumnStruct ] = 
{
    { 
"bank_money"Column_Int11 },
    { 
"bank_created"Column_Int11 }
}

public 
plugin_init( )
{
    
// turn the g_DatabaseColumns array into a dynamic array
    
    // the first param for ArrayCreate is always ClassColumnStruct, the second is the number of columns
    
new Array: aColumns ArrayCreateClassColumnStructDatabaseColumns )
    for( new 
iDatabaseColumns++ )
    {
        
ArrayPushArrayaColumnsg_DatabaseColumns] )
    }
    
    
// register the class
    // -1 because we don't need a composite key, we only want one row per player
    
g_hBank CSRP_CreatePlayerClass"orm_examplebank"aColumns, -1"_Callback" )
    
    
// three commands to withdraw/deposit cash and to tell us the info about our account
    
register_clcmd"withdraw""_cWithdraw" )
    
register_clcmd"deposit""_cDeposit" )
    
register_clcmd"accountinfo""_cAccountInfo" )
    
}

public 
_cWithdrawid )
{
    
    
// halt if the player hasn't loaded yet
    
if( !g_bReadyid ] )
    {
        
client_printidprint_console"Please wait for load." )
        return 
PLUGIN_HANDLED
    
}
    
    new 
szArgs11 ]
    
read_argsszArgscharsmaxszArgs ) )
    
    
remove_quotesszArgs )
    
trimszArgs )
    
    new 
iArgs str_to_numszArgs )
    
    
// get the player's account
    
new Array: aBankAccount CSRP_FindInPlayerClassUniqueg_hBankid )
    
    
// get the actual bank money; Bank_Money is 0 in our enum which is the first column
    
new iBankMoney ArrayGetCellaBankAccountBank_Money )
    
    if( 
iArgs iBankMoney )
    {
        
client_printidprint_console"You don't have that much money in your account!" )
        return 
PLUGIN_HANDLED
    
}
    
    
// the player has the money, so withdraw them
    
cs_set_user_moneyidcs_get_user_moneyid ) + iArgs )
    
    
// update the money in the bank account
    
ArraySetCellaBankAccountBank_MoneyiBankMoney iArgs )
    
    
client_printidprint_console"You have withdrawn $%d. You now have $%d in your account."iArgsiBankMoney iArgs )
    return 
PLUGIN_HANDLED
}

public 
_cDepositid )
{
    
// halt if the player hasn't loaded yet
    
if( !g_bReadyid ] )
    {
        
client_printidprint_console"Please wait for load." )
        return 
PLUGIN_HANDLED
    
}

    new 
szArgs11 ]
    
read_argsszArgscharsmaxszArgs ) )
    
    
remove_quotesszArgs )
    
trimszArgs )
    
    new 
iArgs str_to_numszArgs )
    new 
iMoney cs_get_user_moneyid )
    
    if( 
iMoney iArgs )
    {
        
client_printidprint_console"You don't have that much money!" )
        return 
PLUGIN_HANDLED
    
}
    
    
// get the player's account
    
new Array: aBankAccount CSRP_FindInPlayerClassUniqueg_hBankid )
    
    
// get the actual bank money; Bank_Money is 0 in our enum which is the first column
    
new iBankMoney ArrayGetCellaBankAccountBank_Money )
    
    
// increase the money
    
ArraySetCellaBankAccountBank_MoneyiBankMoney iArgs )
    
cs_set_user_moneyidiMoney iArgs )
    
    
client_printidprint_console"You have deposited $%d. You now have $%d in your bank account."iArgsiBankMoney iArgs )
    return 
PLUGIN_HANDLED
}

public 
_cAccountInfoid )
{
    
// halt if the player hasn't loaded yet
    
if( !g_bReadyid ] )
    {
        
client_printidprint_console"Please wait for load." )
        return 
PLUGIN_HANDLED
    
}
    
    new Array: 
aBankAccount CSRP_FindInPlayerClassUniqueg_hBankid )
    
    
// for the sake of tutorial, we just show the timestamp instead of actual date, sorry
    
client_printidprint_console"Your account was created on %d.^nYou have $%d in your account."
        
ArrayGetCellaBankAccountBank_CreationDate ),
        
ArrayGetCellaBankAccountBank_Money )
    )
    
    return 
PLUGIN_HANDLED
}

// player has loaded
public CSRP_OnPlayerLoadid )
{
    
g_bReadyid ] = true
    
    
// we check if they already have a bank account, otherwise we create one
    
new Array: aBankAccount CSRP_FindInPlayerClassUniqueg_hBankid )
    
    
// no bank account found, let's create it
    
if( aBankAccount == Invalid_Array )
    {
        
// since we only use integer columns, 1 as the cell size is enough
        // if we used at least one string, the value should be the highest
        // maxlen of all of the columns.
        
aBankAccount ArrayCreate1DatabaseColumns )
        
        
// we insert the data of the first column, which is the bank money and that is 0.
        
ArrayPushCellaBankAccount)
        
        
// the second column is the timestamp
        
ArrayPushCellaBankAccountget_systime( ) )
        
        
// finally, let's push the item to the class
        
CSRP_PushPlayerClassItemg_hBankidaBankAccount )
    }
}

public 
client_disconnectid )
{
    
g_bReadyid ] = false
}

// the save cycle has been called, let's save our class
public CSRP_OnSave( )
{
    
// we make sure the class is initialized properly
    
if( g_hBank != Invalid_Class )
    {
        
CSRP_SavePlayerClassg_hBank )
    }
}

public 
_Callback( )
{
    
// we don't need anything to happen

Output:
Spoiler

__________________
Currently busy working on a very large scale anime database project.

Last edited by Backstabnoob; 06-26-2014 at 20:28.
Backstabnoob is offline
Backstabnoob
Veteran Member
Join Date: Feb 2009
Location: Iwotadai Dorm
Old 06-25-2014 , 12:53   Re: Database ORM (MySQL Data Wrapper) v1.0b
Reply With Quote #5


Plugins using this top
There are no plugins using this system yet. Be the first one ;)



Support me top
If you think that my work is worth something, I certainly wouldn't mind any kind of a donation


Or, add me on Steam and give me some trading cards or a TF2 key
__________________
Currently busy working on a very large scale anime database project.

Last edited by Backstabnoob; 06-26-2014 at 05:46.
Backstabnoob is offline
Kia
AlliedModders Donor
Join Date: Apr 2010
Location: In a world of madness
Old 06-25-2014 , 13:18   Re: Database ORM (MySQL Data Wrapper) v1.0b
Reply With Quote #6



Great job, will post a example Plugin soon including effiency comparision.
__________________

Last edited by Kia; 06-25-2014 at 13:59.
Kia is offline
Backstabnoob
Veteran Member
Join Date: Feb 2009
Location: Iwotadai Dorm
Old 06-25-2014 , 14:02   Re: Database ORM (MySQL Data Wrapper) v1.0b
Reply With Quote #7

There's probably not going to be a huge efficiency improvement over normal queries if they're done correctly. This is designed for high data usage, where correct query system is the performance key. If anything, the performance between two plugins should be the same if they're both coded correctly.

I'll add the examples and stuff later today/early tomorrow.
__________________
Currently busy working on a very large scale anime database project.
Backstabnoob is offline
Jhob94
AMX Mod X Donor
Join Date: Jul 2012
Old 06-25-2014 , 14:33   Re: Database ORM (MySQL Data Wrapper) v1.0b
Reply With Quote #8

I am not a plugin approver, but i approve this one. Move the section of this

Well, really good job. Unfortunetly i haven't time, but when i have, i will make sure of use this
__________________

Last edited by Jhob94; 06-25-2014 at 14:33.
Jhob94 is offline
Kia
AlliedModders Donor
Join Date: Apr 2010
Location: In a world of madness
Old 06-25-2014 , 15:44   Re: Database ORM (MySQL Data Wrapper) v1.0b
Reply With Quote #9

Can we just insta-approve this one?
__________________
Kia is offline
Backstabnoob
Veteran Member
Join Date: Feb 2009
Location: Iwotadai Dorm
Old 06-25-2014 , 15:49   Re: Database ORM (MySQL Data Wrapper) v1.0b
Reply With Quote #10

Haha, I'd first like to make sure this works as intended when used on an actual server with a lot of players ^^

Thanks for the feedback.
__________________
Currently busy working on a very large scale anime database project.
Backstabnoob is offline
Old 06-25-2014, 16:00
jonnzus
This message has been deleted by jonnzus. Reason: asd
Reply



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 00:07.


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