diff --git a/core/smn_database.cpp b/core/smn_database.cpp index fb903052..3d884aa1 100644 --- a/core/smn_database.cpp +++ b/core/smn_database.cpp @@ -1277,6 +1277,76 @@ static cell_t SQL_CheckConfig(IPluginContext *pContext, const cell_t *params) return (g_DBMan.FindDatabaseConf(name) != NULL) ? 1 : 0; } +static cell_t SQL_ConnectCustom(IPluginContext *pContext, const cell_t *params) +{ + KeyValues *kv; + HandleError err; + + kv = g_SourceMod.ReadKeyValuesHandle(params[1], &err, false); + if (kv == NULL) + { + return pContext->ThrowNativeError("Invalid KeyValues handle %x (error: %d)", + params[1], + err); + } + + DatabaseInfo info; + info.database = kv->GetString("database", ""); + info.driver = kv->GetString("driver", "default"); + info.host = kv->GetString("host", ""); + info.maxTimeout = kv->GetInt("timeout", 0); + info.pass = kv->GetString("pass", ""); + info.port = kv->GetInt("port", 0); + info.user = kv->GetString("user", ""); + + IDBDriver *driver; + if (info.driver[0] == '\0' || strcmp(info.driver, "default") == 0) + { + driver = g_DBMan.GetDefaultDriver(); + } + else + { + driver = g_DBMan.FindOrLoadDriver(info.driver); + } + + if (driver == NULL) + { + char buffer[255]; + + UTIL_Format(buffer, sizeof(buffer), "Could not find driver \"%s\"", info.driver); + pContext->StringToLocalUTF8(params[2], params[3], buffer, NULL); + + return BAD_HANDLE; + } + + char *buffer; + IDatabase *db; + + pContext->LocalToString(params[2], &buffer); + + db = driver->Connect(&info, params[4] ? true : false, buffer, params[3]); + if (db == NULL) + { + return BAD_HANDLE; + } + + Handle_t hndl = g_DBMan.CreateHandle(DBHandle_Database, db, pContext->GetIdentity()); + if (!hndl) + { + db->Close(); + return pContext->ThrowNativeError("Out of handles!"); + } + + /* HACK! Add us to the dependency list */ + CExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity()); + if (pExt) + { + g_Extensions.BindChildPlugin(pExt, g_PluginSys.GetPluginByCtx(pContext->GetContext())); + } + + return hndl; +} + REGISTER_NATIVES(dbNatives) { {"SQL_BindParamInt", SQL_BindParamInt}, @@ -1317,5 +1387,7 @@ REGISTER_NATIVES(dbNatives) {"SQL_TConnect", SQL_TConnect}, {"SQL_TQuery", SQL_TQuery}, {"SQL_UnlockDatabase", SQL_UnlockDatabase}, + {"SQL_ConnectCustom", SQL_ConnectCustom}, {NULL, NULL}, }; + diff --git a/plugins/include/dbi.inc b/plugins/include/dbi.inc index acd412d0..046decb6 100644 --- a/plugins/include/dbi.inc +++ b/plugins/include/dbi.inc @@ -115,6 +115,7 @@ native Handle:SQL_Connect(const String:confname[], bool:persistent, String:error * @param persistent True to re-use a previous persistent connection * if possible, false otherwise. * @return A database connection Handle, or INVALID_HANDLE on failure. + * On failure the error buffer will be filled with a message. */ stock Handle:SQL_DefConnect(String:error[], maxlength, bool:persistent=true) { @@ -122,22 +123,66 @@ stock Handle:SQL_DefConnect(String:error[], maxlength, bool:persistent=true) } /** - * Creates an SQL connection from specific parameters. + * Connects to a database using key value pairs containing the database info. + * The key/value pairs should match what would be in databases.cfg. * - * @param driver Driver Handle, or INVALID_HANDLE for default. - * @param host Host name. - * @param user User name. - * @param pass User password. - * @param database Database name. + * I.e. "driver" should be "default" or a driver name (or ommitted for + * the default). For SQLite, only the "database" parameter is needed in addition. + * For drivers which require external connections, more of the parameters may be + * needed. + * + * In general it is discouraged to use this function. Connections should go through + * databases.cfg for greatest flexibility on behalf of users. + * + * @param keyvalues Key/value pairs from a KeyValues handle, describing the connection. * @param error Error buffer. * @param maxlength Maximum length of the error buffer. - * @param persistent True to re-use a previous persistent connection - * if possible, false otherwise. - * @param port Optional port to specify. - * @param maxTimeout Maximum timeout in seconds if applicable. * @return A database connection Handle, or INVALID_HANDLE on failure. - * @error Invalid driver Handle other than INVALID_HANDLE. + * On failure the error buffer will be filled with a message. + * @error Invalid KeyValues handle. */ +native Handle:SQL_ConnectCustom(Handle:keyvalues, + String:error[], + maxlength, + bool:persistent); + +/** + * Grabs a handle to an SQLite database, creating one if it does not exist. + * + * Unless there are extenuating circumstances, you should consider using "sourcemod-local" as the + * database name. This gives provides some unification between plugins on behalf of users. + * + * As a precaution, you should always create some sort of unique prefix to your table names so + * there are no conflicts, and you should never drop or modify tables that you do not own. + * + * @param database Database name. + * @param error Error buffer. + * @param maxlength Maximum length of the error buffer. + * @param persistent Persistent or not. + * @return A database connection Handle, or INVALID_HANDLE on failure. + * On failure the error buffer will be filled with a message. + */ +stock Handle:SQLite_UseDatabase(const String:database[], + String:buffer[], + maxlength) +{ + new Handle:kv, Handle:db; + + kv = CreateKeyValues(""); + KvSetString(kv, "driver", "sqlite"); + KvSetString(kv, "database", database); + + db = SQL_ConnectCustom(kv, buffer, maxlength, false); + + CloseHandle(kv); + + return db; +} + +/** + * This function is deprecated. Use SQL_ConnectCustom or SQLite_UseDatabase instead. + */ +#pragma deprecated Use SQL_ConnectCustom instead. native Handle:SQL_ConnectEx(Handle:driver, const String:host[], const String:user[], diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index d7ababb2..c72d0512 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -57,6 +57,7 @@ struct Plugin #include #include #include +#include #include #include #include @@ -66,7 +67,6 @@ struct Plugin #include #include #include -#include #include #include #include