/** * Ruby/mSQL is a mSQL library * * @author DATE Ken (as Itacchi) / ge6537@i.bekkoame.ne.jp * @code-name Tomoko * @see http://www.isc.meiji.ac.jp/~ee77038/ruby/ * @todo convert method that between Ruby's Time and mSQL's TIME. * $Id: msql.c 1.5 2000/12/01 16:17:23 date Exp date $ */ #include "ruby_msql.h" #define FIX2BOOL(val) if(FIX2INT(val)==0){val=Qfalse;}else{val=Qtrue;} #define CHECK_CONNECTION(msql) if(msql->sock==-1){rb_raise(eMsql,"no connection");} VALUE cMsql; VALUE cMsqlResult; VALUE cMsqlField; VALUE cMsqlSequence; VALUE eMsql; /* * -------- * Msql * -------- */ /* =begin = (({Msql})) mSQL client class. === constant --- Msql::CONFIG_GROUP_GENERAL For (()). --- Msql::CONFIG_GROUP_SYSTEM For (()). --- Msql::CONFIG_GROUP_W3MSQL For (()). --- Msql::INST_DIR mSQL installed directory. --- Msql::SERVER_VERSION mSQL server version. --- Msql::TARGET mSQL target platform. --- Msql::VERSION Ruby/mSQL versions. === class method --- Msql.connect([host], [database_name]) Try to connect mSQL server specified the ((|host|)) and select database specified the ((|database_name|)). If you omit ((|host|)) or specified the ((|nil|)) as ((|host|)), then connect local mSQL server. ((*ex.*)) Msql.connect 'sublime', 'artists' #=> connect server on host 'sublime' and select database 'artists'. Msql.connect nil, 'singles' #=> connect local server and select database 'singles'. Msql.connect 'frogman' #=> connect server on host 'frogman'. Msql.connect #=> connect local server. :Returns: *Msql: mSQL client. :Exceptions: *TypeError: ((|host|)) and/or ((|database_name|)) aren't String. *MsqlError: connection failed. --- Msql.get_config(group) Get config values from loaded config file. ((|group|)) only accepts below *(()) --- "general" *(()) --- "system" *(()) --- "w3-msql" :Returns: *Hash: config values of specified group. *nil : unkown group. --- Msql.load_config_file([conf_file]) Load config file specified the ((|conf_file|)). :Exceptions: *TypeError: ((|conf_file|)) isn't String. *MsqlError: loading failed. === instance method --- Msql#close Close the connection with the connected server. :Exceptions: *MsqlError: closing failed. --- Msql#connect([host], [database_name]) See (()). :Exceptions: *TypeError: ((|host|)) and/or ((|database_name|)) aren't String. *MsqlError: already connected or connection failed. --- Msql#copy_db(src_db, dest_db) Copy a database from the ((|src_db|)) to the ((|dest_db|)). ((*This is administrator operation*)). :Exceptions: *TypeError: ((|src_db|)) and/or ((|dest_db|)) aren't String. *MsqlError: copying failed. --- Msql#create_db(db_name) Create new database named ((|db_name|)). ((*This is administrator operation*)). :Exceptions: *TypeError: ((|db_name|)) isn't String. *MsqlError: creating failed. --- Msql#drop_db(db_name) Delete database named ((|db_name|)) completely. ((*This is administrator operation*)). :Exceptions: *TypeError: ((|db_name|)) isn't String. *MsqlError: droping failed. --- Msql#database Get selected database name (same as specified in (()) or (()) or (())). :Returns: *String: database name. --- Msql#get_host Get connected host name (same as specified in (()) or (())). :Returns: *String: host name. --- Msql#get_host_info Get connected host name and connection protocol name. :Returns: *String: host name and protocol name. --- Msql#get_sequence_info Get information of sequence. :Returns: *MsqlSequence: sequence info. *nil: no sequence exists. --- Msql#get_server_stats Get states of the connected server (for console ouput). Output config file name, max connections, current connections, server running as user and connection table. --- Msql#get_server_info Get version of the connected mSQL server. :Returns: *String: version number. --- Msql#list_dbs Get all database names on the connected server. :Returns: *MsqlResult: database names. :Exceptions: *MsqlError: failed. --- Msql#list_fields(table_name) Get all filed names on the table specified the ((|table_name|)). :Returns: *MsqlResult: field names. :Exceptions: *TypeError: ((|table_name|)) isn't String. *MsqlError: failed. --- Msql#list_index(table_name, index) Get information of the ((|index|)) on the table specified the ((|table_name|)). :Returns: *MsqlResult: type of the ((|index|)) and filed names included by the ((|index|)). :Exceptions: *TypeError: ((|table_name|)) and/or ((|index|)) aren't String. *MsqlError: failed. --- Msql#list_tables Get all table names on the connected server. :Returns: *MsqlResult: table names. :Exceptions: *MsqlError: failed. --- Msql#move_db(src_db, dest_db) Move a database from the ((|src_db|)) to the ((|dest_db|)). ((*This is administrator operation*)). :Exceptions: *TypeError: ((|src_db|)) and ((|dest_db|)) aren't String. *MsqlError: moving failed. --- Msql#query(query) Execute ((|query|)). ((*Must do (()) before this operaion*)). :Returns: *Integer: number of records effected by the ((|query|)). :Exceptions: *MsqlError: ((|query|)) failed. --- Msql#reload_acls Reload ACL(Access Control List) file. ((*This is administrator operation*)). :Exceptions: *MsqlError: reloading failed. --- Msql#select_db(db_name) Select database on the connected server. ((*Must do this before (())*)). :Exceptions: *MsqlError: selection failed. --- Msql#shutdown Shutdown connected server. ((*This is administrator operation*)). :Exceptions: *MsqlError: shutdowning failed. --- Msql#store_result --- Msql#get_result Get query results (SELECT statement). ((*Must do (()) before this operaion*)). ((*And must do this operaion before execute next (())*)). :Returns: *MsqlResult: query results. *nil: no results. :Exceptions: *MsqlError: failed. =end */ /* * -------------- * MsqlResult * -------------- */ /* =begin = (({MsqlResult})) mSQL query result class. === class method No class method. === instance method --- MsqlResult#data_seek(pos) Set cursor at ((|pos|)). (()) fetch a row at a position of the cursor. --- MsqlResult#each_field {|field|...} Iterated access to each filed. (notice: start at cursor position) --- MsqlResult#each_field_with_index {|field, index|...} Iterated access to each filed with index number. (notice: start at cursor position) --- MsqlResult#each_row {|row|...} Iterated access to each row. (notice: start at cursor position) --- MsqlResult#each_row_with_index {|row, index|...} Iterated access to each row with index number. (notice: start at cursor position) --- MsqlResult#fetch_all_fields Get all fields. (notice: range of fields is from the cursor position to the end) :Returns: *Array: array of fields. --- MsqlResult#fetch_all_rows Get all rows. (notice: range of rows is from the cursor position to the end) :Returns: *Array: array of rows. --- MsqlResult#fetch_field Fetch one field from the result. :Returns: *MsqlField: information of the field. ex. As if a MsqlResult instance has a result such as +---------------------+-----------+ | name | genre | +---------------------+-----------+ | Anthony & Cleopatra | Tragedies | | Corilanus | Tragedies | | Hamlet | Tragedies | | Julius Caesar | Tragedies | | King Lear | Tragedies | +---------------------+-----------+ then fetch_field returns field object of 'name' and the cursor move to the next 'genre' field (next fetch_field return this field). *nil: no more fileds. --- MsqlResult#fetch_hash Fetch one row as hash from the result. :Returns: *Hash: key is field name and value is element. ex. As if a MsqlResult instance has a result such as +---------------------+-----------+ | name | genre | +---------------------+-----------+ | Anthony & Cleopatra | Tragedies | | Corilanus | Tragedies | | Hamlet | Tragedies | | Julius Caesar | Tragedies | | King Lear | Tragedies | +---------------------+-----------+ then fetch_hash returns {"name"=>"Anthony & Cleopatra", "genre"=>"Tragedies"} and the cursor move to the next row. *nil: no more rows. --- MsqlResult#fetch_row Fetch one row from the result. :Returns: *Array: array of (String) elements of each fields. ex. As if a MsqlResult instance has a result such as +---------------------+-----------+ | name | genre | +---------------------+-----------+ | Anthony & Cleopatra | Tragedies | | Corilanus | Tragedies | | Hamlet | Tragedies | | Julius Caesar | Tragedies | | King Lear | Tragedies | +---------------------+-----------+ then fetch_row returns ["Anthony & Cleopatra", "Tragedies"] and the cursor move to the next row: ["Corilanus", "Tragedies"](next fetch_row return this row). *nil: no more rows. --- MsqlResult#field_seek(pos) Set cursor at ((|pos|)). (()) fetch a field at a position of the cursor. --- MsqlResult#num_fields Get number of fields of the results. :Returns: *Integer: number of fields. --- MsqlResult#num_rows Get number of rows of the results. :Returns: *Integer: number of rows. =end */ /* * ------------- * MsqlField * ------------- */ /* =begin = (({MsqlField})) mSQL field has a information of column. === constant --- MsqlField::INT_TYPE Field data type: integer. --- MsqlField::CHAR_TYPE Field data type: charactor. --- MsqlField::REAL_TYPE Field data type: real number. --- MsqlField::IDENT_TYPE Field data type: identify. --- MsqlField::NULL_TYPE Field data type: null. --- MsqlField::TEXT_TYPE Field data type: text. --- MsqlField::DATE_TYPE Field data type: date. --- MsqlField::UINT_TYPE Field data type: unsigned integer. --- MsqlField::MONEY_TYPE Field data type: money. --- MsqlField::LAST_REAL_TYPE Field data type: last real number. --- MsqlField::IDX_TYPE Field data type: index. --- MsqlField::SYSVAR_TYPE Field data type: system variable. --- MsqlField::ANY_TYPE Field data type: any. === class method No class method. === instance method --- MsqlField#name Get field name. :Returns: *String: field name. --- MsqlField#table Get table name. :Returns: *String: table name. --- MsqlField#type Get filed type. :Returns: *Integer: filed type. *(()) *(()) *(()) *(()) *(()) *(()) *(()) *(()) *(()) *(()) *(()) *(()) *(()) --- MsqlField#length Get filed length. :Returns: *Integer: filed length. --- MsqlField#flags Get field flags. Usually, access with (()) or (()). :Returns: *Integer: field flags. --- MsqlField#is_not_null --- MsqlField#is_not_null? Return true if field defined as NOT NULL. :Returns: *true/false: field is 'NOT NULL' or not. --- MsqlField#is_unique --- MsqlField#is_unique? Return true if field is unique. Returns: *true/false: field is unique or not. =end */ /* * ---------------- * MsqlSequence * ---------------- */ /* =begin = (({MsqlSequence})) Sequence information. === class method No class method. === instance method --- MsqlSequence#step Get sequence step. :Returns: *Integer: sequence step. --- MsqlSequence#value Get sequence value. :Returns: *Integer: sequence value. =end */ /* * +------+ * | Msql | * +------+ */ static void msql_free(msql) msql_object *msql; { if (msql->sock != -1) msqlClose(msql->sock); free(msql); } /* * --------------- * class method of * Msql * --------------- */ static VALUE msql_connect(argc, argv, klass) int argc; VALUE *argv, klass; { VALUE new_obj; msql_object *msql; new_obj = Data_Make_Struct(klass, msql_object, 0, msql_free, msql); msql->sock = -1; msql_connect2(argc, argv, new_obj); return new_obj; } /* private function for msql_get_(general|system|w3-msql)_conf */ static VALUE msql_get_char_conf(group, key) char *group, *key; { return rb_str_new2((char *)msqlGetCharConf(group, key)); } /* private function for msql_get_(general|system|w3-msql)_conf */ static VALUE msql_get_int_conf(group, key) char *group, *key; { return INT2FIX(msqlGetIntConf(group, key)); } /* private function for msql_get_conf */ static VALUE msql_get_general_conf(void) { VALUE hash; VALUE val; hash = rb_eval_string("Hash.new"); val = msql_get_char_conf("general", "inst_dir"); rb_funcall(hash, rb_intern("[]="),2, rb_str_new2("Inst_Dir"), val); /* don't exist in ver.2.0.4 val = msql_get_char_conf("general", "db_dir"); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("DB_Dir"), val); */ val = msql_get_char_conf("general", "msql_user"); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("mSQL_User"), val); val = msql_get_char_conf("general", "admin_user"); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("Admin_User"), val); val = msql_get_char_conf("general", "pid_file"); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("Pid_File"), val); val = msql_get_int_conf("general", "tcp_port"); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("TCP_Port"), val); val = msql_get_char_conf("general", "unix_port"); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("UNIX_Port"), val); return hash; } /* private function for msql_get_conf */ static VALUE msql_get_system_conf(void) { VALUE hash; VALUE val; hash = rb_eval_string("Hash.new"); val = msql_get_int_conf("system", "msync_timer"); rb_funcall(hash, rb_intern("[]="),2, rb_str_new2("Msync_Timer"), val); val = msql_get_int_conf("system", "host_lookup"); FIX2BOOL(val); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("Host_Lookup"), val); val = msql_get_int_conf("system", "read_only"); FIX2BOOL(val); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("Read_Only"), val); val = msql_get_int_conf("system", "remote_access"); FIX2BOOL(val); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("Remote_Access"), val); val = msql_get_int_conf("system", "local_access"); FIX2BOOL(val); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("local_access"), val); /* don't exist in ver.2.0.4 val = msql_get_int_conf("system", "query_log"); FIX2BOOL(val); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("Query_Log"), val); val = msql_get_char_conf("system", "query_log_file"); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("Query_Log_File"), val); */ return hash; } /* private function for msql_get_conf */ static VALUE msql_get_w3msql_conf(void) { VALUE hash; VALUE val; hash = rb_eval_string("Hash.new"); /* val = msql_get_char_conf("w3-msql", "auth_host"); rb_funcall(hash, rb_intern("[]="),2, rb_str_new2("Auth_Host"), val); */ val = msql_get_int_conf("w3-msql", "footer"); FIX2BOOL(val); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("Footer"), val); val = msql_get_int_conf("w3-msql", "force_private"); FIX2BOOL(val); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("Force_Private"), val); /* val = msql_get_char_conf("w3-msql", "force_suffix"); rb_funcall(hash, rb_intern("[]="), 2, rb_str_new2("Force_Suffix"), val); */ return hash; } static VALUE msql_get_conf(klass, _group) VALUE klass, _group; { char *group; Check_Type(_group, T_STRING); group = STR2CSTR(_group); if (strcmp(group, "general") == 0) return msql_get_general_conf(); if (strcmp(group, "system") == 0) return msql_get_system_conf(); if (strcmp(group, "w3-msql") == 0) return msql_get_w3msql_conf(); return Qnil; } static VALUE msql_load_config_file(klass, conf_file) VALUE klass, conf_file; { int retcode; Check_Type(conf_file, T_STRING); retcode = msqlLoadConfigFile(STR2CSTR(conf_file)); if (retcode < 0) rb_raise(eMsql, "%s", msqlErrMsg); return Qnil; } static VALUE msql_new(klass) VALUE klass; { VALUE new_obj; msql_object *msql; new_obj = Data_Make_Struct(klass, msql_object, 0, msql_free, msql); msql->sock = -1; rb_iv_set(new_obj, "database", rb_str_new2("")); rb_iv_set(new_obj, "host", rb_str_new2("")); return new_obj; } /* * ------------------ * instance method of * Msql * ------------------ */ static VALUE msql_initialize(obj) VALUE obj; { return Qnil; } static VALUE msql_close(obj) VALUE obj; { msql_object *msql; Data_Get_Struct(obj, msql_object, msql); if (msql->sock != -1) msqlClose(msql->sock); return Qnil; } static VALUE msql_connect2(argc, argv, obj) int argc; VALUE *argv, obj; { VALUE _host, db_name; msql_object *msql; char *host; int retcode; Data_Get_Struct(obj, msql_object, msql); if(msql->sock != -1) rb_raise(eMsql, "already connected"); rb_scan_args(argc, argv, "02", &_host, &db_name); /* get host name */ switch (TYPE(_host)){ /* if NULL specified, connect local server */ case T_NIL: host = NULL; break; case T_STRING: host = STR2CSTR(_host); break; default: rb_raise(rb_eTypeError, "wrong argument type %s (expected String/nil)", rb_class2name(CLASS_OF(_host))); } msql->sock = msqlConnect(host); rb_iv_set(obj, "host", rb_str_new2(host ? host : "localhost")); if(msql->sock == -1) rb_raise(eMsql, "connect error"); /* select database */ switch (TYPE(db_name)){ case T_NIL: break; case T_STRING: retcode = msqlSelectDB(msql->sock, STR2CSTR(db_name)); if (retcode < 0) rb_raise(eMsql, "%s", msqlErrMsg); rb_iv_set(obj, "database", db_name); break; default: rb_raise(rb_eTypeError, "wrong argument type %s (expected String)", rb_class2name(CLASS_OF(db_name))); } return obj; } static VALUE msql_copy_db(obj, src_db, dest_db) VALUE obj, src_db, dest_db; { msql_object *msql; int retcode; Check_Type(src_db, T_STRING); Check_Type(dest_db, T_STRING); Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); retcode = msqlCopyDB(msql->sock, STR2CSTR(src_db), STR2CSTR(dest_db)); if (retcode < 0) rb_raise(eMsql, "%s", msqlErrMsg); return obj; } static VALUE msql_create_db(obj, db_name) VALUE obj, db_name; { msql_object *msql; int retcode; Check_Type(db_name, T_STRING); Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); retcode = msqlCreateDB(msql->sock, STR2CSTR(db_name)); if (retcode < 0) rb_raise(eMsql, "%s", msqlErrMsg); return obj; } static VALUE msql_drop_db(obj, db_name) VALUE obj, db_name; { msql_object *msql; int retcode; Check_Type(db_name, T_STRING); Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); retcode = msqlDropDB(msql->sock, STR2CSTR(db_name)); if (retcode < 0) rb_raise(eMsql, "%s", msqlErrMsg); return obj; } static VALUE msql_get_database(obj) { return rb_iv_get(obj, "database"); } static VALUE msql_get_host(obj) { return rb_iv_get(obj, "host"); } static VALUE msql_get_host_info(obj) VALUE obj; { return rb_str_new2(msqlGetHostInfo()); } static VALUE msql_get_protocol_info(obj) VALUE obj; { return INT2FIX(msqlGetProtoInfo()); } static VALUE msql_get_sequence_info(obj, table_name) VALUE obj, table_name; { msql_object *msql; m_seq *seq; Check_Type(table_name, T_STRING); Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); seq = msqlGetSequenceInfo(msql->sock, STR2CSTR(table_name)); if (seq == NULL) return Qnil; return msql_seq_create(seq); } static VALUE msql_get_server_info(obj) VALUE obj; { return rb_str_new2(msqlGetServerInfo()); } static VALUE msql_get_server_stats(obj) VALUE obj; { msql_object *msql; Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); return INT2FIX(msqlGetServerStats(msql->sock)); } static VALUE msql_inspect(obj) VALUE obj; { msql_object *msql; VALUE str; char buf[256]; sprintf(buf, "#", msqlGetHostInfo()); str = rb_str_new2(buf); return str; } static VALUE msql_list_dbs(obj) VALUE obj; { msql_object *msql; m_result *res; VALUE result; Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); res = msqlListDBs(msql->sock); if (res == NULL) rb_raise(eMsql, "%s", msqlErrMsg); result = msql_res_create(cMsqlResult, res); return result; } static VALUE msql_list_fields(obj, table_name) VALUE obj, table_name; { msql_object *msql; m_result *res; VALUE result; Check_Type(table_name, T_STRING); Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); res = msqlListFields(msql->sock, STR2CSTR(table_name)); if (res == NULL) rb_raise(eMsql, "%s", msqlErrMsg); result = msql_res_create(cMsqlResult, res); return result; } static VALUE msql_list_index(obj, table_name, index) VALUE obj, table_name, index; { msql_object *msql; m_result *res; VALUE result; Check_Type(table_name, T_STRING); Check_Type(index, T_STRING); Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); res = msqlListIndex(msql->sock, STR2CSTR(table_name), STR2CSTR(index)); if (res == NULL) rb_raise(eMsql, "%s", msqlErrMsg); result = msql_res_create(cMsqlResult, res); return result; } static VALUE msql_list_tables(obj) VALUE obj; { msql_object *msql; m_result *res; VALUE result; Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); res = msqlListTables(msql->sock); if (res == NULL) rb_raise(eMsql, "%s", msqlErrMsg); result = msql_res_create(cMsqlResult, res); return result; } static VALUE msql_move_db(obj, src_db, dest_db) VALUE obj, src_db, dest_db; { msql_object *msql; int retcode; Check_Type(src_db, T_STRING); Check_Type(dest_db, T_STRING); Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); retcode = msqlMoveDB(msql->sock, STR2CSTR(src_db), STR2CSTR(dest_db)); if (retcode < 0) rb_raise(eMsql, "%s", msqlErrMsg); return obj; } static VALUE msql_query(obj, query) VALUE obj, query; { msql_object *msql; int retcode; Check_Type(query, T_STRING); Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); retcode = msqlQuery(msql->sock, STR2CSTR(query)); if (retcode < 0) rb_raise(eMsql, "%s", msqlErrMsg); return INT2FIX(retcode); } static VALUE msql_reload_acls(obj) VALUE obj; { msql_object *msql; int retcode; Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); retcode = msqlReloadAcls(msql->sock); if (retcode < 0) rb_raise(eMsql, "%s", msqlErrMsg); return obj; } static VALUE msql_select_db(obj, db_name) VALUE obj, db_name; { msql_object *msql; int retcode; Check_Type(db_name, T_STRING); Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); retcode = msqlSelectDB(msql->sock, STR2CSTR(db_name)); if (retcode < 0) rb_raise(eMsql, "%s", msqlErrMsg); return obj; } static VALUE msql_shutdown(obj) VALUE obj; { msql_object *msql; int retcode; Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); retcode = msqlShutdown(msql->sock); if (retcode < 0) rb_raise(eMsql, "%s", msqlErrMsg); return obj; } static VALUE msql_store_result(obj) VALUE obj; { msql_object *msql; m_result *res; Data_Get_Struct(obj, msql_object, msql); CHECK_CONNECTION(msql); res = msqlStoreResult(); if (res == NULL) return Qnil; return msql_res_create(cMsqlResult, res); } /* * +------------+ * | MsqlResult | * +------------+ */ static void msql_res_free(msql_res) msql_res_object *msql_res; { msqlFreeResult(msql_res->result); free(msql_res); } static VALUE msql_res_create(klass, result) VALUE klass; m_result *result; { VALUE new_obj; msql_res_object *msql_res; new_obj = Data_Make_Struct(klass, msql_res_object, NULL, msql_res_free, msql_res); msql_res->result = result; return new_obj; } /* * ------------------ * instance method of * MsqlResult * ------------------ */ static VALUE msql_res_initialize(obj) VALUE obj; { return Qnil; } static VALUE msql_res_data_seek(obj, pos) VALUE obj, pos; { msql_res_object *msql_res; FIXNUM_P(pos); Data_Get_Struct(obj, msql_res_object, msql_res); msqlDataSeek(msql_res->result, FIX2INT(pos)); return Qnil; } static VALUE msql_res_each_field(obj) VALUE obj; { msql_res_object *msql_res; VALUE field; Data_Get_Struct(obj, msql_res_object, msql_res); while ((field = msql_res_fetch_field(obj)) != Qnil) rb_yield(field); return obj; } static VALUE msql_res_each_field_with_index(obj) VALUE obj; { msql_res_object *msql_res; VALUE ary, field; int index; Data_Get_Struct(obj, msql_res_object, msql_res); index = 0; while ((field = msql_res_fetch_field(obj)) != Qnil){ ary = rb_ary_new(); rb_ary_push(ary, field); rb_ary_push(ary, INT2FIX(index)); rb_yield(ary); index++; } return obj; } static VALUE msql_res_each_row(obj) VALUE obj; { msql_res_object *msql_res; VALUE row; Data_Get_Struct(obj, msql_res_object, msql_res); while ((row = msql_res_fetch_row(obj)) != Qnil) rb_yield(row); return obj; } static VALUE msql_res_each_row_with_index(obj) VALUE obj; { msql_res_object *msql_res; VALUE ary, row; int index; Data_Get_Struct(obj, msql_res_object, msql_res); index = 0; while ((row = msql_res_fetch_row(obj)) != Qnil){ ary = rb_ary_new(); rb_ary_push(ary, row); rb_ary_push(ary, INT2FIX(index)); rb_yield(ary); index++; } return obj; } static VALUE msql_res_fetch_all_fields(obj) VALUE obj; { msql_res_object *msql_res; VALUE ary, field; Data_Get_Struct(obj, msql_res_object, msql_res); ary = rb_ary_new(); while ((field = msql_res_fetch_field(obj)) != Qnil) rb_ary_push(ary, field); return ary; } static VALUE msql_res_fetch_all_rows(obj) VALUE obj; { msql_res_object *msql_res; VALUE ary, row; Data_Get_Struct(obj, msql_res_object, msql_res); ary = rb_ary_new(); while ((row = msql_res_fetch_row(obj)) != Qnil) rb_ary_push(ary, row); return ary; } static VALUE msql_res_fetch_field(obj) VALUE obj; { msql_res_object *msql_res; m_field *field; Data_Get_Struct(obj, msql_res_object, msql_res); field = msqlFetchField(msql_res->result); if (field == NULL) return Qnil; return msql_field_create(field); } static VALUE msql_res_fetch_hash(obj) VALUE obj; { msql_res_object *msql_res; m_row _row; VALUE row, fields, hash; int num_fields, i; Data_Get_Struct(obj, msql_res_object, msql_res); _row = msqlFetchRow(msql_res->result); if (_row == NULL) return Qnil; fields = msql_res_fetch_all_fields(obj); hash = rb_eval_string("Hash.new"); num_fields = msqlNumFields(msql_res->result); for (i = 0; i < num_fields; i++){ rb_funcall(hash, rb_intern("[]="), 2, rb_iv_get(RARRAY(fields)->ptr[i], "name"), rb_str_new2(_row[i])); } return hash; } static VALUE msql_res_fetch_row(obj) VALUE obj; { msql_res_object *msql_res; m_row _row; VALUE row; int num_fields, i; Data_Get_Struct(obj, msql_res_object, msql_res); _row = msqlFetchRow(msql_res->result); if (!_row) return Qnil; row = rb_ary_new(); num_fields = msqlNumFields(msql_res->result); for (i=0; i < num_fields; i++){ if (!_row[i]) rb_ary_push(row, Qnil); else rb_ary_push(row, rb_str_new2(_row[i])); } return row; } static VALUE msql_res_field_seek(obj, pos) VALUE obj, pos; { msql_res_object *msql_res; FIXNUM_P(pos); Data_Get_Struct(obj, msql_res_object, msql_res); msqlFieldSeek(msql_res->result, FIX2INT(pos)); return obj; } static VALUE msql_res_num_fields(obj) VALUE obj; { msql_res_object *msql_res; int num_fields; Data_Get_Struct(obj, msql_res_object, msql_res); num_fields = msqlNumFields(msql_res->result); return INT2FIX(num_fields); } static VALUE msql_res_num_rows(obj) VALUE obj; { msql_res_object *msql_res; int num_rows; Data_Get_Struct(obj, msql_res_object, msql_res); num_rows = msqlNumRows(msql_res->result); return INT2FIX(num_rows); } /* * +-----------+ * | MsqlField | * +-----------+ */ static VALUE msql_field_create(field_src) m_field *field_src; { VALUE new_obj; if (field_src == NULL) return Qnil; new_obj = rb_obj_alloc(cMsqlField); rb_iv_set(new_obj, "name", field_src->name ? rb_str_freeze(rb_tainted_str_new2(field_src->name)) : Qnil); rb_iv_set(new_obj, "table", field_src->table ? rb_str_freeze(rb_tainted_str_new2(field_src->table)) : Qnil); rb_iv_set(new_obj, "type", INT2FIX(field_src->type)); rb_iv_set(new_obj, "length", INT2FIX(field_src->length)); rb_iv_set(new_obj, "flags", INT2FIX(field_src->flags)); return new_obj; } /* * ------------------ * instance method of * MsqlField * ------------------ */ static VALUE msql_field_get_name(obj) VALUE obj; { return rb_iv_get(obj, "name"); } static VALUE msql_field_get_table(obj) VALUE obj; { return rb_iv_get(obj, "table"); } static VALUE msql_field_get_type(obj) VALUE obj; { return rb_iv_get(obj, "type"); } static VALUE msql_field_get_length(obj) VALUE obj; { return rb_iv_get(obj, "length"); } static VALUE msql_field_get_flags(obj) VALUE obj; { return rb_iv_get(obj, "flags"); } static VALUE msql_field_inspect(obj) VALUE obj; { VALUE name, str; name = rb_iv_get(obj, "name"); str = rb_str_new(0, RSTRING(name)->len + 14); sprintf(RSTRING(str)->ptr, "#", RSTRING(name)->ptr); return str; } static VALUE msql_field_is_not_null(obj) VALUE obj; { int flags; flags = FIX2INT(rb_iv_get(obj, "flags")); if (IS_NOT_NULL(flags)) return Qtrue; return Qfalse; } static VALUE msql_field_is_unique(obj) VALUE obj; { int flags; flags = FIX2INT(rb_iv_get(obj, "flags")); if (IS_UNIQUE(flags)) return Qtrue; return Qfalse; } static VALUE msql_field_to_s(obj) VALUE obj; { VALUE name, type, length, flags, str; char buf[64]; name = rb_iv_get(obj, "name"); type = rb_iv_get(obj, "type"); flags = rb_iv_get(obj, "flags"); Check_Type(name, T_STRING); FIXNUM_P(type); FIXNUM_P(flags); str = rb_str_new2(STR2CSTR(name)); rb_str_cat(str, " ", 1); switch(FIX2INT(type)){ case INT_TYPE: rb_str_cat(str, "INT", 3); break; case UINT_TYPE: rb_str_cat(str, "UINT", 4); break; case MONEY_TYPE: rb_str_cat(str, "MONEY", 5); break; case TIME_TYPE: rb_str_cat(str, "TIME", 4); break; case DATE_TYPE: rb_str_cat(str, "DATE", 4); break; case CHAR_TYPE: length = rb_iv_get(obj, "length"); FIXNUM_P(length); sprintf(buf, "CHAR(%d)", FIX2INT(length)); rb_str_cat(str, buf, strlen(buf)); break; case REAL_TYPE: rb_str_cat(str, "REAL", 4); break; case TEXT_TYPE: length = rb_iv_get(obj, "length"); FIXNUM_P(length); sprintf(buf, "TEXT(%d)", FIX2INT(length)); rb_str_cat(str, buf, strlen(buf)); break; default: rb_raise(eMsql, "Unkonwn field type: %d\n", FIX2INT(type)); } if (IS_NOT_NULL(FIX2INT(flags))) rb_str_cat(str, " NOT NULL", 9); return str; } /* * +--------------+ * | MsqlSequence | * +--------------+ */ static VALUE msql_seq_create(seq_src) m_seq *seq_src; { VALUE new_obj; if (seq_src == NULL) return Qnil; new_obj = rb_obj_alloc(cMsqlSequence); rb_iv_set(new_obj, "step", INT2FIX(seq_src->step)); rb_iv_set(new_obj, "value", INT2FIX(seq_src->value)); return new_obj; } /* * ------------------ * instance method of * MsqlSequence * ------------------ */ static VALUE msql_seq_inspect(obj) VALUE obj; { VALUE step, str, value; char buf[64]; step = rb_iv_get(obj, "step"); value = rb_iv_get(obj, "value"); sprintf(buf, "#", FIX2INT(step), FIX2INT(value)); str = rb_str_new(buf, strlen(buf)); return str; } static VALUE msql_seq_get_step(obj) VALUE obj; { return rb_iv_get(obj, "step"); } static VALUE msql_seq_get_value(obj) VALUE obj; { return rb_iv_get(obj, "value"); } static VALUE msql_seq_to_s(obj) VALUE obj; { VALUE step, str, value; char buf[64]; step = rb_iv_get(obj, "step"); value = rb_iv_get(obj, "value"); sprintf(buf, "STEP %d VALUE %d", FIX2INT(step), FIX2INT(value)); str = rb_str_new(buf, strlen(buf)); return str; } void Init_msql() { cMsql = rb_define_class("Msql", rb_cObject); cMsqlResult = rb_define_class("MsqlResult", rb_cObject); cMsqlField = rb_define_class("MsqlField", rb_cObject); cMsqlSequence = rb_define_class("MsqlSequence", rb_cObject); eMsql = rb_define_class("MsqlError", rb_eException); /* * +--------+ * | Msql | * +--------+ */ rb_define_const(cMsql, "CONFIG_GROUP_GENERAL", rb_str_new2("general")); rb_define_const(cMsql, "CONFIG_GROUP_SYSTEM", rb_str_new2("system")); rb_define_const(cMsql, "CONFIG_GROUP_W3MSQL", rb_str_new2("w3-msql")); rb_define_const(cMsql, "INST_DIR", rb_str_new2(INST_DIR)); rb_define_const(cMsql, "SERVER_VERSION", rb_str_new2(SERVER_VERSION)); rb_define_const(cMsql, "TARGET", rb_str_new2(TARGET)); rb_define_const(cMsql, "VERSION", rb_str_new2(RUBY_MSQL_VERSION)); rb_define_singleton_method(cMsql, "connect", msql_connect, -1); rb_define_singleton_method(cMsql, "get_config", msql_get_conf, 1); rb_define_singleton_method(cMsql, "load_config_file", msql_load_config_file, 1); rb_define_singleton_method(cMsql, "new", msql_new, 0); rb_define_method(cMsql, "close", msql_close, 0); rb_define_method(cMsql, "connect", msql_connect2, 1); rb_define_method(cMsql, "copy_db", msql_copy_db, 2); rb_define_method(cMsql, "create_db", msql_create_db, 1); rb_define_method(cMsql, "drop_db", msql_drop_db, 1); rb_define_method(cMsql, "get_database", msql_get_database, 0); rb_define_method(cMsql, "get_host", msql_get_host, 0); rb_define_method(cMsql, "get_host_info", msql_get_host_info, 0); rb_define_method(cMsql, "get_protocol_info", msql_get_protocol_info, 0); rb_define_method(cMsql, "get_result", msql_store_result, 0); rb_define_method(cMsql, "get_sequence_info", msql_get_sequence_info, 1); rb_define_method(cMsql, "get_server_info", msql_get_server_info, 0); rb_define_method(cMsql, "get_server_stats", msql_get_server_stats, 0); rb_define_method(cMsql, "initialize", msql_initialize, -1); rb_define_method(cMsql, "inspect", msql_inspect, 0); rb_define_method(cMsql, "list_dbs", msql_list_dbs, 0); rb_define_method(cMsql, "list_tables", msql_list_tables, 0); rb_define_method(cMsql, "list_fields", msql_list_fields, 1); rb_define_method(cMsql, "list_index", msql_list_index, 2); rb_define_method(cMsql, "move_db", msql_move_db, 2); rb_define_method(cMsql, "query", msql_query, 1); rb_define_method(cMsql, "reload_acls", msql_reload_acls, 0); rb_define_method(cMsql, "select_db", msql_select_db, 1); rb_define_method(cMsql, "shutdown", msql_shutdown, 0); rb_define_method(cMsql, "store_result", msql_store_result, 0); /* * +--------------+ * | MsqlResult | * +--------------+ */ rb_undef_method(CLASS_OF(cMsqlResult), "new"); rb_define_method(cMsqlResult, "data_seek", msql_res_data_seek, 1); rb_define_method(cMsqlResult, "each_field_with_index", msql_res_each_field_with_index, 0); rb_define_method(cMsqlResult, "each_field", msql_res_each_field, 0); rb_define_method(cMsqlResult, "each_row", msql_res_each_row, 0); rb_define_method(cMsqlResult, "each_row_with_index", msql_res_each_row_with_index, 0); rb_define_method(cMsqlResult, "fetch_all_fields", msql_res_fetch_all_fields, 0); rb_define_method(cMsqlResult, "fetch_all_rows", msql_res_fetch_all_rows, 0); rb_define_method(cMsqlResult, "fetch_field", msql_res_fetch_field, 0); rb_define_method(cMsqlResult, "fetch_hash", msql_res_fetch_hash, 0); rb_define_method(cMsqlResult, "fetch_row", msql_res_fetch_row, 0); rb_define_method(cMsqlResult, "field_seek", msql_res_field_seek, 1); rb_define_method(cMsqlResult, "initialize", msql_res_initialize, -1); rb_define_method(cMsqlResult, "num_fields", msql_res_num_fields, 0); rb_define_method(cMsqlResult, "num_rows", msql_res_num_rows, 0); /* * +-------------+ * | MsqlField | * +-------------+ */ /* constants for field type */ rb_define_const(cMsqlField, "INT_TYPE", INT2FIX(INT_TYPE)); rb_define_const(cMsqlField, "CHAR_TYPE", INT2FIX(CHAR_TYPE)); rb_define_const(cMsqlField, "REAL_TYPE", INT2FIX(REAL_TYPE)); rb_define_const(cMsqlField, "IDENT_TYPE", INT2FIX(IDENT_TYPE)); rb_define_const(cMsqlField, "NULL_TYPE", INT2FIX(NULL_TYPE)); rb_define_const(cMsqlField, "TEXT_TYPE", INT2FIX(TEXT_TYPE)); rb_define_const(cMsqlField, "DATE_TYPE", INT2FIX(DATE_TYPE)); rb_define_const(cMsqlField, "UINT_TYPE", INT2FIX(UINT_TYPE)); rb_define_const(cMsqlField, "MONEY_TYPE", INT2FIX(MONEY_TYPE)); rb_define_const(cMsqlField, "TIME_TYPE", INT2FIX(TIME_TYPE)); rb_define_const(cMsqlField, "LAST_REAL_TYPE", INT2FIX(LAST_REAL_TYPE)); rb_define_const(cMsqlField, "IDX_TYPE", INT2FIX(IDX_TYPE)); rb_define_const(cMsqlField, "SYSVAR_TYPE", INT2FIX(SYSVAR_TYPE)); rb_define_const(cMsqlField, "ANY_TYPE", INT2FIX(ANY_TYPE)); rb_undef_method(CLASS_OF(cMsqlField), "new"); rb_define_method(cMsqlField, "inspect", msql_field_inspect, 0); rb_define_method(cMsqlField, "to_s", msql_field_to_s, 0); rb_define_method(cMsqlField, "is_not_null", msql_field_is_not_null, 0); rb_define_method(cMsqlField, "is_not_null?", msql_field_is_not_null, 0); rb_define_method(cMsqlField, "is_unique", msql_field_is_unique, 0); rb_define_method(cMsqlField, "is_unique?", msql_field_is_unique, 0); rb_define_method(cMsqlField, "name", msql_field_get_name, 0); rb_define_method(cMsqlField, "table", msql_field_get_table, 0); rb_define_method(cMsqlField, "type", msql_field_get_type, 0); rb_define_method(cMsqlField, "length", msql_field_get_length, 0); rb_define_method(cMsqlField, "flags", msql_field_get_flags, 0); /* * +----------------+ * | MsqlSequence | * +----------------+ */ rb_undef_method(CLASS_OF(cMsqlSequence), "new"); rb_define_method(cMsqlSequence, "inspect", msql_seq_inspect, 0); rb_define_method(cMsqlSequence, "to_s", msql_seq_to_s, 0); rb_define_method(cMsqlSequence, "step", msql_seq_get_step, 0); rb_define_method(cMsqlSequence, "value", msql_seq_get_value, 0); }