Setting up database connection using Vapor framework - swift

I'm trying to build APIs using Swift and I've chosen to use Vapor.
I've created a SQLite database and am able to connect to it using a DB client.
Now I want my Swift Vapor project to connect to it as well using the FluentSQLite package.
I've created my database in the root folder of my project:
/Users/rutgerhuijsmans/Documents/runk-3.0
My database is called runk-3.0-database
The folder looks like this:
I try to connect to my DB using the following configuration:
import FluentSQLite
import Vapor
/// Called before your application initializes.
public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
/// Register providers first
try services.register(FluentSQLiteProvider())
/// Register routes to the router
let router = EngineRouter.default()
try routes(router)
services.register(router, as: Router.self)
/// Register middleware
var middlewares = MiddlewareConfig() // Create _empty_ middleware config
/// middlewares.use(FileMiddleware.self) // Serves files from `Public/` directory
middlewares.use(ErrorMiddleware.self) // Catches errors and converts to HTTP response
services.register(middlewares)
let sqlite: SQLiteDatabase?
do {
sqlite = try SQLiteDatabase(storage: .file(path: "runk-3.0-database"))
print("data base connected") // This gets printed
/// Register the configured SQLite database to the database config.
var databases = DatabasesConfig()
databases.add(database: sqlite!, as: .sqlite)
services.register(databases)
/// Configure migrations
var migrations = MigrationConfig()
migrations.add(model: User.self, database: .sqlite)
services.register(migrations)
} catch {
print("couldn't connect") // This doesn't get printed
}
}
What am I doing wrong?

As IMike17 explained, your code just creates the new DB file into the Build/Products/Debug or release folder. You have to set full path dynamically as below:
do {
let directory = DirectoryConfig.detect()
let filePath = directory.workDir + "runk-3.0-database"
sqlite = try SQLiteDatabase(storage: .file(path: filePath))
......

Using the .file(path: "runk-3.0-database") the method, if you specify only the name, creates a database file with the specified name in the Derived Data folder. If the file exists in the Derived Data folder, SQLiteDatabase uses it. So the DB is erased when cleaning the build folder.
The console prints out the path of the Derived Data where you can find the DB:
Running default command: /Users/username/Library/Developer/Xcode/DerivedData/SQLiteDB-xxxxxxxxxxxxxxxxxxxxxxx/Build/Products/Debug/
If you use a full path to the DB in your project then the file is used.
Change your init method as follows and you should be good to go for a local environment:
sqlite = try SQLiteDatabase(storage: .file(path: "/Users/rutgerhuijsmans/Documents/runk-3.0/runk-3.0-database"))

Related

how to form url in prisma.schema file using system variable

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = "postgresql://${app_db_username}:${app_db_password}#${endpoint}/${dbname}?schema=public"
}
I'm trying to form the below url, so how to use it
String concatenation is not implemented in Prisma yet. As of now you need to provide an environment variable that contains full database url:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
You can use an .env file to prepare the environment variable (Prisma v2.7.0+):
# .env
DATABASE_URL=postgresql://${app_db_username}:${app_db_password}#${endpoint}/${dbname}?schema=public

Can`t connect my MySQL database in Vapor project

I'm new at Vapor and I wanted to try to connect my MySQL database. I found on official documentation how to do it but when I try to send a query it throws an error:
No services are available for 'DatabaseConnectionPoolCache'. (Container.swift:112)
I just copy-paste the code from documentation and it doesn`t work. Could someone help me to found out why?
I have MySQL#5.7 on Mojave. Actually simple requests work well, for example :
router.get("hey") { req in
return "Stas, hey"
}
Code in configure.swift :
import FluentSQLite
import MySQL
import Vapor
/// Called before your application initializes.
public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
/// Register providers first
try services.register(FluentSQLiteProvider())
try services.register(MySQLProvider())
/// Register routes to the router
let router = EngineRouter.default()
try routes(router)
services.register(router, as: Router.self)
/// Register middleware
var middlewares = MiddlewareConfig() // Create _empty_ middleware config
/// middlewares.use(FileMiddleware.self) // Serves files from `Public/` directory
middlewares.use(ErrorMiddleware.self) // Catches errors and converts to HTTP response
services.register(middlewares)
// Configure a SQLite database
let sqlite = try SQLiteDatabase(storage: .memory)
/// Register the configured SQLite database to the database config.
var databases = DatabasesConfig()
databases.add(database: sqlite, as: .sqlite)
services.register(databases)
/// Configure migrations
var migrations = MigrationConfig()
migrations.add(model: Todo.self, database: .sqlite)
services.register(migrations)
//Configure a MySQL database
let mysql = try MySQLDatabase(config: MySQLDatabaseConfig(
hostname: "127.0.0.1",
port: 3306,
username: "root",
password: "7374",
database: "WORK_TIME"))
///Register to the congig
var mysqlDatabases = DatabasesConfig()
mysqlDatabases.add(database: mysql, as: .mysql)
services.register(mysqlDatabases)
}
My query in main.swift :
public struct MySQLVersion: Codable {
let version: String
}
router.get("sql") { req in
return req.withPooledConnection(to: .mysql) {conn in
return conn.raw("SELECT ##version as version")
.all(decoding: MySQLVersion.self)
}.map { rows in
return rows[0].version
}
}
It should return the version of my MySQL but it throws a strange error.
Your issue is that there is some leftover SQLite stuff from the original project template.
Start by removing the fluent-sqlite dependency from your Package.swift file and the FluentSQLite target from any target dependencies. Then run swift package update (and vapor xcode if you use Xcode) in your terminal.
Now that you have removed the FluentSQLite dependency from your project, you should be able to follow to compiler errors to fix your issue. Here are the ones I found:
import FluentSQLite
import MySQL
Should be:
import FluentMySQL
try services.register(FluentSQLiteProvider())
try services.register(MySQLProvider())
Should be
try services.register(FluentMySQLProvider())
Delete this, since you are using MySQL instead of SQLite:
// Configure a SQLite database
let sqlite = try SQLiteDatabase(storage: .memory)
/// Register the configured SQLite database to the database config.
var databases = DatabasesConfig()
databases.add(database: sqlite, as: .sqlite)
services.register(databases)
migrations.add(model: Todo.self, database: .sqlite)
Should be
migrations.add(model: Todo.self, database: .mysql)
I think that covers everything. Your /sql route should work now.
To solve this problem you should get rid of all leftover SQLite stuff from the original project and have to write your routes in routes.swift

