| rev | 
   line source | 
| 
jbe/bsw@0
 | 
     1 #include <lua.h>
 | 
| 
jbe/bsw@0
 | 
     2 #include <lauxlib.h>
 | 
| 
jbe/bsw@0
 | 
     3 #include <libpq-fe.h>
 | 
| 
jbe/bsw@0
 | 
     4 #include <postgres.h>
 | 
| 
jbe/bsw@0
 | 
     5 #include <catalog/pg_type.h>
 | 
| 
jbe/bsw@0
 | 
     6 #include <stdint.h>
 | 
| 
jbe/bsw@0
 | 
     7 
 | 
| 
jbe/bsw@0
 | 
     8 #define MONDELEFANT_REGKEY "e449ba8d9a53d353_mondelefant"
 | 
| 
jbe/bsw@0
 | 
     9 
 | 
| 
jbe/bsw@0
 | 
    10 #define MONDELEFANT_MODULE_REGKEY (MONDELEFANT_REGKEY "_module")
 | 
| 
jbe/bsw@0
 | 
    11 #define MONDELEFANT_CONN_MT_REGKEY (MONDELEFANT_REGKEY "_connection")
 | 
| 
jbe/bsw@0
 | 
    12 #define MONDELEFANT_CONN_DATA_REGKEY (MONDELEFANT_REGKEY "_connection_data")
 | 
| 
jbe/bsw@0
 | 
    13 #define MONDELEFANT_RESULT_MT_REGKEY (MONDELEFANT_REGKEY "_result")
 | 
| 
jbe/bsw@0
 | 
    14 #define MONDELEFANT_ERROROBJECT_MT_REGKEY (MONDELEFANT_REGKEY "_errorobject")
 | 
| 
jbe/bsw@0
 | 
    15 #define MONDELEFANT_CLASS_MT_REGKEY (MONDELEFANT_REGKEY "_class")
 | 
| 
jbe/bsw@0
 | 
    16 #define MONDELEFANT_CLASS_PROTO_REGKEY (MONDELEFANT_REGKEY "_class_proto")
 | 
| 
jbe/bsw@0
 | 
    17 
 | 
| 
jbe/bsw@0
 | 
    18 #define MONDELEFANT_SERVER_ENCODING_ASCII 0
 | 
| 
jbe/bsw@0
 | 
    19 #define MONDELEFANT_SERVER_ENCODING_UTF8  1
 | 
| 
jbe/bsw@0
 | 
    20 
 | 
| 
jbe/bsw@0
 | 
    21 typedef struct {
 | 
| 
jbe/bsw@0
 | 
    22   PGconn *pgconn;
 | 
| 
jbe/bsw@0
 | 
    23   int server_encoding;
 | 
| 
jbe/bsw@0
 | 
    24 } mondelefant_conn_t;
 | 
| 
jbe/bsw@0
 | 
    25 
 | 
| 
jbe/bsw@0
 | 
    26 static size_t utf8_position_to_byte(const char *str, size_t utf8pos) {
 | 
| 
jbe/bsw@0
 | 
    27   size_t bytepos;
 | 
| 
jbe/bsw@0
 | 
    28   for (bytepos = 0; utf8pos > 0; bytepos++) {
 | 
| 
jbe/bsw@0
 | 
    29     uint8_t c;
 | 
| 
jbe/bsw@0
 | 
    30     c = ((const uint8_t *)str)[bytepos];
 | 
| 
jbe/bsw@0
 | 
    31     if (!c) break;
 | 
| 
jbe/bsw@0
 | 
    32     if (c <= 0x7f || c >= 0xc0) utf8pos--;
 | 
| 
jbe/bsw@0
 | 
    33   }
 | 
| 
jbe/bsw@0
 | 
    34   return bytepos;
 | 
| 
jbe/bsw@0
 | 
    35 }
 | 
| 
jbe/bsw@0
 | 
    36 
 | 
| 
jbe/bsw@0
 | 
    37 #define MONDELEFANT_POSTGRESQL_BINARY_OID ((Oid)17)
 | 
| 
jbe/bsw@0
 | 
    38 
 | 
| 
jbe/bsw@0
 | 
    39 static const char *mondelefant_oid_to_typestr(Oid oid) {
 | 
| 
jbe/bsw@0
 | 
    40   switch (oid) {
 | 
| 
jbe/bsw@0
 | 
    41     case 16: return "bool";
 | 
| 
jbe/bsw@0
 | 
    42     case 17: return "bytea";
 | 
| 
jbe/bsw@0
 | 
    43     case 18: return "char";
 | 
| 
jbe/bsw@0
 | 
    44     case 19: return "name";
 | 
| 
jbe/bsw@0
 | 
    45     case 20: return "int8";
 | 
| 
jbe/bsw@0
 | 
    46     case 21: return "int2";
 | 
| 
jbe/bsw@0
 | 
    47     case 23: return "int4";
 | 
| 
jbe/bsw@0
 | 
    48     case 25: return "text";
 | 
| 
jbe/bsw@0
 | 
    49     case 26: return "oid";
 | 
| 
jbe/bsw@0
 | 
    50     case 27: return "tid";
 | 
| 
jbe/bsw@0
 | 
    51     case 28: return "xid";
 | 
| 
jbe/bsw@0
 | 
    52     case 29: return "cid";
 | 
| 
jbe/bsw@0
 | 
    53     case 600: return "point";
 | 
| 
jbe/bsw@0
 | 
    54     case 601: return "lseg";
 | 
| 
jbe/bsw@0
 | 
    55     case 602: return "path";
 | 
| 
jbe/bsw@0
 | 
    56     case 603: return "box";
 | 
| 
jbe/bsw@0
 | 
    57     case 604: return "polygon";
 | 
| 
jbe/bsw@0
 | 
    58     case 628: return "line";
 | 
| 
jbe/bsw@0
 | 
    59     case 700: return "float4";
 | 
| 
jbe/bsw@0
 | 
    60     case 701: return "float8";
 | 
| 
jbe/bsw@0
 | 
    61     case 705: return "unknown";
 | 
| 
jbe/bsw@0
 | 
    62     case 718: return "circle";
 | 
| 
jbe/bsw@0
 | 
    63     case 790: return "money";
 | 
| 
jbe/bsw@0
 | 
    64     case 829: return "macaddr";
 | 
| 
jbe/bsw@0
 | 
    65     case 869: return "inet";
 | 
| 
jbe/bsw@0
 | 
    66     case 650: return "cidr";
 | 
| 
jbe/bsw@0
 | 
    67     case 1042: return "bpchar";
 | 
| 
jbe/bsw@0
 | 
    68     case 1043: return "varchar";
 | 
| 
jbe/bsw@0
 | 
    69     case 1082: return "date";
 | 
| 
jbe/bsw@0
 | 
    70     case 1083: return "time";
 | 
| 
jbe/bsw@0
 | 
    71     case 1114: return "timestamp";
 | 
| 
jbe/bsw@0
 | 
    72     case 1184: return "timestamptz";
 | 
| 
jbe/bsw@0
 | 
    73     case 1186: return "interval";
 | 
| 
jbe/bsw@0
 | 
    74     case 1266: return "timetz";
 | 
| 
jbe/bsw@0
 | 
    75     case 1560: return "bit";
 | 
| 
jbe/bsw@0
 | 
    76     case 1562: return "varbit";
 | 
| 
jbe/bsw@0
 | 
    77     case 1700: return "numeric";
 | 
| 
jbe/bsw@0
 | 
    78     default: return NULL;
 | 
| 
jbe/bsw@0
 | 
    79   }
 | 
| 
jbe/bsw@0
 | 
    80 }
 | 
| 
jbe/bsw@0
 | 
    81 
 | 
| 
jbe/bsw@0
 | 
    82 #define mondelefant_errcode_item(incode, outcode) \
 | 
| 
jbe/bsw@0
 | 
    83   if (!strncmp(pgcode, (incode), strlen(incode))) return outcode; else
 | 
| 
jbe/bsw@0
 | 
    84 
 | 
| 
jbe/bsw@0
 | 
    85 #define MONDELEFANT_ERRCODE_UNKNOWN "unknown"
 | 
| 
jbe/bsw@0
 | 
    86 #define MONDELEFANT_ERRCODE_CONNECTION "ConnectionException"
 | 
| 
jbe/bsw@0
 | 
    87 #define MONDELEFANT_ERRCODE_RESULTCOUNT_LOW "WrongResultSetCount.ResultSetMissing"
 | 
| 
jbe/bsw@0
 | 
    88 #define MONDELEFANT_ERRCODE_RESULTCOUNT_HIGH "WrongResultSetCount.TooManyResults"
 | 
| 
jbe/bsw@0
 | 
    89 #define MONDELEFANT_ERRCODE_QUERY1_NO_ROWS "NoData.OneRowExpected"
 | 
| 
jbe/bsw@0
 | 
    90 #define MONDELEFANT_ERRCODE_QUERY1_MULTIPLE_ROWS "CardinalityViolation.OneRowExpected"
 | 
| 
jbe/bsw@0
 | 
    91 
 | 
| 
jbe/bsw@0
 | 
    92 static const char *mondelefant_translate_errcode(const char *pgcode) {
 | 
| 
jbe/bsw@0
 | 
    93   if (!pgcode) abort();  // should not happen
 | 
| 
jbe/bsw@0
 | 
    94   mondelefant_errcode_item("02", "NoData")
 | 
| 
jbe/bsw@0
 | 
    95   mondelefant_errcode_item("03", "SqlStatementNotYetComplete")
 | 
| 
jbe/bsw@0
 | 
    96   mondelefant_errcode_item("08", "ConnectionException")
 | 
| 
jbe/bsw@0
 | 
    97   mondelefant_errcode_item("09", "TriggeredActionException")
 | 
| 
jbe/bsw@0
 | 
    98   mondelefant_errcode_item("0A", "FeatureNotSupported")
 | 
| 
jbe/bsw@0
 | 
    99   mondelefant_errcode_item("0B", "InvalidTransactionInitiation")
 | 
| 
jbe/bsw@0
 | 
   100   mondelefant_errcode_item("0F", "LocatorException")
 | 
| 
jbe/bsw@0
 | 
   101   mondelefant_errcode_item("0L", "InvalidGrantor")
 | 
| 
jbe/bsw@0
 | 
   102   mondelefant_errcode_item("0P", "InvalidRoleSpecification")
 | 
| 
jbe/bsw@0
 | 
   103   mondelefant_errcode_item("21", "CardinalityViolation")
 | 
| 
jbe/bsw@0
 | 
   104   mondelefant_errcode_item("22", "DataException")
 | 
| 
jbe/bsw@0
 | 
   105   mondelefant_errcode_item("23001", "IntegrityConstraintViolation.RestrictViolation")
 | 
| 
jbe/bsw@0
 | 
   106   mondelefant_errcode_item("23502", "IntegrityConstraintViolation.NotNullViolation")
 | 
| 
jbe/bsw@0
 | 
   107   mondelefant_errcode_item("23503", "IntegrityConstraintViolation.ForeignKeyViolation")
 | 
| 
jbe/bsw@0
 | 
   108   mondelefant_errcode_item("23505", "IntegrityConstraintViolation.UniqueViolation")
 | 
| 
jbe/bsw@0
 | 
   109   mondelefant_errcode_item("23514", "IntegrityConstraintViolation.CheckViolation")
 | 
| 
jbe/bsw@0
 | 
   110   mondelefant_errcode_item("23",    "IntegrityConstraintViolation")
 | 
| 
jbe/bsw@0
 | 
   111   mondelefant_errcode_item("24", "InvalidCursorState")
 | 
| 
jbe/bsw@0
 | 
   112   mondelefant_errcode_item("25", "InvalidTransactionState")
 | 
| 
jbe/bsw@0
 | 
   113   mondelefant_errcode_item("26", "InvalidSqlStatementName")
 | 
| 
jbe/bsw@0
 | 
   114   mondelefant_errcode_item("27", "TriggeredDataChangeViolation")
 | 
| 
jbe/bsw@0
 | 
   115   mondelefant_errcode_item("28", "InvalidAuthorizationSpecification")
 | 
| 
jbe/bsw@0
 | 
   116   mondelefant_errcode_item("2B", "DependentPrivilegeDescriptorsStillExist")
 | 
| 
jbe/bsw@0
 | 
   117   mondelefant_errcode_item("2D", "InvalidTransactionTermination")
 | 
| 
jbe/bsw@0
 | 
   118   mondelefant_errcode_item("2F", "SqlRoutineException")
 | 
| 
jbe/bsw@0
 | 
   119   mondelefant_errcode_item("34", "InvalidCursorName")
 | 
| 
jbe/bsw@0
 | 
   120   mondelefant_errcode_item("38", "ExternalRoutineException")
 | 
| 
jbe/bsw@0
 | 
   121   mondelefant_errcode_item("39", "ExternalRoutineInvocationException")
 | 
| 
jbe/bsw@0
 | 
   122   mondelefant_errcode_item("3B", "SavepointException")
 | 
| 
jbe/bsw@0
 | 
   123   mondelefant_errcode_item("3D", "InvalidCatalogName")
 | 
| 
jbe/bsw@0
 | 
   124   mondelefant_errcode_item("3F", "InvalidSchemaName")
 | 
| 
jbe/bsw@0
 | 
   125   mondelefant_errcode_item("40", "TransactionRollback")
 | 
| 
jbe/bsw@0
 | 
   126   mondelefant_errcode_item("42", "SyntaxErrorOrAccessRuleViolation")
 | 
| 
jbe/bsw@0
 | 
   127   mondelefant_errcode_item("44", "WithCheckOptionViolation")
 | 
| 
jbe/bsw@0
 | 
   128   mondelefant_errcode_item("53", "InsufficientResources")
 | 
| 
jbe/bsw@0
 | 
   129   mondelefant_errcode_item("54", "ProgramLimitExceeded")
 | 
| 
jbe/bsw@0
 | 
   130   mondelefant_errcode_item("55", "ObjectNotInPrerequisiteState")
 | 
| 
jbe/bsw@0
 | 
   131   mondelefant_errcode_item("57", "OperatorIntervention")
 | 
| 
jbe/bsw@0
 | 
   132   mondelefant_errcode_item("58", "SystemError")
 | 
| 
jbe/bsw@0
 | 
   133   mondelefant_errcode_item("F0", "ConfigurationFileError")
 | 
| 
jbe/bsw@0
 | 
   134   mondelefant_errcode_item("P0", "PlpgsqlError")
 | 
| 
jbe/bsw@0
 | 
   135   mondelefant_errcode_item("XX", "InternalError")
 | 
| 
jbe/bsw@0
 | 
   136   return "unknown";
 | 
| 
jbe/bsw@0
 | 
   137 }
 | 
| 
jbe/bsw@0
 | 
   138 
 | 
| 
jbe/bsw@0
 | 
   139 static int mondelefant_check_error_class(
 | 
| 
jbe/bsw@0
 | 
   140   const char *errcode, const char *errclass
 | 
| 
jbe/bsw@0
 | 
   141 ) {
 | 
| 
jbe/bsw@0
 | 
   142   size_t i = 0;
 | 
| 
jbe/bsw@0
 | 
   143   while (1) {
 | 
| 
jbe/bsw@0
 | 
   144     if (errclass[i] == 0) {
 | 
| 
jbe/bsw@0
 | 
   145       if (errcode[i] == 0 || errcode[i] == '.') return 1;
 | 
| 
jbe/bsw@0
 | 
   146       else return 0;
 | 
| 
jbe/bsw@0
 | 
   147     }
 | 
| 
jbe/bsw@0
 | 
   148     if (errcode[i] != errclass[i]) return 0;
 | 
| 
jbe/bsw@0
 | 
   149     i++;
 | 
| 
jbe/bsw@0
 | 
   150   }
 | 
| 
jbe/bsw@0
 | 
   151 }
 | 
| 
jbe/bsw@0
 | 
   152 
 | 
| 
jbe/bsw@0
 | 
   153 static void mondelefant_push_first_line(lua_State *L, const char *str) {
 | 
| 
jbe/bsw@0
 | 
   154   char *str2;
 | 
| 
jbe/bsw@0
 | 
   155   size_t i = 0;
 | 
| 
jbe/bsw@0
 | 
   156   if (!str) abort();  // should not happen
 | 
| 
jbe/bsw@0
 | 
   157   str2 = strdup(str);
 | 
| 
jbe/bsw@0
 | 
   158   while (1) {
 | 
| 
jbe/bsw@0
 | 
   159     char c = str2[i];
 | 
| 
jbe/bsw@0
 | 
   160     if (c == '\n' || c == '\r' || c == 0) { str2[i] = 0; break; }
 | 
| 
jbe/bsw@0
 | 
   161     i++;
 | 
| 
jbe/bsw@0
 | 
   162   };
 | 
| 
jbe/bsw@0
 | 
   163   lua_pushstring(L, str2);
 | 
| 
jbe/bsw@0
 | 
   164   free(str2);
 | 
| 
jbe/bsw@0
 | 
   165 }
 | 
| 
jbe/bsw@0
 | 
   166 
 | 
