📄 main.c
字号:
/***************************************************************************** query_fill() Fill a result buffer with the value of each field of a record. <result> is the handle of the result. <pos> is the index of the record in the result. <buffer> points to an array having one element for each field in the result. <next> is a boolean telling if we want the next row. This function must use GB.StoreVariant() to store the value in the buffer.*****************************************************************************/static void query_fill(DB_RESULT result, int pos, GB_VARIANT_VALUE *buffer, int next){ MYSQL_RES *res = (MYSQL_RES *)result; MYSQL_FIELD *field; MYSQL_ROW row; int i; char *data; GB_VARIANT value; if (!next) mysql_data_seek(res, pos);/* move to record */ row = mysql_fetch_row(res); mysql_field_seek(res, 0); for ( i=0; i < mysql_num_fields(res); i++) { field = mysql_fetch_field(res); data = row[i]; value.type = GB_T_VARIANT; value.value._object.type = GB_T_NULL; //if (field->type != FIELD_TYPE_NULL) if (data){ conv_data(data, &value.value, field->type, field->length); } GB.StoreVariant(&value, &buffer[i]); }}/***************************************************************************** field_name() Return the name of a field in a result from its index. <result> is the result handle. <field> is the field index.*****************************************************************************/static char *field_name(DB_RESULT result, int field){ MYSQL_FIELD *fld; int i, num_fields = mysql_num_fields((MYSQL_RES *)result); char *table1 = mysql_fetch_field_direct((MYSQL_RES *)result, 0)->table; bool MultiTables = FALSE; // Need to identify whether multiple tables included fld = mysql_fetch_fields((MYSQL_RES *)result); for ( i = 1; i < num_fields; i++ ){ if (strcmp(table1, fld[i].table) != 0){ MultiTables = TRUE; break; } } fld = mysql_fetch_field_direct((MYSQL_RES *)result, field); // GB.Alloc((void **)&full, strlen(fld->table) + strlen(fld->name)); if (MultiTables && *fld->table){ sprintf(_buffer, "%s.%s", fld->table, fld->name); return _buffer; } else { return fld->name; } //return mysql_fetch_field_direct((MYSQL_RES *)result, field)->name;}/***************************************************************************** field_index() Return the index of a field in a result from its name. <Result> is the result handle. <name> is the field name.*****************************************************************************/static int field_index(DB_RESULT Result, char *name, DB_DATABASE handle, long version){ unsigned int num_fields; unsigned int i; MYSQL_FIELD *field; //char *table = NULL, *fld = NULL; char *table, *fld; MYSQL_RES *result = (MYSQL_RES *)Result; fld = strchr(name, (int)FLD_SEP); if (fld){ /* Field does includes table info */ GB.NewString(&table, name, fld - name); fld = fld + 1; } else { table = NULL; fld = name; } num_fields = mysql_num_fields(result); if (strcmp(name,fld)!=0){ /* table name included */ mysql_field_seek(result,0); /* start at beginning */ for (i = 0; i < num_fields; i++) { field = mysql_fetch_field(result); if ( strcasecmp( fld, field->name) == 0 && strcmp( table, field->table) == 0){ GB.FreeString(&table); return i; } } fld = name; } if (table) GB.FreeString(&table); /* Do not consider table name, also reached where table cannot be found. * * Mysql can include . in the fieldname!! */ mysql_field_seek(result,0); /* start at beginning */ for (i = 0; i < num_fields; i++) { field = mysql_fetch_field(result); if ( strcasecmp( fld, field->name) == 0) return i; } return -1;}/***************************************************************************** field_type() Return the Gambas type of a field in a result from its index. <result> is the result handle. <field> is the field index.*****************************************************************************/static GB_TYPE field_type(DB_RESULT result, int field){ MYSQL_FIELD *f = mysql_fetch_field_direct((MYSQL_RES *)result, field); return conv_type(f->type, f->length);}/***************************************************************************** field_length() Return the length of a field in a result from its index. <result> is the result handle. <field> is the field index.*****************************************************************************/static int field_length(DB_RESULT result, int field){ MYSQL_FIELD *f = mysql_fetch_field_direct((MYSQL_RES *)result, field); GB_TYPE type = conv_type(f->type, f->length); if (type != GB_T_STRING) return 0; else return f->length;}/***************************************************************************** begin_transaction() Begin a transaction. <handle> is the database handle. This function returns TRUE if the command has failed, and FALSE if everything was OK. In mysql commit/rollback can only be used with transaction safe tables (BDB, or InnoDB tables) ISAM, MyISAM and HEAP tables will commit straight away. The transaction methods are therefore ignored.*****************************************************************************/static int begin_transaction(DB_DATABASE handle){ /* Autocommit is on by default. Lets set it off. */ /* BM: why not doing that when we open the connection ? */ do_query((MYSQL *)handle, "Unable to set autocommit to 0: &1", NULL, "set autocommit=0", 0); return do_query((MYSQL *)handle, "Unable to begin transaction: &1", NULL, "BEGIN", 0);}/***************************************************************************** commit_transaction() Commit a transaction. <handle> is the database handle. This function returns TRUE if the command has failed, and FALSE if everything was OK.*****************************************************************************/static int commit_transaction(DB_DATABASE handle){ bool ret = do_query((MYSQL *)handle, "Unable to commit transaction: &1", NULL, "COMMIT", 0); /* Autocommit needs to be set back on. */ /* BM: and what happens if transactions are imbricated ? */ do_query((MYSQL *)handle, "Unable to set autocommit to On: &1", NULL, "set autocommit=1", 0); return ret;}/***************************************************************************** rollback_transaction() Rollback a transaction. <handle> is the database handle. This function returns TRUE if the command has failed, and FALSE if everything was OK. In mysql commit/rollback can only be used with transaction safe tables (BDB, or InnoDB tables) ISAM, MyISAM and HEAP tables will commit straight away. Therefore a rollback cannot occur!*****************************************************************************/static int rollback_transaction(DB_DATABASE handle){ bool ret = do_query((MYSQL *)handle, "Unable to rollback transaction: &1", NULL, "ROLLBACK", 0); /* Autocommit needs to be set back on. */ /* BM: and what happens if transactions are imbricated ? */ do_query((MYSQL *)handle, "Unable to set autocommit to On: &1", NULL, "set autocommit=1", 0); return ret;}/***************************************************************************** table_init() Initialize an info structure from table fields. <handle> is the database handle. <table> is the table name. <info> points at the info structure. This function must initialize the following info fields: - info->nfield must contain the number of fields in the table. - info->fields is a char*[] pointing at the name of each field. - info->types is a GB_TYPE[] giving the gambas type of each field. This function returns TRUE if the command has failed, and FALSE if everything was OK.*****************************************************************************/static int table_init(DB_DATABASE db, char *table, DB_INFO *info){ MYSQL_FIELD *field; MYSQL *conn = (MYSQL *)db; MYSQL_RES *res; int i, n; DB_FIELD *f; /* Nom de la table */ GB.NewString(&info->table, table, 0); res = mysql_list_fields( conn, table, 0); if (!res) return TRUE; info->nfield = n = mysql_num_fields(res); if (n == 0) return TRUE; GB.Alloc((void **)&info->field, sizeof(DB_FIELD) * n); i = 0; while ((field = mysql_fetch_field(res))) { f = &info->field[i]; GB.NewString(&f->name, field->name, 0); f->type = conv_type(field->type, field->length); f->length = 0; if (f->type == GB_T_STRING) f->length = field->length; i++; } mysql_free_result(res); return FALSE;}/***************************************************************************** table_index() Initialize an info structure from table primary index. <handle> is the database handle. <table> is the table name. <info> points at the info structure. This function must initialize the following info fields: - info->nindex must contain the number of fields in the primary index. - info->index is a int[] giving the index of each index field in info->fields. This function must be called after table_init(). This function returns TRUE if the command has failed, and FALSE if everything was OK.*****************************************************************************/static int table_index(DB_DATABASE db, char *table, DB_INFO *info){ char *qindex = "show index from `&1`"; MYSQL *conn = (MYSQL *)db; MYSQL_RES *res; MYSQL_ROW row; int i, j, n; /* Index primaire */ if (do_query(conn, "Unable to get primary index: &1", &res, qindex, 1, table)) return TRUE; for ( i = 0, n = 0; i < mysql_num_rows(res); i++ ) { row = mysql_fetch_row(res); if (strcmp("PRIMARY", row[2]) == 0) /* Use only Primary key */ n++; } mysql_data_seek(res, 0);/* move back to first record */ info->nindex = n; /* Note: Col 3 is Key_name, Col 4 is Sq_in_index, Col 5 is Field Name */ if (n <= 0) { GB.Error("Table '&1' has no primary index", table); return TRUE; } GB.Alloc((void **)&info->index, sizeof(int) * n); for (i = 0; i < n; i++) { row = mysql_fetch_row(res); if (strcmp("PRIMARY", row[2]) == 0) /* Use only Primary key */ { for (j = 0; j < info->nfield; j++) { if (strcasecmp(info->field[j].name, row[4]) == 0) { info->index[i] = j; break; } } } } mysql_free_result(res); return FALSE;}/***************************************************************************** table_release() Free the info structure filled by table_init() and/or table_index() <handle> is the database handle. <info> points at the info structure.*****************************************************************************/static void table_release(DB_DATABASE db, DB_INFO *info){ /* All is done outside the driver */}/***************************************************************************** table_exist() Returns if a table exists <handle> is the database handle. <table> is the table name. This function returns TRUE if the table exists, and FALSE if not.*****************************************************************************/static int table_exist(DB_DATABASE handle, char *table){ MYSQL *conn = (MYSQL *)handle; MYSQL_RES *res; int exist; const char *query = "show tables like '&1'"; if (do_query(conn, "Unable to check table: &1", &res, query, 1, table)) return FALSE; exist = mysql_num_rows(res); mysql_free_result(res); //return FALSE; return exist;}/***************************************************************************** table_list() Returns an array containing the name of each table in the database <handle> is the database handle. <tables> points to a variable that will receive the char* array. This function returns the number of tables, or -1 if the command has failed. Be careful: <tables> can be NULL, so that just the count is returned.*****************************************************************************/static long table_list(DB_DATABASE handle, char ***tables, long version){ MYSQL *conn = (MYSQL *)handle; MYSQL_RES *res; MYSQL_ROW row; long i; long rows; const char *query = "show tables"; if (do_query(conn, "Unable to get tables", &res, query, 0)) return -1; rows = mysql_num_rows(res); GB.NewArray(tables, sizeof(char *), rows); for (i = 0; i < rows; i++){ row = mysql_fetch_row(res); GB.NewString(&(*tables)[i], row[0], 0); } mysql_free_result(res); return rows;}/***************************************************************************** table_primary_key() Returns a string representing the primary key of a table. <handle> is the database handle. <table> is the table name. <key> points to a string that will receive the primary key. This function returns TRUE if the command has failed, and FALSE if everything was OK.*****************************************************************************/static int table_primary_key(DB_DATABASE handle, char *table, char ***primary){ const char *query = "show index from `&1`"; MYSQL *conn = (MYSQL *)handle; MYSQL_RES *res; MYSQL_ROW row; int i; if (do_query(conn, "Unable to get primary key: &1", &res, query, 1, table)) return TRUE; GB.NewArray(primary, sizeof(char *), 0); for (i = 0; i < mysql_num_rows(res); i++) { row = mysql_fetch_row(res); if (strcmp("PRIMARY", row[2]) == 0) GB.NewString((char **)GB.Add(primary), row[4], 0); } mysql_free_result(res); return FALSE;}/***************************************************************************** table_is_system() Returns if a table is a system table. <handle> is the database handle. <table> is the table name. This function returns TRUE if the table is a system table, and FALSE if not. Note: In mysql the system tables are stored in a separate database. The tables are mysql.columns_priv, mysql.db, mysql.func, mysql.host, mysql.tables_priv, mysql.user. This has therefore not been implemented.*****************************************************************************/static int table_is_system(DB_DATABASE handle, char *table, long version){ const char *query = "select database()"; MYSQL *conn = (MYSQL *)handle; MYSQL_RES *res; MYSQL_ROW row; int system; if (do_query(conn, "Unable to check database: &1", &res, query, 0)) return FALSE; if (mysql_num_rows(res) != 1 ){ GB.Error("Unable to check database: More than one database returned !?"); return FALSE; } /* (BM) Check that the current database is mysql */ row = mysql_fetch_row(res); if (strcmp(row[0], "mysql")) system = FALSE; else { if (strcmp(table, "columns_priv") == 0 || strcmp(table, "db") == 0 || strcmp(table, "func") == 0 || strcmp(table, "host") == 0 || strcmp(table, "tables_priv") == 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -