示例#1
0
/*!
  \brief Open update cursor

  \param driver db driver
  \param table_name table name
  \param select SQL update statement (?)
  \param cursor db cursor to be opened
  \param mode open mode (?)

  \return DB_OK on success
  \return DB_FAILED on failure
 */
int db_open_update_cursor(dbDriver * driver, dbString * table_name,
			  dbString * select, dbCursor * cursor, int mode)
{
    int ret_code;

    db_init_cursor(cursor);
    cursor->driver = driver;

    /* start the procedure call */
    db__set_protocol_fds(driver->send, driver->recv);
    DB_START_PROCEDURE_CALL(DB_PROC_OPEN_UPDATE_CURSOR);

    /* send the argument(s) to the procedure */
    DB_SEND_STRING(table_name);
    DB_SEND_STRING(select);
    DB_SEND_INT(mode);

    /* get the return code for the procedure call */
    DB_RECV_RETURN_CODE(&ret_code);

    if (ret_code != DB_OK)
	return ret_code;	/* ret_code SHOULD == DB_FAILED */

    /* get the results */
    DB_RECV_TOKEN(&cursor->token);
    DB_RECV_INT(&cursor->type);
    DB_RECV_INT(&cursor->mode);
    DB_RECV_TABLE_DEFINITION(&cursor->table);
    db_alloc_cursor_column_flags(cursor);
    return DB_OK;
}
示例#2
0
/*!
   \brief Add column to table

   \param driver db driver
   \param tableName table name
   \param column new column description (dbColumn structure)

   \return DB_OK on success
   \return DB_FAILED on failure
*/
int db_add_column(dbDriver * driver, dbString * tableName, dbColumn * column)
{
    int ret_code;

    /* start the procedure call */
    db__set_protocol_fds(driver->send, driver->recv);
    DB_START_PROCEDURE_CALL(DB_PROC_ADD_COLUMN);

    /* send the argument(s) to the procedure */
    DB_SEND_STRING(tableName);
    DB_SEND_COLUMN_DEFINITION(column);

    /* get the return code for the procedure call */
    DB_RECV_RETURN_CODE(&ret_code);

    if (ret_code != DB_OK)
	return ret_code;	/* ret_code SHOULD == DB_FAILED */

    /* no results */
    return DB_OK;
}
示例#3
0
/*!
  \brief ?
  
  \param cursor db cursor
  
  \return DB_OK on success
  \return DB_FAILED on failure
*/
int db_bind_update(dbCursor * cursor)
{
    int ret_code;

    /* start the procedure call */
    db__set_protocol_fds(cursor->driver->send, cursor->driver->recv);
    DB_START_PROCEDURE_CALL(DB_PROC_BIND_UPDATE);

    /* send the argument(s) to the procedure */
    DB_SEND_TOKEN(&cursor->token);
    DB_SEND_SHORT_ARRAY(cursor->column_flags,
			db_get_cursor_number_of_columns(cursor));

    /* get the return code for the procedure call */
    DB_RECV_RETURN_CODE(&ret_code);

    if (ret_code != DB_OK)
	return ret_code;	/* ret_code SHOULD == DB_FAILED */

    /* no results */
    return DB_OK;
}
示例#4
0
/*!
  \brief Get driver (?)

  \param argc, argv arguments

  \return 0 on success
  \return 1 on failure
 */
