AdnanD

easydbmulti

Jul 25th, 2015
214
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 9.53 KB | None | 0 0
  1. #if !defined DB_MULTIGET_MAX_ENTRIES
  2.     #define DB_MULTIGET_MAX_ENTRIES  (16)
  3. #endif
  4.  
  5. #if !defined DB_MULTISET_MAX_ENTRIES
  6.     #define DB_MULTISET_MAX_ENTRIES  (16)
  7. #endif
  8.  
  9. #if !defined DB_MULTISET_MAX_STRING_SIZE
  10.     #define DB_MULTISET_MAX_STRING_SIZE (DB::MAX_ENTRY_STRING)
  11. #endif
  12.  
  13. #if !defined DB_CHECK_STRING_LENGTH
  14.     #define DB_CHECK_STRING_LENGTH  (false)
  15. #endif
  16.  
  17. dbglobal bool:DB::MultiSet(table, key, const szTypeDefinitions[], { _, Float }:...) {
  18.     new
  19.         iEntries = numargs() - 3
  20.     ;
  21.  
  22.     if (iEntries & 0b1) {
  23.         DB::Error("A parameter is missing in DB::MultiSet; expecting a variable/value in the end.", numargs() - 3);
  24.  
  25.         return false;
  26.     }
  27.  
  28.     iEntries /= 2;
  29.  
  30.     if (iEntries > DB::MULTISET_MAX_ENTRIES) {
  31.         DB::Error("Too many entires passed to DB::MultiSet; entires: %d, limit: %d.", iEntries, DB::MULTISET_MAX_ENTRIES);
  32.  
  33.         return false;
  34.     }
  35.  
  36.     new
  37.         iNumTypeDefinitions = strlen(szTypeDefinitions)
  38.     ;
  39.  
  40.     if (iEntries != iNumTypeDefinitions) {
  41.         DB::Error("The number of type definitions doesn't match the number of entries passed to DB::MultiSet; typedefs: %d, entries: %d.", iNumTypeDefinitions, iEntries);
  42.  
  43.         return false;
  44.     }
  45.  
  46.     for (new i = 0; i < iNumTypeDefinitions; i++) {
  47.         switch (szTypeDefinitions[i]) {
  48.             case 'i', 'd', 'f', 's': { }
  49.             default: {
  50.                 DB::Error("Unknown type definition passed to DB::MultiSet; expected: i/s/f, given: %c.", szTypeDefinitions[i]);
  51.  
  52.                 return false;
  53.             }
  54.         }
  55.     }
  56.  
  57.     if (! DB::Get())
  58.     {
  59.         return false;
  60.     }
  61.  
  62.     new
  63.         szColumn[DB::MAX_COLUMN_NAME],
  64.         iColumnArg,
  65.         szValue[DB::MULTISET_MAX_STRING_SIZE * 2]
  66.     ;
  67.  
  68.     format(g_Query, sizeof(g_Query), "UPDATE `%s` SET ", g_TableData[table][DB::TABLE_NAME]);
  69.  
  70.     for (new iEntry = 0; iEntry < iEntries; iEntry++) {
  71.         iColumnArg = 3 + iEntry * 2;
  72.  
  73.         __getstringarg(szColumn, iColumnArg);
  74.  
  75.         ++iColumnArg;
  76.  
  77.         #if (DB::CHECK_STRING_LENGTH)
  78.             if (strlen(szColumn) >= DB::MAX_COLUMN_NAME)
  79.                 return false;
  80.         #endif
  81.  
  82.         strcat(g_Query, "`");
  83.         strcat(g_Query, szColumn);
  84.         strcat(g_Query, "`=");
  85.  
  86.         switch (szTypeDefinitions[iEntry]) {
  87.             case 'i', 'd': {
  88.                 valstr(szValue, getarg(iColumnArg));
  89.             }
  90.  
  91.             case 'f': {
  92.                 format(szValue, sizeof(szValue), "%f", Float:getarg(iColumnArg));
  93.             }
  94.  
  95.             case 's': {
  96.                 __getstringarg(szValue, iColumnArg, DB::MULTISET_MAX_STRING_SIZE);
  97.  
  98.                 szValue[DB::MULTISET_MAX_STRING_SIZE - 1] = EOS;
  99.  
  100.                 DB::Escape(szValue);
  101.  
  102.                 strcat(g_Query, "'");
  103.             }
  104.         }
  105.  
  106.         strcat(g_Query, szValue);
  107.  
  108.         if (szTypeDefinitions[iEntry] == 's')
  109.             strcat(g_Query, "'");
  110.  
  111.         if (iEntry < iEntries - 1)
  112.             strcat(g_Query, ", ");
  113.     }
  114.  
  115.     new endstr[128];
  116.     format(endstr, sizeof(endstr), " WHERE `%s`='%d'", g_TableData[table][DB::TABLE_KEY], key);
  117.     strcat(g_Query, endstr);
  118.  
  119.     new
  120.         DBResult:i_DBResult = db_query(g_Database, g_Query)
  121.     ;
  122.  
  123.     if (i_DBResult)
  124.     {
  125.         db_free_result(i_DBResult);
  126.  
  127.         return true;
  128.     }
  129.     else
  130.     {
  131.         return false;
  132.     }
  133. }
  134.  
  135. dbglobal bool:DB::MultiGet(table, key, const szTypeDefinitions[], { _, Float }:...) {
  136.     new
  137.         iEntries = numargs() - 3
  138.     ;
  139.  
  140.     if (iEntries & 0b1) {
  141.         DB::Error("A parameter is missing in DB::MultiGet; expecting a variable %d in the end.", numargs() - 3);
  142.  
  143.         return false;
  144.     }
  145.  
  146.     iEntries /= 2;
  147.  
  148.     if (iEntries > DB::MULTIGET_MAX_ENTRIES) {
  149.         DB::Error("Too many entires passed to DB::MultiGet; entires: %d, limit: %d.", iEntries, DB::MULTIGET_MAX_ENTRIES);
  150.  
  151.         return false;
  152.     }
  153.  
  154.     new
  155.         iNumTypeDefinitions,
  156.         iTypeDefinitions[DB::MULTIGET_MAX_ENTRIES char],
  157.         iTypeLengths[DB::MULTIGET_MAX_ENTRIES]
  158.     ;
  159.  
  160.     for (new i = 0, l = strlen(szTypeDefinitions); i < l; i++) {
  161.         switch (szTypeDefinitions[i]) {
  162.             case 'i', 'd', 'f': {
  163.                 iTypeDefinitions{ iNumTypeDefinitions++ } = szTypeDefinitions[i];
  164.             }
  165.  
  166.             case 's': {
  167.                 if (szTypeDefinitions[i + 1] == '[' && szTypeDefinitions[i + 2]) {
  168.                     ++i;
  169.  
  170.                     new
  171.                         szLength[11],
  172.                         iEndingBracket = strfind(szTypeDefinitions, "]", .pos = i + 2)
  173.                     ;
  174.  
  175.                     if (iEndingBracket != -1) {
  176.                         strmid(szLength, szTypeDefinitions, i + 1, iEndingBracket);
  177.  
  178.                         iTypeLengths[iNumTypeDefinitions] = strval(szLength);
  179.  
  180.                         if (iTypeLengths[iNumTypeDefinitions] <= 0) {
  181.                             DB::Error("Invalid string length given in the type definitions for DB::MultiGet: %d.", iTypeLengths[iNumTypeDefinitions]);
  182.  
  183.                             return false;
  184.                         }
  185.  
  186.                         iTypeDefinitions{ iNumTypeDefinitions++ } = 's';
  187.  
  188.                         i = iEndingBracket;
  189.  
  190.                         continue;
  191.                     }
  192.                 }
  193.  
  194.                 DB::Error("String size has to be passed in the type definitions for DB::MultiGet; example: \"iffs[32]ii\".", iNumTypeDefinitions, iEntries);
  195.  
  196.                 return false;
  197.             }
  198.  
  199.             default: {
  200.                 DB::Error("Unknown type definition passed to DB::MultiGet; expected: i/s/f, given: %c.", szTypeDefinitions[i]);
  201.  
  202.                 return false;
  203.             }
  204.         }
  205.     }
  206.  
  207.     if (iEntries != iNumTypeDefinitions) {
  208.         DB::Error("The number of type definitions doesn't match the number of entries passed to DB::MultiGet; typedefs: %d, entries: %d.", iNumTypeDefinitions, iEntries);
  209.  
  210.         return false;
  211.     }
  212.  
  213.     if (!DB::Get())
  214.         return false;
  215.  
  216.     new
  217.         szColumn[DB::MAX_COLUMN_NAME],
  218.         iColumnArg,
  219.         g_szzBiffer[DB::BUFFER_SIZE],
  220.         tempquer[128]
  221.     ;
  222.  
  223.     g_szzBiffer = "SELECT `";
  224.  
  225.     for (new iEntry = 0; iEntry < iEntries; iEntry++) {
  226.         iColumnArg = 3 + iEntry * 2;
  227.  
  228.         __getstringarg(szColumn, iColumnArg);
  229.  
  230.         #if (DB::CHECK_STRING_LENGTH)
  231.             if (strlen(szColumn) >= DB::MAX_COLUMN_NAME)
  232.                 return false;
  233.         #endif
  234.  
  235.         strcat(g_szzBiffer, szColumn);
  236.  
  237.         if (iEntry < iEntries - 1)
  238.             strcat(g_szzBiffer, "`,`");
  239.     }
  240.  
  241.     format(tempquer, sizeof(tempquer), "` FROM `%s` WHERE `%s`='%d'", g_TableData[table][DB::TABLE_NAME], g_TableData[table][DB::TABLE_KEY], key);
  242.  
  243.     strcat(g_szzBiffer, tempquer);
  244.  
  245.     new
  246.         DBResult:dbrResult
  247.     ;
  248.  
  249.     dbrResult = db_query(g_Database, g_szzBiffer);
  250.  
  251.     if (dbrResult) {
  252.         new
  253.             iRows = db_num_rows(dbrResult)
  254.         ;
  255.  
  256.         if (iRows == 1) {
  257.             new
  258.                 iFields = db_num_fields(dbrResult)
  259.             ;
  260.  
  261.             if (iEntries != iFields)
  262.                 DB::Warning("The number of entries requested doesn't match the given number; requested: %d, given: %d", iEntries, iFields);
  263.  
  264.             for (new iField = 0; iField < iFields; iField++) {
  265.                 if (iTypeDefinitions{ iField } == 's')
  266.                     db_get_field(dbrResult, iField, g_szzBiffer, iTypeLengths[iField] - 1);
  267.                 else
  268.                     db_get_field(dbrResult, iField, g_szzBiffer, sizeof(g_szzBiffer) - 1);
  269.  
  270.                 switch (iTypeDefinitions{ iField }) {
  271.                     case 'i', 'd': {
  272.                         setarg(3 + iField * 2 + 1, .value = strval(g_szzBiffer));
  273.                     }
  274.  
  275.                     case 'f': {
  276.                         setarg(3 + iField * 2 + 1, .value = _:floatstr(g_szzBiffer));
  277.                     }
  278.  
  279.                     case 's': {
  280.                         __setstringarg(3 + iField * 2 + 1, g_szzBiffer);
  281.                     }
  282.                 }
  283.             }
  284.         } else if (iRows > 1) {
  285.             DB::Error("Multiple rows fetched from one Key; Key: %d, rows: %d", key, iRows);
  286.  
  287.             db_free_result(dbrResult);
  288.  
  289.             return false;
  290.         }
  291.  
  292.         db_free_result(dbrResult);
  293.  
  294.         return true;
  295.     }
  296.  
  297.     return false;
  298. }
  299.  
  300.  
  301. dbstatic __getstringarg(dest[], arg, len = sizeof (dest))
  302. {
  303.     // Get the address of the previous function's stack.  First get the index of
  304.     // the argument required.
  305.     #emit LOAD.S.pri arg
  306.     // Then convert that number to bytes from cells.
  307.     #emit SMUL.C     4
  308.     // Get the previous function's frame.  Stored in variable 0 (in the current
  309.     // frame).  Parameters are FRM+n+12, locals are FRM-n, previous frame is
  310.     // FRM+0, return address is FRM+4, parameter count is FRM+8.  We could add
  311.     // checks that "arg * 4 < *(*(FRM + 0) + 8)", for the previous frame parameter
  312.     // count (in C pointer speak).
  313.     #emit LOAD.S.alt 0
  314.     // Add the frame pointer to the argument offset in bytes.
  315.     #emit ADD
  316.     // Add 12 to skip over the function header.
  317.     #emit ADD.C      12
  318.     // Load the address stored in the specified address.
  319.     #emit LOAD.I
  320.     // Push the length for "strcat".
  321.     #emit PUSH.S     len
  322.     // Push the address we just determined was the source.
  323.     #emit PUSH.pri
  324.     // Load the address of the destination.
  325.     #emit LOAD.S.alt dest
  326.     // Blank the first cell so "strcat" behaves like "strcpy".
  327.     #emit CONST.pri  0
  328.     // Store the loaded number 0 to the loaded address.
  329.     #emit STOR.I
  330.     // Push the loaded address.
  331.     #emit PUSH.alt
  332.     // Push the number of parameters passed (in bytes) to the function.
  333.     #emit PUSH.C     12
  334.     // Call the function.
  335.     #emit SYSREQ.C   strcat
  336.     // Restore the stack to its level before we called this native.
  337.     #emit STACK      16
  338. }
  339.  
  340. stock __setstringarg(iArg, const szValue[], iLength = sizeof(szValue)) {
  341.     new
  342.         iAddress
  343.     ;
  344.  
  345.     // Get the address of the previous function's stack.  First get the index of
  346.     // the argument required.
  347.     #emit LOAD.S.pri iArg
  348.     // Then convert that number to bytes from cells.
  349.     #emit SMUL.C     4
  350.     // Get the previous function's frame.
  351.     #emit LOAD.S.alt 0
  352.     // Add the frame pointer to the argument offset in bytes.
  353.     #emit ADD
  354.     // Add 12 to skip over the function header.
  355.     #emit ADD.C      12
  356.     // Load the address stored in the specified address.
  357.     #emit LOAD.I
  358.     #emit STOR.S.PRI iAddress
  359.  
  360.     // Push the length (last argument first)
  361.     #emit PUSH.S     iLength
  362.  
  363.     // Push the new value (source) szValue
  364.     #emit PUSH.S     szValue
  365.  
  366.     // Blank out the first cell of the argument
  367.     #emit CONST.pri  0
  368.     #emit SREF.S.pri iAddress
  369.  
  370.     // Push the destination
  371.     #emit PUSH.S     iAddress
  372.  
  373.     // Push the number of parameters passed (in bytes) to the function.
  374.     #emit PUSH.C     12
  375.  
  376.     // Call the function.
  377.     #emit SYSREQ.C   strcat
  378.  
  379.     // Restore the stack to its level before we called this native.
  380.     #emit STACK      16
  381. }
Advertisement
Add Comment
Please, Sign In to add comment