| 
jbe/bsw@0
 | 
   167 static int mondelefant_connect(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   168   luaL_Buffer buf;
 | 
| 
jbe/bsw@0
 | 
   169   const char *conninfo;
 | 
| 
jbe/bsw@0
 | 
   170   PGconn *pgconn;
 | 
| 
jbe/bsw@0
 | 
   171   mondelefant_conn_t *conn;
 | 
| 
jbe/bsw@0
 | 
   172   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
   173   lua_getfield(L, 1, "engine");  // 2
 | 
| 
jbe/bsw@0
 | 
   174   if (!lua_toboolean(L, 2)) {
 | 
| 
jbe/bsw@0
 | 
   175     return luaL_error(L, "No database engine selected.");
 | 
| 
jbe/bsw@0
 | 
   176   }
 | 
| 
jbe/bsw@0
 | 
   177   lua_pushliteral(L, "postgresql");  // 3
 | 
| 
jbe/bsw@0
 | 
   178   if (!lua_rawequal(L, 2, 3)) {
 | 
| 
jbe/bsw@0
 | 
   179     return luaL_error(L,
 | 
| 
jbe/bsw@0
 | 
   180       "Only database engine 'postgresql' is supported."
 | 
| 
jbe/bsw@0
 | 
   181     );
 | 
| 
jbe/bsw@0
 | 
   182   }
 | 
| 
jbe/bsw@0
 | 
   183   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
   184   lua_pushnil(L);  // slot for key at stack position 2
 | 
| 
jbe/bsw@0
 | 
   185   lua_pushnil(L);  // slot for value at stack position 3
 | 
| 
jbe/bsw@0
 | 
   186   luaL_buffinit(L, &buf);
 | 
| 
jbe/bsw@0
 | 
   187   {
 | 
| 
jbe/bsw@0
 | 
   188     int need_seperator = 0;
 | 
| 
jbe/bsw@0
 | 
   189     while (lua_pushvalue(L, 2), lua_next(L, 1)) {
 | 
| 
jbe/bsw@0
 | 
   190       lua_replace(L, 3);
 | 
| 
jbe/bsw@0
 | 
   191       lua_replace(L, 2);
 | 
| 
jbe/bsw@0
 | 
   192       // NOTE: numbers will be converted to strings automatically here,
 | 
| 
jbe/bsw@0
 | 
   193       // but perhaps this will change in future versions of lua
 | 
| 
jbe/bsw@0
 | 
   194       luaL_argcheck(L,
 | 
| 
jbe/bsw@0
 | 
   195         lua_isstring(L, 2) && lua_isstring(L, 3), 1, "non-string contained"
 | 
| 
jbe/bsw@0
 | 
   196       );
 | 
| 
jbe/bsw@0
 | 
   197       lua_pushvalue(L, 2);
 | 
| 
jbe/bsw@0
 | 
   198       lua_pushliteral(L, "engine");
 | 
| 
jbe/bsw@0
 | 
   199       if (!lua_rawequal(L, -2, -1)) {
 | 
| 
jbe/bsw@0
 | 
   200         const char *value;
 | 
| 
jbe/bsw@0
 | 
   201         size_t value_len;
 | 
| 
jbe/bsw@0
 | 
   202         size_t value_pos = 0;
 | 
| 
jbe/bsw@0
 | 
   203         lua_pop(L, 1);
 | 
| 
jbe/bsw@0
 | 
   204         if (need_seperator) luaL_addchar(&buf, ' ');
 | 
| 
jbe/bsw@0
 | 
   205         luaL_addvalue(&buf);
 | 
| 
jbe/bsw@0
 | 
   206         luaL_addchar(&buf, '=');
 | 
| 
jbe/bsw@0
 | 
   207         luaL_addchar(&buf, '\'');
 | 
| 
jbe/bsw@0
 | 
   208         value = lua_tolstring(L, 3, &value_len);
 | 
| 
jbe/bsw@0
 | 
   209         do {
 | 
| 
jbe/bsw@0
 | 
   210           char c;
 | 
| 
jbe/bsw@0
 | 
   211           c = value[value_pos++];
 | 
| 
jbe/bsw@0
 | 
   212           if (c == '\'') luaL_addchar(&buf, '\\');
 | 
| 
jbe/bsw@0
 | 
   213           luaL_addchar(&buf, c);
 | 
| 
jbe/bsw@0
 | 
   214         } while (value_pos < value_len);
 | 
| 
jbe/bsw@0
 | 
   215         luaL_addchar(&buf, '\'');
 | 
| 
jbe/bsw@0
 | 
   216         need_seperator = 1;
 | 
| 
jbe/bsw@0
 | 
   217       } else {
 | 
| 
jbe/bsw@0
 | 
   218         lua_pop(L, 1);
 | 
| 
jbe/bsw@0
 | 
   219       }
 | 
| 
jbe/bsw@0
 | 
   220     }
 | 
| 
jbe/bsw@0
 | 
   221   }
 | 
| 
jbe/bsw@0
 | 
   222   luaL_pushresult(&buf);
 | 
| 
jbe/bsw@0
 | 
   223   lua_replace(L, 2);
 | 
| 
jbe/bsw@0
 | 
   224   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
   225   conninfo = lua_tostring(L, 2);
 | 
| 
jbe/bsw@0
 | 
   226   pgconn = PQconnectdb(conninfo);
 | 
| 
jbe/bsw@0
 | 
   227   if (!pgconn) {
 | 
| 
jbe/bsw@0
 | 
   228     return luaL_error(L,
 | 
| 
jbe/bsw@0
 | 
   229       "Error in libpq while creating 'PGconn' structure."
 | 
| 
jbe/bsw@0
 | 
   230     );
 | 
| 
jbe/bsw@0
 | 
   231   }
 | 
| 
jbe/bsw@0
 | 
   232   if (PQstatus(pgconn) != CONNECTION_OK) {
 | 
| 
jbe/bsw@0
 | 
   233     const char *errmsg;
 | 
| 
jbe/bsw@0
 | 
   234     lua_pushnil(L);
 | 
| 
jbe/bsw@0
 | 
   235     errmsg = PQerrorMessage(pgconn);
 | 
| 
jbe/bsw@0
 | 
   236     if (errmsg) {
 | 
| 
jbe/bsw@0
 | 
   237       mondelefant_push_first_line(L, errmsg);
 | 
| 
jbe/bsw@0
 | 
   238     } else {
 | 
| 
jbe/bsw@0
 | 
   239       lua_pushliteral(L,
 | 
| 
jbe/bsw@0
 | 
   240         "Error while connecting to database, but no error message given."
 | 
| 
jbe/bsw@0
 | 
   241       );
 | 
| 
jbe/bsw@0
 | 
   242     }
 | 
| 
jbe/bsw@0
 | 
   243     lua_pushliteral(L, MONDELEFANT_ERRCODE_CONNECTION);
 | 
| 
jbe/bsw@0
 | 
   244     PQfinish(pgconn);
 | 
| 
jbe/bsw@0
 | 
   245     return 3;
 | 
| 
jbe/bsw@0
 | 
   246   }
 | 
| 
jbe/bsw@0
 | 
   247   lua_settop(L, 0);
 | 
| 
jbe/bsw@0
 | 
   248   conn = lua_newuserdata(L, sizeof(*conn));  // 1
 | 
| 
jbe/bsw@0
 | 
   249   conn->pgconn = pgconn;
 | 
| 
jbe/bsw@0
 | 
   250   {
 | 
| 
jbe/bsw@0
 | 
   251     const char *charset;
 | 
| 
jbe/bsw@0
 | 
   252     charset = PQparameterStatus(pgconn, "server_encoding");
 | 
| 
jbe/bsw@0
 | 
   253     if (charset && !strcmp(charset, "UTF8")) {
 | 
| 
jbe/bsw@0
 | 
   254       conn->server_encoding = MONDELEFANT_SERVER_ENCODING_UTF8;
 | 
| 
jbe/bsw@0
 | 
   255     } else {
 | 
| 
jbe/bsw@0
 | 
   256       conn->server_encoding = MONDELEFANT_SERVER_ENCODING_ASCII;
 | 
| 
jbe/bsw@0
 | 
   257     }
 | 
| 
jbe/bsw@0
 | 
   258   }
 | 
| 
jbe/bsw@0
 | 
   259 
 | 
| 
jbe/bsw@0
 | 
   260   luaL_getmetatable(L, MONDELEFANT_CONN_MT_REGKEY);  // 2
 | 
| 
jbe/bsw@0
 | 
   261   lua_setmetatable(L, 1);
 | 
| 
jbe/bsw@0
 | 
   262 
 | 
| 
jbe/bsw@0
 | 
   263   lua_getfield(L, LUA_REGISTRYINDEX, MONDELEFANT_CONN_DATA_REGKEY);  // 2
 | 
| 
jbe/bsw@0
 | 
   264   lua_pushvalue(L, 1);  // 3
 | 
| 
jbe/bsw@0
 | 
   265   lua_newtable(L);  // 4
 | 
| 
jbe/bsw@0
 | 
   266   lua_settable(L, 2);
 | 
| 
jbe/bsw@0
 | 
   267   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
   268 
 | 
| 
jbe/bsw@0
 | 
   269   lua_pushliteral(L, "postgresql");
 | 
| 
jbe/bsw@0
 | 
   270   lua_setfield(L, 1, "engine");
 | 
| 
jbe/bsw@0
 | 
   271   return 1;
 | 
| 
jbe/bsw@0
 | 
   272 }
 | 
| 
jbe/bsw@0
 | 
   273 
 | 
| 
jbe/bsw@0
 | 
   274 static mondelefant_conn_t *mondelefant_get_conn(lua_State *L, int index) {
 | 
| 
jbe/bsw@0
 | 
   275   mondelefant_conn_t *conn;
 | 
| 
jbe/bsw@0
 | 
   276   conn = luaL_checkudata(L, index, MONDELEFANT_CONN_MT_REGKEY);
 | 
| 
jbe/bsw@0
 | 
   277   if (!conn->pgconn) {
 | 
| 
jbe/bsw@0
 | 
   278     luaL_error(L, "PostgreSQL connection has been closed.");
 | 
| 
jbe/bsw@0
 | 
   279     return NULL;
 | 
| 
jbe/bsw@0
 | 
   280   }
 | 
| 
jbe/bsw@0
 | 
   281   return conn;
 | 
| 
jbe/bsw@0
 | 
   282 }
 | 
| 
jbe/bsw@0
 | 
   283 
 | 
| 
jbe/bsw@0
 | 
   284 static int mondelefant_conn_index(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   285   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
   286   lua_getfield(L, LUA_REGISTRYINDEX, MONDELEFANT_CONN_DATA_REGKEY);  // 3
 | 
| 
jbe/bsw@0
 | 
   287   lua_pushvalue(L, 1);  // 4
 | 
| 
jbe/bsw@0
 | 
   288   lua_gettable(L, 3);  // 4
 | 
| 
jbe/bsw@0
 | 
   289   lua_remove(L, 3);  // connection specific data-table at stack position 3
 | 
| 
jbe/bsw@0
 | 
   290   lua_pushvalue(L, 2);  // 4
 | 
| 
jbe/bsw@0
 | 
   291   lua_gettable(L, 3);  // 4
 | 
| 
jbe/bsw@0
 | 
   292   if (!lua_isnil(L, 4)) return 1;
 | 
| 
jbe/bsw@0
 | 
   293   lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
   294   lua_getfield(L, 3, "prototype");  // 4
 | 
| 
jbe/bsw@0
 | 
   295   if (lua_toboolean(L, 4)) {
 | 
| 
jbe/bsw@0
 | 
   296     lua_pushvalue(L, 2);  // 5
 | 
| 
jbe/bsw@0
 | 
   297     lua_gettable(L, 4);  // 5
 | 
| 
jbe/bsw@0
 | 
   298     if (!lua_isnil(L, 5)) return 1;
 | 
| 
jbe/bsw@0
 | 
   299   }
 | 
| 
jbe/bsw@0
 | 
   300   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
   301   lua_getfield(L, LUA_REGISTRYINDEX, MONDELEFANT_MODULE_REGKEY);  // 3
 | 
| 
jbe/bsw@0
 | 
   302   lua_getfield(L, 3, "postgresql_connection_prototype");  // 4
 | 
| 
jbe/bsw@0
 | 
   303   if (lua_toboolean(L, 4)) {
 | 
| 
jbe/bsw@0
 | 
   304     lua_pushvalue(L, 2);  // 5
 | 
| 
jbe/bsw@0
 | 
   305     lua_gettable(L, 4);  // 5
 | 
| 
jbe/bsw@0
 | 
   306     if (!lua_isnil(L, 5)) return 1;
 | 
| 
jbe/bsw@0
 | 
   307   }
 | 
| 
jbe/bsw@0
 | 
   308   lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
   309   lua_getfield(L, 3, "connection_prototype");  // 4
 | 
| 
jbe/bsw@0
 | 
   310   if (lua_toboolean(L, 4)) {
 | 
| 
jbe/bsw@0
 | 
   311     lua_pushvalue(L, 2);  // 5
 | 
| 
jbe/bsw@0
 | 
   312     lua_gettable(L, 4);  // 5
 | 
| 
jbe/bsw@0
 | 
   313     if (!lua_isnil(L, 5)) return 1;
 | 
| 
jbe/bsw@0
 | 
   314   }
 | 
| 
jbe/bsw@0
 | 
   315   return 0;
 | 
| 
jbe/bsw@0
 | 
   316 }
 | 
| 
jbe/bsw@0
 | 
   317 
 | 
| 
jbe/bsw@0
 | 
   318 static int mondelefant_conn_newindex(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   319   lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
   320   lua_getfield(L, LUA_REGISTRYINDEX, MONDELEFANT_CONN_DATA_REGKEY);  // 4
 | 
| 
jbe/bsw@0
 | 
   321   lua_pushvalue(L, 1);  // 5
 | 
| 
jbe/bsw@0
 | 
   322   lua_gettable(L, 4);  // 5
 | 
| 
jbe/bsw@0
 | 
   323   lua_remove(L, 4);  // connection specific data-table  at stack position 4
 | 
| 
jbe/bsw@0
 | 
   324   lua_pushvalue(L, 2);
 | 
| 
jbe/bsw@0
 | 
   325   lua_pushvalue(L, 3);
 | 
| 
jbe/bsw@0
 | 
   326   lua_settable(L, 4);
 | 
| 
jbe/bsw@0
 | 
   327   return 0;
 | 
| 
jbe/bsw@0
 | 
   328 }
 | 
| 
jbe/bsw@0
 | 
   329 
 | 
| 
jbe/bsw@0
 | 
   330 static int mondelefant_conn_free(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   331   mondelefant_conn_t *conn;
 | 
| 
jbe/bsw@0
 | 
   332   conn = luaL_checkudata(L, 1, MONDELEFANT_CONN_MT_REGKEY);
 | 
| 
jbe/bsw@0
 | 
   333   if (conn->pgconn) PQfinish(conn->pgconn);
 | 
| 
jbe/bsw@0
 | 
   334   conn->pgconn = NULL;
 | 
| 
jbe/bsw@0
 | 
   335   return 0;
 | 
| 
jbe/bsw@0
 | 
   336 }
 | 
| 
jbe/bsw@0
 | 
   337 
 | 
| 
jbe/bsw@0
 | 
   338 static int mondelefant_conn_close(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   339   mondelefant_conn_t *conn;
 | 
| 
jbe/bsw@0
 | 
   340   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
   341   conn = mondelefant_get_conn(L, 1);
 | 
| 
jbe/bsw@0
 | 
   342   PQfinish(conn->pgconn);
 | 
| 
jbe/bsw@0
 | 
   343   conn->pgconn = NULL;
 | 
| 
jbe/bsw@0
 | 
   344   return 0;
 | 
| 
jbe/bsw@0
 | 
   345 }
 | 
| 
jbe/bsw@0
 | 
   346 
 | 
| 
jbe/bsw@0
 | 
   347 static int mondelefant_conn_is_ok(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   348   mondelefant_conn_t *conn;
 | 
| 
jbe/bsw@0
 | 
   349   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
   350   conn = mondelefant_get_conn(L, 1);
 | 
| 
jbe/bsw@0
 | 
   351   lua_pushboolean(L, PQstatus(conn->pgconn) == CONNECTION_OK);
 | 
| 
jbe/bsw@0
 | 
   352   return 1;
 | 
| 
jbe/bsw@0
 | 
   353 }
 | 
| 
jbe/bsw@0
 | 
   354 
 | 
| 
jbe/bsw@0
 | 
   355 static int mondelefant_conn_get_transaction_status(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   356   mondelefant_conn_t *conn;
 | 
| 
jbe/bsw@0
 | 
   357   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
   358   conn = mondelefant_get_conn(L, 1);
 | 
| 
jbe/bsw@0
 | 
   359   switch (PQtransactionStatus(conn->pgconn)) {
 | 
| 
jbe/bsw@0
 | 
   360   case PQTRANS_IDLE:
 | 
| 
jbe/bsw@0
 | 
   361     lua_pushliteral(L, "idle");
 | 
| 
jbe/bsw@0
 | 
   362     break;
 | 
| 
jbe/bsw@0
 | 
   363   case PQTRANS_ACTIVE:
 | 
| 
jbe/bsw@0
 | 
   364     lua_pushliteral(L, "active");
 | 
| 
jbe/bsw@0
 | 
   365     break;
 | 
| 
jbe/bsw@0
 | 
   366   case PQTRANS_INTRANS:
 | 
| 
jbe/bsw@0
 | 
   367     lua_pushliteral(L, "intrans");
 | 
| 
jbe/bsw@0
 | 
   368     break;
 | 
| 
jbe/bsw@0
 | 
   369   case PQTRANS_INERROR:
 | 
| 
jbe/bsw@0
 | 
   370     lua_pushliteral(L, "inerror");
 | 
| 
jbe/bsw@0
 | 
   371     break;
 | 
| 
jbe/bsw@0
 | 
   372   default:
 | 
| 
jbe/bsw@0
 | 
   373     lua_pushliteral(L, "unknown");
 | 
| 
jbe/bsw@0
 | 
   374   }
 | 
| 
jbe/bsw@0
 | 
   375   return 1;
 | 
| 
jbe/bsw@0
 | 
   376 }
 | 
| 
jbe/bsw@0
 | 
   377 
 | 