How to retrieve data from sqlite db in unity where db file is present in downloads folder

I am trying to connect SQLite DB file to my unity project where db file is present in downloads folder but I am unable to get data from tables. How can I connect download folder contain DB file to unity project SQLite. My requirement is able to run a project with downloaded db file which is present in the downloads folder. Please suggest any idea. Thanks in advance. Here is the code I am using for connecting db file to SQLite.
Sample code :
Debug.Log("Call to OpenDB:" + databaseName);
var tempdbPath = Path.GetFullPath("log -29-10-2018 - .db");
var tempdbbytes = File.ReadAllBytes(tempdbPath);
var _filePath = tempdbPath;
ApplicationContext.CurrentDatabasePath = _filePath;
//open db connection
_connectionString = "URI=file:" + _filePath;
(where _filePaht = /Users/deepak/Projects/testproject/test/log -29-10-2018 - .db)
ApplicationContext.TempConnectionString = _filePath;
ApplicationContext.ConnectionString = _connectionString;
Debug.Log("Stablishing connection to: " + _connectionString);
dbcon = new SqliteConnection(_connectionString);
dbcon.Open();
}
catch (Exception exception)
{
LoggingManager.Error(exception);
}
}
When I connect persistence folder contain db file it's working well, I am getting a problem when I am trying to connect db file present in the downloads folder.

How do I log SQL statements in Vapor 3/Fluent?

It looks like in Vapor 2 you could do something like:
let query = <some fluent query object>
logger?.debug(query)
and it would print out the full SQL statement, but I'm not seeing any documentation of how to do that now in Vapor 3.
How can I see what SQL is being generated by my QueryBuilder?
Thanks to Nick in the comments, who pointed me to the right set of docs. This can be accomplished by using the enableLogging method. So now my configure.swift includes this code:
let dbConfig: PostgreSQLDatabaseConfig
if let url = Environment.get("DATABASE_URL"), let psqlConfig = PostgreSQLDatabaseConfig(url: url, transport: .unverifiedTLS) {
dbConfig = psqlConfig
} else {
dbConfig = ...something for the local db...
}
let postgresql = PostgreSQLDatabase(config: dbConfig)
/// Register the configured SQLite database to the database config.
var databases = DatabasesConfig()
databases.enableLogging(on: .psql)
databases.add(database: postgresql, as: .psql)
services.register(databases)
The important line being the third from the bottom. For a while I was trying to enable debugging on PostgreSQLDatabaseConfig, so to anyone in the future, take note that you're enabling it on the DatabasesConfig object instead.

No change in database when I have checked in sqliteBrowser

I am using sqlite3 with fmdb and xcode6.1 (swift).
In my application, need to update some data from db.
It’s updated.
But when I have checked in sqliteBrowser ,it didn’t update.(that sqlite file is in my project folder).
Is it normal ??
or Something wrong??
I am confused because when I restart my app, it's really updated.(not updated only when I have checked db with sqliteBrowser)
var database:FMDatabase!
let resourcePath = NSBundle.mainBundle().resourceURL!.absoluteString
let dbPath = resourcePath?.stringByAppendingPathComponent("mydbname.sqlite")
let dbTest = FMDatabase(path: dbPath)
if (!dbTest.open()) {
println("Could not open database at \(dbPath).")
} else {
println("open database at \(dbPath).")
var sql = "UPDATE tblEducation SET edu_fav = 0"
let results = dbTest.executeUpdate(sql, withArgumentsInArray: nil)
if results {
println("Success Update")
}
When you run sql file from your project and make changes with it. For that App create a sqlite file to your project folder and do changes with it only. So if you want to see changes done in simulator than check into project directory and database file.