コード例 #1
0
ファイル: cli_fastdb.cpp プロジェクト: jiajw0426/easyscada
int cli_insert_fdb(int statement, cli_oid_t* oid)
{
    int rc = cli_send_columns_fdb(statement, cli_cmd_insert);
    if (rc == cli_ok) { 
        char buf[sizeof(cli_oid_t) + 8];
        statement_desc* s = statements.get(statement);
        if (!s->session->sock->read(buf, sizeof buf)) { 
            rc = cli_network_error;
        } else { 
            rc = unpack4(buf);
            s->prepared = true;
            s->oid = unpack_oid(buf + 8);
            if (oid != NULL) { 
                *oid = s->oid;
            }
           if (s->autoincrement) {
               int4 rowid = unpack4(buf + 4);
               for (column_binding* cb = s->columns; cb != NULL; cb = cb->next) {
                   if (cb->var_type == cli_autoincrement) {
                       *(int4*)cb->var_ptr = rowid;
                   }
               }
           }
        }
    }
    return rc;
}
コード例 #2
0
ファイル: cli_fastdb.cpp プロジェクト: jiajw0426/easyscada
int put_db_online_fdb(int session, const char_t* filename)
{
    int4 response;

	session_desc* s = sessions.get(session);
    if (s == NULL) {
        return cli_bad_descriptor;
    }

	int len = sizeof(cli_request);

    dbSmallBuffer buf(len);
    cli_request* req = (cli_request*)buf.base();
    req->length = len;
    req->cmd    = cli_cmd_is_db_online;
    req->stmt_id = 0;
        
	req->pack();
    if (!s->sock->write(buf, len)) 
	{
		return cli_network_error;
    }
    	
    if (!s->sock->read(&response, sizeof response)) 
	{
		return cli_network_error;
    }
    unpack4(response);

	if(response == cli_database_is_offline)
	{
		int len = sizeof(cli_request) + (strlen(filename)+ 1)*sizeof(char_t);
		dbSmallBuffer buf(len);
		char_t* p = (char_t*)buf.base();
		cli_request* req = (cli_request*)p;
		req->length = len;
		req->cmd    = cli_cmd_put_db_online;
		req->stmt_id = 0;
		p += sizeof(cli_request);
		p = pack_str(p, filename);
    
		req->pack();
		if (!s->sock->write(buf, len)) 
		{
			return cli_network_error;
		}
    
		if (!s->sock->read(&response, sizeof response)) 
		{
			return cli_network_error;
		}
		unpack4(response);
	}

	return response;
}
コード例 #3
0
ファイル: TimeBtree.cpp プロジェクト: knizhnik/goods-samples
skey_t CTimeSetMember::get_key() const
{
	skey_t skey = 0;

	if(getKeyLength() == 4)
	{
#ifdef PGSQL_ORM
		unpack4((char*)&skey, (char*)key);
#else
		DWORD t;
		memcpy(&t, key, sizeof(DWORD));
		skey = (skey_t)t;
#endif
	}
	else
	{
#ifdef PGSQL_ORM
		unpack8((char*)&skey, (char*)key);
#else
		time_t t;
		memcpy(&t, key, sizeof(time_t));
		skey = t;
#endif
	}

	return skey;
}
コード例 #4
0
ファイル: cli_fastdb.cpp プロジェクト: jiajw0426/easyscada
int cli_alter_index_fdb(int session, char const* tableName, char const* fieldName, int newFlags)
{
    session_desc* s = sessions.get(session);
    if (s == NULL) {
        return cli_bad_descriptor;
    }
    int size = sizeof(cli_request) + 1 + strlen(tableName)+strlen(fieldName)+2;
    dbSmallBuffer buf(size);
    cli_request* req = (cli_request*)buf.base();
    req->length  = size;
    req->cmd     = cli_cmd_alter_index;
    req->stmt_id = 0;
    char* dst = (char*)(req + 1);
    strcpy(dst, tableName);
    dst += strlen(dst) + 1;
    strcpy(dst, fieldName);
    dst += strlen(dst) + 1;
    *dst++ = newFlags;
    req->pack();
    if (!s->sock->write(buf, size)) {
        return cli_network_error;
    }
    int4 response;
    if (!s->sock->read(&response, sizeof response)) {
        return cli_network_error;
    }
    unpack4(response);
    return response;
}
コード例 #5
0
ファイル: cli_fastdb.cpp プロジェクト: jiajw0426/easyscada
int cli_show_tables_fdb(int session, cli_table_descriptor** tables)
{
    session_desc* s = sessions.get(session);
    if (s == NULL) {
        return cli_bad_descriptor;
    }
    cli_request req;
    req.length  = sizeof(cli_request);
    req.cmd     = cli_cmd_show_tables;
    req.stmt_id = 0;
    req.pack();
    if (!s->sock->write(&req, sizeof req)) {
        return cli_network_error;
    }
    int4 response[2];
    if (!s->sock->read(&response, sizeof response)) {
        return cli_network_error;
    }
    unpack4(response[0]);
    unpack4(response[1]);
    int len = response[0];
    int nTables = response[1];

	//01-11-09
	if(nTables > 10000)
	{
		return cli_network_error;		
	}

    if (nTables == -1) {
        return cli_table_not_found;
    }
    char* p = (char*)malloc(nTables*sizeof(cli_table_descriptor) + len);
    cli_table_descriptor* fp = (cli_table_descriptor*)p;
    p += nTables*sizeof(cli_table_descriptor);
    if (!s->sock->read(p, len)) {
        free(p);
        return cli_network_error;
    }
    *tables = fp;
    for (int i = nTables; --i >= 0; fp++) {
        fp->name = (char*)p;
        p += strlen((char*)p)+1;
    }
    return nTables;
}
コード例 #6
0
ファイル: cli_fastdb.cpp プロジェクト: jiajw0426/easyscada
static int cli_update_table(int cmd, int session, char const* tableName, int nColumns, 
                            cli_field_descriptor* columns)
{
    int i;
    session_desc* s = sessions.get(session);
    if (s == NULL) {
        return cli_bad_descriptor;
    }
    int size = sizeof(cli_request) + 4 + strlen(tableName)+1;
    for (i = 0; i < nColumns; i++) { 
        size += 2 + (strlen(columns[i].name)+3);
        if (columns[i].refTableName != NULL) { 
            size += strlen(columns[i].refTableName);
        }
        if (columns[i].inverseRefFieldName != NULL) { 
            size += strlen(columns[i].inverseRefFieldName);
        }
    }
    dbSmallBuffer buf(size);
    cli_request* req = (cli_request*)buf.base();
    req->length  = size;
    req->cmd     = cmd;
    req->stmt_id = 0;
    char* dst = (char*)(req + 1);
    strcpy(dst, tableName);
    dst += strlen(dst) + 1;
    *dst++ = (char)nColumns;
    for (i = 0; i < nColumns; i++) { 
        *dst++ = (char)columns[i].type;
        *dst++ = (char)columns[i].flags;
        strcpy(dst, columns[i].name);
        dst += strlen(dst) + 1;
        if (columns[i].refTableName != NULL) { 
            strcpy(dst, columns[i].refTableName);
            dst += strlen(dst) + 1;        
        } else { 
            *dst++ = 0;
        }
        if (columns[i].inverseRefFieldName != NULL) { 
            strcpy(dst, columns[i].inverseRefFieldName);
            dst += strlen(dst) + 1;
        } else { 
            *dst++ = 0;
        }
    }
    req->pack();
    if (!s->sock->write(buf, size)) {
        return cli_network_error;
    }
    int4 response;
    if (!s->sock->read(&response, sizeof response)) {
        return cli_network_error;
    }
    unpack4(response);
    return response;
}
コード例 #7
0
int cli_update(int statement)
{
    int rc = cli_send_columns(statement, cli_cmd_update);
    if (rc == cli_ok) { 
	int4 response;
	statement_desc* s = statements.get(statement);
	if (!s->session->sock->read(&response, sizeof response)) { 
	    rc = cli_network_error;
	} else { 
	    unpack4(response);
	    rc = response;
	}
    }
    return rc;      
}
コード例 #8
0
int cli_insert(int statement, cli_oid_t* oid)
{
    int rc = cli_send_columns(statement, cli_cmd_insert);
    if (rc == cli_ok) { 
	char buf[sizeof(cli_oid_t) + 4];
	statement_desc* s = statements.get(statement);
	if (!s->session->sock->read(buf, sizeof buf)) { 
	    rc = cli_network_error;
	} else { 
	    rc = unpack4(buf);
	    s->prepared = true;
	    s->oid = unpack_oid(buf + 4);
	    if (oid != NULL) { 
		*oid = s->oid;
	    }
	}
    }
    return rc;
}
コード例 #9
0
static int cli_send_command(int session, int statement, int cmd)
{
    session_desc* s = sessions.get(session);
    if (s == NULL) { 
	return cli_bad_descriptor;
    }	
    cli_request req;
    req.length  = sizeof(cli_request);
    req.cmd     = cmd;
    req.stmt_id = statement;
    req.pack();
    if (!s->sock->write(&req, sizeof req)) { 
	return cli_network_error;
    }
    int4 response;
    if (!s->sock->read(&response, sizeof response)) { 
	return cli_network_error;
    }
    unpack4(response);
    return response;
}
コード例 #10
0
ファイル: cli_fastdb.cpp プロジェクト: jiajw0426/easyscada
int cli_drop_table_fdb(int session, char const* tableName)
{
    session_desc* s = sessions.get(session);
    if (s == NULL) {
        return cli_bad_descriptor;
    }
    int size = sizeof(cli_request) + strlen(tableName) + 1;
    dbSmallBuffer buf(size);
    cli_request* req = (cli_request*)buf.base();
    req->length  = size;
    req->cmd     = cli_cmd_drop_table;
    req->stmt_id = 0;
    strcpy((char*)(req + 1), tableName);
    req->pack();
    if (!s->sock->write(buf, size)) {
        return cli_network_error;
    }
    int4 response;
    if (!s->sock->read(&response, sizeof response)) {
        return cli_network_error;
    }
    unpack4(response);
    return response;
}
コード例 #11
0
ファイル: cli_fastdb.cpp プロジェクト: jiajw0426/easyscada
static int send_receive(int statement, int cmd)
{
    statement_desc* s = statements.get(statement);
    if (s == NULL) { 
        return cli_bad_descriptor;
    }
    if (!s->prepared) { 
        return cli_not_fetched;
    }
    cli_request req;
    req.length = sizeof(req);
    req.cmd = cmd;
    req.stmt_id = statement;
    req.pack();
    int4 response = cli_ok;
    if (!s->session->sock->write(&req, sizeof req)) { 
        return cli_network_error;
    } 
    if (!s->session->sock->read(&response, sizeof response)) { 
        return cli_network_error;
    }
    unpack4(response);
    return response;
}
コード例 #12
0
static int cli_get(int statement, int cmd)
{
    statement_desc* s = statements.get(statement);
    if (s == NULL) { 
	return cli_bad_descriptor;
    }
    if (!s->prepared) { 
	return cli_not_fetched;
    }
    cli_request req;
    req.length  = sizeof(cli_request);
    req.cmd     = cmd;
    req.stmt_id = statement;
    req.pack();
    if (!s->session->sock->write(&req, sizeof req)) { 
	return cli_network_error;
    }   
    int4 response;
    if (!s->session->sock->read(&response, sizeof response)) { 
	return cli_network_error;
    }
    unpack4(response);
    if (response <= 0) { 
	return response;
    }
    dbSmallBuffer buf(response-4);
    if (!s->session->sock->read(buf, response-4)) { 
	return cli_network_error;
    }
    char* p = buf;
    s->oid = unpack_oid(p);
    if (s->oid == 0) { 
	return cli_not_found;
    }
    p += sizeof(cli_oid_t);
    for (column_binding* cb = s->columns; cb != NULL; cb = cb->next) { 
	if (cb->set_fnc != NULL) { 
	    int len = unpack4(p);
	    p += 4;
	    char* dst = (char*)cb->set_fnc(cb->var_type, cb->var_ptr, len);
	    if (cb->var_type >= cli_array_of_oid) { 
		switch (sizeof_type[cb->var_type-cli_array_of_oid]) { 
		  case 2:		    
		    while (--len >= 0) { 
			p = unpack2(dst, p);
			dst += 2;
		    }
		    break;
		  case 4:
		    while (--len >= 0) { 
			p = unpack4(dst, p);
			dst += 4;
		    }
		    break;
		  case 8:
		    while (--len >= 0) { 
			p = unpack8(dst, p);
			dst += 8;
		    }
		    break;
		  default:
		    memcpy(dst, p, len);
		    p += len;
		}
	    } else { 
		memcpy(dst, p, len);
		p += len;
	    }
	} else { 
	    if (cb->var_type >= cli_asciiz) { 
		int len = unpack4(p);
		p += 4;
		char* dst = (char*)cb->var_ptr;
		char* src = p;
		int n = len;
		if (cb->var_len != NULL) { 
		    if (n > *cb->var_len) { 
			n = *cb->var_len;
		    }
		    *cb->var_len = n;
		}
		if (cb->var_type >= cli_array_of_oid) { 
		    switch (sizeof_type[cb->var_type-cli_array_of_oid]) { 
		      case 2:		    
			while (--n >= 0) { 
			    src = unpack2(dst, src);
			    dst += 2;
			}
			p += len*2;
			break;
		      case 4:
			while (--n >= 0) { 
			    src = unpack4(dst, src);
			    dst += 4;
			}
			p += len*4;
			break;
		      case 8:
			while (--n >= 0) { 
			    src = unpack8(dst, src);
			    dst += 8;
			}
			p += len*8;
			break;
		      default:
			memcpy(dst, p, n);
			p += len;
		    }
		} else { 
		    if (cb->var_type == cli_pasciiz) { 
			dst = *(char**)dst;
		    }
		    memcpy(dst, p, n);
		    p += len;
		}
	    } else { 
		switch (sizeof_type[cb->var_type]) { 
		  case 2:
		    p = unpack2((char*)cb->var_ptr, p);
		    break;
		  case 4:
		    p = unpack4((char*)cb->var_ptr, p);
		    break;
		  case 8:
		    p = unpack8((char*)cb->var_ptr, p);
		    break;
		  default:
		    *(char*)cb->var_ptr = *p++;
		}
	    }
	}
    }
    return cli_ok;
}
コード例 #13
0
int cli_fetch(int statement, int for_update)
{
    parameter_binding* pb;
    column_binding*    cb;
    statement_desc* stmt = statements.get(statement);
    char *p, *s;

    if (stmt == NULL) { 
	return cli_bad_descriptor;
    }
    stmt->for_update = for_update;
    int msg_size = sizeof(cli_request) + 1;
    for (pb = stmt->params; pb != NULL; pb = pb->next) { 
	if (pb->var_ptr == NULL) { 
	    return cli_unbound_parameter;
	}
	if (pb->var_type == cli_asciiz) { 
	    msg_size += strlen((char*)pb->var_ptr) + 1;
	} else if (pb->var_type == cli_pasciiz) { 
	    msg_size += strlen(*(char**)pb->var_ptr) + 1;
	} else { 
	    msg_size += sizeof_type[pb->var_type];
	}
    }
    stmt->oid = 0;
    if (!stmt->prepared) { 
	msg_size += 4 + stmt->stmt_len + stmt->n_params;
	msg_size += stmt->columns_len + stmt->n_columns;
    }
    dbSmallBuffer buf(msg_size);
    p = buf;
    cli_request* req = (cli_request*)p;
    req->length  = msg_size;
    req->cmd     = stmt->prepared 
	? cli_cmd_execute : cli_cmd_prepare_and_execute;
    req->stmt_id = statement;
    req->pack();
    p += sizeof(cli_request);

    if (!stmt->prepared) { 
	*p++ = stmt->n_params;
	*p++ = stmt->n_columns;
	p = pack2(p, stmt->stmt_len + stmt->n_params);
	pb = stmt->params;
	char* end = p + stmt->stmt_len + stmt->n_params;
	char* src = stmt->stmt;
	while (p < end) { 
	    while ((*p++ = *src++) != '\0');
	    if (pb != NULL) { 
		*p++ = pb->var_type == cli_pasciiz ? cli_asciiz : pb->var_type;
		pb = pb->next;
	    }
	}
	for (cb = stmt->columns; cb != NULL; cb = cb->next) { 
	    *p++ = cb->var_type;
	    s = cb->name;
	    while ((*p++ = *s++) != '\0');
	}
    }	
    *p++ = for_update;
    for (pb = stmt->params; pb != NULL; pb = pb->next) { 
	switch (pb->var_type) { 
	  case cli_asciiz:
	    s = (char*)pb->var_ptr;
	    while ((*p++ = *s++) != '\0');
	    continue;
	  case cli_pasciiz:
	    s = *(char**)pb->var_ptr;
	    while ((*p++ = *s++) != '\0');
	    continue;
	  default:
	    switch (sizeof_type[pb->var_type]) { 
	      case 1:
		*p++ = *(char*)pb->var_ptr;
		continue;
	      case 2:
		p = pack2(p, *(int2*)pb->var_ptr);
		continue;
	      case 4:
		p = pack4(p, *(int4*)pb->var_ptr);
		continue;
	      case 8:
		p = pack8(p, *(int8*)pb->var_ptr);
		continue;
	    }
	}
    }
    assert(msg_size == p - buf);
    if (!stmt->session->sock->write(buf, msg_size)) { 
	return cli_network_error;
    }
    int4 response;
    if (!stmt->session->sock->read(&response, sizeof response)) { 
	return cli_network_error;
    }
    unpack4(response);
    if (response >= 0) { 
	stmt->prepared = true;
    }
    return response;
}
コード例 #14
0
ファイル: cli_fastdb.cpp プロジェクト: jiajw0426/easyscada
static int cli_get_fdb(int statement, int cmd, cli_oid_t value = 0)
{
    statement_desc* s = statements.get(statement);
    if (s == NULL) { 
        return cli_bad_descriptor;
    }
    if (!s->prepared) { 
        return cli_not_fetched;
    }
    struct get_req { 
        cli_request req;
        cli_oid_t   value;
    } get;
    int length = sizeof(cli_request);
    if (cmd == cli_cmd_skip) { 
        length += 4;
        pack4((char*)(&get.req+1), (int)value);
    } else if (cmd == cli_cmd_seek) { 
        length += sizeof(cli_oid_t);
        pack_oid((char*)(&get.req+1), value);
    }
    get.req.length  = length;
    get.req.cmd     = cmd;
    get.req.stmt_id = statement;
    get.req.pack();
    if (!s->session->sock->write(&get.req, length)) { 
        return cli_network_error;
    }   
    int4 response;
    if (!s->session->sock->read(&response, sizeof response)) { 
        return cli_network_error;
    }
    unpack4(response);
    if (response <= 0) { 
        return response;
    }
    if (s->buf_size < (size_t)response-4) { 
        delete[] s->buf;
        s->buf_size = response-4 < DEFAULT_BUF_SIZE ? DEFAULT_BUF_SIZE : response-4;
        s->buf = new char[s->buf_size];
    }
    char* buf = s->buf;
    if (!s->session->sock->read(buf, response-4)) { 
        return cli_network_error;
    }
    char* p = buf;
    int result = cli_ok;
    if (cmd == cli_cmd_seek) { 
        s->oid = value;
        result = unpack_oid(p);
    } else { 
        s->oid = unpack_oid(p);
        if (s->oid == 0) { 
            return cli_not_found;
        }
    }
    p += sizeof(cli_oid_t);
    for (column_binding* cb = s->columns; cb != NULL; cb = cb->next) { 
        int type = *p++;
        if (cb->var_type == cli_any) { 
            cb->var_type = type;
        } else { 
            assert(cb->var_type == type);
        }
        if (cb->set_fnc != NULL) { 
            int len = unpack4(p);
            p += 4;
            char* dst = (char*)cb->set_fnc(cb->var_type, cb->var_ptr, len, 
                                           cb->name, statement, p, cb->user_data);
            if (dst == NULL) {
                continue;
            }
            if (cb->var_type == cli_array_of_string) { 
                char** s = (char**)dst;
                while (--len >= 0) {
                    *s++ = p;
                    p += strlen(p) + 1;
                }
            } else if (cb->var_type == cli_array_of_wstring) { 
                wchar_t** s = (wchar_t**)dst;
                while (--len >= 0) {
                    *s++ = (wchar_t*)p;
                    p += (wcslen((wchar_t*)p) + 1)*sizeof(wchar_t);
                }
            } else if (cb->var_type >= cli_array_of_oid && cb->var_type < cli_array_of_string) { 
                switch (sizeof_type[cb->var_type-cli_array_of_oid]) { 
                  case 2:                   
                    while (--len >= 0) { 
                        p = unpack2(dst, p);
                        dst += 2;
                    }
                    break;
                  case 4:
                    while (--len >= 0) { 
                        p = unpack4(dst, p);
                        dst += 4;
                    }
                    break;
                  case 8:
                    while (--len >= 0) { 
                        p = unpack8(dst, p);
                        dst += 8;
                    }
                    break;
                  default:
                    memcpy(dst, p, len);
                    p += len;
                }
            } else { 
                memcpy(dst, p, len);
                p += len;
            }
        } else { 
            if (cb->var_type >= cli_asciiz && (cb->var_type <= cli_array_of_string || cb->var_type == cli_array_of_wstring)) { 
                int len = unpack4(p);
                p += 4;
                char* dst = (char*)cb->var_ptr;
                char* src = p;
                int n = len;
                if (cb->var_len != NULL) { 
                    if (n > *cb->var_len) { 
                        n = *cb->var_len;
                    }
                    *cb->var_len = n;
                }
                if (cb->var_type == cli_wstring || cb->var_type == cli_pwstring) { 
                    if (cb->var_type == cli_pwstring) { 
                        dst = *(char**)dst;
                    }
                    memcpy(dst, p, n*sizeof(wchar_t));
                    p += len*sizeof(wchar_t);
                } else if (cb->var_type >= cli_array_of_oid) { 
                    if (cb->var_type == cli_array_of_string) { 
                        char** s = (char**)dst;
                        len -= n;
                        while (--n >= 0) {
                            *s++ = p;
                            p += strlen(p) + 1;
                        }
                        while (--len >= 0) { 
                            p += strlen(p) + 1;
                        }
                    } else if (cb->var_type == cli_array_of_wstring) { 
                        wchar_t** s = (wchar_t**)dst;
                        len -= n;
                        while (--n >= 0) {
                            *s++ = (wchar_t*)p;
                            p += (wcslen((wchar_t*)p) + 1)*sizeof(wchar_t);
                        }
                        while (--len >= 0) { 
                            p += (wcslen((wchar_t*)p) + 1)*sizeof(wchar_t);
                        }
                    } else { 
                        switch (sizeof_type[cb->var_type-cli_array_of_oid]) { 
                          case 2:                   
                            while (--n >= 0) { 
                                src = unpack2(dst, src);
                                dst += 2;
                            }
                            p += len*2;
                            break;
                          case 4:
                            while (--n >= 0) { 
                                src = unpack4(dst, src);
                                dst += 4;
                            }
                            p += len*4;
                            break;
                          case 8:
                            while (--n >= 0) { 
                                src = unpack8(dst, src);
                                dst += 8;
                            }
                            p += len*8;
                            break;
                          default:
                            memcpy(dst, p, n);
                            p += len;
                        }
                    }
                } else { 
                    if (cb->var_type == cli_pasciiz) { 
                        dst = *(char**)dst;
                    }
                    memcpy(dst, p, n);
                    p += len;
                }
            } else if (cb->var_type == cli_rectangle) { 
                p = unpack_rectangle((cli_rectangle_t*)cb->var_ptr, p);
            } else { 
                switch (sizeof_type[cb->var_type]) { 
                  case 2:
                    p = unpack2((char*)cb->var_ptr, p);
                    break;
                  case 4:
                    p = unpack4((char*)cb->var_ptr, p);
                    break;
                  case 8:
                    p = unpack8((char*)cb->var_ptr, p);
                    break;
                  default:
                    *(char*)cb->var_ptr = *p++;
                }
            }
        }
    }
    s->updated = false;
    return result;
}
コード例 #15
0
ファイル: cli_fastdb.cpp プロジェクト: jiajw0426/easyscada
int cli_describe_fdb(int session, char const* table, cli_field_descriptor** fields)
{
    int len = sizeof(cli_request) + strlen(table) + 1;
    dbSmallBuffer buf(len);
    cli_request* req = (cli_request*)buf.base();
    req->length = len;
    req->cmd    = cli_cmd_describe_table;
    req->stmt_id = 0;
    strcpy((char*)(req+1), table);
    session_desc* s = sessions.get(session);
    if (s == NULL) {
        return cli_bad_descriptor;
    }
    req->pack();
    if (!s->sock->write(buf, len)) {
        return cli_network_error;
    }
    int4 response[2];
    if (!s->sock->read(&response, sizeof response)) {
        return cli_network_error;
    }
    unpack4(response[0]);
    unpack4(response[1]);
    len = response[0];
    int nFields = response[1];
    if (nFields == -1) { 
        return cli_table_not_found;
    }

	if(nFields > 256)
	{
		return cli_network_error;
	}

    char* p = (char*)malloc(nFields*sizeof(cli_field_descriptor) + len);
    cli_field_descriptor* fp = (cli_field_descriptor*)p;
    p += nFields*sizeof(cli_field_descriptor);
    if (!s->sock->read(p, len)) {
        return cli_network_error;
    }
    *fields = fp;
    for (int i = nFields; --i >= 0; fp++) {
        fp->type = (enum cli_var_type)*p++;
        fp->flags = *p++ & 0xFF;
        fp->name = p;
        p += strlen(p) + 1;
        if (*p != 0) { 
            fp->refTableName = p;
        } else { 
            fp->refTableName = NULL;
        }
        p += strlen(p) + 1;
        if (*p != 0) { 
            fp->inverseRefFieldName = p;
        } else { 
            fp->inverseRefFieldName = NULL;
        }
        p += strlen(p) + 1;
    }
    return nFields;
}