/** Helper function to build and send a database-related event to the server hook. * * \param self Database on which the event happened * \param event event to report * * \return 0 on success (even if the hook is disabled), -1 otherwise * * \see HOOK_CMD_DBCREATED, HOOK_CMD_DBOPENED, HOOK_CMD_DBCLOSED */ static int database_hook_send_event(Database *self, const char* event){ char dburi[PATH_MAX+1]; MString *hook_command = mstring_create(); if(hook_enabled()) { if(!self->get_uri(self, dburi, sizeof(dburi))) { logwarn("%s: Unable to get full URI to database for hook\n", self->name); } else if (mstring_sprintf(hook_command, "%s %s\n", event, dburi) == -1) { logwarn("%s: Failed to construct command string for event hook\n", self->name); mstring_delete(hook_command); return -1; } else if(hook_write(mstring_buf(hook_command), mstring_len(hook_command)) < (int)mstring_len(hook_command)) { logwarn("%s: Failed to send command string to event hook: %s\n", self->name, strerror(errno)); mstring_delete(hook_command); return -1; } } return 0; }
/** Create or open an PostgreSQL database * \param db the databse to associate with the sqlite3 database * \return 0 if successful, -1 otherwise */ int psql_create_database(Database* db) { MString *conninfo; MString *str; PGconn *conn; PGresult *res = NULL; int ret = -1; loginfo ("psql:%s: Accessing database\n", db->name); /* * Make a connection to the database server -- check if the * requested database exists or not by connecting to the 'postgres' * database and querying that. */ conninfo = psql_prepare_conninfo("postgres", pg_host, pg_port, pg_user, pg_pass, pg_conninfo); conn = PQconnectdb(mstring_buf (conninfo)); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { logerror ("psql: Could not connect to PostgreSQL database (conninfo \"%s\"): %s\n", mstring_buf(conninfo), PQerrorMessage (conn)); goto cleanup_exit; } PQsetNoticeReceiver(conn, psql_receive_notice, "postgres"); str = mstring_create(); mstring_sprintf (str, "SELECT datname from pg_database where datname='%s';", db->name); res = PQexec (conn, mstring_buf (str)); if (PQresultStatus (res) != PGRES_TUPLES_OK) { logerror ("psql: Could not get list of existing databases\n"); goto cleanup_exit; } /* No result rows means database doesn't exist, so create it instead */ if (PQntuples (res) == 0) { loginfo ("psql:%s: Database does not exist, creating it\n", db->name); mstring_set (str, ""); mstring_sprintf (str, "CREATE DATABASE \"%s\";", db->name); res = PQexec (conn, mstring_buf (str)); if (PQresultStatus (res) != PGRES_COMMAND_OK) { logerror ("psql:%s: Could not create database: %s\n", db->name, PQerrorMessage (conn)); goto cleanup_exit; } } PQfinish (conn); mstring_delete(conninfo); /* Now that the database should exist, make a connection to the it for real */ conninfo = psql_prepare_conninfo(db->name, pg_host, pg_port, pg_user, pg_pass, pg_conninfo); conn = PQconnectdb(mstring_buf (conninfo)); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { logerror ("psql:%s: Could not connect to PostgreSQL database (conninfo \"%s\"): %s\n", db->name, mstring_buf(conninfo), PQerrorMessage (conn)); goto cleanup_exit; } PQsetNoticeReceiver(conn, psql_receive_notice, db->name); PsqlDB* self = (PsqlDB*)xmalloc(sizeof(PsqlDB)); self->conn = conn; self->last_commit = time (NULL); db->create = psql_create_database; db->release = psql_release; db->table_create = psql_table_create; db->table_create_meta = psql_table_create_meta; db->table_free = psql_table_free; db->insert = psql_insert; db->add_sender_id = psql_add_sender_id; db->get_metadata = psql_get_metadata; db->set_metadata = psql_set_metadata; db->get_uri = psql_get_uri; db->get_table_list = psql_get_table_list; db->handle = self; begin_transaction (self); /* Everything was successufl, prepare for cleanup */ ret = 0; cleanup_exit: if (res) PQclear (res); if (ret) PQfinish (conn); /* If return !=0, cleanup connection */ mstring_delete (str); mstring_delete (conninfo); return ret; }
TableDescr* psql_get_table_list (Database *database, int *num_tables) { PsqlDB *self = database->handle; const char *stmt_tablename = "SELECT tablename FROM pg_tables WHERE tablename NOT LIKE 'pg%' AND tablename NOT LIKE 'sql%';"; PGresult *res; TableDescr *tables = NULL; int rows, cols, i; *num_tables = -1; res = PQexec (self->conn, stmt_tablename); if (PQresultStatus (res) != PGRES_TUPLES_OK) { logerror("psql:%s: Couldn't get list of tables: %s\n", database->name, PQerrorMessage (self->conn)); PQclear (res); return NULL; } rows = PQntuples (res); cols = PQnfields (res); if (cols < 1) return NULL; int have_meta = 0; for (i = 0; i < rows && !have_meta; i++) if (strcmp (PQgetvalue (res, i, 0), "_experiment_metadata") == 0) have_meta = 1; if(!have_meta) logdebug("psql:%s: No metadata found\n", database->name); *num_tables = 0; for (i = 0; i < rows; i++) { char *val = PQgetvalue (res, i, 0); logdebug("psql:%s: Found table '%s'", database->name, val); MString *str = mstring_create (); TableDescr *t = NULL; if (have_meta) { mstring_sprintf (str, "SELECT value FROM _experiment_metadata WHERE key='table_%s';", val); PGresult *schema_res = PQexec (self->conn, mstring_buf (str)); if (PQresultStatus (schema_res) != PGRES_TUPLES_OK) { logdebug("psql:%s: Couldn't get schema for table '%s': %s; skipping\n", database->name, val, PQerrorMessage (self->conn)); mstring_delete (str); continue; } int rows = PQntuples (schema_res); if (rows == 0) { logdebug("psql:%s: Metadata for table '%s' found but empty\n", database->name, val); t = table_descr_new (val, NULL); // Don't know the schema for this table } else { logdebug("psql:%s: Stored schema for table '%s': %s\n", database->name, val, PQgetvalue (schema_res, 0, 0)); struct schema *schema = schema_from_meta (PQgetvalue (schema_res, 0, 0)); t = table_descr_new (val, schema); } PQclear (schema_res); mstring_delete (str); } else { t = table_descr_new (val, NULL); } if (t) { t->next = tables; tables = t; (*num_tables)++; } } return tables; }
/** * @brief Create a PostgreSQL table * @param db the database that contains the sqlite3 db * @param table the table to associate in sqlite3 database * @return 0 if successful, -1 otherwise */ static int table_create (Database* db, DbTable* table, int backend_create) { if (db == NULL) { logerror("psql: Tried to create a table in a NULL database\n"); return -1; } if (table == NULL) { logerror("psql:%s: Tried to create a table from a NULL definition\n", db->name); return -1; } if (table->schema == NULL) { logerror("psql:%s: No schema defined for table, cannot create\n", db->name); return -1; } MString *insert = NULL, *create = NULL; PsqlDB* psqldb = (PsqlDB*)db->handle; PGresult *res; if (backend_create) { int sindex = table->schema->index; table->schema->index = -1; MString *mstr = mstring_create (); mstring_sprintf (mstr, "table_%s", table->schema->name); const char *meta = schema_to_meta (table->schema); table->schema->index = sindex; logdebug("psql:%s: SET META: %s\n", db->name, meta); psql_set_metadata (db, mstring_buf (mstr), meta); create = schema_to_sql (table->schema, oml_to_postgresql_type); if (!create) { logerror("psql:%s: Failed to build SQL CREATE TABLE statement string for table '%s'\n", db->name, table->schema->name); goto fail_exit; } if (sql_stmt (psqldb, mstring_buf (create))) { logerror("psql:%s: Could not create table '%s': %s\n", db->name, table->schema->name, PQerrorMessage (psqldb->conn)); goto fail_exit; } } insert = psql_make_sql_insert (table); if (!insert) { logerror("psql:%s: Failed to build SQL INSERT INTO statement for table '%s'\n", db->name, table->schema->name); goto fail_exit; } /* Prepare the insert statement and update statement */ PsqlTable* psqltable = (PsqlTable*)xmalloc(sizeof(PsqlTable)); table->handle = psqltable; MString *insert_name = mstring_create(); mstring_set (insert_name, "OMLInsert-"); mstring_cat (insert_name, table->schema->name); res = PQprepare(psqldb->conn, mstring_buf (insert_name), mstring_buf (insert), table->schema->nfields + 4, // FIXME: magic number of metadata cols NULL); if (PQresultStatus(res) != PGRES_COMMAND_OK) { logerror("psql:%s: Could not prepare statement: %s\n", db->name, PQerrorMessage(psqldb->conn)); PQclear(res); goto fail_exit; return -1; } PQclear(res); psqltable->insert_stmt = insert_name; if (create) mstring_delete (create); if (insert) mstring_delete (insert); return 0; fail_exit: if (create) mstring_delete (create); if (insert) mstring_delete (insert); return -1; }
bool loadStandardState () { cstring fpath; FILE *stdlib; bool result; cstring libname = fileLib_addExtension (context_selectedLibrary (), cstring_makeLiteralTemp (DUMP_SUFFIX)); if (osd_findOnLarchPath (libname, &fpath) != OSD_FILEFOUND) { lldiagmsg (message ("Cannot find %sstandard library: %s", cstring_makeLiteralTemp (context_getFlag (FLG_STRICTLIB) ? "strict " : (context_getFlag (FLG_UNIXLIB) ? "unix " : "")), libname)); lldiagmsg (cstring_makeLiteral (" Check LARCH_PATH environment variable.")); result = FALSE; } else { stdlib = fileTable_openReadFile (context_fileTable (), fpath); if (stdlib == NULL) { lldiagmsg (message ("Cannot read standard library: %s", fpath)); lldiagmsg (cstring_makeLiteral (" Check LARCH_PATH environment variable.")); result = FALSE; } else { if (context_getFlag (FLG_WHICHLIB)) { char *t = mstring_create (MAX_NAME_LENGTH); char *ot = t; if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) == NULL) { llfatalerror (cstring_makeLiteral ("Standard library format invalid")); } if ((t = reader_readLine (stdlib, t, MAX_NAME_LENGTH)) != NULL) { if (*t == ';' && *(t + 1) == ';') { t += 2; } } if (t == NULL) { lldiagmsg (message ("Standard library: %s <cannot read creation information>", fpath)); } else { char *tt; tt = strrchr (t, '\n'); if (tt != NULL) *tt = '\0'; lldiagmsg (message ("Standard library: %s", fpath)); /* evans 2004-01-13: removed this (it is the libversion which is confusing) */ /* lldiagmsg (message (" (created using %s)", cstring_fromChars (t))); */ } sfree (ot); check (fileTable_closeFile (context_fileTable (), stdlib)); stdlib = fileTable_openReadFile (context_fileTable (), fpath); } llassert (stdlib != NULL); fileloc_reallyFree (g_currentloc); g_currentloc = fileloc_createLib (libname); DPRINTF (("Loading: %s", fpath)); displayScanOpen (message ("loading standard library %s ", fpath)); result = loadLCDFile (stdlib, fpath); displayScanClose (); check (fileTable_closeFile (context_fileTable (), stdlib)); } } cstring_free (libname); return result; }
mstring_t* mstring_wrap(byte* str){ mstring_t* ret = mstring_create(); mstring_put(ret, str, strlen((const char *) str)); return ret; }