forked from cindustries/unreal-sqlite3
-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathSQLiteDatabase.h
More file actions
233 lines (182 loc) · 9.53 KB
/
SQLiteDatabase.h
File metadata and controls
233 lines (182 loc) · 9.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
#pragma once
#include "sqlite3.h"
#include "SQLiteBlueprintNodes.h"
#include "SQLiteDatabaseStructs.h"
#include "SQLiteDatabase.generated.h"
USTRUCT(BlueprintType)
struct CISQLITE3_API FSQLiteDatabaseReference
{
GENERATED_USTRUCT_BODY()
/** The database name (not the filename) */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SQLite Database Reference")
FString DatabaseName;
/** The database tables we want to get data from */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SQLite Database Reference")
TArray<FString> Tables;
};
USTRUCT(BlueprintType)
struct CISQLITE3_API FSQLiteKeyValuePair
{
GENERATED_USTRUCT_BODY()
/** The database table field name */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SQLite Key Value Pair")
FString Key;
/** The value of the field */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SQLite Key Value Pair")
FString Value;
};
USTRUCT(BlueprintType)
struct CISQLITE3_API FSQLiteQueryResultRow
{
GENERATED_USTRUCT_BODY()
/** A list of field name, field value pairs */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SQLite Query Result")
TArray<FSQLiteKeyValuePair> Fields;
};
USTRUCT(BlueprintType)
struct CISQLITE3_API FSQLiteQueryResult
{
GENERATED_USTRUCT_BODY()
/** The resulting rows from the query */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SQLite Query Result")
TArray<FSQLiteQueryResultRow> ResultRows;
/** Was the query successful or not */
UPROPERTY(BlueprintReadOnly, Category = "SQLite Query Result")
bool Success;
/** If the query was unsuccessful a human readable error message will be populated here */
UPROPERTY(BlueprintReadOnly, Category = "SQLite Query Result")
FString ErrorMessage;
};
// A few things for internal use here.
namespace SQLiteResultValueTypes
{
enum SQLiteResultValType
{
Integer,
Float,
Text,
UnsupportedValueType
};
}
// Result field, used as an intermediary when collecting results from
// an SQLITE3 query.
struct SQLiteResultField
{
FString StringValue;
double DoubleValue;
int64 IntValue;
FString Name;
SQLiteResultValueTypes::SQLiteResultValType Type;
FString ToString()
{
if (Type == SQLiteResultValueTypes::Text)
return StringValue;
else if (Type == SQLiteResultValueTypes::Integer)
return FString::Printf(TEXT("%i"), IntValue);
else if (Type == SQLiteResultValueTypes::Float)
return FString::Printf(TEXT("%f"), DoubleValue);
return StringValue;
}
};
// Represents a single row in the result.
struct SQLiteResultValue
{
TArray<SQLiteResultField> Fields;
};
// The internal result object.
struct SQLiteQueryResult
{
bool Success;
FString ErrorMessage;
TArray<SQLiteResultValue> Results;
};
/**
* SQLite main database class.
*/
UCLASS()
class CISQLITE3_API USQLiteDatabase : public UObject
{
GENERATED_UCLASS_BODY()
public:
/** Create a sqlite database file if it doesn't exist already. Does nothing if already exists.
* Returns false if the file couldn't be created */
UFUNCTION(BlueprintCallable, Category = "SQLite")
static bool CreateDatabase(const FString& Filename, bool RelativeToGameContentDirectory);
/** Checks if the database is registered, ie. that it can be found in Databases. */
/** Add a database to the list of databases. It will be checked that it's valid (will try to open it) */
UFUNCTION(BlueprintCallable, Category = "SQLite")
static bool RegisterDatabase(const FString& Name, const FString& Filename, bool RelativeToGameContentDirectory, bool KeepOpen=false);
/** Remove a database from the list of databases. Closes the database in case KeepOpen flag was set during @ref RegisterDatabase */
UFUNCTION(BlueprintCallable, Category = "SQLite")
static void UnregisterDatabase(const FString& Name);
/** Checks if the database is registered, ie. that it can be found in Databases. */
UFUNCTION(BlueprintCallable, Category = "SQLite")
static bool IsDatabaseRegistered(const FString& DatabaseName);
/** Get data from the database using a select statement straight into an UObject, ie. populates its properties. */
UFUNCTION(BlueprintCallable, Category = "SQLite", meta = (DisplayName = "Get Data Into Object (manual query)"))
static bool GetDataIntoObject(const FString& DatabaseName, const FString& Query, UObject* ObjectToPopulate);
/** Blueprint: Gets data from the database using a select statement straight into an UObject, ie. populates its properties.
* Note: Does not create a new object. ObjectToPopulate is the reference to the object you want to populate. */
UFUNCTION(BlueprintCallable, Category = "SQLite", meta = (DisplayName = "Get Data Into Object"))
static bool GetDataIntoObjectBP(const FSQLiteDatabaseReference& DataSource, TArray<FString> Fields, FSQLiteQueryFinalizedQuery Query, UObject* ObjectToPopulate);
/** Get data from the database using a select statement and return the rows. */
UFUNCTION(BlueprintCallable, Category = "SQLite", meta = (DisplayName = "Get Data From Table(s) (manual query)"))
static FSQLiteQueryResult GetData(const FString& DatabaseName, const FString& Query);
/** Blueprint: Get data from the database. Returns the resulting rows. */
UFUNCTION(BlueprintCallable, Category = "SQLite", meta = (DisplayName = "Get Data From Table(s)"))
static FSQLiteQueryResult GetDataBP(const FSQLiteDatabaseReference& DataSource, TArray<FString> Fields, FSQLiteQueryFinalizedQuery Query, int32 MaxResults = -1, int32 ResultOffset = 0);
/** Create table in the database. */
UFUNCTION(BlueprintCallable, Category = "SQLite|Query", meta = (DisplayName = "Create Table"))
static FSQLiteTable CreateTable(const FString& DatabaseName, const FString& TableName,
const TArray<FSQLiteTableField> Fields, const FSQLitePrimaryKey PK);
/** Create indexes for table */
UFUNCTION(BlueprintCallable, Category = "SQLite|Query", meta = (DisplayName = "Create Indexes"))
static bool CreateIndexes(const FString& DatabaseName, const FString& TableName, const TArray<FSQLiteIndex> Indexes);
/** Create index for table */
UFUNCTION(BlueprintCallable, Category = "SQLite|Query", meta = (DisplayName = "Create Index"))
static bool CreateIndex(const FString& DatabaseName, const FString& TableName, const FSQLiteIndex Index);
/** Drop index*/
UFUNCTION(BlueprintCallable, Category = "SQLite|Query", meta = (DisplayName = "Drop Index"))
static bool DropIndex(const FString& DatabaseName, const FString& IndexName);
/** Drop Table*/
UFUNCTION(BlueprintCallable, Category = "SQLite|Query", meta = (DisplayName = "Drop Table"))
static bool DropTable(const FString& DatabaseName, const FString& TableName);
/** Truncate Table*/
UFUNCTION(BlueprintCallable, Category = "SQLite|Query", meta = (DisplayName = "Truncate Table"))
static bool TruncateTable(const FString& DatabaseName, const FString& TableName);
/** Is table exists?*/
UFUNCTION(BlueprintCallable, Category = "SQLite|Query", meta = (DisplayName = "Is table exists?"))
static bool IsTableExists(const FString& DatabaseName, const FString& TableName);
/** Insert rows into table */
UFUNCTION(BlueprintCallable, Category = "SQLite|Query", meta = (DisplayName = "Insert Rows Into Table"))
static void InsertRowsIntoTable(const FString& DatabaseName, const FString& TableName, TArray<FSQLiteTableRowSimulator> rowsOfFields);
/** Compact database*/
UFUNCTION(BlueprintCallable, Category = "SQLite|Query", meta = (DisplayName = "Compact database"))
static bool Vacuum(const FString& DatabaseName);
/** Execute SQL (can be used for insert statement)*/
UFUNCTION(BlueprintCallable, Category = "SQLite|Query", meta = (DisplayName = "Execute SQL"))
static bool ExecSql(const FString& DatabaseName, const FString& Query);
/** Checks database validity (if the file exists and/or if it can be opened). */
UFUNCTION(BlueprintCallable, Category = "SQLite|Query", meta = (DisplayName = "Is Valid Database"))
static bool IsValidDatabase(const FString& DatabaseFilename, bool TestByOpening);
static TArray<uint8> Dump(const FString& DatabaseFilename);
static bool Restore(const FString& DatabaseFilename, const TArray<uint8>& data);
/** Runs a query and returns fetched rows. */
static TUniquePtr<SQLiteQueryResult> RunQueryAndGetResults(const FString& DatabaseName, const FString& Query);
private:
/** Tries to open a database. */
static bool CanOpenDatabase(const FString& DatabaseFilename);
/** Collects all properties from an UObject and maps them by the property name. */
static TMap<FString, FProperty*> CollectProperties(UObject* SourceObject);
/** Constructs an SQL query from the blueprint fed data. */
static FString ConstructQuery(TArray<FString> Tables, TArray<FString> Fields, FSQLiteQueryFinalizedQuery QueryObject, int32 MaxResults = -1, int32 ResultOffset = 0);
/** Assigns a result row's fields' values to an UObject, ie. assigns them to the properties that have the same name. */
static void AssignResultsToObjectProperties(const SQLiteResultValue& ResultValue, UObject* ObjectToPopulate);
/** @brief Prepare given statement, returns whether to keep the database open */
static bool PrepareStatement(const FString& DatabaseName, const FString& Query, sqlite3** Db, int32** SqlReturnCode,
sqlite3_stmt** PreparedStatement);
private:
/** A list of the databases for convenience, easier to refer to them by name rather than a long filename. */
static TMap<FString, FString> Databases;
static TMap<FString, sqlite3*> SQLite3Databases;
};