| 
jbe/bsw@0
 | 
   378 static int mondelefant_conn_create_list(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   379   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
   380   luaL_checkudata(L, 1, MONDELEFANT_CONN_MT_REGKEY);
 | 
| 
jbe/bsw@0
 | 
   381   if (!lua_toboolean(L, 2)) {
 | 
| 
jbe/bsw@0
 | 
   382     lua_newtable(L);
 | 
| 
jbe/bsw@0
 | 
   383     lua_replace(L, 2);  // new result at stack position 2
 | 
| 
jbe/bsw@0
 | 
   384   }
 | 
| 
jbe/bsw@0
 | 
   385   lua_getfield(L, LUA_REGISTRYINDEX, MONDELEFANT_RESULT_MT_REGKEY);  // 3
 | 
| 
jbe/bsw@0
 | 
   386   lua_setmetatable(L, 2);
 | 
| 
jbe/bsw@0
 | 
   387   lua_pushvalue(L, 1);  // 3
 | 
| 
jbe/bsw@0
 | 
   388   lua_setfield(L, 2, "_connection");
 | 
| 
jbe/bsw@0
 | 
   389   lua_pushliteral(L, "list");  // 3
 | 
| 
jbe/bsw@0
 | 
   390   lua_setfield(L, 2, "_type");
 | 
| 
jbe/bsw@0
 | 
   391   return 1;
 | 
| 
jbe/bsw@0
 | 
   392 }
 | 
| 
jbe/bsw@0
 | 
   393 
 | 
| 
jbe/bsw@0
 | 
   394 static int mondelefant_conn_create_object(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   395   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
   396   luaL_checkudata(L, 1, MONDELEFANT_CONN_MT_REGKEY);
 | 
| 
jbe/bsw@0
 | 
   397   if (!lua_toboolean(L, 2)) {
 | 
| 
jbe/bsw@0
 | 
   398     lua_newtable(L);
 | 
| 
jbe/bsw@0
 | 
   399     lua_replace(L, 2);  // new result at stack position 2
 | 
| 
jbe/bsw@0
 | 
   400   }
 | 
| 
jbe/bsw@0
 | 
   401   lua_getfield(L, LUA_REGISTRYINDEX, MONDELEFANT_RESULT_MT_REGKEY);  // 3
 | 
| 
jbe/bsw@0
 | 
   402   lua_setmetatable(L, 2);
 | 
| 
jbe/bsw@0
 | 
   403   lua_pushvalue(L, 1);  // 3
 | 
| 
jbe/bsw@0
 | 
   404   lua_setfield(L, 2, "_connection");
 | 
| 
jbe/bsw@0
 | 
   405   lua_pushliteral(L, "object");  // 3
 | 
| 
jbe/bsw@0
 | 
   406   lua_setfield(L, 2, "_type");  // "object" or "list"
 | 
| 
jbe/bsw@0
 | 
   407   lua_newtable(L);  // 3
 | 
| 
jbe/bsw@0
 | 
   408   lua_setfield(L, 2, "_data");
 | 
| 
jbe/bsw@0
 | 
   409   lua_newtable(L);  // 3
 | 
| 
jbe/bsw@0
 | 
   410   lua_setfield(L, 2, "_dirty");
 | 
| 
jbe/bsw@0
 | 
   411   lua_newtable(L);  // 3
 | 
| 
jbe/bsw@0
 | 
   412   lua_setfield(L, 2, "_ref");  // nil=no info, false=nil, else table
 | 
| 
jbe/bsw@0
 | 
   413   return 1;
 | 
| 
jbe/bsw@0
 | 
   414 }
 | 
| 
jbe/bsw@0
 | 
   415 
 | 
| 
jbe/bsw@0
 | 
   416 static int mondelefant_conn_quote_string(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   417   mondelefant_conn_t *conn;
 | 
| 
jbe/bsw@0
 | 
   418   const char *input;
 | 
| 
jbe/bsw@0
 | 
   419   size_t input_len;
 | 
| 
jbe/bsw@0
 | 
   420   char *output;
 | 
| 
jbe/bsw@0
 | 
   421   size_t output_len;
 | 
| 
jbe/bsw@0
 | 
   422   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
   423   conn = mondelefant_get_conn(L, 1);
 | 
| 
jbe/bsw@0
 | 
   424   input = luaL_checklstring(L, 2, &input_len);
 | 
| 
jbe/bsw@0
 | 
   425   if (input_len > (SIZE_MAX / sizeof(char) - 3) / 2) {
 | 
| 
jbe/bsw@0
 | 
   426     return luaL_error(L, "String to be escaped is too long.");
 | 
| 
jbe/bsw@0
 | 
   427   }
 | 
| 
jbe/bsw@0
 | 
   428   output = malloc((2 * input_len + 3) * sizeof(char));
 | 
| 
jbe/bsw@0
 | 
   429   if (!output) {
 | 
| 
jbe/bsw@0
 | 
   430     return luaL_error(L, "Could not allocate memory for string quoting.");
 | 
| 
jbe/bsw@0
 | 
   431   }
 | 
| 
jbe/bsw@0
 | 
   432   output[0] = '\'';
 | 
| 
jbe/bsw@0
 | 
   433   output_len = PQescapeStringConn(
 | 
| 
jbe/bsw@0
 | 
   434     conn->pgconn, output + 1, input, input_len, NULL
 | 
| 
jbe/bsw@0
 | 
   435   );
 | 
| 
jbe/bsw@0
 | 
   436   output[output_len + 1] = '\'';
 | 
| 
jbe/bsw@0
 | 
   437   output[output_len + 2] = 0;
 | 
| 
jbe/bsw@0
 | 
   438   lua_pushlstring(L, output, output_len + 2);
 | 
| 
jbe/bsw@0
 | 
   439   free(output);
 | 
| 
jbe/bsw@0
 | 
   440   return 1;
 | 
| 
jbe/bsw@0
 | 
   441 }
 | 
| 
jbe/bsw@0
 | 
   442 
 | 
| 
jbe/bsw@0
 | 
   443 static int mondelefant_conn_quote_binary(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   444   mondelefant_conn_t *conn;
 | 
| 
jbe/bsw@0
 | 
   445   const char *input;
 | 
| 
jbe/bsw@0
 | 
   446   size_t input_len;
 | 
| 
jbe/bsw@0
 | 
   447   char *output;
 | 
| 
jbe/bsw@0
 | 
   448   size_t output_len;
 | 
| 
jbe/bsw@0
 | 
   449   luaL_Buffer buf;
 | 
| 
jbe/bsw@0
 | 
   450   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
   451   conn = mondelefant_get_conn(L, 1);
 | 
| 
jbe/bsw@0
 | 
   452   input = luaL_checklstring(L, 2, &input_len);
 | 
| 
jbe/bsw@0
 | 
   453   output = (char *)PQescapeByteaConn(
 | 
| 
jbe/bsw@0
 | 
   454     conn->pgconn, (const unsigned char *)input, input_len, &output_len
 | 
| 
jbe/bsw@0
 | 
   455   );
 | 
| 
jbe/bsw@0
 | 
   456   if (!output) {
 | 
| 
jbe/bsw@0
 | 
   457     return luaL_error(L, "Could not allocate memory for binary quoting.");
 | 
| 
jbe/bsw@0
 | 
   458   }
 | 
| 
jbe/bsw@0
 | 
   459   luaL_buffinit(L, &buf);
 | 
| 
jbe/bsw@0
 | 
   460   luaL_addchar(&buf, '\'');
 | 
| 
jbe/bsw@0
 | 
   461   luaL_addlstring(&buf, output, output_len - 1);
 | 
| 
jbe/bsw@0
 | 
   462   luaL_addchar(&buf, '\'');
 | 
| 
jbe/bsw@0
 | 
   463   luaL_pushresult(&buf);
 | 
| 
jbe/bsw@0
 | 
   464   PQfreemem(output);
 | 
| 
jbe/bsw@0
 | 
   465   return 1;
 | 
| 
jbe/bsw@0
 | 
   466 }
 | 
| 
jbe/bsw@0
 | 
   467 
 | 
| 
jbe/bsw@0
 | 
   468 static int mondelefant_conn_assemble_command(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   469   mondelefant_conn_t *conn;
 | 
| 
jbe/bsw@0
 | 
   470   int paramidx = 2;
 | 
| 
jbe/bsw@0
 | 
   471   const char *template;
 | 
| 
jbe/bsw@0
 | 
   472   size_t template_pos = 0;
 | 
| 
jbe/bsw@0
 | 
   473   luaL_Buffer buf;
 | 
| 
jbe/bsw@0
 | 
   474   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
   475   conn = mondelefant_get_conn(L, 1);
 | 
| 
jbe/bsw@0
 | 
   476   if (lua_isstring(L, 2)) {
 | 
| 
jbe/bsw@0
 | 
   477     lua_tostring(L, 2);
 | 
| 
jbe/bsw@0
 | 
   478     return 1;
 | 
| 
jbe/bsw@0
 | 
   479   }
 | 
| 
jbe/bsw@0
 | 
   480   // extra feature for objects with __tostring meta-method:
 | 
| 
jbe/bsw@0
 | 
   481   if (luaL_callmeta(L, 2, "__tostring")) return 1;
 | 
| 
jbe/bsw@0
 | 
   482   luaL_checktype(L, 2, LUA_TTABLE);
 | 
| 
jbe/bsw@0
 | 
   483   lua_rawgeti(L, 2, 1);  // 3
 | 
| 
jbe/bsw@0
 | 
   484   luaL_argcheck(L,
 | 
| 
jbe/bsw@0
 | 
   485     lua_isstring(L, 3),
 | 
| 
jbe/bsw@0
 | 
   486     2,
 | 
| 
jbe/bsw@0
 | 
   487     "First entry of SQL command structure is not a string."
 | 
| 
jbe/bsw@0
 | 
   488   );
 | 
| 
jbe/bsw@0
 | 
   489   template = lua_tostring(L, 3);
 | 
| 
jbe/bsw@0
 | 
   490   lua_pushliteral(L, "input_converter");  // 4
 | 
| 
jbe/bsw@0
 | 
   491   lua_gettable(L, 1);  // input_converter at stack position 4
 | 
| 
jbe/bsw@0
 | 
   492   lua_pushnil(L);  // free space at stack position 5
 | 
| 
jbe/bsw@0
 | 
   493   lua_pushnil(L);  // free space at stack position 6
 | 
| 
jbe/bsw@0
 | 
   494   luaL_buffinit(L, &buf);
 | 
| 
jbe/bsw@0
 | 
   495   while (1) {
 | 
| 
jbe/bsw@0
 | 
   496     char c;
 | 
| 
jbe/bsw@0
 | 
   497     c = template[template_pos++];
 | 
| 
jbe/bsw@0
 | 
   498     if (!c) break;
 | 
| 
jbe/bsw@0
 | 
   499     if (c == '?' || c == '$') {
 | 
| 
jbe/bsw@0
 | 
   500       if (template[template_pos] == c) {
 | 
| 
jbe/bsw@0
 | 
   501         template_pos++;
 | 
| 
jbe/bsw@0
 | 
   502         luaL_addchar(&buf, c);
 | 
| 
jbe/bsw@0
 | 
   503       } else {
 | 
| 
jbe/bsw@0
 | 
   504         luaL_Buffer keybuf;
 | 
| 
jbe/bsw@0
 | 
   505         int subcmd;
 | 
| 
jbe/bsw@0
 | 
   506         subcmd = (c == '$');
 | 
| 
jbe/bsw@0
 | 
   507         luaL_buffinit(L, &keybuf);
 | 
| 
jbe/bsw@0
 | 
   508         while (1) {
 | 
| 
jbe/bsw@0
 | 
   509           c = template[template_pos];
 | 
| 
jbe/bsw@0
 | 
   510           if (
 | 
| 
jbe/bsw@0
 | 
   511             (c < 'A' || c > 'Z') &&
 | 
| 
jbe/bsw@0
 | 
   512             (c < 'a' || c > 'z') &&
 | 
| 
jbe/bsw@0
 | 
   513             (c < '0' || c > '9') &&
 | 
| 
jbe/bsw@0
 | 
   514             (c != '_')
 | 
| 
jbe/bsw@0
 | 
   515           ) break;
 | 
| 
jbe/bsw@0
 | 
   516           luaL_addchar(&keybuf, c);
 | 
| 
jbe/bsw@0
 | 
   517           template_pos++;
 | 
| 
jbe/bsw@0
 | 
   518         }
 | 
| 
jbe/bsw@0
 | 
   519         luaL_pushresult(&keybuf);
 | 
| 
jbe/bsw@0
 | 
   520         if (lua_objlen(L, -1)) {
 | 
| 
jbe/bsw@0
 | 
   521           lua_pushvalue(L, -1);           // save key on stack
 | 
| 
jbe/bsw@0
 | 
   522           lua_gettable(L, 2);             // fetch value
 | 
| 
jbe/bsw@0
 | 
   523         } else {
 | 
| 
jbe/bsw@0
 | 
   524           lua_pop(L, 1);
 | 
| 
jbe/bsw@0
 | 
   525           lua_pushnil(L);                 // put nil on key position
 | 
| 
jbe/bsw@0
 | 
   526           lua_rawgeti(L, 2, paramidx++);  // fetch value
 | 
| 
jbe/bsw@0
 | 
   527         }
 | 
| 
jbe/bsw@0
 | 
   528         // stack: ..., <buffer>, key, pre-value
 | 
| 
jbe/bsw@0
 | 
   529         if (subcmd) {
 | 
| 
jbe/bsw@0
 | 
   530           size_t i;
 | 
| 
jbe/bsw@0
 | 
   531           size_t count;
 | 
| 
jbe/bsw@0
 | 
   532           lua_replace(L, 5);  // sub-structure at stack position 5
 | 
| 
jbe/bsw@0
 | 
   533           lua_pop(L, 1);      // drop stored key
 | 
| 
jbe/bsw@0
 | 
   534           // stack: ..., <buffer>
 | 
| 
jbe/bsw@0
 | 
   535           luaL_argcheck(L,
 | 
| 
jbe/bsw@0
 | 
   536             !lua_isnil(L, 5),
 | 
| 
jbe/bsw@0
 | 
   537             2,
 | 
| 
jbe/bsw@0
 | 
   538             "SQL sub-structure not found."
 | 
| 
jbe/bsw@0
 | 
   539           );
 | 
| 
jbe/bsw@0
 | 
   540           luaL_argcheck(L,
 | 
| 
jbe/bsw@0
 | 
   541             lua_type(L, 5) == LUA_TTABLE,
 | 
| 
jbe/bsw@0
 | 
   542             2,
 | 
| 
jbe/bsw@0
 | 
   543             "SQL sub-structure must be a table."
 | 
| 
jbe/bsw@0
 | 
   544           );
 | 
| 
jbe/bsw@0
 | 
   545           // stack: ..., <buffer>
 | 
| 
jbe/bsw@0
 | 
   546           lua_getfield(L, 5, "sep");
 | 
| 
jbe/bsw@0
 | 
   547           lua_replace(L, 6);  // seperator at stack position 6
 | 
| 
jbe/bsw@0
 | 
   548           if (lua_isnil(L, 6)) {
 | 
| 
jbe/bsw@0
 | 
   549             lua_pushstring(L, ", ");
 | 
| 
jbe/bsw@0
 | 
   550             lua_replace(L, 6);
 | 
| 
jbe/bsw@0
 | 
   551           } else {
 | 
| 
jbe/bsw@0
 | 
   552             luaL_argcheck(L,
 | 
| 
jbe/bsw@0
 | 
   553               lua_isstring(L, 6),
 | 
| 
jbe/bsw@0
 | 
   554               2,
 | 
| 
jbe/bsw@0
 | 
   555               "Seperator of SQL sub-structure has to be a string."
 | 
| 
jbe/bsw@0
 | 
   556             );
 | 
| 
jbe/bsw@0
 | 
   557           }
 | 
| 
jbe/bsw@0
 | 
   558           count = lua_objlen(L, 5);
 | 
| 
jbe/bsw@0
 | 
   559           for (i = 0; i < count; i++) {
 | 
| 
jbe/bsw@0
 | 
   560             if (i) {
 | 
| 
jbe/bsw@0
 | 
   561               lua_pushvalue(L, 6);
 | 
| 
jbe/bsw@0
 | 
   562               luaL_addvalue(&buf);
 | 
| 
jbe/bsw@0
 | 
   563             }
 | 
| 
jbe/bsw@0
 | 
   564             lua_pushcfunction(L, mondelefant_conn_assemble_command);
 | 
| 
jbe/bsw@0
 | 
   565             lua_pushvalue(L, 1);
 | 
| 
jbe/bsw@0
 | 
   566             lua_rawgeti(L, 5, i+1);
 | 
| 
jbe/bsw@0
 | 
   567             lua_call(L, 2, 1);
 | 
| 
jbe/bsw@0
 | 
   568             luaL_addvalue(&buf);
 | 
| 
jbe/bsw@0
 | 
   569           }
 | 
| 
jbe/bsw@0
 | 
   570         } else {
 | 
| 
jbe/bsw@0
 | 
   571           if (lua_toboolean(L, 4)) {
 | 
| 
jbe/bsw@0
 | 
   572             // call input_converter with connection handle, value and info
 | 
| 
jbe/bsw@0
 | 
   573             lua_pushvalue(L, 4);
 | 
| 
jbe/bsw@0
 | 
   574             lua_pushvalue(L, 1);
 | 
| 
jbe/bsw@0
 | 
   575             lua_pushvalue(L, -3);
 | 
| 
jbe/bsw@0
 | 
   576             lua_newtable(L);
 | 
| 
jbe/bsw@0
 | 
   577             lua_pushvalue(L, -6);
 | 
| 
jbe/bsw@0
 | 
   578             lua_setfield(L, -2, "field_name");
 | 
| 
jbe/bsw@0
 | 
   579             lua_call(L, 3, 1);
 | 
| 
jbe/bsw@0
 | 
   580             // stack: ..., <buffer>, key, pre-value, final-value
 | 
| 
jbe/bsw@0
 | 
   581             lua_remove(L, -2);
 | 
| 
jbe/bsw@0
 | 
   582             lua_remove(L, -2);
 | 
| 
jbe/bsw@0
 | 
   583             // stack: ..., <buffer>, final-value
 | 
| 
jbe/bsw@0
 | 
   584             if (!lua_isstring(L, -1)) {
 | 
| 
jbe/bsw@0
 | 
   585               return luaL_error(L, "input_converter returned non-string.");
 | 
| 
jbe/bsw@0
 | 
   586             }
 | 
| 
jbe/bsw@0
 | 
   587           } else {
 | 
| 
jbe/bsw@0
 | 
   588             lua_remove(L, -2);
 | 
| 
jbe/bsw@0
 | 
   589             // stack: ..., <buffer>, pre-value
 | 
| 
jbe/bsw@0
 | 
   590             if (lua_isnil(L, -1)) {
 | 
| 
jbe/bsw@0
 | 
   591               lua_pushliteral(L, "NULL");
 | 
| 
jbe/bsw@0
 | 
   592             } else if (lua_type(L, -1) == LUA_TBOOLEAN) {
 | 
| 
jbe/bsw@0
 | 
   593               lua_pushstring(L, lua_toboolean(L, -1) ? "TRUE" : "FALSE");
 | 
| 
jbe/bsw@0
 | 
   594             } else if (lua_isstring(L, -1)) {
 | 
| 
jbe/bsw@0
 | 
   595               // NOTE: In this version of lua a number will be converted
 | 
| 
jbe/bsw@0
 | 
   596               lua_tostring(L, -1);
 | 
| 
jbe/bsw@0
 | 
   597               lua_pushcfunction(L, mondelefant_conn_quote_string);
 | 
| 
jbe/bsw@0
 | 
   598               lua_pushvalue(L, 1);
 | 
| 
jbe/bsw@0
 | 
   599               lua_pushvalue(L, -3);
 | 
| 
jbe/bsw@0
 | 
   600               lua_call(L, 2, 1);
 | 
| 
jbe/bsw@0
 | 
   601             } else {
 | 
| 
jbe/bsw@0
 | 
   602               return luaL_error(L,
 | 
| 
jbe/bsw@0
 | 
   603                 "Unable to convert SQL value due to unknown type "
 | 
| 
jbe/bsw@0
 | 
   604                 "or missing input_converter."
 | 
| 
jbe/bsw@0
 | 
   605               );
 | 
| 
jbe/bsw@0
 | 
   606             }
 | 
| 
jbe/bsw@0
 | 
   607             // stack: ..., <buffer>, pre-value, final-value
 | 
| 
jbe/bsw@0
 | 
   608             lua_remove(L, -2);
 | 
| 
jbe/bsw@0
 | 
   609             // stack: ..., <buffer>, final-value
 | 
| 
jbe/bsw@0
 | 
   610           }
 | 
| 
jbe/bsw@0
 | 
   611           luaL_addvalue(&buf);
 | 
| 
jbe/bsw@0
 | 
   612         }
 | 
| 
jbe/bsw@0
 | 
   613       }
 | 
| 
jbe/bsw@0
 | 
   614     } else {
 | 
| 
jbe/bsw@0
 | 
   615       luaL_addchar(&buf, c);
 | 
| 
jbe/bsw@0
 | 
   616     }
 | 
| 
jbe/bsw@0
 | 
   617   }
 | 
| 
jbe/bsw@0
 | 
   618   luaL_pushresult(&buf);
 | 
| 
jbe/bsw@0
 | 
   619   return 1;
 | 
| 
jbe/bsw@0
 | 
   620 }
 | 