int db_driver(int argc, char *argv[])
{
    int stat;
    int procnum;
    int i;
    int rfd, wfd;
    FILE *send, *recv;
    char *modestr;

    /* Read and set environment variables, see dbmi_client/start.c */
    if ((modestr = getenv("GRASS_DB_DRIVER_GISRC_MODE"))) {
	int mode;

	mode = atoi(modestr);

	if (mode == G_GISRC_MODE_MEMORY) {
	    G_set_gisrc_mode(G_GISRC_MODE_MEMORY);
	    G__setenv("DEBUG", getenv("DEBUG"));
	    G__setenv("GISDBASE", getenv("GISDBASE"));
	    G__setenv("LOCATION_NAME", getenv("LOCATION_NAME"));
	    G__setenv("MAPSET", getenv("MAPSET"));
	    G_debug(3, "Driver GISDBASE set to '%s'", G_getenv("GISDBASE"));
	}
    }

#ifdef __MINGW32__
    /* TODO: */
    /* We should close everything except stdin, stdout but _fcloseall()
     * closes open streams not file descriptors. _getmaxstdio too big number.
     * 
     * Because the pipes were created just before this driver was started 
     * the file descriptors should not be above a closed descriptor
     * until it was run from a multithread application and some descriptors 
     * were closed in the mean time. 
     * Also Windows documentation does not say that new file descriptor is 
     * the lowest available.
     */

    {
	int err_count = 0;
	int cfd = 3;

	while (1) {
	    if (close(cfd) == -1)
		err_count++;

	    /* no good reason for 10 */
	    if (err_count > 10)
		break;

	    cfd++;
	}
    }
#endif

    send = stdout;
    recv = stdin;

    /* THIS CODE IS FOR DEBUGGING WITH CODECENTER */

/**********************************************/
    if (argc == 3) {
	rfd = wfd = -1;
	sscanf(argv[1], "%d", &rfd);
	sscanf(argv[2], "%d", &wfd);
	send = fdopen(wfd, "w");
	if (send == NULL) {
	    db_syserror(argv[1]);
	    exit(1);
	}
	recv = fdopen(rfd, "r");
	if (recv == NULL) {
	    db_syserror(argv[2]);
	    exit(1);
	}
    }

/**********************************************/

    db_clear_error();
    db_auto_print_errors(0);
    db_auto_print_protocol_errors(1);
    db__init_driver_state();

#ifndef USE_BUFFERED_IO
    setbuf(recv, NULL);
    setbuf(send, NULL);
#endif
    db__set_protocol_fds(send, recv);

    if (db_driver_init(argc, argv) == DB_OK)
	db__send_success();
    else {
	db__send_failure();
	exit(1);
    }

    stat = DB_OK;
    /* get the procedure number */
    while (db__recv_procnum(&procnum) == DB_OK) {
#ifdef __MINGW32__
	if (procnum == DB_PROC_SHUTDOWN_DRIVER) {
	    db__send_procedure_ok(procnum);
	    break;
	}
#endif
	db_clear_error();

	/* find this procedure */
	for (i = 0; procedure[i].routine; i++)
	    if (procedure[i].procnum == procnum)
		break;

	/* if found, call it */
	if (procedure[i].routine) {
	    if ((stat = db__send_procedure_ok(procnum)) != DB_OK)
		break;		/* while loop */
	    if ((stat = (*procedure[i].routine) ()) != DB_OK)
		break;
	}
	else if ((stat =
		  db__send_procedure_not_implemented(procnum)) != DB_OK)
	    break;
    }

    db_driver_finish();

    exit(stat == DB_OK ? 0 : 1);
}
示例#5
0
/*!
  \brief Initialize a new dbDriver for db transaction.
 
  If <i>name</i> is NULL, the db name will be assigned 
  connection.driverName.
  
  \param name driver name
  
  \return pointer to dbDriver structure
  \return NULL on error
*/
dbDriver *db_start_driver(const char *name)
{
    dbDriver *driver;
    dbDbmscap *list, *cur;
    const char *startup;
    int p1[2], p2[2];
    int pid;
    int stat;
    dbConnection connection;
    char ebuf[5];

    /* Set some environment variables which are later read by driver.
     * This is necessary when application is running without GISRC file and all
     * gis variables are set by application. 
     * Even if GISRC is set, application may change some variables during runtime,
     * if for example reads data from different gdatabase, location or mapset*/

    /* setenv() is not portable, putenv() is POSIX, putenv() in glibc 2.0-2.1.1 doesn't conform to SUSv2,
     * G_putenv() as well, but that is what we want, makes a copy of string */
    if (G_get_gisrc_mode() == G_GISRC_MODE_MEMORY) {
	G_debug(3, "G_GISRC_MODE_MEMORY\n");
	sprintf(ebuf, "%d", G_GISRC_MODE_MEMORY);
	G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf);	/* to tell driver that it must read variables */

	if (G_getenv_nofatal("DEBUG")) {
	    G_putenv("DEBUG", G_getenv_nofatal("DEBUG"));
	}
	else {
	    G_putenv("DEBUG", "0");
	}

	G_putenv("GISDBASE", G_getenv_nofatal("GISDBASE"));
	G_putenv("LOCATION_NAME", G_getenv_nofatal("LOCATION_NAME"));
	G_putenv("MAPSET", G_getenv_nofatal("MAPSET"));
    }
    else {
	/* Warning: GISRC_MODE_MEMORY _must_ be set to G_GISRC_MODE_FILE, because the module can be 
	 *          run from an application which previously set environment variable to G_GISRC_MODE_MEMORY */
	sprintf(ebuf, "%d", G_GISRC_MODE_FILE);
	G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf);
    }

    /* read the dbmscap file */
    if (NULL == (list = db_read_dbmscap()))
	return (dbDriver *) NULL;

    /* if name is empty use connection.driverName, added by RB 4/2000 */
    if (name == '\0') {
	db_get_connection(&connection);
	if (NULL == (name = connection.driverName))
	    return (dbDriver *) NULL;
    }

    /* find this system name */
    for (cur = list; cur; cur = cur->next)
	if (strcmp(cur->driverName, name) == 0)
	    break;
    if (cur == NULL) {
	char msg[256];

	db_free_dbmscap(list);
	sprintf(msg, "%s: no such driver available", name);
	db_error(msg);
	return (dbDriver *) NULL;
    }

    /* allocate a driver structure */
    driver = (dbDriver *) db_malloc(sizeof(dbDriver));
    if (driver == NULL) {
	db_free_dbmscap(list);
	return (dbDriver *) NULL;
    }

    /* copy the relevant info from the dbmscap entry into the driver structure */
    db_copy_dbmscap_entry(&driver->dbmscap, cur);
    startup = driver->dbmscap.startup;

    /* free the dbmscap list */
    db_free_dbmscap(list);

    /* run the driver as a child process and create pipes to its stdin, stdout */

