ext/Generator.c in rubyfb-0.5.9 vs ext/Generator.c in rubyfb-0.6

- old
+ new

@@ -31,56 +31,24 @@ #include "Transaction.h" #include "DataArea.h" #include "rfbint.h" /* Function prototypes. */ -static VALUE allocateGenerator(VALUE); static VALUE initializeGenerator(VALUE, VALUE, VALUE); static VALUE getGeneratorName(VALUE); static VALUE getGeneratorConnection(VALUE); -static VALUE getLastGeneratorValue(VALUE); -static VALUE getNextGeneratorValue(VALUE, VALUE); -static VALUE dropGenerator(VALUE); -static VALUE doesGeneratorExist(VALUE, VALUE, VALUE); -static VALUE createGenerator(VALUE, VALUE, VALUE); -int checkForGenerator(const char *, isc_db_handle *); -int installGenerator(const char *, isc_db_handle *); -int deleteGenerator(const char *, isc_db_handle *); +static VALUE getLastGeneratorValue(int, VALUE*, VALUE); +static VALUE getNextGeneratorValue(int, VALUE*, VALUE); +static VALUE dropGenerator(int, VALUE*, VALUE); +static VALUE doesGeneratorExist(int, VALUE*, VALUE); +static VALUE createGenerator(int, VALUE*, VALUE); XSQLDA *createStorage(void); -int32_t getGeneratorValue(const char *, int, isc_db_handle *); /* Globals. */ VALUE cGenerator; - /** - * This function provides for the allocation of new Generator objects through - * the Ruby language. - * - * @param klass A reference to the Generator Class object. - * - * @return A reference to the newly allocated Generator object. - * - */ -static VALUE allocateGenerator(VALUE klass) { - VALUE instance = Qnil; - GeneratorHandle *generator = ALLOC(GeneratorHandle); - - if(generator != NULL) { - generator->connection = NULL; - instance = Data_Wrap_Struct(klass, NULL, generatorFree, - generator); - } else { - rb_raise(rb_eNoMemError, - "Memory allocation failure allocating a generator."); - } - - return(instance); -} - - -/** * This function provides the initialize method for the Generator class. * * @param self A reference to the object instance being initialized. * @param name A reference to a string containing the name of the * generator. @@ -91,13 +59,10 @@ * */ static VALUE initializeGenerator(VALUE self, VALUE name, VALUE connection) { - GeneratorHandle *generator = NULL; - ConnectionHandle *handle = NULL; - if(TYPE(name) != T_STRING) { rb_fireruby_raise(NULL, "Invalid generator name specified."); } if(TYPE(connection) != T_DATA && @@ -106,14 +71,10 @@ } rb_iv_set(self, "@name", name); rb_iv_set(self, "@connection", connection); - Data_Get_Struct(connection, ConnectionHandle, handle); - Data_Get_Struct(self, GeneratorHandle, generator); - generator->connection = &handle->handle; - return(self); } /** @@ -142,29 +103,39 @@ */ static VALUE getGeneratorConnection(VALUE self) { return(rb_iv_get(self, "@connection")); } +VALUE selectGeneratorValue(VALUE self, int step, VALUE transaction) { + VALUE result_set = Qnil, + row = Qnil, + connection = rb_iv_get(self, "@connection"), + name = rb_iv_get(self, "@name"); + char sql[100]; + sprintf(sql, "SELECT GEN_ID(%s, %d) FROM RDB$DATABASE", StringValuePtr(name), step); + result_set = rb_execute_sql(connection, rb_str_new2(sql), Qnil, transaction); + row = rb_funcall(result_set, rb_intern("fetch"), 0); + rb_funcall(result_set, rb_intern("close"), 0); + + row = rb_funcall(row, rb_intern("values"), 0); + return rb_funcall(row, rb_intern("first"), 0); +} + /** * This function fetches the last value retrieved from a Generator. * * @param self A reference to the Generator to fetch the value for. * * @return A reference to the last value retrieved from the generator. * */ -static VALUE getLastGeneratorValue(VALUE self) { - VALUE name = rb_iv_get(self, "@name"); - GeneratorHandle *generator = NULL; - int32_t number = 0; +static VALUE getLastGeneratorValue(int argc, VALUE *argv, VALUE self) { + VALUE transaction= Qnil; + rb_scan_args(argc, argv, "01", &transaction); - Data_Get_Struct(self, GeneratorHandle, generator); - - number = getGeneratorValue(StringValuePtr(name), 0, generator->connection); - - return(INT2NUM(number)); + return selectGeneratorValue(self, 0, transaction); } /** * This function provides the next method for the Generator class. @@ -174,26 +145,20 @@ * @param step The amount of increment to be applied to the Generator. * * @return A reference to an integer containing the next generator value. * */ -static VALUE getNextGeneratorValue(VALUE self, VALUE step) { - VALUE name = rb_iv_get(self, "@name"); - GeneratorHandle *generator = NULL; - int32_t number = 0; +static VALUE getNextGeneratorValue(int argc, VALUE *argv, VALUE self) { + VALUE step, transaction= Qnil; + rb_scan_args(argc, argv, "11", &step, &transaction); - Data_Get_Struct(self, GeneratorHandle, generator); - /* Check the step type. */ if(TYPE(step) != T_FIXNUM) { rb_fireruby_raise(NULL, "Invalid generator step value."); } - number = getGeneratorValue(StringValuePtr(name), FIX2INT(step), - generator->connection); - - return(INT2NUM(number)); + return selectGeneratorValue(self, FIX2INT(step), transaction); } /** * This function provides the drop method for the Generator class. @@ -201,19 +166,20 @@ * @param self A reference to the Generator object to be dropped. * * @return A reference to the Generator object dropped. * */ -static VALUE dropGenerator(VALUE self) { - GeneratorHandle *generator = NULL; - VALUE name; +static VALUE dropGenerator(int argc, VALUE *argv, VALUE self) { + VALUE name, connection, transaction = Qnil; + char sql[100]; - Data_Get_Struct(self, GeneratorHandle, generator); name = rb_iv_get(self, "@name"); + connection = rb_iv_get(self, "@connection"); + rb_scan_args(argc, argv, "01", &transaction); - /* Drop the generator. */ - deleteGenerator(StringValuePtr(name), generator->connection); + sprintf(sql, "DROP GENERATOR %s", StringValuePtr(name)); + rb_execute_sql(connection, rb_str_new2(sql), Qnil, transaction); return(self); } @@ -228,28 +194,28 @@ * * @return True if the generator already exists in the database, false * otherwise. * */ -static VALUE doesGeneratorExist(VALUE klass, VALUE name, VALUE connection) { - VALUE exists = Qfalse; - ConnectionHandle *handle = NULL; +static VALUE doesGeneratorExist(int argc, VALUE *argv, VALUE klass) { + VALUE name, connection, transaction = Qnil, + exists = Qfalse, + result_set = Qnil; + char sql[200]; // 93(statement) + 2*(31)max_generator_name = 155 + rb_scan_args(argc, argv, "21", &name, &connection, &transaction); if(TYPE(connection) != T_DATA || RDATA(connection)->dfree != (RUBY_DATA_FUNC)connectionFree) { rb_fireruby_raise(NULL, "Invalid connection specified."); } - Data_Get_Struct(connection, ConnectionHandle, handle); - - if(handle->handle == 0) { - rb_fireruby_raise(NULL, "Connection is closed."); - } - - if(checkForGenerator(StringValuePtr(name), &handle->handle)) { + sprintf(sql, "SELECT RDB$GENERATOR_NAME FROM RDB$GENERATORS WHERE RDB$GENERATOR_NAME in ('%s', UPPER('%s'))", StringValuePtr(name), StringValuePtr(name)); + result_set = rb_execute_sql(connection, rb_str_new2(sql), Qnil, transaction); + if(Qnil != rb_funcall(result_set, rb_intern("fetch"), 0)) { exists = Qtrue; } + rb_funcall(result_set, rb_intern("close"), 0); return(exists); } @@ -265,212 +231,32 @@ * generator through. * * @return A reference to a Generator object. * */ -static VALUE createGenerator(VALUE klass, VALUE name, VALUE connection) { - VALUE result = Qnil; - ConnectionHandle *handle = NULL; +static VALUE createGenerator(int argc, VALUE *argv, VALUE klass) { + VALUE name, connection, transaction = Qnil; + char sql[100]; + rb_scan_args(argc, argv, "21", &name, &connection, &transaction); if(TYPE(name) != T_STRING) { rb_fireruby_raise(NULL, "Invalid generator name specified."); } if(TYPE(connection) != T_DATA && RDATA(connection)->dfree != (RUBY_DATA_FUNC)connectionFree) { rb_fireruby_raise(NULL, "Invalid connection specified for generator creation."); } - Data_Get_Struct(connection, ConnectionHandle, handle); - if(handle->handle != 0) { - installGenerator(StringValuePtr(name), &handle->handle); - result = rb_generator_new(name, connection); - } else { - rb_fireruby_raise(NULL, - "Closed connection specified for generator creation."); - } + sprintf(sql, "CREATE GENERATOR %s", StringValuePtr(name)); + rb_execute_sql(connection, rb_str_new2(sql), Qnil, transaction); - return(result); + return rb_generator_new(name, connection); } - /** - * This function executes a check for a named generator. - * - * @param name A pointer to the string containing the generator name - * to check for. - * @param connection A pointer to the connection to be used to perform the - * check. - * - * @return Returns 0 if the generator does not exist, 1 if the generator does - * exist or -1 if there was an error. - * - */ -int checkForGenerator(const char *name, isc_db_handle *connection) { - int result = -1; - isc_stmt_handle statement = 0; - ISC_STATUS status[ISC_STATUS_LENGTH]; - - if(isc_dsql_allocate_statement(status, connection, &statement) == 0) { - isc_tr_handle transaction = 0; - - if(isc_start_transaction(status, &transaction, 1, connection, 0, - NULL) == 0) { - XSQLDA *da = (XSQLDA *)ALLOC_N(char, XSQLDA_LENGTH(1)); - - if(da != NULL) { - char sql[100]; - - da->version = SQLDA_VERSION1; - da->sqln = 1; - sprintf(sql, "SELECT COUNT(*) FROM %sS WHERE %s_NAME = UPPER('%s')", - "RDB$GENERATOR", "RDB$GENERATOR", name); - if(isc_dsql_prepare(status, &transaction, &statement, strlen(sql), - sql, 3, da) == 0) { - /* Prepare the XSQLDA and provide it with data room. */ - allocateOutXSQLDA(da->sqld, &statement, 3); - prepareDataArea(da); - if(isc_dsql_execute(status, &transaction, &statement, - 3, da) == 0) { - if(isc_dsql_fetch(status, &statement, 3, da) == 0) { - int32_t count = *((long *)da->sqlvar->sqldata); - - result = (count > 0 ? 1 : 0); - } else { - rb_fireruby_raise(status, - "Error checking for generator."); - } - } else { - rb_fireruby_raise(status, - "Error checking for generator."); - } - } else { - rb_fireruby_raise(status, "Error checking for generator."); - } - - releaseDataArea(da); - } else { - rb_raise(rb_eNoMemError, "Memory allocation failure checking " \ - "generator existence."); - } - - if(transaction != 0) { - isc_commit_transaction(status, &transaction); - } - } else { - rb_fireruby_raise(status, "Error checking for generator."); - } - - isc_dsql_free_statement(status, &statement, DSQL_drop); - } - - return(result); -} - - -/** - * This function creates a new generator within a database. - * - * @param name A pointer to the string containing the generator name - * to be created. - * @param connection A pointer to the connection to be used to create the new - * generator. - * - * @return Returns 0 if the generator was created or -1 if there was an error. - * - */ -int installGenerator(const char *name, isc_db_handle *connection) { - int result = -1; - isc_stmt_handle statement = 0; - ISC_STATUS status[ISC_STATUS_LENGTH]; - - if(isc_dsql_allocate_statement(status, connection, &statement) == 0) { - isc_tr_handle transaction = 0; - - if(isc_start_transaction(status, &transaction, 1, connection, 0, - NULL) == 0) { - char sql[100]; - - sprintf(sql, "CREATE GENERATOR %s", name); - if(isc_dsql_prepare(status, &transaction, &statement, strlen(sql), - sql, 3, NULL) == 0) { - if(isc_dsql_execute(status, &transaction, &statement, - 3, NULL) == 0) { - result = 0; - } else { - rb_fireruby_raise(status, "Error creating generator."); - } - } else { - rb_fireruby_raise(status, "Error creating generator."); - } - - if(transaction != 0) { - isc_commit_transaction(status, &transaction); - } - } else { - rb_fireruby_raise(status, "Error creating generator."); - } - - isc_dsql_free_statement(status, &statement, DSQL_drop); - } - - return(result); -} - - -/** - * This function drops an existing generator within a database. - * - * @param name A pointer to the string containing the generator name - * to be dropped. - * @param connection A pointer to the connection to be used to drop the - * generator. - * - * @return Returns 0 if the generator was dropped or -1 if there was an error. - * - */ -int deleteGenerator(const char *name, isc_db_handle *connection) { - int result = -1; - isc_stmt_handle statement = 0; - ISC_STATUS status[ISC_STATUS_LENGTH]; - - if(isc_dsql_allocate_statement(status, connection, &statement) == 0) { - isc_tr_handle transaction = 0; - - if(isc_start_transaction(status, &transaction, 1, connection, 0, - NULL) == 0) { - char sql[100]; - - sprintf(sql, "DROP GENERATOR %s", name); - if(isc_dsql_prepare(status, &transaction, &statement, strlen(sql), - sql, 3, NULL) == 0) { - if(isc_dsql_execute(status, &transaction, &statement, - 3, NULL) == 0) { - result = 0; - } else { - rb_fireruby_raise(status, "Error dropping generator."); - } - } else { - rb_fireruby_raise(status, "Error dropping generator."); - } - - if(transaction != 0) { - isc_commit_transaction(status, &transaction); - } - } else { - rb_fireruby_raise(status, "Error dropping generator."); - } - - isc_dsql_free_statement(status, &statement, DSQL_drop); - } - - return(result); -} - - -/** * This function prepares storage space for statements that will fetch values * from a generator. * * @return A pointer to an allocated XSQLDA that is ready to receive values * from a generator. @@ -497,56 +283,10 @@ return(da); } /** - * This function executes a SQL statement to fetch a value from a named - * generator in the database. - * - * @param name The name of the generator to fetch the value from. - * @param step The step interval to be used in the call to the database - * generator. - * @param connection The connection to make the call through. - * - * @return A long integer containing the generator value. - * - */ -int32_t getGeneratorValue(const char *name, int step, isc_db_handle *connection) { - int32_t result = 0; - ISC_STATUS status[ISC_STATUS_LENGTH]; - isc_tr_handle transaction = 0; - XSQLDA *da = createStorage(); - - if(isc_start_transaction(status, &transaction, 1, connection, 0, NULL) == 0) { - char sql[100]; - - sprintf(sql, "SELECT GEN_ID(%s, %d) FROM RDB$DATABASE", name, step); - if(isc_dsql_exec_immed2(status, connection, &transaction, 0, sql, - 3, NULL, da) == 0) { - result = *((int32_t *)da->sqlvar->sqldata); - } else { - ISC_STATUS local[20]; - - isc_rollback_transaction(local, &transaction); - rb_fireruby_raise(status, "Error obtaining generator value."); - } - - isc_commit_transaction(status, &transaction); - } else { - rb_fireruby_raise(status, "Error obtaining generator value."); - } - - /* Clean up. */ - if(da != NULL) { - releaseDataArea(da); - } - - return(result); -} - - -/** * This function provides a means of programmatically creating a Generator * object. * * @param name A reference to the new generator name. * @param step A reference to the generator interval step value. @@ -554,49 +294,31 @@ * * @return A reference to the new Generator object. * */ VALUE rb_generator_new(VALUE name, VALUE connection) { - VALUE instance = allocateGenerator(cGenerator); + VALUE args[2]; + args[0] = name; + args[1] = connection; - initializeGenerator(instance, name, connection); - - return(instance); + return rb_class_new_instance(2, args, cGenerator); } - /** - * This function integrates with the Ruby garbage collector to insure that all - * of the resources associated with a Generator object are release whenever a - * Generator object is collected. - * - * @param generator A pointer to the GeneratorHandle structure associated - * with the Generator object being collected. - * - */ -void generatorFree(void *generator) { - if(generator != NULL) { - free((GeneratorHandle *)generator); - } -} - - -/** * This function initializes the Generator class within the Ruby environment. * The class is established under the module specified to the function. * * @param module A reference to the module to create the class within. * */ void Init_Generator(VALUE module) { cGenerator = rb_define_class_under(module, "Generator", rb_cObject); - rb_define_alloc_func(cGenerator, allocateGenerator); rb_define_method(cGenerator, "initialize", initializeGenerator, 2); rb_define_method(cGenerator, "initialize_copy", forbidObjectCopy, 1); - rb_define_method(cGenerator, "last", getLastGeneratorValue, 0); - rb_define_method(cGenerator, "next", getNextGeneratorValue, 1); + rb_define_method(cGenerator, "last", getLastGeneratorValue, -1); + rb_define_method(cGenerator, "next", getNextGeneratorValue, -1); rb_define_method(cGenerator, "connection", getGeneratorConnection, 0); rb_define_method(cGenerator, "name", getGeneratorName, 0); - rb_define_method(cGenerator, "drop", dropGenerator, 0); - rb_define_module_function(cGenerator, "exists?", doesGeneratorExist, 2); - rb_define_module_function(cGenerator, "create", createGenerator, 2); + rb_define_method(cGenerator, "drop", dropGenerator, -1); + rb_define_module_function(cGenerator, "exists?", doesGeneratorExist, -1); + rb_define_module_function(cGenerator, "create", createGenerator, -1); }