| 
jbe/bsw@0
 | 
   621 
 | 
| 
jbe/bsw@0
 | 
   622 #define MONDELEFANT_MAX_COMMAND_COUNT 64
 | 
| 
jbe/bsw@0
 | 
   623 #define MONDELEFANT_MAX_COLUMN_COUNT 1024
 | 
| 
jbe/bsw@0
 | 
   624 #define MONDELEFANT_QUERY_MODE_LIST 1
 | 
| 
jbe/bsw@0
 | 
   625 #define MONDELEFANT_QUERY_MODE_OBJECT 2
 | 
| 
jbe/bsw@0
 | 
   626 #define MONDELEFANT_QUERY_MODE_OPT_OBJECT 3
 | 
| 
jbe/bsw@0
 | 
   627 
 | 
| 
jbe/bsw@0
 | 
   628 static int mondelefant_conn_try_query(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   629   mondelefant_conn_t *conn;
 | 
| 
jbe/bsw@0
 | 
   630   int command_count;
 | 
| 
jbe/bsw@0
 | 
   631   int command_idx;
 | 
| 
jbe/bsw@0
 | 
   632   int modes[MONDELEFANT_MAX_COMMAND_COUNT];
 | 
| 
jbe/bsw@0
 | 
   633   luaL_Buffer buf;
 | 
| 
jbe/bsw@0
 | 
   634   int sent_success;
 | 
| 
jbe/bsw@0
 | 
   635   PGresult *res;
 | 
| 
jbe/bsw@0
 | 
   636   int rows, cols, row, col;
 | 
| 
jbe/bsw@0
 | 
   637   conn = mondelefant_get_conn(L, 1);
 | 
| 
jbe/bsw@0
 | 
   638   command_count = lua_gettop(L) / 2;
 | 
| 
jbe/bsw@0
 | 
   639   lua_pushnil(L);  // needed, if last mode was omitted
 | 
| 
jbe/bsw@0
 | 
   640   if (command_count > MONDELEFANT_MAX_COMMAND_COUNT) {
 | 
| 
jbe/bsw@0
 | 
   641     return luaL_error(L, "Exceeded maximum command count in one query.");
 | 
| 
jbe/bsw@0
 | 
   642   }
 | 
| 
jbe/bsw@0
 | 
   643   luaL_buffinit(L, &buf);
 | 
| 
jbe/bsw@0
 | 
   644   for (command_idx = 0; command_idx < command_count; command_idx++) {
 | 
| 
jbe/bsw@0
 | 
   645     int mode;
 | 
| 
jbe/bsw@0
 | 
   646     int mode_idx;  // stack index of mode string
 | 
| 
jbe/bsw@0
 | 
   647     if (command_idx) luaL_addchar(&buf, ' ');
 | 
| 
jbe/bsw@0
 | 
   648     lua_pushcfunction(L, mondelefant_conn_assemble_command);
 | 
| 
jbe/bsw@0
 | 
   649     lua_pushvalue(L, 1);
 | 
| 
jbe/bsw@0
 | 
   650     lua_pushvalue(L, 2 + 2 * command_idx);
 | 
| 
jbe/bsw@0
 | 
   651     lua_call(L, 2, 1);
 | 
| 
jbe/bsw@0
 | 
   652     luaL_addvalue(&buf);
 | 
| 
jbe/bsw@0
 | 
   653     luaL_addchar(&buf, ';');
 | 
| 
jbe/bsw@0
 | 
   654     mode_idx = 3 + 2 * command_idx;
 | 
| 
jbe/bsw@0
 | 
   655     if (lua_isnil(L, mode_idx)) {
 | 
| 
jbe/bsw@0
 | 
   656       mode = MONDELEFANT_QUERY_MODE_LIST;
 | 
| 
jbe/bsw@0
 | 
   657     } else {
 | 
| 
jbe/bsw@0
 | 
   658       const char *modestr;
 | 
| 
jbe/bsw@0
 | 
   659       modestr = luaL_checkstring(L, mode_idx);
 | 
| 
jbe/bsw@0
 | 
   660       if (!strcmp(modestr, "list")) {
 | 
| 
jbe/bsw@0
 | 
   661         mode = MONDELEFANT_QUERY_MODE_LIST;
 | 
| 
jbe/bsw@0
 | 
   662       } else if (!strcmp(modestr, "object")) {
 | 
| 
jbe/bsw@0
 | 
   663         mode = MONDELEFANT_QUERY_MODE_OBJECT;
 | 
| 
jbe/bsw@0
 | 
   664       } else if (!strcmp(modestr, "opt_object")) {
 | 
| 
jbe/bsw@0
 | 
   665         mode = MONDELEFANT_QUERY_MODE_OPT_OBJECT;
 | 
| 
jbe/bsw@0
 | 
   666       } else {
 | 
| 
jbe/bsw@0
 | 
   667         return luaL_error(L, "Unknown query mode specified.");
 | 
| 
jbe/bsw@0
 | 
   668       }
 | 
| 
jbe/bsw@0
 | 
   669     }
 | 
| 
jbe/bsw@0
 | 
   670     modes[command_idx] = mode;
 | 
| 
jbe/bsw@0
 | 
   671   }
 | 
| 
jbe/bsw@0
 | 
   672   luaL_pushresult(&buf);  // stack position unknown
 | 
| 
jbe/bsw@0
 | 
   673   lua_replace(L, 2);  // SQL command string to stack position 2
 | 
| 
jbe/bsw@0
 | 
   674   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
   675   lua_getfield(L, 1, "sql_tracer");  // tracer at stack position 3
 | 
| 
jbe/bsw@0
 | 
   676   if (lua_toboolean(L, 3)) {
 | 
| 
jbe/bsw@0
 | 
   677     lua_pushvalue(L, 1);  // 4
 | 
| 
jbe/bsw@0
 | 
   678     lua_pushvalue(L, 2);  // 5
 | 
| 
jbe/bsw@0
 | 
   679     lua_call(L, 2, 1);  // trace callback at stack position 3
 | 
| 
jbe/bsw@0
 | 
   680   }
 | 
| 
jbe/bsw@0
 | 
   681   sent_success = PQsendQuery(conn->pgconn, lua_tostring(L, 2));
 | 
| 
jbe/bsw@0
 | 
   682   lua_newtable(L);  // results in table at stack position 4
 | 
| 
jbe/bsw@0
 | 
   683   for (command_idx = 0; ; command_idx++) {
 | 
| 
jbe/bsw@0
 | 
   684     int mode;
 | 
| 
jbe/bsw@0
 | 
   685     char binary[MONDELEFANT_MAX_COLUMN_COUNT];
 | 
| 
jbe/bsw@0
 | 
   686     ExecStatusType pgstatus;
 | 
| 
jbe/bsw@0
 | 
   687     mode = modes[command_idx];
 | 
| 
jbe/bsw@0
 | 
   688     if (sent_success) {
 | 
| 
jbe/bsw@0
 | 
   689       res = PQgetResult(conn->pgconn);
 | 
| 
jbe/bsw@0
 | 
   690       if (command_idx >= command_count && !res) break;
 | 
| 
jbe/bsw@0
 | 
   691       if (res) {
 | 
| 
jbe/bsw@0
 | 
   692         pgstatus = PQresultStatus(res);
 | 
| 
jbe/bsw@0
 | 
   693         rows = PQntuples(res);
 | 
| 
jbe/bsw@0
 | 
   694         cols = PQnfields(res);
 | 
| 
jbe/bsw@0
 | 
   695       }
 | 
| 
jbe/bsw@0
 | 
   696     }
 | 
| 
jbe/bsw@0
 | 
   697     if (
 | 
| 
jbe/bsw@0
 | 
   698       !sent_success || command_idx >= command_count || !res ||
 | 
| 
jbe/bsw@0
 | 
   699       (pgstatus != PGRES_TUPLES_OK && pgstatus != PGRES_COMMAND_OK) ||
 | 
| 
jbe/bsw@0
 | 
   700       (rows < 1 && mode == MONDELEFANT_QUERY_MODE_OBJECT) ||
 | 
| 
jbe/bsw@0
 | 
   701       (rows > 1 && mode != MONDELEFANT_QUERY_MODE_LIST)
 | 
| 
jbe/bsw@0
 | 
   702     ) {
 | 
| 
jbe/bsw@0
 | 
   703       const char *command;
 | 
| 
jbe/bsw@0
 | 
   704       command = lua_tostring(L, 2);
 | 
| 
jbe/bsw@0
 | 
   705       lua_newtable(L);  // 5
 | 
| 
jbe/bsw@0
 | 
   706       lua_getfield(L,
 | 
| 
jbe/bsw@0
 | 
   707         LUA_REGISTRYINDEX,
 | 
| 
jbe/bsw@0
 | 
   708         MONDELEFANT_ERROROBJECT_MT_REGKEY
 | 
| 
jbe/bsw@0
 | 
   709       );
 | 
| 
jbe/bsw@0
 | 
   710       lua_setmetatable(L, 5);
 | 
| 
jbe/bsw@0
 | 
   711       lua_pushvalue(L, 1);
 | 
| 
jbe/bsw@0
 | 
   712       lua_setfield(L, 5, "connection");
 | 
| 
jbe/bsw@0
 | 
   713       lua_pushinteger(L, command_idx + 1);
 | 
| 
jbe/bsw@0
 | 
   714       lua_setfield(L, 5, "command_number");
 | 
| 
jbe/bsw@0
 | 
   715       lua_pushvalue(L, 2);
 | 
| 
jbe/bsw@0
 | 
   716       lua_setfield(L, 5, "sql_command");
 | 
| 
jbe/bsw@0
 | 
   717       if (!res) {
 | 
| 
jbe/bsw@0
 | 
   718         lua_pushliteral(L, MONDELEFANT_ERRCODE_RESULTCOUNT_LOW);
 | 
| 
jbe/bsw@0
 | 
   719         lua_setfield(L, 5, "code");
 | 
| 
jbe/bsw@0
 | 
   720         lua_pushliteral(L, "Received too few database result sets.");
 | 
| 
jbe/bsw@0
 | 
   721         lua_setfield(L, 5, "message");
 | 
| 
jbe/bsw@0
 | 
   722       } else if (command_idx >= command_count) {
 | 
| 
jbe/bsw@0
 | 
   723         lua_pushliteral(L, MONDELEFANT_ERRCODE_RESULTCOUNT_HIGH);
 | 
| 
jbe/bsw@0
 | 
   724         lua_setfield(L, 5, "code");
 | 
| 
jbe/bsw@0
 | 
   725         lua_pushliteral(L, "Received too many database result sets.");
 | 
| 
jbe/bsw@0
 | 
   726         lua_setfield(L, 5, "message");
 | 
| 
jbe/bsw@0
 | 
   727       } else if (
 | 
| 
jbe/bsw@0
 | 
   728         pgstatus != PGRES_TUPLES_OK && pgstatus != PGRES_COMMAND_OK
 | 
| 
jbe/bsw@0
 | 
   729       ) {
 | 
| 
jbe/bsw@0
 | 
   730         const char *sqlstate;
 | 
| 
jbe/bsw@0
 | 
   731         const char *errmsg;
 | 
| 
jbe/bsw@0
 | 
   732         lua_pushstring(L, PQresultErrorField(res, PG_DIAG_SEVERITY));
 | 
| 
jbe/bsw@0
 | 
   733         lua_setfield(L, 5, "pg_severity");
 | 
| 
jbe/bsw@0
 | 
   734         sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
 | 
| 
jbe/bsw@0
 | 
   735         if (sqlstate) {
 | 
| 
jbe/bsw@0
 | 
   736           lua_pushstring(L, sqlstate);
 | 
| 
jbe/bsw@0
 | 
   737           lua_setfield(L, 5, "pg_sqlstate");
 | 
| 
jbe/bsw@0
 | 
   738           lua_pushstring(L, mondelefant_translate_errcode(sqlstate));
 | 
| 
jbe/bsw@0
 | 
   739           lua_setfield(L, 5, "code");
 | 
| 
jbe/bsw@0
 | 
   740         } else {
 | 
| 
jbe/bsw@0
 | 
   741           lua_pushliteral(L, MONDELEFANT_ERRCODE_UNKNOWN);
 | 
| 
jbe/bsw@0
 | 
   742           lua_setfield(L, 5, "code");
 | 
| 
jbe/bsw@0
 | 
   743         }
 | 
| 
jbe/bsw@0
 | 
   744         errmsg = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
 | 
| 
jbe/bsw@0
 | 
   745         if (errmsg) {
 | 
| 
jbe/bsw@0
 | 
   746           mondelefant_push_first_line(L, errmsg);
 | 
| 
jbe/bsw@0
 | 
   747           lua_setfield(L, 5, "message");
 | 
| 
jbe/bsw@0
 | 
   748           lua_pushstring(L, errmsg);
 | 
| 
jbe/bsw@0
 | 
   749           lua_setfield(L, 5, "pg_message_primary");
 | 
| 
jbe/bsw@0
 | 
   750         } else {
 | 
| 
jbe/bsw@0
 | 
   751           lua_pushliteral(L,
 | 
| 
jbe/bsw@0
 | 
   752             "Error while fetching result, but no error message given."
 | 
| 
jbe/bsw@0
 | 
   753           );
 | 
| 
jbe/bsw@0
 | 
   754           lua_setfield(L, 5, "message");
 | 
| 
jbe/bsw@0
 | 
   755         }
 | 
| 
jbe/bsw@0
 | 
   756         lua_pushstring(L, PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL));
 | 
| 
jbe/bsw@0
 | 
   757         lua_setfield(L, 5, "pg_message_detail");
 | 
| 
jbe/bsw@0
 | 
   758         lua_pushstring(L, PQresultErrorField(res, PG_DIAG_MESSAGE_HINT));
 | 
| 
jbe/bsw@0
 | 
   759         lua_setfield(L, 5, "pg_message_hint");
 | 
| 
jbe/bsw@0
 | 
   760         // NOTE: "position" and "pg_internal_position" are recalculated to
 | 
| 
jbe/bsw@0
 | 
   761         // byte offsets, as Lua 5.1 is not Unicode aware.
 | 
| 
jbe/bsw@0
 | 
   762         {
 | 
| 
jbe/bsw@0
 | 
   763           char *tmp;
 | 
| 
jbe/bsw@0
 | 
   764           tmp = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION);
 | 
| 
jbe/bsw@0
 | 
   765           if (tmp) {
 | 
| 
jbe/bsw@0
 | 
   766             int pos;
 | 
| 
jbe/bsw@0
 | 
   767             pos = atoi(tmp) - 1;
 | 
| 
jbe/bsw@0
 | 
   768             if (conn->server_encoding == MONDELEFANT_SERVER_ENCODING_UTF8) {
 | 
| 
jbe/bsw@0
 | 
   769               pos = utf8_position_to_byte(command, pos);
 | 
| 
jbe/bsw@0
 | 
   770             }
 | 
| 
jbe/bsw@0
 | 
   771             lua_pushinteger(L, pos + 1);
 | 
| 
jbe/bsw@0
 | 
   772             lua_setfield(L, 5, "position");
 | 
| 
jbe/bsw@0
 | 
   773           }
 | 
| 
jbe/bsw@0
 | 
   774         }
 | 
| 
jbe/bsw@0
 | 
   775         {
 | 
| 
jbe/bsw@0
 | 
   776           const char *internal_query;
 | 
| 
jbe/bsw@0
 | 
   777           internal_query = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
 | 
| 
jbe/bsw@0
 | 
   778           lua_pushstring(L, internal_query);
 | 
| 
jbe/bsw@0
 | 
   779           lua_setfield(L, 5, "pg_internal_query");
 | 
| 
jbe/bsw@0
 | 
   780           char *tmp;
 | 
| 
jbe/bsw@0
 | 
   781           tmp = PQresultErrorField(res, PG_DIAG_INTERNAL_POSITION);
 | 
| 
jbe/bsw@0
 | 
   782           if (tmp) {
 | 
| 
jbe/bsw@0
 | 
   783             int pos;
 | 
| 
jbe/bsw@0
 | 
   784             pos = atoi(tmp) - 1;
 | 
| 
jbe/bsw@0
 | 
   785             if (conn->server_encoding == MONDELEFANT_SERVER_ENCODING_UTF8) {
 | 
| 
jbe/bsw@0
 | 
   786               pos = utf8_position_to_byte(internal_query, pos);
 | 
| 
jbe/bsw@0
 | 
   787             }
 | 
| 
jbe/bsw@0
 | 
   788             lua_pushinteger(L, pos + 1);
 | 
| 
jbe/bsw@0
 | 
   789             lua_setfield(L, 5, "pg_internal_position");
 | 
| 
jbe/bsw@0
 | 
   790           }
 | 
| 
jbe/bsw@0
 | 
   791         }
 | 
| 
jbe/bsw@0
 | 
   792         lua_pushstring(L, PQresultErrorField(res, PG_DIAG_CONTEXT));
 | 
| 
jbe/bsw@0
 | 
   793         lua_setfield(L, 5, "pg_context");
 | 
| 
jbe/bsw@0
 | 
   794         lua_pushstring(L, PQresultErrorField(res, PG_DIAG_SOURCE_FILE));
 | 
| 
jbe/bsw@0
 | 
   795         lua_setfield(L, 5, "pg_source_file");
 | 
| 
jbe/bsw@0
 | 
   796         lua_pushstring(L, PQresultErrorField(res, PG_DIAG_SOURCE_LINE));
 | 
| 
jbe/bsw@0
 | 
   797         lua_setfield(L, 5, "pg_source_line");
 | 
| 
jbe/bsw@0
 | 
   798         lua_pushstring(L, PQresultErrorField(res, PG_DIAG_SOURCE_FUNCTION));
 | 
| 
jbe/bsw@0
 | 
   799         lua_setfield(L, 5, "pg_source_function");
 | 
| 
jbe/bsw@0
 | 
   800       } else if (rows < 1 && mode == MONDELEFANT_QUERY_MODE_OBJECT) {
 | 
| 
jbe/bsw@0
 | 
   801         lua_pushliteral(L, MONDELEFANT_ERRCODE_QUERY1_NO_ROWS);
 | 
| 
jbe/bsw@0
 | 
   802         lua_setfield(L, 5, "code");
 | 
| 
jbe/bsw@0
 | 
   803         lua_pushliteral(L, "Expected one row, but got empty set.");
 | 
| 
jbe/bsw@0
 | 
   804         lua_setfield(L, 5, "message");
 | 
| 
jbe/bsw@0
 | 
   805       } else if (rows > 1 && mode != MONDELEFANT_QUERY_MODE_LIST) {
 | 
| 
jbe/bsw@0
 | 
   806         lua_pushliteral(L, MONDELEFANT_ERRCODE_QUERY1_MULTIPLE_ROWS);
 | 
| 
jbe/bsw@0
 | 
   807         lua_setfield(L, 5, "code");
 | 
| 
jbe/bsw@0
 | 
   808         lua_pushliteral(L, "Got more than one result row.");
 | 
| 
jbe/bsw@0
 | 
   809         lua_setfield(L, 5, "message");
 | 
| 
jbe/bsw@0
 | 
   810       } else {
 | 
| 
jbe/bsw@0
 | 
   811         // should not happen
 | 
| 
jbe/bsw@0
 | 
   812         abort();
 | 
| 
jbe/bsw@0
 | 
   813       }
 | 
| 
jbe/bsw@0
 | 
   814       if (res) {
 | 
| 
jbe/bsw@0
 | 
   815         PQclear(res);
 | 
| 
jbe/bsw@0
 | 
   816         while ((res = PQgetResult(conn->pgconn))) PQclear(res);
 | 
| 
jbe/bsw@0
 | 
   817       }
 | 
| 
jbe/bsw@0
 | 
   818       if (lua_toboolean(L, 3)) {
 | 
| 
jbe/bsw@0
 | 
   819         lua_pushvalue(L, 3);
 | 
| 
jbe/bsw@0
 | 
   820         lua_pushvalue(L, 5);
 | 
| 
jbe/bsw@0
 | 
   821         lua_call(L, 1, 0);
 | 
| 
jbe/bsw@0
 | 
   822       }
 | 
| 
jbe/bsw@0
 | 
   823       return 1;
 | 
| 
jbe/bsw@0
 | 
   824     }
 | 