#ifdef __MINGW32__
#define pipe(fds) _pipe(fds, 250000, _O_BINARY | _O_NOINHERIT)
#endif

    /* open the pipes */
    if ((pipe(p1) < 0) || (pipe(p2) < 0)) {
	db_syserror("can't open any pipes");
	return (dbDriver *) NULL;
    }

    close_on_exec(p1[READ]);
    close_on_exec(p1[WRITE]);
    close_on_exec(p2[READ]);
    close_on_exec(p2[WRITE]);

    pid = G_spawn_ex(startup,
		     SF_BACKGROUND,
		     SF_REDIRECT_DESCRIPTOR, 0, p1[READ],
		     SF_CLOSE_DESCRIPTOR, p1[WRITE],
		     SF_REDIRECT_DESCRIPTOR, 1, p2[WRITE],
		     SF_CLOSE_DESCRIPTOR, p2[READ],
		     startup, NULL);

    /* create a child */
    if (pid < 0) {
	db_syserror("can't create fork");
	return (dbDriver *) NULL;
    }

    close(p1[READ]);
    close(p2[WRITE]);

    /* record driver process id in driver struct */
    driver->pid = pid;

    /* convert pipes to FILE* */
    driver->send = fdopen(p1[WRITE], "wb");
    driver->recv = fdopen(p2[READ], "rb");

    /* most systems will have to use unbuffered io to get the send/recv to work */
#ifndef USE_BUFFERED_IO
    setbuf(driver->send, NULL);
    setbuf(driver->recv, NULL);
#endif

    db__set_protocol_fds(driver->send, driver->recv);
    if (db__recv_return_code(&stat) != DB_OK || stat != DB_OK)
	driver = NULL;

    return driver;
}