| 
jbe/bsw@0
 | 
   825     rows = PQntuples(res);
 | 
| 
jbe/bsw@0
 | 
   826     cols = PQnfields(res);
 | 
| 
jbe/bsw@0
 | 
   827     if (modes[command_idx] == MONDELEFANT_QUERY_MODE_LIST) {
 | 
| 
jbe/bsw@0
 | 
   828       lua_pushcfunction(L, mondelefant_conn_create_list);  // 5
 | 
| 
jbe/bsw@0
 | 
   829       lua_pushvalue(L, 1);  // 6
 | 
| 
jbe/bsw@0
 | 
   830       lua_call(L, 1, 1);  // 5
 | 
| 
jbe/bsw@0
 | 
   831     } else {
 | 
| 
jbe/bsw@0
 | 
   832       lua_pushcfunction(L, mondelefant_conn_create_object);  // 5
 | 
| 
jbe/bsw@0
 | 
   833       lua_pushvalue(L, 1);  // 6
 | 
| 
jbe/bsw@0
 | 
   834       lua_call(L, 1, 1);  // 5
 | 
| 
jbe/bsw@0
 | 
   835     }
 | 
| 
jbe/bsw@0
 | 
   836     lua_newtable(L);  // column_info at atack position 6
 | 
| 
jbe/bsw@0
 | 
   837     for (col = 0; col < cols; col++) {
 | 
| 
jbe/bsw@0
 | 
   838       lua_newtable(L);  // 7
 | 
| 
jbe/bsw@0
 | 
   839       lua_pushstring(L, PQfname(res, col));
 | 
| 
jbe/bsw@0
 | 
   840       lua_setfield(L, 7, "field_name");
 | 
| 
jbe/bsw@0
 | 
   841       {
 | 
| 
jbe/bsw@0
 | 
   842         Oid tmp;
 | 
| 
jbe/bsw@0
 | 
   843         tmp = PQftable(res, col);
 | 
| 
jbe/bsw@0
 | 
   844         if (tmp == InvalidOid) lua_pushnil(L);
 | 
| 
jbe/bsw@0
 | 
   845         else lua_pushinteger(L, tmp);
 | 
| 
jbe/bsw@0
 | 
   846         lua_setfield(L, 7, "table_oid");
 | 
| 
jbe/bsw@0
 | 
   847       }
 | 
| 
jbe/bsw@0
 | 
   848       {
 | 
| 
jbe/bsw@0
 | 
   849         int tmp;
 | 
| 
jbe/bsw@0
 | 
   850         tmp = PQftablecol(res, col);
 | 
| 
jbe/bsw@0
 | 
   851         if (tmp == 0) lua_pushnil(L);
 | 
| 
jbe/bsw@0
 | 
   852         else lua_pushinteger(L, tmp);
 | 
| 
jbe/bsw@0
 | 
   853         lua_setfield(L, 7, "table_column_number");
 | 
| 
jbe/bsw@0
 | 
   854       }
 | 
| 
jbe/bsw@0
 | 
   855       {
 | 
| 
jbe/bsw@0
 | 
   856         Oid tmp;
 | 
| 
jbe/bsw@0
 | 
   857         tmp = PQftype(res, col);
 | 
| 
jbe/bsw@0
 | 
   858         binary[col] = (tmp == MONDELEFANT_POSTGRESQL_BINARY_OID);
 | 
| 
jbe/bsw@0
 | 
   859         lua_pushinteger(L, tmp);
 | 
| 
jbe/bsw@0
 | 
   860         lua_setfield(L, 7, "type_oid");
 | 
| 
jbe/bsw@0
 | 
   861         lua_pushstring(L, mondelefant_oid_to_typestr(tmp));
 | 
| 
jbe/bsw@0
 | 
   862         lua_setfield(L, 7, "type");
 | 
| 
jbe/bsw@0
 | 
   863       }
 | 
| 
jbe/bsw@0
 | 
   864       {
 | 
| 
jbe/bsw@0
 | 
   865         int tmp;
 | 
| 
jbe/bsw@0
 | 
   866         tmp = PQfmod(res, col);
 | 
| 
jbe/bsw@0
 | 
   867         if (tmp == -1) lua_pushnil(L);
 | 
| 
jbe/bsw@0
 | 
   868         else lua_pushinteger(L, tmp);
 | 
| 
jbe/bsw@0
 | 
   869         lua_setfield(L, 7, "type_modifier");
 | 
| 
jbe/bsw@0
 | 
   870       }
 | 
| 
jbe/bsw@0
 | 
   871       lua_rawseti(L, 6, col+1);
 | 
| 
jbe/bsw@0
 | 
   872     }
 | 
| 
jbe/bsw@0
 | 
   873     lua_setfield(L, 5, "_column_info");  // stack at position 5 with result
 | 
| 
jbe/bsw@0
 | 
   874     {
 | 
| 
jbe/bsw@0
 | 
   875       char *tmp;
 | 
| 
jbe/bsw@0
 | 
   876       tmp = PQcmdTuples(res);
 | 
| 
jbe/bsw@0
 | 
   877       if (tmp[0]) {
 | 
| 
jbe/bsw@0
 | 
   878         lua_pushinteger(L, atoi(tmp));
 | 
| 
jbe/bsw@0
 | 
   879         lua_setfield(L, 5, "_rows_affected");
 | 
| 
jbe/bsw@0
 | 
   880       }
 | 
| 
jbe/bsw@0
 | 
   881     }
 | 
| 
jbe/bsw@0
 | 
   882     {
 | 
| 
jbe/bsw@0
 | 
   883       Oid tmp;
 | 
| 
jbe/bsw@0
 | 
   884       tmp = PQoidValue(res);
 | 
| 
jbe/bsw@0
 | 
   885       if (tmp != InvalidOid) {
 | 
| 
jbe/bsw@0
 | 
   886         lua_pushinteger(L, tmp);
 | 
| 
jbe/bsw@0
 | 
   887         lua_setfield(L, 5, "_oid");
 | 
| 
jbe/bsw@0
 | 
   888       }
 | 
| 
jbe/bsw@0
 | 
   889     }
 | 
| 
jbe/bsw@0
 | 
   890     if (modes[command_idx] == MONDELEFANT_QUERY_MODE_LIST) {
 | 
| 
jbe/bsw@0
 | 
   891       for (row = 0; row < rows; row++) {
 | 
| 
jbe/bsw@0
 | 
   892         lua_pushcfunction(L, mondelefant_conn_create_object);  // 6
 | 
| 
jbe/bsw@0
 | 
   893         lua_pushvalue(L, 1);  // 7
 | 
| 
jbe/bsw@0
 | 
   894         lua_call(L, 1, 1);  // 6
 | 
| 
jbe/bsw@0
 | 
   895         for (col = 0; col < cols; col++) {
 | 
| 
jbe/bsw@0
 | 
   896           if (PQgetisnull(res, row, col)) {
 | 
| 
jbe/bsw@0
 | 
   897             lua_pushnil(L);
 | 
| 
jbe/bsw@0
 | 
   898           } else if (binary[col]) {
 | 
| 
jbe/bsw@0
 | 
   899             size_t binlen;
 | 
| 
jbe/bsw@0
 | 
   900             char *binval;
 | 
| 
jbe/bsw@0
 | 
   901             binval = (char *)PQunescapeBytea(
 | 
| 
jbe/bsw@0
 | 
   902               (unsigned char *)PQgetvalue(res, row, col), &binlen
 | 
| 
jbe/bsw@0
 | 
   903             );
 | 
| 
jbe/bsw@0
 | 
   904             if (!binval) {
 | 
| 
jbe/bsw@0
 | 
   905               return luaL_error(L,
 | 
| 
jbe/bsw@0
 | 
   906                 "Could not allocate memory for binary unescaping."
 | 
| 
jbe/bsw@0
 | 
   907               );
 | 
| 
jbe/bsw@0
 | 
   908             }
 | 
| 
jbe/bsw@0
 | 
   909             lua_pushlstring(L, binval, binlen);
 | 
| 
jbe/bsw@0
 | 
   910             PQfreemem(binval);
 | 
| 
jbe/bsw@0
 | 
   911           } else {
 | 
| 
jbe/bsw@0
 | 
   912             lua_pushstring(L, PQgetvalue(res, row, col));
 | 
| 
jbe/bsw@0
 | 
   913           }
 | 
| 
jbe/bsw@0
 | 
   914           lua_rawseti(L, 6, col+1);
 | 
| 
jbe/bsw@0
 | 
   915         }
 | 
| 
jbe/bsw@0
 | 
   916         lua_rawseti(L, 5, row+1);
 | 
| 
jbe/bsw@0
 | 
   917       }
 | 
| 
jbe/bsw@0
 | 
   918     } else if (rows == 1) {
 | 
| 
jbe/bsw@0
 | 
   919       for (col = 0; col < cols; col++) {
 | 
| 
jbe/bsw@0
 | 
   920         if (PQgetisnull(res, 0, col)) {
 | 
| 
jbe/bsw@0
 | 
   921           lua_pushnil(L);
 | 
| 
jbe/bsw@0
 | 
   922         } else if (binary[col]) {
 | 
| 
jbe/bsw@0
 | 
   923           size_t binlen;
 | 
| 
jbe/bsw@0
 | 
   924           char *binval;
 | 
| 
jbe/bsw@0
 | 
   925           binval = (char *)PQunescapeBytea(
 | 
| 
jbe/bsw@0
 | 
   926             (unsigned char *)PQgetvalue(res, 0, col), &binlen
 | 
| 
jbe/bsw@0
 | 
   927           );
 | 
| 
jbe/bsw@0
 | 
   928           if (!binval) {
 | 
| 
jbe/bsw@0
 | 
   929             return luaL_error(L,
 | 
| 
jbe/bsw@0
 | 
   930               "Could not allocate memory for binary unescaping."
 | 
| 
jbe/bsw@0
 | 
   931             );
 | 
| 
jbe/bsw@0
 | 
   932           }
 | 
| 
jbe/bsw@0
 | 
   933           lua_pushlstring(L, binval, binlen);
 | 
| 
jbe/bsw@0
 | 
   934           PQfreemem(binval);
 | 
| 
jbe/bsw@0
 | 
   935         } else {
 | 
| 
jbe/bsw@0
 | 
   936           lua_pushstring(L, PQgetvalue(res, 0, col));
 | 
| 
jbe/bsw@0
 | 
   937         }
 | 
| 
jbe/bsw@0
 | 
   938         lua_rawseti(L, 5, col+1);
 | 
| 
jbe/bsw@0
 | 
   939       }
 | 
| 
jbe/bsw@0
 | 
   940     } else {
 | 
| 
jbe/bsw@0
 | 
   941       // no row in optrow mode
 | 
| 
jbe/bsw@0
 | 
   942       lua_pop(L, 1);
 | 
| 
jbe/bsw@0
 | 
   943       lua_pushnil(L);
 | 
| 
jbe/bsw@0
 | 
   944     }
 | 
| 
jbe/bsw@0
 | 
   945     lua_rawseti(L, 4, command_idx+1);
 | 
| 
jbe/bsw@0
 | 
   946     if (lua_gettop(L) != 4) abort();  // should not happen
 | 
| 
jbe/bsw@0
 | 
   947     PQclear(res);
 | 
| 
jbe/bsw@0
 | 
   948   }
 | 
| 
jbe/bsw@0
 | 
   949   // trace callback at stack position 3
 | 
| 
jbe/bsw@0
 | 
   950   // result at stack position 4 (top of stack)
 | 
| 
jbe/bsw@0
 | 
   951   if (lua_toboolean(L, 3)) {
 | 
| 
jbe/bsw@0
 | 
   952     lua_pushvalue(L, 3);
 | 
| 
jbe/bsw@0
 | 
   953     lua_call(L, 0, 0);
 | 
| 
jbe/bsw@0
 | 
   954   }
 | 
| 
jbe/bsw@0
 | 
   955   lua_replace(L, 3);  // result at stack position 3
 | 
| 
jbe/bsw@0
 | 
   956   lua_getfield(L, 1, "output_converter");  // output converter at stack position 4
 | 
| 
jbe/bsw@0
 | 
   957   for (command_idx = 0; command_idx < command_count; command_idx++) {
 | 
| 
jbe/bsw@0
 | 
   958     int mode;
 | 
| 
jbe/bsw@0
 | 
   959     mode = modes[command_idx];
 | 
| 
jbe/bsw@0
 | 
   960     lua_rawgeti(L, 3, command_idx+1);  // raw result at stack position 5
 | 
| 
jbe/bsw@0
 | 
   961     if (lua_toboolean(L, 5)) {
 | 
| 
jbe/bsw@0
 | 
   962       lua_getfield(L, 5, "_column_info");  // column_info list at position 6
 | 
| 
jbe/bsw@0
 | 
   963       cols = lua_objlen(L, 6);
 | 
| 
jbe/bsw@0
 | 
   964       if (mode == MONDELEFANT_QUERY_MODE_LIST) {
 | 
| 
jbe/bsw@0
 | 
   965         rows = lua_objlen(L, 5);
 | 
| 
jbe/bsw@0
 | 
   966         for (row = 0; row < rows; row++) {
 | 
| 
jbe/bsw@0
 | 
   967           lua_rawgeti(L, 5, row+1);  // row at stack position 7
 | 
| 
jbe/bsw@0
 | 
   968           lua_getfield(L, 7, "_data");  // _data table at stack position 8
 | 
| 
jbe/bsw@0
 | 
   969           for (col = 0; col < cols; col++) {
 | 
| 
jbe/bsw@0
 | 
   970             lua_rawgeti(L, 6, col+1);  // this column info at position 9
 | 
| 
jbe/bsw@0
 | 
   971             lua_getfield(L, 9, "field_name");  // 10
 | 
| 
jbe/bsw@0
 | 
   972             if (lua_toboolean(L, 4)) {
 | 
| 
jbe/bsw@0
 | 
   973               lua_pushvalue(L, 4);  // output-converter
 | 
| 
jbe/bsw@0
 | 
   974               lua_pushvalue(L, 1);  // connection
 | 
| 
jbe/bsw@0
 | 
   975               lua_rawgeti(L, 7, col+1);  // raw-value
 | 
| 
jbe/bsw@0
 | 
   976               lua_pushvalue(L, 9);  // this column info
 | 
| 
jbe/bsw@0
 | 
   977               lua_call(L, 3, 1);  // converted value at position 11
 | 
| 
jbe/bsw@0
 | 
   978             } else {
 | 
| 
jbe/bsw@0
 | 
   979               lua_rawgeti(L, 7, col+1);  // raw-value at position 11
 | 
| 
jbe/bsw@0
 | 
   980             }
 | 
| 
jbe/bsw@0
 | 
   981             lua_pushvalue(L, 11);  // 12
 | 
| 
jbe/bsw@0
 | 
   982             lua_rawseti(L, 7, col+1);
 | 
| 
jbe/bsw@0
 | 
   983             lua_rawset(L, 8);
 | 
| 
jbe/bsw@0
 | 
   984             lua_settop(L, 8);
 | 
| 
jbe/bsw@0
 | 
   985           }
 | 
| 
jbe/bsw@0
 | 
   986           lua_settop(L, 6);
 | 
| 
jbe/bsw@0
 | 
   987         }
 | 
| 
jbe/bsw@0
 | 
   988       } else {
 | 
| 
jbe/bsw@0
 | 
   989         lua_getfield(L, 5, "_data");  // _data table at stack position 7
 | 
| 
jbe/bsw@0
 | 
   990         for (col = 0; col < cols; col++) {
 | 
| 
jbe/bsw@0
 | 
   991           lua_rawgeti(L, 6, col+1);  // this column info at position 8
 | 
| 
jbe/bsw@0
 | 
   992           lua_getfield(L, 8, "field_name");  // 9
 | 
| 
jbe/bsw@0
 | 
   993           if (lua_toboolean(L, 4)) {
 | 
| 
jbe/bsw@0
 | 
   994             lua_pushvalue(L, 4);  // output-converter
 | 
| 
jbe/bsw@0
 | 
   995             lua_pushvalue(L, 1);  // connection
 | 
| 
jbe/bsw@0
 | 
   996             lua_rawgeti(L, 5, col+1);  // raw-value
 | 
| 
jbe/bsw@0
 | 
   997             lua_pushvalue(L, 8);  // this column info
 | 
| 
jbe/bsw@0
 | 
   998             lua_call(L, 3, 1);  // converted value at position 10
 | 
| 
jbe/bsw@0
 | 
   999           } else {
 | 
| 
jbe/bsw@0
 | 
  1000             lua_rawgeti(L, 5, col+1);  // raw-value at position 10
 | 
| 
jbe/bsw@0
 | 
  1001           }
 | 
| 
jbe/bsw@0
 | 
  1002           lua_pushvalue(L, 10);  // 11
 | 
| 
jbe/bsw@0
 | 
  1003           lua_rawseti(L, 5, col+1);
 | 
| 
jbe/bsw@0
 | 
  1004           lua_rawset(L, 7);
 | 
| 
jbe/bsw@0
 | 
  1005           lua_settop(L, 7);
 | 
| 
jbe/bsw@0
 | 
  1006         }
 | 
| 
jbe/bsw@0
 | 
  1007       }
 | 
| 
jbe/bsw@0
 | 
  1008     }
 | 
| 
jbe/bsw@0
 | 
  1009     lua_settop(L, 4);
 | 
| 
jbe/bsw@0
 | 
  1010   }
 | 
| 
jbe/bsw@0
 | 
  1011   lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1012   lua_pushnil(L);
 | 
| 
jbe/bsw@0
 | 
  1013   for (command_idx = 0; command_idx < command_count; command_idx++) {
 | 
| 
jbe/bsw@0
 | 
  1014     lua_rawgeti(L, 3, command_idx+1);
 | 
| 
jbe/bsw@0
 | 
  1015   }
 | 
| 
jbe/bsw@0
 | 
  1016   return command_count+1;
 | 
| 
jbe/bsw@0
 | 
  1017 }
 | 
| 
jbe/bsw@0
 | 
  1018 
 | 
| 
jbe/bsw@0
 | 
  1019 static int mondelefant_errorobject_escalate(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
  1020   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1021   lua_getfield(L, 1, "connection");  // 2
 | 
| 
jbe/bsw@0
 | 
  1022   lua_getfield(L, 2, "error_objects");  // 3
 | 
| 
jbe/bsw@0
 | 
  1023   if (lua_toboolean(L, 3)) {
 | 
| 
jbe/bsw@0
 | 
  1024     lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1025     return lua_error(L);
 | 
| 
jbe/bsw@0
 | 
  1026   } else {
 | 
| 
jbe/bsw@0
 | 
  1027     lua_getfield(L, 1, "message");  // 4
 | 
| 
jbe/bsw@0
 | 
  1028     if (lua_isnil(L, 4)) {
 | 
| 
jbe/bsw@0
 | 
  1029       return luaL_error(L, "No error message given for escalation.");
 | 
| 
jbe/bsw@0
 | 
  1030     }
 | 
| 
jbe/bsw@0
 | 
  1031     return lua_error(L);
 | 
| 
jbe/bsw@0
 | 
  1032   }
 | 
| 
jbe/bsw@0
 | 
  1033 }
 | 
| 
jbe/bsw@0
 | 
  1034 
 | 
| 
jbe/bsw@0
 | 
  1035 static int mondelefant_errorobject_is_kind_of(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
  1036   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1037   lua_getfield(L, 1, "code");  // 3
 | 
| 
jbe/bsw@0
 | 
  1038   if (lua_isstring(L, 3)) {
 | 
| 
jbe/bsw@0
 | 
  1039     lua_pushboolean(L,
 | 
| 
jbe/bsw@0
 | 
  1040       mondelefant_check_error_class(
 | 
| 
jbe/bsw@0
 | 
  1041         lua_tostring(L, 3), luaL_checkstring(L, 2)
 | 
| 
jbe/bsw@0
 | 
  1042       )
 | 
| 
jbe/bsw@0
 | 
  1043     );
 | 
| 
jbe/bsw@0
 | 
  1044   } else {
 | 
| 
jbe/bsw@0
 | 
  1045     // only happens for errors where code is not set
 | 
| 
jbe/bsw@0
 | 
  1046     lua_pushboolean(L, 0);
 | 
| 
jbe/bsw@0
 | 
  1047   }
 | 
| 
jbe/bsw@0
 | 
  1048   return 1;
 | 
| 
jbe/bsw@0
 | 
  1049 }
 | 
| 
jbe/bsw@0
 | 
  1050 
 | 
| 
jbe/bsw@0
 | 
  1051 static int mondelefant_conn_query(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
  1052   int argc;
 | 
| 
jbe/bsw@0
 | 
  1053   argc = lua_gettop(L);
 | 
| 
jbe/bsw@0
 | 
  1054   lua_pushvalue(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1055   lua_insert(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1056   lua_pushcfunction(L, mondelefant_conn_try_query);
 | 
| 
jbe/bsw@0
 | 
  1057   lua_insert(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1058   lua_call(L, argc, LUA_MULTRET);  // results (with error) starting at index 2
 | 
| 
jbe/bsw@0
 | 
  1059   if (lua_toboolean(L, 2)) {
 | 
| 
jbe/bsw@0
 | 
  1060     lua_pushcfunction(L, mondelefant_errorobject_escalate);
 | 
| 
jbe/bsw@0
 | 
  1061     lua_pushvalue(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1062     lua_call(L, 1, 0);  // will raise an error
 | 
| 
jbe/bsw@0
 | 
  1063     return 0;  // should not be executed
 | 
| 
jbe/bsw@0
 | 
  1064   } else {
 | 
| 
jbe/bsw@0
 | 
  1065     return lua_gettop(L) - 2;
 | 
| 
jbe/bsw@0
 | 
  1066   }
 | 
| 
jbe/bsw@0
 | 
  1067 }
 | 
| 
jbe/bsw@0
 | 
  1068 
 | 
| 
jbe/bsw@0
 | 
  1069 static int mondelefant_set_class(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
  1070   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1071   lua_getmetatable(L, 1);  // 3
 | 
| 
jbe/bsw@0
 | 
  1072   lua_getfield(L, LUA_REGISTRYINDEX, MONDELEFANT_RESULT_MT_REGKEY);  // 4
 | 
| 
jbe/bsw@0
 | 
  1073   luaL_argcheck(L, lua_equal(L, 3, 4), 1, "not a database result");
 | 
| 
jbe/bsw@0
 | 
  1074   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1075   lua_getmetatable(L, 2);  // 3
 | 
| 
jbe/bsw@0
 | 
  1076   lua_getfield(L, LUA_REGISTRYINDEX, MONDELEFANT_CLASS_MT_REGKEY);  // 4
 | 
| 
jbe/bsw@0
 | 
  1077   luaL_argcheck(L, lua_equal(L, 3, 4), 2, "not a database class");
 | 
| 
jbe/bsw@0
 | 
  1078   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1079   lua_pushvalue(L, 2);  // 3
 | 
| 
jbe/bsw@0
 | 
  1080   lua_setfield(L, 1, "_class");
 | 
| 
jbe/bsw@0
 | 
  1081   lua_getfield(L, 1, "_type");  // 3
 | 
| 
jbe/bsw@0
 | 
  1082   lua_pushliteral(L, "list");  // 4
 | 
| 
jbe/bsw@0
 | 
  1083   if (lua_rawequal(L, 3, 4)) {
 | 
| 
jbe/bsw@0
 | 
  1084     int i;
 | 
| 
jbe/bsw@0
 | 
  1085     for (i=0; i < lua_objlen(L, 1); i++) {
 | 
| 
jbe/bsw@0
 | 
  1086       lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1087       lua_rawgeti(L, 1, i+1);  // 3
 | 
| 
jbe/bsw@0
 | 
  1088       lua_pushvalue(L, 2);  // 4
 | 
| 
jbe/bsw@0
 | 
  1089       lua_setfield(L, 3, "_class");
 | 
| 
jbe/bsw@0
 | 
  1090     }
 | 
| 
jbe/bsw@0
 | 
  1091   }
 | 
| 
jbe/bsw@0
 | 
  1092   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1093   return 1;
 | 
| 
jbe/bsw@0
 | 
  1094 }
 | 
| 
jbe/bsw@0
 | 
  1095 
 | 
| 
jbe/bsw@0
 | 
  1096 static int mondelefant_new_class(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
  1097   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1098   if (!lua_toboolean(L, 1)) {
 | 
| 
jbe/bsw@0
 | 
  1099     lua_settop(L, 0);
 | 
| 
jbe/bsw@0
 | 
  1100     lua_newtable(L);  // 1
 | 
| 
jbe/bsw@0
 | 
  1101   }
 | 
| 
jbe/bsw@0
 | 
  1102   lua_getfield(L, LUA_REGISTRYINDEX, MONDELEFANT_CLASS_MT_REGKEY);  // 2
 | 
| 
jbe/bsw@0
 | 
  1103   lua_setmetatable(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1104   lua_pushliteral(L, "prototype");  // 2
 | 
| 
jbe/bsw@0
 | 
  1105   lua_rawget(L, 1);  // 2
 | 
| 
jbe/bsw@0
 | 
  1106   if (!lua_toboolean(L, 2)) {
 | 
| 
jbe/bsw@0
 | 
  1107     lua_pushliteral(L, "prototype");  // 3
 | 
| 
jbe/bsw@0
 | 
  1108     lua_getfield(L,
 | 
| 
jbe/bsw@0
 | 
  1109       LUA_REGISTRYINDEX,
 | 
| 
jbe/bsw@0
 | 
  1110       MONDELEFANT_CLASS_PROTO_REGKEY
 | 
| 
jbe/bsw@0
 | 
  1111     );  // 4
 | 
| 
jbe/bsw@0
 | 
  1112     lua_rawset(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1113   }
 | 
| 
jbe/bsw@0
 | 
  1114   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1115   lua_pushliteral(L, "object");  // 2
 | 
| 
jbe/bsw@0
 | 
  1116   lua_rawget(L, 1);  // 2
 | 
| 
jbe/bsw@0
 | 
  1117   if (!lua_toboolean(L, 2)) {
 | 
| 
jbe/bsw@0
 | 
  1118     lua_pushliteral(L, "object");  // 3
 | 
| 
jbe/bsw@0
 | 
  1119     lua_newtable(L);  // 4
 | 
| 
jbe/bsw@0
 | 
  1120     lua_rawset(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1121   }
 | 
| 
jbe/bsw@0
 | 
  1122   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1123   lua_pushliteral(L, "object_get");  // 2
 | 
| 
jbe/bsw@0
 | 
  1124   lua_rawget(L, 1);  // 2
 | 
| 
jbe/bsw@0
 | 
  1125   if (!lua_toboolean(L, 2)) {
 | 
| 
jbe/bsw@0
 | 
  1126     lua_pushliteral(L, "object_get");  // 3
 | 
| 
jbe/bsw@0
 | 
  1127     lua_newtable(L);  // 4
 | 
| 
jbe/bsw@0
 | 
  1128     lua_rawset(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1129   }
 | 
| 
jbe/bsw@0
 | 
  1130   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1131   lua_pushliteral(L, "object_set");  // 2
 | 
| 
jbe/bsw@0
 | 
  1132   lua_rawget(L, 1);  // 2
 | 
| 
jbe/bsw@0
 | 
  1133   if (!lua_toboolean(L, 2)) {
 | 
| 
jbe/bsw@0
 | 
  1134     lua_pushliteral(L, "object_set");  // 3
 | 
| 
jbe/bsw@0
 | 
  1135     lua_newtable(L);  // 4
 | 
| 
jbe/bsw@0
 | 
  1136     lua_rawset(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1137   }
 | 
| 
jbe/bsw@0
 | 
  1138   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1139   lua_pushliteral(L, "list");  // 2
 | 
| 
jbe/bsw@0
 | 
  1140   lua_rawget(L, 1);  // 2
 | 
| 
jbe/bsw@0
 | 
  1141   if (!lua_toboolean(L, 2)) {
 | 
| 
jbe/bsw@0
 | 
  1142     lua_pushliteral(L, "list");  // 3
 | 
| 
jbe/bsw@0
 | 
  1143     lua_newtable(L);  // 4
 | 
| 
jbe/bsw@0
 | 
  1144     lua_rawset(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1145   }
 | 
| 
jbe/bsw@0
 | 
  1146   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1147   lua_pushliteral(L, "references");  // 2
 | 
| 
jbe/bsw@0
 | 
  1148   lua_rawget(L, 1);  // 2
 | 
| 
jbe/bsw@0
 | 
  1149   if (!lua_toboolean(L, 2)) {
 | 
| 
jbe/bsw@0
 | 
  1150     lua_pushliteral(L, "references");  // 3
 | 
| 
jbe/bsw@0
 | 
  1151     lua_newtable(L);  // 4
 | 
| 
jbe/bsw@0
 | 
  1152     lua_rawset(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1153   }
 | 
| 
jbe/bsw@0
 | 
  1154   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1155   lua_pushliteral(L, "foreign_keys");  // 2
 | 
| 
jbe/bsw@0
 | 
  1156   lua_rawget(L, 1);  // 2
 | 
| 
jbe/bsw@0
 | 
  1157   if (!lua_toboolean(L, 2)) {
 | 
| 
jbe/bsw@0
 | 
  1158     lua_pushliteral(L, "foreign_keys");  // 3
 | 
| 
jbe/bsw@0
 | 
  1159     lua_newtable(L);  // 4
 | 
| 
jbe/bsw@0
 | 
  1160     lua_rawset(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1161   }
 | 
| 
jbe/bsw@0
 | 
  1162   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1163   return 1;
 | 
| 
jbe/bsw@0
 | 
  1164 }
 | 
| 
jbe/bsw@0
 | 
  1165 
 | 
| 
jbe/bsw@0
 | 
  1166 static int mondelefant_class_get_reference(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
  1167   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1168   while (lua_toboolean(L, 1)) {
 | 
| 
jbe/bsw@0
 | 
  1169     lua_getfield(L, 1, "references");  // 3
 | 
| 
jbe/bsw@0
 | 
  1170     lua_pushvalue(L, 2);  // 4
 | 
| 
jbe/bsw@0
 | 
  1171     lua_gettable(L, 3);  // 4
 | 
| 
jbe/bsw@0
 | 
  1172     if (!lua_isnil(L, 4)) return 1;
 | 
| 
jbe/bsw@0
 | 
  1173     lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1174     lua_pushliteral(L, "prototype");  // 3
 | 
| 
jbe/bsw@0
 | 
  1175     lua_rawget(L, 1);  // 3
 | 
| 
jbe/bsw@0
 | 
  1176     lua_replace(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1177   }
 | 
| 
jbe/bsw@0
 | 
  1178   return 0;
 | 
| 
jbe/bsw@0
 | 
  1179 }
 | 
| 
jbe/bsw@0
 | 
  1180 
 | 
| 
jbe/bsw@0
 | 
  1181 static int mondelefant_class_iterate_over_references(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
  1182   return luaL_error(L, "Reference iterator not implemented yet.");  // TODO
 | 
| 
jbe/bsw@0
 | 
  1183 }
 | 
| 
jbe/bsw@0
 | 
  1184 
 | 
| 
jbe/bsw@0
 | 
  1185 static int mondelefant_class_get_foreign_key_reference_name(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
  1186   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1187   while (lua_toboolean(L, 1)) {
 | 
| 
jbe/bsw@0
 | 
  1188     lua_getfield(L, 1, "foreign_keys");  // 3
 | 
| 
jbe/bsw@0
 | 
  1189     lua_pushvalue(L, 2);  // 4
 | 
| 
jbe/bsw@0
 | 
  1190     lua_gettable(L, 3);  // 4
 | 
| 
jbe/bsw@0
 | 
  1191     if (!lua_isnil(L, 4)) return 1;
 | 
| 
jbe/bsw@0
 | 
  1192     lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1193     lua_pushliteral(L, "prototype");  // 3
 | 
| 
jbe/bsw@0
 | 
  1194     lua_rawget(L, 1);  // 3
 | 
| 
jbe/bsw@0
 | 
  1195     lua_replace(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1196   }
 | 
| 
jbe/bsw@0
 | 
  1197   return 0;
 | 
| 
jbe/bsw@0
 | 
  1198 }
 | 
| 
jbe/bsw@0
 | 
  1199 
 | 
| 
jbe/bsw@0
 | 
  1200 static int mondelefant_result_index(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
  1201   const char *result_type;
 | 
| 
jbe/bsw@0
 | 
  1202   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1203   if (lua_type(L, 2) != LUA_TSTRING || lua_tostring(L, 2)[0] == '_') {
 | 
| 
jbe/bsw@0
 | 
  1204     lua_rawget(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1205     return 1;
 | 
| 
jbe/bsw@0
 | 
  1206   }
 | 
| 
jbe/bsw@0
 | 
  1207   lua_getfield(L, 1, "_class");  // 3
 | 
| 
jbe/bsw@0
 | 
  1208   if (!lua_toboolean(L, 3)) {
 | 
| 
jbe/bsw@0
 | 
  1209     lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1210     lua_getfield(L,
 | 
| 
jbe/bsw@0
 | 
  1211       LUA_REGISTRYINDEX,
 | 
| 
jbe/bsw@0
 | 
  1212       MONDELEFANT_CLASS_PROTO_REGKEY
 | 
| 
jbe/bsw@0
 | 
  1213     );  // 3
 | 
| 
jbe/bsw@0
 | 
  1214   }
 | 
| 
jbe/bsw@0
 | 
  1215   lua_getfield(L, 1, "_type");  // 4
 | 
| 
jbe/bsw@0
 | 
  1216   result_type = lua_tostring(L, 4);
 | 
| 
jbe/bsw@0
 | 
  1217   if (result_type && !strcmp(result_type, "object")) {
 | 
| 
jbe/bsw@0
 | 
  1218     lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1219     // try inherited attributes, methods or getter functions:
 | 
| 
jbe/bsw@0
 | 
  1220     while (lua_toboolean(L, 3)) {
 | 
| 
jbe/bsw@0
 | 
  1221       lua_getfield(L, 3, "object");  // 4
 | 
| 
jbe/bsw@0
 | 
  1222       lua_pushvalue(L, 2);  // 5
 | 
| 
jbe/bsw@0
 | 
  1223       lua_gettable(L, 4);  // 5
 | 
| 
jbe/bsw@0
 | 
  1224       if (!lua_isnil(L, 5)) return 1;
 | 
| 
jbe/bsw@0
 | 
  1225       lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1226       lua_getfield(L, 3, "object_get");  // 4
 | 
| 
jbe/bsw@0
 | 
  1227       lua_pushvalue(L, 2);  // 5
 | 
| 
jbe/bsw@0
 | 
  1228       lua_gettable(L, 4);  // 5
 | 
| 
jbe/bsw@0
 | 
  1229       if (lua_toboolean(L, 5)) {
 | 
| 
jbe/bsw@0
 | 
  1230         lua_pushvalue(L, 1);  // 6
 | 
| 
jbe/bsw@0
 | 
  1231         lua_call(L, 1, 1);  // 5
 | 
| 
jbe/bsw@0
 | 
  1232         return 1;
 | 
| 
jbe/bsw@0
 | 
  1233       }
 | 
| 
jbe/bsw@0
 | 
  1234       lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1235       lua_pushliteral(L, "prototype");  // 4
 | 
| 
jbe/bsw@0
 | 
  1236       lua_rawget(L, 3);  // 4
 | 
| 
jbe/bsw@0
 | 
  1237       lua_replace(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1238     }
 | 
| 
jbe/bsw@0
 | 
  1239     lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1240     // try primary keys of referenced objects:
 | 
| 
jbe/bsw@0
 | 
  1241     lua_pushcfunction(L,
 | 
| 
jbe/bsw@0
 | 
  1242       mondelefant_class_get_foreign_key_reference_name
 | 
| 
jbe/bsw@0
 | 
  1243     );  // 3
 | 
| 
jbe/bsw@0
 | 
  1244     lua_getfield(L, 1, "_class");  // 4
 | 
| 
jbe/bsw@0
 | 
  1245     lua_pushvalue(L, 2);  // 5
 | 
| 
jbe/bsw@0
 | 
  1246     lua_call(L, 2, 1);  // 3
 | 
| 
jbe/bsw@0
 | 
  1247     if (!lua_isnil(L, 3)) {
 | 
| 
jbe/bsw@0
 | 
  1248       // reference name at stack position 3
 | 
| 
jbe/bsw@0
 | 
  1249       lua_pushcfunction(L, mondelefant_class_get_reference);  // 4
 | 
| 
jbe/bsw@0
 | 
  1250       lua_getfield(L, 1, "_class");  // 5
 | 
| 
jbe/bsw@0
 | 
  1251       lua_pushvalue(L, 3);  // 6
 | 
| 
jbe/bsw@0
 | 
  1252       lua_call(L, 2, 1);  // reference info at stack position 4
 | 
| 
jbe/bsw@0
 | 
  1253       lua_getfield(L, 1, "_ref");  // 5
 | 
| 
jbe/bsw@0
 | 
  1254       lua_getfield(L, 4, "ref");  // 6
 | 
| 
jbe/bsw@0
 | 
  1255       lua_gettable(L, 5);  // 6
 | 
| 
jbe/bsw@0
 | 
  1256       if (!lua_isnil(L, 6)) {
 | 
| 
jbe/bsw@0
 | 
  1257         if (lua_toboolean(L, 6)) {
 | 
| 
jbe/bsw@0
 | 
  1258           lua_getfield(L, 4, "that_key");  // 7
 | 
| 
jbe/bsw@0
 | 
  1259           if (lua_isnil(L, 7)) {
 | 
| 
jbe/bsw@0
 | 
  1260             return luaL_error(L, "Missing 'that_key' entry in model reference.");
 | 
| 
jbe/bsw@0
 | 
  1261           }
 | 
| 
jbe/bsw@0
 | 
  1262           lua_gettable(L, 6);  // 7
 | 
| 
jbe/bsw@0
 | 
  1263         } else {
 | 
| 
jbe/bsw@0
 | 
  1264           lua_pushnil(L);
 | 
| 
jbe/bsw@0
 | 
  1265         }
 | 
| 
jbe/bsw@0
 | 
  1266         return 1;
 | 
| 
jbe/bsw@0
 | 
  1267       }
 | 
| 
jbe/bsw@0
 | 
  1268     }
 | 
| 
jbe/bsw@0
 | 
  1269     lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1270     // try normal data field info:
 | 
| 
jbe/bsw@0
 | 
  1271     lua_getfield(L, 1, "_data");  // 3
 | 
| 
jbe/bsw@0
 | 
  1272     lua_pushvalue(L, 2);  // 4
 | 
| 
jbe/bsw@0
 | 
  1273     lua_gettable(L, 3);  // 4
 | 
| 
jbe/bsw@0
 | 
  1274     if (!lua_isnil(L, 4)) return 1;
 | 
| 
jbe/bsw@0
 | 
  1275     lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1276     // try cached referenced object (or cached NULL reference):
 | 
| 
jbe/bsw@0
 | 
  1277     lua_getfield(L, 1, "_ref");  // 3
 | 
| 
jbe/bsw@0
 | 
  1278     lua_pushvalue(L, 2);  // 4
 | 
| 
jbe/bsw@0
 | 
  1279     lua_gettable(L, 3);  // 4
 | 
| 
jbe/bsw@0
 | 
  1280     if (lua_isboolean(L, 4) && !lua_toboolean(L, 4)) {
 | 
| 
jbe/bsw@0
 | 
  1281       lua_pushnil(L);
 | 
| 
jbe/bsw@0
 | 
  1282       return 1;
 | 
| 
jbe/bsw@0
 | 
  1283     } else if (!lua_isnil(L, 4)) {
 | 
| 
jbe/bsw@0
 | 
  1284       return 1;
 | 
| 
jbe/bsw@0
 | 
  1285     }
 | 
| 
jbe/bsw@0
 | 
  1286     lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1287     // try to load a referenced object:
 | 
| 
jbe/bsw@0
 | 
  1288     lua_pushcfunction(L, mondelefant_class_get_reference);  // 3
 | 
| 
jbe/bsw@0
 | 
  1289     lua_getfield(L, 1, "_class");  // 4
 | 
| 
jbe/bsw@0
 | 
  1290     lua_pushvalue(L, 2);  // 5
 | 
| 
jbe/bsw@0
 | 
  1291     lua_call(L, 2, 1);  // 3
 | 
| 
jbe/bsw@0
 | 
  1292     if (!lua_isnil(L, 3)) {
 | 
| 
jbe/bsw@0
 | 
  1293       lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1294       lua_getfield(L, 1, "load");  // 3
 | 
| 
jbe/bsw@0
 | 
  1295       lua_pushvalue(L, 1);  // 4 (self)
 | 
| 
jbe/bsw@0
 | 
  1296       lua_pushvalue(L, 2);  // 5
 | 
| 
jbe/bsw@0
 | 
  1297       lua_call(L, 2, 0);
 | 
| 
jbe/bsw@0
 | 
  1298       lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1299       lua_getfield(L, 1, "_ref");  // 3
 | 
| 
jbe/bsw@0
 | 
  1300       lua_pushvalue(L, 2);  // 4
 | 
| 
jbe/bsw@0
 | 
  1301       lua_gettable(L, 3);  // 4
 | 
| 
jbe/bsw@0
 | 
  1302       if (lua_isboolean(L, 4) && !lua_toboolean(L, 4)) lua_pushnil(L);  // TODO: use special object instead of false
 | 
| 
jbe/bsw@0
 | 
  1303       return 1;
 | 
| 
jbe/bsw@0
 | 
  1304     }
 | 
| 
jbe/bsw@0
 | 
  1305     return 0;
 | 
| 
jbe/bsw@0
 | 
  1306   } else if (result_type && !strcmp(result_type, "list")) {
 | 
| 
jbe/bsw@0
 | 
  1307     lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1308     // try inherited list attributes or methods:
 | 
| 
jbe/bsw@0
 | 
  1309     while (lua_toboolean(L, 3)) {
 | 
| 
jbe/bsw@0
 | 
  1310       lua_getfield(L, 3, "list");  // 4
 | 
| 
jbe/bsw@0
 | 
  1311       lua_pushvalue(L, 2);  // 5
 | 
| 
jbe/bsw@0
 | 
  1312       lua_gettable(L, 4);  // 5
 | 
| 
jbe/bsw@0
 | 
  1313       if (!lua_isnil(L, 5)) return 1;
 | 
| 
jbe/bsw@0
 | 
  1314       lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1315       lua_pushliteral(L, "prototype");  // 4
 | 
| 
jbe/bsw@0
 | 
  1316       lua_rawget(L, 3);  // 4
 | 
| 
jbe/bsw@0
 | 
  1317       lua_replace(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1318     }
 | 
| 
jbe/bsw@0
 | 
  1319   }
 | 
| 
jbe/bsw@0
 | 
  1320   return 0;
 | 
| 
jbe/bsw@0
 | 
  1321 }
 | 
| 
jbe/bsw@0
 | 
  1322 
 | 
| 
jbe/bsw@0
 | 
  1323 static int mondelefant_result_newindex(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
  1324   const char *result_type;
 | 
| 
jbe/bsw@0
 | 
  1325   lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1326   if (lua_type(L, 2) != LUA_TSTRING || lua_tostring(L, 2)[0] == '_') {
 | 
| 
jbe/bsw@0
 | 
  1327     lua_rawset(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1328     return 1;
 | 
| 
jbe/bsw@0
 | 
  1329   }
 | 
| 
jbe/bsw@0
 | 
  1330   lua_getfield(L, 1, "_class");  // 4
 | 
| 
jbe/bsw@0
 | 
  1331   if (!lua_toboolean(L, 4)) {
 | 
| 
jbe/bsw@0
 | 
  1332     lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1333     lua_getfield(L,
 | 
| 
jbe/bsw@0
 | 
  1334       LUA_REGISTRYINDEX,
 | 
| 
jbe/bsw@0
 | 
  1335       MONDELEFANT_CLASS_PROTO_REGKEY
 | 
| 
jbe/bsw@0
 | 
  1336     );  // 4
 | 
| 
jbe/bsw@0
 | 
  1337   }
 | 
| 
jbe/bsw@0
 | 
  1338   lua_getfield(L, 1, "_type");  // 5
 | 
| 
jbe/bsw@0
 | 
  1339   result_type = lua_tostring(L, 5);
 | 
| 
jbe/bsw@0
 | 
  1340   if (result_type && !strcmp(result_type, "object")) {
 | 
| 
jbe/bsw@0
 | 
  1341     lua_settop(L, 4);
 | 
| 
jbe/bsw@0
 | 
  1342     // try object setter functions:
 | 
| 
jbe/bsw@0
 | 
  1343     while (lua_toboolean(L, 4)) {
 | 
| 
jbe/bsw@0
 | 
  1344       lua_getfield(L, 4, "object_set");  // 5
 | 
| 
jbe/bsw@0
 | 
  1345       lua_pushvalue(L, 2);  // 6
 | 
| 
jbe/bsw@0
 | 
  1346       lua_gettable(L, 5);  // 6
 | 
| 
jbe/bsw@0
 | 
  1347       if (lua_toboolean(L, 6)) {
 | 
| 
jbe/bsw@0
 | 
  1348         lua_pushvalue(L, 1);  // 7
 | 
| 
jbe/bsw@0
 | 
  1349         lua_pushvalue(L, 3);  // 8
 | 
| 
jbe/bsw@0
 | 
  1350         lua_call(L, 2, 0);
 | 
| 
jbe/bsw@0
 | 
  1351         return 0;
 | 
| 
jbe/bsw@0
 | 
  1352       }
 | 
| 
jbe/bsw@0
 | 
  1353       lua_settop(L, 4);
 | 
| 
jbe/bsw@0
 | 
  1354       lua_pushliteral(L, "prototype");  // 5
 | 
| 
jbe/bsw@0
 | 
  1355       lua_rawget(L, 4);  // 5
 | 
| 
jbe/bsw@0
 | 
  1356       lua_replace(L, 4);
 | 
| 
jbe/bsw@0
 | 
  1357     }
 | 
| 
jbe/bsw@0
 | 
  1358     lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1359     // check, if a object reference is changed:
 | 
| 
jbe/bsw@0
 | 
  1360     lua_pushcfunction(L, mondelefant_class_get_reference);  // 4
 | 
| 
jbe/bsw@0
 | 
  1361     lua_getfield(L, 1, "_class");  // 5
 | 
| 
jbe/bsw@0
 | 
  1362     lua_pushvalue(L, 2);  // 6
 | 
| 
jbe/bsw@0
 | 
  1363     lua_call(L, 2, 1);  // 4
 | 
| 
jbe/bsw@0
 | 
  1364     if (!lua_isnil(L, 4)) {
 | 
| 
jbe/bsw@0
 | 
  1365       // store object in _ref table (use false for nil):  // TODO: use special object instead of false
 | 
| 
jbe/bsw@0
 | 
  1366       lua_getfield(L, 1, "_ref");  // 5
 | 
| 
jbe/bsw@0
 | 
  1367       lua_pushvalue(L, 2);  // 6
 | 
| 
jbe/bsw@0
 | 
  1368       if (lua_isnil(L, 3)) lua_pushboolean(L, 0);  // 7
 | 
| 
jbe/bsw@0
 | 
  1369       else lua_pushvalue(L, 3);  // 7
 | 
| 
jbe/bsw@0
 | 
  1370       lua_settable(L, 5);
 | 
| 
jbe/bsw@0
 | 
  1371       lua_settop(L, 4);
 | 
| 
jbe/bsw@0
 | 
  1372       // delete referencing key from _data table:
 | 
| 
jbe/bsw@0
 | 
  1373       lua_getfield(L, 4, "this_key");  // 5
 | 
| 
jbe/bsw@0
 | 
  1374       if (lua_isnil(L, 5)) {
 | 
| 
jbe/bsw@0
 | 
  1375         return luaL_error(L, "Missing 'this_key' entry in model reference.");
 | 
| 
jbe/bsw@0
 | 
  1376       }
 | 
| 
jbe/bsw@0
 | 
  1377       lua_getfield(L, 1, "_data");  // 6
 | 
| 
jbe/bsw@0
 | 
  1378       lua_pushvalue(L, 5);  // 7
 | 
| 
jbe/bsw@0
 | 
  1379       lua_pushnil(L);  // 8
 | 
| 
jbe/bsw@0
 | 
  1380       lua_settable(L, 6);
 | 
| 
jbe/bsw@0
 | 
  1381       lua_settop(L, 5);
 | 
| 
jbe/bsw@0
 | 
  1382       lua_getfield(L, 1, "_dirty");  // 6
 | 
| 
jbe/bsw@0
 | 
  1383       lua_pushvalue(L, 5);  // 7
 | 
| 
jbe/bsw@0
 | 
  1384       lua_pushboolean(L, 1);  // 8
 | 
| 
jbe/bsw@0
 | 
  1385       lua_settable(L, 6);
 | 
| 
jbe/bsw@0
 | 
  1386       return 0;
 | 
| 
jbe/bsw@0
 | 
  1387     }
 | 
| 
jbe/bsw@0
 | 
  1388     lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1389     // store value in data field info:
 | 
| 
jbe/bsw@0
 | 
  1390     lua_getfield(L, 1, "_data");  // 4
 | 
| 
jbe/bsw@0
 | 
  1391     lua_pushvalue(L, 2);  // 5
 | 
| 
jbe/bsw@0
 | 
  1392     lua_pushvalue(L, 3);  // 6
 | 
| 
jbe/bsw@0
 | 
  1393     lua_settable(L, 4);
 | 
| 
jbe/bsw@0
 | 
  1394     lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1395     // mark field as dirty (needs to be UPDATEd on save):
 | 
| 
jbe/bsw@0
 | 
  1396     lua_getfield(L, 1, "_dirty");  // 4
 | 
| 
jbe/bsw@0
 | 
  1397     lua_pushvalue(L, 2);  // 5
 | 
| 
jbe/bsw@0
 | 
  1398     lua_pushboolean(L, 1);  // 6
 | 
| 
jbe/bsw@0
 | 
  1399     lua_settable(L, 4);
 | 
| 
jbe/bsw@0
 | 
  1400     lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1401     // reset reference cache, if neccessary:
 | 
| 
jbe/bsw@0
 | 
  1402     lua_pushcfunction(L,
 | 
| 
jbe/bsw@0
 | 
  1403       mondelefant_class_get_foreign_key_reference_name
 | 
| 
jbe/bsw@0
 | 
  1404     );  // 4
 | 
| 
jbe/bsw@0
 | 
  1405     lua_getfield(L, 1, "_class");  // 5
 | 
| 
jbe/bsw@0
 | 
  1406     lua_pushvalue(L, 2);  // 6
 | 
| 
jbe/bsw@0
 | 
  1407     lua_call(L, 2, 1);  // 4
 | 
| 
jbe/bsw@0
 | 
  1408     if (!lua_isnil(L, 4)) {
 | 
| 
jbe/bsw@0
 | 
  1409       lua_getfield(L, 1, "_ref");  // 5
 | 
| 
jbe/bsw@0
 | 
  1410       lua_pushvalue(L, 4);  // 6
 | 
| 
jbe/bsw@0
 | 
  1411       lua_pushnil(L);  // 7
 | 
| 
jbe/bsw@0
 | 
  1412       lua_settable(L, 5);
 | 
| 
jbe/bsw@0
 | 
  1413     }
 | 
| 
jbe/bsw@0
 | 
  1414     return 0;
 | 
| 
jbe/bsw@0
 | 
  1415   } else {
 | 
| 
jbe/bsw@0
 | 
  1416     lua_settop(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1417     lua_rawset(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1418     return 0;
 | 
| 
jbe/bsw@0
 | 
  1419   }
 | 
| 
jbe/bsw@0
 | 
  1420   return 0;
 | 
| 
jbe/bsw@0
 | 
  1421 }
 | 
| 
jbe/bsw@0
 | 
  1422 
 | 
| 
jbe/bsw@0
 | 
  1423 static int mondelefant_class_index(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
  1424   lua_settop(L, 2);
 | 
| 
jbe/bsw@0
 | 
  1425   lua_pushliteral(L, "prototype");  // 3
 | 
| 
jbe/bsw@0
 | 
  1426   lua_rawget(L, 1);  // 3
 | 
| 
jbe/bsw@0
 | 
  1427   lua_pushvalue(L, 2);  // 4
 | 
| 
jbe/bsw@0
 | 
  1428   lua_gettable(L, 3);  // 4
 | 
| 
jbe/bsw@0
 | 
  1429   return 1;
 | 
| 
jbe/bsw@0
 | 
  1430 }
 | 
| 
jbe/bsw@0
 | 
  1431 
 | 
| 
jbe/bsw@0
 | 
  1432 static const struct luaL_Reg mondelefant_module_functions[] = {
 | 
| 
jbe/bsw@0
 | 
  1433   {"connect", mondelefant_connect},
 | 
| 
jbe/bsw@0
 | 
  1434   {"set_class", mondelefant_set_class},
 | 
| 
jbe/bsw@0
 | 
  1435   {"new_class", mondelefant_new_class},
 | 
| 
jbe/bsw@0
 | 
  1436   {NULL, NULL}
 | 
| 
jbe/bsw@0
 | 
  1437 };
 | 
| 
jbe/bsw@0
 | 
  1438 
 | 
| 
jbe/bsw@0
 | 
  1439 static const struct luaL_Reg mondelefant_conn_mt_functions[] = {
 | 
| 
jbe/bsw@0
 | 
  1440   {"__gc", mondelefant_conn_free},
 | 
| 
jbe/bsw@0
 | 
  1441   {"__index", mondelefant_conn_index},
 | 
| 
jbe/bsw@0
 | 
  1442   {"__newindex", mondelefant_conn_newindex},
 | 
| 
jbe/bsw@0
 | 
  1443   {NULL, NULL}
 | 
| 
jbe/bsw@0
 | 
  1444 };
 | 
| 
jbe/bsw@0
 | 
  1445 
 | 
| 
jbe/bsw@0
 | 
  1446 static const struct luaL_Reg mondelefant_conn_methods[] = {
 | 
| 
jbe/bsw@0
 | 
  1447   {"close", mondelefant_conn_close},
 | 
| 
jbe/bsw@0
 | 
  1448   {"is_ok", mondelefant_conn_is_ok},
 | 
| 
jbe/bsw@0
 | 
  1449   {"get_transaction_status", mondelefant_conn_get_transaction_status},
 | 
| 
jbe/bsw@0
 | 
  1450   {"create_list", mondelefant_conn_create_list},
 | 
| 
jbe/bsw@0
 | 
  1451   {"create_object", mondelefant_conn_create_object},
 | 
| 
jbe/bsw@0
 | 
  1452   {"quote_string", mondelefant_conn_quote_string},
 | 
| 
jbe/bsw@0
 | 
  1453   {"quote_binary", mondelefant_conn_quote_binary},
 | 
| 
jbe/bsw@0
 | 
  1454   {"assemble_command", mondelefant_conn_assemble_command},
 | 
| 
jbe/bsw@0
 | 
  1455   {"try_query", mondelefant_conn_try_query},
 | 
| 
jbe/bsw@0
 | 
  1456   {"query", mondelefant_conn_query},
 | 
| 
jbe/bsw@0
 | 
  1457   {NULL, NULL}
 | 
| 
jbe/bsw@0
 | 
  1458 };
 | 
| 
jbe/bsw@0
 | 
  1459 
 | 
| 
jbe/bsw@0
 | 
  1460 static const struct luaL_Reg mondelefant_errorobject_mt_functions[] = {
 | 
| 
jbe/bsw@0
 | 
  1461   {NULL, NULL}
 | 
| 
jbe/bsw@0
 | 
  1462 };
 | 
| 
jbe/bsw@0
 | 
  1463 
 | 
| 
jbe/bsw@0
 | 
  1464 static const struct luaL_Reg mondelefant_errorobject_methods[] = {
 | 
| 
jbe/bsw@0
 | 
  1465   {"escalate", mondelefant_errorobject_escalate},
 | 
| 
jbe/bsw@0
 | 
  1466   {"is_kind_of", mondelefant_errorobject_is_kind_of},
 | 
| 
jbe/bsw@0
 | 
  1467   {NULL, NULL}
 | 
| 
jbe/bsw@0
 | 
  1468 };
 | 
| 
jbe/bsw@0
 | 
  1469 
 | 
| 
jbe/bsw@0
 | 
  1470 static const struct luaL_Reg mondelefant_result_mt_functions[] = {
 | 
| 
jbe/bsw@0
 | 
  1471   {"__index", mondelefant_result_index},
 | 
| 
jbe/bsw@0
 | 
  1472   {"__newindex", mondelefant_result_newindex},
 | 
| 
jbe/bsw@0
 | 
  1473   {NULL, NULL}
 | 
| 
jbe/bsw@0
 | 
  1474 };
 | 
| 
jbe/bsw@0
 | 
  1475 
 | 
| 
jbe/bsw@0
 | 
  1476 static const struct luaL_Reg mondelefant_class_mt_functions[] = {
 | 
| 
jbe/bsw@0
 | 
  1477   {"__index", mondelefant_class_index},
 | 
| 
jbe/bsw@0
 | 
  1478   {NULL, NULL}
 | 
| 
jbe/bsw@0
 | 
  1479 };
 | 
| 
jbe/bsw@0
 | 
  1480 
 | 
| 
jbe/bsw@0
 | 
  1481 static const struct luaL_Reg mondelefant_class_methods[] = {
 | 
| 
jbe/bsw@0
 | 
  1482   {"get_reference", mondelefant_class_get_reference},
 | 
| 
jbe/bsw@0
 | 
  1483   {"iterate_over_references", mondelefant_class_iterate_over_references},
 | 
| 
jbe/bsw@0
 | 
  1484   {"get_foreign_key_reference_name",
 | 
| 
jbe/bsw@0
 | 
  1485     mondelefant_class_get_foreign_key_reference_name},
 | 
| 
jbe/bsw@0
 | 
  1486   {NULL, NULL}
 | 
| 
jbe/bsw@0
 | 
  1487 };
 | 
| 
jbe/bsw@0
 | 
  1488 
 | 
| 
jbe/bsw@0
 | 
  1489 static const struct luaL_Reg mondelefant_object_methods[] = {
 | 
| 
jbe/bsw@0
 | 
  1490   {NULL, NULL}
 | 
| 
jbe/bsw@0
 | 
  1491 };
 | 
| 
jbe/bsw@0
 | 
  1492 
 | 
| 
jbe/bsw@0
 | 
  1493 static const struct luaL_Reg mondelefant_list_methods[] = {
 | 
| 
jbe/bsw@0
 | 
  1494   {NULL, NULL}
 | 
| 
jbe/bsw@0
 | 
  1495 };
 | 
| 
jbe/bsw@0
 | 
  1496 
 | 
| 
jbe/bsw@0
 | 
  1497 int luaopen_mondelefant_native(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
  1498   lua_settop(L, 0);
 | 
| 
jbe/bsw@0
 | 
  1499   lua_newtable(L);  // module at stack position 1
 | 
| 
jbe/bsw@0
 | 
  1500   luaL_register(L, NULL, mondelefant_module_functions);
 | 
| 
jbe/bsw@0
 | 
  1501 
 | 
| 
jbe/bsw@0
 | 
  1502   lua_pushvalue(L, 1);  // 2
 | 
| 
jbe/bsw@0
 | 
  1503   lua_setfield(L, LUA_REGISTRYINDEX, MONDELEFANT_MODULE_REGKEY);
 | 
| 
jbe/bsw@0
 | 
  1504 
 | 
| 
jbe/bsw@0
 | 
  1505   lua_newtable(L);  // 2
 | 
| 
jbe/bsw@0
 | 
  1506   // NOTE: only PostgreSQL is supported yet:
 | 
| 
jbe/bsw@0
 | 
  1507   luaL_register(L, NULL, mondelefant_conn_methods);
 | 
| 
jbe/bsw@0
 | 
  1508   lua_setfield(L, 1, "postgresql_connection_prototype");
 | 
| 
jbe/bsw@0
 | 
  1509   lua_newtable(L);  // 2
 | 
| 
jbe/bsw@0
 | 
  1510   lua_setfield(L, 1, "connection_prototype");
 | 
| 
jbe/bsw@0
 | 
  1511 
 | 
| 
jbe/bsw@0
 | 
  1512   luaL_newmetatable(L, MONDELEFANT_CONN_MT_REGKEY);  // 2
 | 
| 
jbe/bsw@0
 | 
  1513   luaL_register(L, NULL, mondelefant_conn_mt_functions);
 | 
| 
jbe/bsw@0
 | 
  1514   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1515   luaL_newmetatable(L, MONDELEFANT_RESULT_MT_REGKEY);  // 2
 | 
| 
jbe/bsw@0
 | 
  1516   luaL_register(L, NULL, mondelefant_result_mt_functions);
 | 
| 
jbe/bsw@0
 | 
  1517   lua_setfield(L, 1, "result_metatable");
 | 
| 
jbe/bsw@0
 | 
  1518   luaL_newmetatable(L, MONDELEFANT_CLASS_MT_REGKEY);  // 2
 | 
| 
jbe/bsw@0
 | 
  1519   luaL_register(L, NULL, mondelefant_class_mt_functions);
 | 
| 
jbe/bsw@0
 | 
  1520   lua_setfield(L, 1, "class_metatable");
 | 
| 
jbe/bsw@0
 | 
  1521 
 | 
| 
jbe/bsw@0
 | 
  1522   lua_newtable(L);  // 2
 | 
| 
jbe/bsw@0
 | 
  1523   lua_newtable(L);  // 3
 | 
| 
jbe/bsw@0
 | 
  1524   luaL_register(L, NULL, mondelefant_object_methods);
 | 
| 
jbe/bsw@0
 | 
  1525   lua_setfield(L, 2, "object");
 | 
| 
jbe/bsw@0
 | 
  1526   lua_newtable(L);  // 3
 | 
| 
jbe/bsw@0
 | 
  1527   lua_setfield(L, 2, "object_get");
 | 
| 
jbe/bsw@0
 | 
  1528   lua_newtable(L);  // 3
 | 
| 
jbe/bsw@0
 | 
  1529   lua_setfield(L, 2, "object_set");
 | 
| 
jbe/bsw@0
 | 
  1530   lua_newtable(L);  // 3
 | 
| 
jbe/bsw@0
 | 
  1531   luaL_register(L, NULL, mondelefant_list_methods);
 | 
| 
jbe/bsw@0
 | 
  1532   lua_setfield(L, 2, "list");
 | 
| 
jbe/bsw@0
 | 
  1533   lua_newtable(L);  // 3
 | 
| 
jbe/bsw@0
 | 
  1534   lua_setfield(L, 2, "references");
 | 
| 
jbe/bsw@0
 | 
  1535   lua_newtable(L);  // 3
 | 
| 
jbe/bsw@0
 | 
  1536   lua_setfield(L, 2, "foreign_keys");
 | 
| 
jbe/bsw@0
 | 
  1537   lua_pushvalue(L, 2);  // 3
 | 
| 
jbe/bsw@0
 | 
  1538   lua_setfield(L, LUA_REGISTRYINDEX, MONDELEFANT_CLASS_PROTO_REGKEY);
 | 
| 
jbe/bsw@0
 | 
  1539   lua_setfield(L, 1, "class_prototype");
 | 
| 
jbe/bsw@0
 | 
  1540 
 | 
| 
jbe/bsw@0
 | 
  1541   lua_newtable(L);  // 2
 | 
| 
jbe/bsw@0
 | 
  1542   lua_pushliteral(L, "k");  // 3
 | 
| 
jbe/bsw@0
 | 
  1543   lua_setfield(L, 2, "__mode");
 | 
| 
jbe/bsw@0
 | 
  1544   lua_newtable(L);  // 3
 | 
| 
jbe/bsw@0
 | 
  1545   lua_pushvalue(L, 2);  // 4
 | 
| 
jbe/bsw@0
 | 
  1546   lua_setmetatable(L, 3);
 | 
| 
jbe/bsw@0
 | 
  1547   lua_setfield(L, LUA_REGISTRYINDEX, MONDELEFANT_CONN_DATA_REGKEY);
 | 
| 
jbe/bsw@0
 | 
  1548   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
  1549 
 | 
| 
jbe/bsw@0
 | 
  1550   luaL_newmetatable(L, MONDELEFANT_ERROROBJECT_MT_REGKEY);  // 2
 | 
| 
jbe/bsw@0
 | 
  1551   luaL_register(L, NULL, mondelefant_errorobject_mt_functions);
 | 
| 
jbe/bsw@0
 | 
  1552   lua_newtable(L);  // 3
 | 
| 
jbe/bsw@0
 | 
  1553   luaL_register(L, NULL, mondelefant_errorobject_methods);
 | 
| 
jbe/bsw@0
 | 
  1554   lua_setfield(L, 2, "__index");
 | 
| 
jbe/bsw@0
 | 
  1555   lua_setfield(L, 1, "errorobject_metatable");
 | 
| 
jbe/bsw@0
 | 
  1556 
 | 
| 
jbe/bsw@0
 | 
  1557   return 1;
 | 
| 
jbe/bsw@0
 | 
  1558 }
 |