@capgo/capacitor-fast-sql 7.0.1 → 7.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -35
- package/android/build.gradle +1 -1
- package/android/src/main/java/app/capgo/capacitor/fastsql/CapgoCapacitorFastSqlPlugin.java +9 -1
- package/android/src/main/java/app/capgo/capacitor/fastsql/SQLDatabase.java +5 -8
- package/android/src/main/java/app/capgo/capacitor/fastsql/SQLHTTPServer.java +5 -8
- package/dist/esm/definitions.d.ts +13 -13
- package/dist/esm/definitions.d.ts.map +1 -1
- package/dist/esm/{native-sql.d.ts → fast-sql.d.ts} +3 -3
- package/dist/esm/fast-sql.d.ts.map +1 -0
- package/dist/esm/{native-sql.js → fast-sql.js} +6 -6
- package/dist/esm/helpers.d.ts +2 -2
- package/dist/esm/helpers.d.ts.map +1 -1
- package/dist/esm/helpers.js +2 -2
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/plugin.d.ts +2 -2
- package/dist/esm/plugin.d.ts.map +1 -1
- package/dist/esm/plugin.js +2 -2
- package/dist/esm/sql-connection.d.ts.map +1 -1
- package/dist/esm/sql-connection.js +1 -3
- package/dist/esm/web.d.ts +2 -2
- package/dist/esm/web.d.ts.map +1 -1
- package/dist/esm/web.js +4 -5
- package/dist/plugin.cjs.js +15 -18
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +16 -19
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapgoCapacitorFastSqlPlugin/CapgoCapacitorFastSqlPlugin.swift +22 -2
- package/ios/Tests/CapgoCapacitorFastSqlPluginTests/CapgoCapacitorFastSqlPluginTests.swift +9 -0
- package/package.json +1 -1
- package/dist/esm/native-sql.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -59,10 +59,10 @@ Add to your `AndroidManifest.xml` if needed:
|
|
|
59
59
|
### Basic Example
|
|
60
60
|
|
|
61
61
|
```typescript
|
|
62
|
-
import {
|
|
62
|
+
import { FastSQL } from '@capgo/capacitor-fast-sql';
|
|
63
63
|
|
|
64
64
|
// Connect to database
|
|
65
|
-
const db = await
|
|
65
|
+
const db = await FastSQL.connect({ database: 'myapp' });
|
|
66
66
|
|
|
67
67
|
// Create table
|
|
68
68
|
await db.execute(`
|
|
@@ -85,13 +85,13 @@ const users = await db.query('SELECT * FROM users WHERE name LIKE ?', ['John%'])
|
|
|
85
85
|
console.log('Users:', users);
|
|
86
86
|
|
|
87
87
|
// Close connection
|
|
88
|
-
await
|
|
88
|
+
await FastSQL.disconnect('myapp');
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
### Transaction Example
|
|
92
92
|
|
|
93
93
|
```typescript
|
|
94
|
-
const db = await
|
|
94
|
+
const db = await FastSQL.connect({ database: 'myapp' });
|
|
95
95
|
|
|
96
96
|
try {
|
|
97
97
|
await db.transaction(async (tx) => {
|
|
@@ -109,7 +109,7 @@ try {
|
|
|
109
109
|
### Batch Operations
|
|
110
110
|
|
|
111
111
|
```typescript
|
|
112
|
-
const db = await
|
|
112
|
+
const db = await FastSQL.connect({ database: 'myapp' });
|
|
113
113
|
|
|
114
114
|
const results = await db.executeBatch([
|
|
115
115
|
{ statement: 'INSERT INTO logs (message) VALUES (?)', params: ['Log 1'] },
|
|
@@ -131,6 +131,7 @@ const results = await db.executeBatch([
|
|
|
131
131
|
* [`rollbackTransaction(...)`](#rollbacktransaction)
|
|
132
132
|
* [`getPluginVersion()`](#getpluginversion)
|
|
133
133
|
* [Interfaces](#interfaces)
|
|
134
|
+
* [Type Aliases](#type-aliases)
|
|
134
135
|
* [Enums](#enums)
|
|
135
136
|
|
|
136
137
|
</docgen-index>
|
|
@@ -138,7 +139,7 @@ const results = await db.executeBatch([
|
|
|
138
139
|
<docgen-api>
|
|
139
140
|
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
140
141
|
|
|
141
|
-
|
|
142
|
+
Fast SQL Plugin for high-performance SQLite database access.
|
|
142
143
|
|
|
143
144
|
This plugin uses a custom HTTP-based protocol for efficient data transfer,
|
|
144
145
|
bypassing Capacitor's standard bridge for better performance with sync operations.
|
|
@@ -151,8 +152,8 @@ connect(options: SQLConnectionOptions) => Promise<{ port: number; token: string;
|
|
|
151
152
|
|
|
152
153
|
Initialize the database connection and start the HTTP server.
|
|
153
154
|
|
|
154
|
-
| Param | Type | Description
|
|
155
|
-
| ------------- | --------------------------------------------------------------------- |
|
|
155
|
+
| Param | Type | Description |
|
|
156
|
+
| ------------- | --------------------------------------------------------------------- | -------------------- |
|
|
156
157
|
| **`options`** | <code><a href="#sqlconnectionoptions">SQLConnectionOptions</a></code> | - Connection options |
|
|
157
158
|
|
|
158
159
|
**Returns:** <code>Promise<{ port: number; token: string; database: string; }></code>
|
|
@@ -170,8 +171,8 @@ disconnect(options: { database: string; }) => Promise<void>
|
|
|
170
171
|
|
|
171
172
|
Close database connection and stop the HTTP server.
|
|
172
173
|
|
|
173
|
-
| Param | Type | Description
|
|
174
|
-
| ------------- | ---------------------------------- |
|
|
174
|
+
| Param | Type | Description |
|
|
175
|
+
| ------------- | ---------------------------------- | ------------------------ |
|
|
175
176
|
| **`options`** | <code>{ database: string; }</code> | - Database name to close |
|
|
176
177
|
|
|
177
178
|
**Since:** 0.0.1
|
|
@@ -207,9 +208,9 @@ execute(options: { database: string; statement: string; params?: SQLValue[]; })
|
|
|
207
208
|
Execute a SQL query via Capacitor bridge (for simple queries).
|
|
208
209
|
For better performance with large datasets, use the HTTP protocol directly via SQLConnection class.
|
|
209
210
|
|
|
210
|
-
| Param | Type
|
|
211
|
-
| ------------- |
|
|
212
|
-
| **`options`** | <code>{ database: string; statement: string; params?:
|
|
211
|
+
| Param | Type | Description |
|
|
212
|
+
| ------------- | -------------------------------------------------------------------------- | ------------------ |
|
|
213
|
+
| **`options`** | <code>{ database: string; statement: string; params?: SQLValue[]; }</code> | - Query parameters |
|
|
213
214
|
|
|
214
215
|
**Returns:** <code>Promise<<a href="#sqlresult">SQLResult</a>></code>
|
|
215
216
|
|
|
@@ -226,8 +227,8 @@ beginTransaction(options: { database: string; isolationLevel?: IsolationLevel; }
|
|
|
226
227
|
|
|
227
228
|
Begin a database transaction.
|
|
228
229
|
|
|
229
|
-
| Param | Type
|
|
230
|
-
| ------------- |
|
|
230
|
+
| Param | Type | Description |
|
|
231
|
+
| ------------- | ------------------------------------------------------------------------------------------------- | --------------------- |
|
|
231
232
|
| **`options`** | <code>{ database: string; isolationLevel?: <a href="#isolationlevel">IsolationLevel</a>; }</code> | - Transaction options |
|
|
232
233
|
|
|
233
234
|
**Since:** 0.0.1
|
|
@@ -291,23 +292,23 @@ Get the native Capacitor plugin version.
|
|
|
291
292
|
|
|
292
293
|
Database connection options
|
|
293
294
|
|
|
294
|
-
| Prop | Type | Description
|
|
295
|
-
| ------------------- | -------------------- |
|
|
295
|
+
| Prop | Type | Description |
|
|
296
|
+
| ------------------- | -------------------- | ---------------------------------------------------------- |
|
|
296
297
|
| **`database`** | <code>string</code> | Database name (file will be created in app data directory) |
|
|
297
|
-
| **`encrypted`** | <code>boolean</code> | Enable encryption (iOS/Android only)
|
|
298
|
-
| **`encryptionKey`** | <code>string</code> | Encryption key (required if encrypted is true)
|
|
299
|
-
| **`readOnly`** | <code>boolean</code> | Read-only mode
|
|
298
|
+
| **`encrypted`** | <code>boolean</code> | Enable encryption (iOS/Android only) |
|
|
299
|
+
| **`encryptionKey`** | <code>string</code> | Encryption key (required if encrypted is true) |
|
|
300
|
+
| **`readOnly`** | <code>boolean</code> | Read-only mode |
|
|
300
301
|
|
|
301
302
|
|
|
302
303
|
#### SQLResult
|
|
303
304
|
|
|
304
305
|
Result of a SQL query execution
|
|
305
306
|
|
|
306
|
-
| Prop
|
|
307
|
-
|
|
|
308
|
-
| **`rows`**
|
|
309
|
-
| **`rowsAffected`**
|
|
310
|
-
| **`insertId`**
|
|
307
|
+
| Prop | Type | Description |
|
|
308
|
+
| ------------------ | --------------------- | ----------------------------------------------------------------------- |
|
|
309
|
+
| **`rows`** | <code>SQLRow[]</code> | Rows returned by the query (for SELECT statements) |
|
|
310
|
+
| **`rowsAffected`** | <code>number</code> | Number of rows affected by the query (for INSERT/UPDATE/DELETE) |
|
|
311
|
+
| **`insertId`** | <code>number</code> | ID of the last inserted row (for INSERT statements with auto-increment) |
|
|
311
312
|
|
|
312
313
|
|
|
313
314
|
#### SQLRow
|
|
@@ -315,19 +316,79 @@ Result of a SQL query execution
|
|
|
315
316
|
SQL row result - values indexed by column name
|
|
316
317
|
|
|
317
318
|
|
|
318
|
-
|
|
319
|
+
#### Uint8Array
|
|
319
320
|
|
|
321
|
+
A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
|
|
322
|
+
requested number of bytes could not be allocated an exception is raised.
|
|
320
323
|
|
|
321
|
-
|
|
324
|
+
| Prop | Type | Description |
|
|
325
|
+
| ----------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
326
|
+
| **`BYTES_PER_ELEMENT`** | <code>number</code> | The size in bytes of each element in the array. |
|
|
327
|
+
| **`buffer`** | <code><a href="#arraybufferlike">ArrayBufferLike</a></code> | The <a href="#arraybuffer">ArrayBuffer</a> instance referenced by the array. |
|
|
328
|
+
| **`byteLength`** | <code>number</code> | The length in bytes of the array. |
|
|
329
|
+
| **`byteOffset`** | <code>number</code> | The offset in bytes of the array. |
|
|
330
|
+
| **`length`** | <code>number</code> | The length of the array. |
|
|
331
|
+
|
|
332
|
+
| Method | Signature | Description |
|
|
333
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
334
|
+
| **copyWithin** | (target: number, start: number, end?: number \| undefined) => this | Returns the this object after copying a section of the array identified by start and end to the same array starting at position target |
|
|
335
|
+
| **every** | (predicate: (value: number, index: number, array: <a href="#uint8array">Uint8Array</a>) => unknown, thisArg?: any) => boolean | Determines whether all the members of an array satisfy the specified test. |
|
|
336
|
+
| **fill** | (value: number, start?: number \| undefined, end?: number \| undefined) => this | Returns the this object after filling the section identified by start and end with value |
|
|
337
|
+
| **filter** | (predicate: (value: number, index: number, array: <a href="#uint8array">Uint8Array</a>) => any, thisArg?: any) => <a href="#uint8array">Uint8Array</a> | Returns the elements of an array that meet the condition specified in a callback function. |
|
|
338
|
+
| **find** | (predicate: (value: number, index: number, obj: <a href="#uint8array">Uint8Array</a>) => boolean, thisArg?: any) => number \| undefined | Returns the value of the first element in the array where predicate is true, and undefined otherwise. |
|
|
339
|
+
| **findIndex** | (predicate: (value: number, index: number, obj: <a href="#uint8array">Uint8Array</a>) => boolean, thisArg?: any) => number | Returns the index of the first element in the array where predicate is true, and -1 otherwise. |
|
|
340
|
+
| **forEach** | (callbackfn: (value: number, index: number, array: <a href="#uint8array">Uint8Array</a>) => void, thisArg?: any) => void | Performs the specified action for each element in an array. |
|
|
341
|
+
| **indexOf** | (searchElement: number, fromIndex?: number \| undefined) => number | Returns the index of the first occurrence of a value in an array. |
|
|
342
|
+
| **join** | (separator?: string \| undefined) => string | Adds all the elements of an array separated by the specified separator string. |
|
|
343
|
+
| **lastIndexOf** | (searchElement: number, fromIndex?: number \| undefined) => number | Returns the index of the last occurrence of a value in an array. |
|
|
344
|
+
| **map** | (callbackfn: (value: number, index: number, array: <a href="#uint8array">Uint8Array</a>) => number, thisArg?: any) => <a href="#uint8array">Uint8Array</a> | Calls a defined callback function on each element of an array, and returns an array that contains the results. |
|
|
345
|
+
| **reduce** | (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: <a href="#uint8array">Uint8Array</a>) => number) => number | Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. |
|
|
346
|
+
| **reduce** | (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: <a href="#uint8array">Uint8Array</a>) => number, initialValue: number) => number | |
|
|
347
|
+
| **reduce** | <U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: <a href="#uint8array">Uint8Array</a>) => U, initialValue: U) => U | Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. |
|
|
348
|
+
| **reduceRight** | (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: <a href="#uint8array">Uint8Array</a>) => number) => number | Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. |
|
|
349
|
+
| **reduceRight** | (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: <a href="#uint8array">Uint8Array</a>) => number, initialValue: number) => number | |
|
|
350
|
+
| **reduceRight** | <U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: <a href="#uint8array">Uint8Array</a>) => U, initialValue: U) => U | Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. |
|
|
351
|
+
| **reverse** | () => <a href="#uint8array">Uint8Array</a> | Reverses the elements in an Array. |
|
|
352
|
+
| **set** | (array: <a href="#arraylike">ArrayLike</a><number>, offset?: number \| undefined) => void | Sets a value or an array of values. |
|
|
353
|
+
| **slice** | (start?: number \| undefined, end?: number \| undefined) => <a href="#uint8array">Uint8Array</a> | Returns a section of an array. |
|
|
354
|
+
| **some** | (predicate: (value: number, index: number, array: <a href="#uint8array">Uint8Array</a>) => unknown, thisArg?: any) => boolean | Determines whether the specified callback function returns true for any element of an array. |
|
|
355
|
+
| **sort** | (compareFn?: ((a: number, b: number) => number) \| undefined) => this | Sorts an array. |
|
|
356
|
+
| **subarray** | (begin?: number \| undefined, end?: number \| undefined) => <a href="#uint8array">Uint8Array</a> | Gets a new <a href="#uint8array">Uint8Array</a> view of the <a href="#arraybuffer">ArrayBuffer</a> store for this array, referencing the elements at begin, inclusive, up to end, exclusive. |
|
|
357
|
+
| **toLocaleString** | () => string | Converts a number to a string by using the current locale. |
|
|
358
|
+
| **toString** | () => string | Returns a string representation of an array. |
|
|
359
|
+
| **valueOf** | () => <a href="#uint8array">Uint8Array</a> | Returns the primitive value of the specified object. |
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
#### ArrayLike
|
|
363
|
+
|
|
364
|
+
| Prop | Type |
|
|
365
|
+
| ------------ | ------------------- |
|
|
366
|
+
| **`length`** | <code>number</code> |
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
#### ArrayBufferTypes
|
|
370
|
+
|
|
371
|
+
Allowed <a href="#arraybuffer">ArrayBuffer</a> types for the buffer of an ArrayBufferView and related Typed Arrays.
|
|
372
|
+
|
|
373
|
+
| Prop | Type |
|
|
374
|
+
| ----------------- | --------------------------------------------------- |
|
|
375
|
+
| **`ArrayBuffer`** | <code><a href="#arraybuffer">ArrayBuffer</a></code> |
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
#### ArrayBuffer
|
|
322
379
|
|
|
323
|
-
|
|
380
|
+
Represents a raw buffer of binary data, which is used to store data for the
|
|
381
|
+
different typed arrays. ArrayBuffers cannot be read from or written to directly,
|
|
382
|
+
but can be passed to a typed array or DataView Object to interpret the raw
|
|
383
|
+
buffer as needed.
|
|
324
384
|
|
|
325
|
-
|
|
|
326
|
-
|
|
|
327
|
-
| **`
|
|
328
|
-
|
|
329
|
-
|
|
|
330
|
-
|
|
|
385
|
+
| Prop | Type | Description |
|
|
386
|
+
| ---------------- | ------------------- | ------------------------------------------------------------------------------- |
|
|
387
|
+
| **`byteLength`** | <code>number</code> | Read-only. The length of the <a href="#arraybuffer">ArrayBuffer</a> (in bytes). |
|
|
388
|
+
|
|
389
|
+
| Method | Signature | Description |
|
|
390
|
+
| --------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
|
|
391
|
+
| **slice** | (begin: number, end?: number \| undefined) => <a href="#arraybuffer">ArrayBuffer</a> | Returns a section of an <a href="#arraybuffer">ArrayBuffer</a>. |
|
|
331
392
|
|
|
332
393
|
|
|
333
394
|
### Type Aliases
|
|
@@ -335,6 +396,26 @@ Transaction isolation levels
|
|
|
335
396
|
|
|
336
397
|
#### SQLValue
|
|
337
398
|
|
|
338
|
-
|
|
399
|
+
SQL value types supported by the plugin
|
|
400
|
+
|
|
401
|
+
<code>string | number | boolean | null | <a href="#uint8array">Uint8Array</a></code>
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
#### ArrayBufferLike
|
|
405
|
+
|
|
406
|
+
<code>ArrayBufferTypes[keyof ArrayBufferTypes]</code>
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
### Enums
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
#### IsolationLevel
|
|
413
|
+
|
|
414
|
+
| Members | Value |
|
|
415
|
+
| --------------------- | ------------------------------- |
|
|
416
|
+
| **`ReadUncommitted`** | <code>'READ UNCOMMITTED'</code> |
|
|
417
|
+
| **`ReadCommitted`** | <code>'READ COMMITTED'</code> |
|
|
418
|
+
| **`RepeatableRead`** | <code>'REPEATABLE READ'</code> |
|
|
419
|
+
| **`Serializable`** | <code>'SERIALIZABLE'</code> |
|
|
339
420
|
|
|
340
421
|
</docgen-api>
|
package/android/build.gradle
CHANGED
|
@@ -18,7 +18,7 @@ buildscript {
|
|
|
18
18
|
apply plugin: 'com.android.library'
|
|
19
19
|
|
|
20
20
|
android {
|
|
21
|
-
namespace
|
|
21
|
+
namespace "app.capgo.capacitor.fastsql"
|
|
22
22
|
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
|
|
23
23
|
defaultConfig {
|
|
24
24
|
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
|
|
@@ -6,7 +6,6 @@ import com.getcapacitor.Plugin;
|
|
|
6
6
|
import com.getcapacitor.PluginCall;
|
|
7
7
|
import com.getcapacitor.PluginMethod;
|
|
8
8
|
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
9
|
-
|
|
10
9
|
import java.io.File;
|
|
11
10
|
import java.util.HashMap;
|
|
12
11
|
import java.util.Map;
|
|
@@ -20,6 +19,8 @@ import java.util.Map;
|
|
|
20
19
|
@CapacitorPlugin(name = "CapgoCapacitorFastSql")
|
|
21
20
|
public class CapgoCapacitorFastSqlPlugin extends Plugin {
|
|
22
21
|
|
|
22
|
+
private final String PLUGIN_VERSION = "7.2.5";
|
|
23
|
+
|
|
23
24
|
private Map<String, SQLDatabase> databases = new HashMap<>();
|
|
24
25
|
private SQLHTTPServer server;
|
|
25
26
|
|
|
@@ -213,6 +214,13 @@ public class CapgoCapacitorFastSqlPlugin extends Plugin {
|
|
|
213
214
|
}
|
|
214
215
|
}
|
|
215
216
|
|
|
217
|
+
@PluginMethod
|
|
218
|
+
public void getPluginVersion(PluginCall call) {
|
|
219
|
+
JSObject ret = new JSObject();
|
|
220
|
+
ret.put("version", PLUGIN_VERSION);
|
|
221
|
+
call.resolve(ret);
|
|
222
|
+
}
|
|
223
|
+
|
|
216
224
|
private File getDatabasePath(String database) {
|
|
217
225
|
File dataDir = getContext().getFilesDir();
|
|
218
226
|
return new File(dataDir, database + ".db");
|
|
@@ -4,21 +4,19 @@ import android.database.Cursor;
|
|
|
4
4
|
import android.database.sqlite.SQLiteDatabase;
|
|
5
5
|
import android.database.sqlite.SQLiteStatement;
|
|
6
6
|
import android.util.Base64;
|
|
7
|
-
|
|
8
7
|
import com.getcapacitor.JSArray;
|
|
9
8
|
import com.getcapacitor.JSObject;
|
|
10
|
-
|
|
9
|
+
import java.util.ArrayList;
|
|
10
|
+
import java.util.List;
|
|
11
11
|
import org.json.JSONArray;
|
|
12
12
|
import org.json.JSONException;
|
|
13
13
|
import org.json.JSONObject;
|
|
14
14
|
|
|
15
|
-
import java.util.ArrayList;
|
|
16
|
-
import java.util.List;
|
|
17
|
-
|
|
18
15
|
/**
|
|
19
16
|
* SQLite database wrapper for Android
|
|
20
17
|
*/
|
|
21
18
|
public class SQLDatabase {
|
|
19
|
+
|
|
22
20
|
private SQLiteDatabase db;
|
|
23
21
|
private boolean inTransaction = false;
|
|
24
22
|
|
|
@@ -41,9 +39,8 @@ public class SQLDatabase {
|
|
|
41
39
|
|
|
42
40
|
// Check if this is a query (SELECT) or a modification (INSERT/UPDATE/DELETE)
|
|
43
41
|
String trimmedStatement = statement.trim().toUpperCase();
|
|
44
|
-
boolean isQuery =
|
|
45
|
-
|
|
46
|
-
trimmedStatement.startsWith("EXPLAIN");
|
|
42
|
+
boolean isQuery =
|
|
43
|
+
trimmedStatement.startsWith("SELECT") || trimmedStatement.startsWith("PRAGMA") || trimmedStatement.startsWith("EXPLAIN");
|
|
47
44
|
|
|
48
45
|
if (isQuery) {
|
|
49
46
|
return executeQuery(statement, params);
|
|
@@ -7,15 +7,12 @@ import com.google.gson.JsonArray;
|
|
|
7
7
|
import com.google.gson.JsonElement;
|
|
8
8
|
import com.google.gson.JsonObject;
|
|
9
9
|
import com.google.gson.JsonParser;
|
|
10
|
-
|
|
11
|
-
import org.json.JSONArray;
|
|
12
|
-
import org.json.JSONObject;
|
|
13
|
-
|
|
10
|
+
import fi.iki.elonen.NanoHTTPD; // Note: org.nanohttpd:nanohttpd:2.3.1 still uses fi.iki.elonen package
|
|
14
11
|
import java.io.IOException;
|
|
15
12
|
import java.security.SecureRandom;
|
|
16
13
|
import java.util.Map;
|
|
17
|
-
|
|
18
|
-
import
|
|
14
|
+
import org.json.JSONArray;
|
|
15
|
+
import org.json.JSONObject;
|
|
19
16
|
|
|
20
17
|
/**
|
|
21
18
|
* HTTP server for efficient SQL operations
|
|
@@ -24,6 +21,7 @@ import fi.iki.elonen.NanoHTTPD; // Note: org.nanohttpd:nanohttpd:2.3.1 still us
|
|
|
24
21
|
* bridge for better performance with large datasets and sync operations.
|
|
25
22
|
*/
|
|
26
23
|
public class SQLHTTPServer extends NanoHTTPD {
|
|
24
|
+
|
|
27
25
|
private final String token;
|
|
28
26
|
private final Map<String, SQLDatabase> databases;
|
|
29
27
|
private final Gson gson = new Gson();
|
|
@@ -80,8 +78,7 @@ public class SQLHTTPServer extends NanoHTTPD {
|
|
|
80
78
|
return newFixedLengthResponse(Response.Status.NOT_FOUND, "text/plain", "Endpoint not found");
|
|
81
79
|
}
|
|
82
80
|
} catch (Exception e) {
|
|
83
|
-
return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, "text/plain",
|
|
84
|
-
"Error: " + e.getMessage());
|
|
81
|
+
return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, "text/plain", "Error: " + e.getMessage());
|
|
85
82
|
}
|
|
86
83
|
}
|
|
87
84
|
|
|
@@ -69,14 +69,14 @@ export declare enum IsolationLevel {
|
|
|
69
69
|
Serializable = "SERIALIZABLE"
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
|
-
*
|
|
72
|
+
* Fast SQL Plugin for high-performance SQLite database access.
|
|
73
73
|
*
|
|
74
74
|
* This plugin uses a custom HTTP-based protocol for efficient data transfer,
|
|
75
75
|
* bypassing Capacitor's standard bridge for better performance with sync operations.
|
|
76
76
|
*
|
|
77
77
|
* @since 0.0.1
|
|
78
78
|
*/
|
|
79
|
-
export interface
|
|
79
|
+
export interface CapgoCapacitorFastSqlPlugin {
|
|
80
80
|
/**
|
|
81
81
|
* Initialize the database connection and start the HTTP server.
|
|
82
82
|
*
|
|
@@ -86,7 +86,7 @@ export interface CapgoCapacitorNativeSqlPlugin {
|
|
|
86
86
|
* @since 0.0.1
|
|
87
87
|
* @example
|
|
88
88
|
* ```typescript
|
|
89
|
-
* const conn = await
|
|
89
|
+
* const conn = await CapgoCapacitorFastSql.connect({ database: 'myapp' });
|
|
90
90
|
* console.log('Connected on port:', conn.port);
|
|
91
91
|
* ```
|
|
92
92
|
*/
|
|
@@ -104,7 +104,7 @@ export interface CapgoCapacitorNativeSqlPlugin {
|
|
|
104
104
|
* @since 0.0.1
|
|
105
105
|
* @example
|
|
106
106
|
* ```typescript
|
|
107
|
-
* await
|
|
107
|
+
* await CapgoCapacitorFastSql.disconnect({ database: 'myapp' });
|
|
108
108
|
* ```
|
|
109
109
|
*/
|
|
110
110
|
disconnect(options: {
|
|
@@ -119,7 +119,7 @@ export interface CapgoCapacitorNativeSqlPlugin {
|
|
|
119
119
|
* @since 0.0.1
|
|
120
120
|
* @example
|
|
121
121
|
* ```typescript
|
|
122
|
-
* const info = await
|
|
122
|
+
* const info = await CapgoCapacitorFastSql.getServerInfo({ database: 'myapp' });
|
|
123
123
|
* console.log('Server port:', info.port);
|
|
124
124
|
* ```
|
|
125
125
|
*/
|
|
@@ -139,7 +139,7 @@ export interface CapgoCapacitorNativeSqlPlugin {
|
|
|
139
139
|
* @since 0.0.1
|
|
140
140
|
* @example
|
|
141
141
|
* ```typescript
|
|
142
|
-
* const result = await
|
|
142
|
+
* const result = await CapgoCapacitorFastSql.execute({
|
|
143
143
|
* database: 'myapp',
|
|
144
144
|
* statement: 'SELECT * FROM users WHERE age > ?',
|
|
145
145
|
* params: [18]
|
|
@@ -161,9 +161,9 @@ export interface CapgoCapacitorNativeSqlPlugin {
|
|
|
161
161
|
* @since 0.0.1
|
|
162
162
|
* @example
|
|
163
163
|
* ```typescript
|
|
164
|
-
* await
|
|
164
|
+
* await CapgoCapacitorFastSql.beginTransaction({ database: 'myapp' });
|
|
165
165
|
* // Execute multiple operations
|
|
166
|
-
* await
|
|
166
|
+
* await CapgoCapacitorFastSql.commitTransaction({ database: 'myapp' });
|
|
167
167
|
* ```
|
|
168
168
|
*/
|
|
169
169
|
beginTransaction(options: {
|
|
@@ -179,7 +179,7 @@ export interface CapgoCapacitorNativeSqlPlugin {
|
|
|
179
179
|
* @since 0.0.1
|
|
180
180
|
* @example
|
|
181
181
|
* ```typescript
|
|
182
|
-
* await
|
|
182
|
+
* await CapgoCapacitorFastSql.commitTransaction({ database: 'myapp' });
|
|
183
183
|
* ```
|
|
184
184
|
*/
|
|
185
185
|
commitTransaction(options: {
|
|
@@ -195,11 +195,11 @@ export interface CapgoCapacitorNativeSqlPlugin {
|
|
|
195
195
|
* @example
|
|
196
196
|
* ```typescript
|
|
197
197
|
* try {
|
|
198
|
-
* await
|
|
198
|
+
* await CapgoCapacitorFastSql.beginTransaction({ database: 'myapp' });
|
|
199
199
|
* // Operations...
|
|
200
|
-
* await
|
|
200
|
+
* await CapgoCapacitorFastSql.commitTransaction({ database: 'myapp' });
|
|
201
201
|
* } catch (error) {
|
|
202
|
-
* await
|
|
202
|
+
* await CapgoCapacitorFastSql.rollbackTransaction({ database: 'myapp' });
|
|
203
203
|
* }
|
|
204
204
|
* ```
|
|
205
205
|
*/
|
|
@@ -214,7 +214,7 @@ export interface CapgoCapacitorNativeSqlPlugin {
|
|
|
214
214
|
* @since 0.0.1
|
|
215
215
|
* @example
|
|
216
216
|
* ```typescript
|
|
217
|
-
* const { version } = await
|
|
217
|
+
* const { version } = await CapgoCapacitorFastSql.getPluginVersion();
|
|
218
218
|
* console.log('Plugin version:', version);
|
|
219
219
|
* ```
|
|
220
220
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,UAAU,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,oBAAY,cAAc;IACxB,eAAe,qBAAqB;IACpC,aAAa,mBAAmB;IAChC,cAAc,oBAAoB;IAClC,YAAY,iBAAiB;CAC9B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,UAAU,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,oBAAY,cAAc;IACxB,eAAe,qBAAqB;IACpC,aAAa,mBAAmB;IAChC,cAAc,oBAAoB;IAClC,YAAY,iBAAiB;CAC9B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC;QAC9C,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IAEH;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzD;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QACpD,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IAEH;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAEnG;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhG;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhE;;;;;;;;;;;;;;;;;OAiBG;IACH,mBAAmB,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElE;;;;;;;;;;;OAWG;IACH,gBAAgB,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { SQLConnectionOptions } from './definitions';
|
|
2
2
|
import { SQLConnection } from './sql-connection';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* FastSQL - High-level API for managing SQL connections
|
|
5
5
|
*
|
|
6
6
|
* This class provides a convenient interface for opening/closing database connections
|
|
7
7
|
* and managing multiple databases simultaneously.
|
|
8
8
|
*/
|
|
9
|
-
export declare class
|
|
9
|
+
export declare class FastSQL {
|
|
10
10
|
private static connections;
|
|
11
11
|
/**
|
|
12
12
|
* Open a database connection
|
|
@@ -39,4 +39,4 @@ export declare class NativeSQL {
|
|
|
39
39
|
*/
|
|
40
40
|
static getOpenDatabases(): string[];
|
|
41
41
|
}
|
|
42
|
-
//# sourceMappingURL=
|
|
42
|
+
//# sourceMappingURL=fast-sql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fast-sql.d.ts","sourceRoot":"","sources":["../../src/fast-sql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE1D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD;;;;;GAKG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAC,WAAW,CAAyC;IAEnE;;;;;OAKG;WACU,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC;IAkB3E;;;;OAIG;WACU,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAaxD;;;;;OAKG;IACH,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAI5D;;OAEG;WACU,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3C;;;;OAIG;IACH,MAAM,CAAC,gBAAgB,IAAI,MAAM,EAAE;CAGpC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CapgoCapacitorFastSql } from './plugin';
|
|
2
2
|
import { SQLConnection } from './sql-connection';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* FastSQL - High-level API for managing SQL connections
|
|
5
5
|
*
|
|
6
6
|
* This class provides a convenient interface for opening/closing database connections
|
|
7
7
|
* and managing multiple databases simultaneously.
|
|
8
8
|
*/
|
|
9
|
-
export class
|
|
9
|
+
export class FastSQL {
|
|
10
10
|
/**
|
|
11
11
|
* Open a database connection
|
|
12
12
|
*
|
|
@@ -19,7 +19,7 @@ export class NativeSQL {
|
|
|
19
19
|
return this.connections.get(options.database);
|
|
20
20
|
}
|
|
21
21
|
// Connect via native plugin
|
|
22
|
-
const info = await
|
|
22
|
+
const info = await CapgoCapacitorFastSql.connect(options);
|
|
23
23
|
// Create connection instance
|
|
24
24
|
const connection = new SQLConnection(info.database, info.port, info.token);
|
|
25
25
|
// Store connection
|
|
@@ -37,7 +37,7 @@ export class NativeSQL {
|
|
|
37
37
|
throw new Error(`Database '${database}' is not connected`);
|
|
38
38
|
}
|
|
39
39
|
// Disconnect via native plugin
|
|
40
|
-
await
|
|
40
|
+
await CapgoCapacitorFastSql.disconnect({ database });
|
|
41
41
|
// Remove connection
|
|
42
42
|
this.connections.delete(database);
|
|
43
43
|
}
|
|
@@ -66,4 +66,4 @@ export class NativeSQL {
|
|
|
66
66
|
return Array.from(this.connections.keys());
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
|
|
69
|
+
FastSQL.connections = new Map();
|
package/dist/esm/helpers.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Helper classes for easier SQL operations
|
|
3
|
-
* Import these separately: import {
|
|
3
|
+
* Import these separately: import { FastSQL, SQLConnection } from '@capgo/capacitor-fast-sql/helpers';
|
|
4
4
|
*/
|
|
5
|
-
export {
|
|
5
|
+
export { FastSQL } from './fast-sql';
|
|
6
6
|
export { SQLConnection } from './sql-connection';
|
|
7
7
|
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/esm/helpers.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Helper classes for easier SQL operations
|
|
3
|
-
* Import these separately: import {
|
|
3
|
+
* Import these separately: import { FastSQL, SQLConnection } from '@capgo/capacitor-fast-sql/helpers';
|
|
4
4
|
*/
|
|
5
|
-
export {
|
|
5
|
+
export { FastSQL } from './fast-sql';
|
|
6
6
|
export { SQLConnection } from './sql-connection';
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from './definitions';
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
2
|
+
export { CapgoCapacitorFastSql } from './plugin';
|
|
3
|
+
export { FastSQL } from './fast-sql';
|
|
4
4
|
export { SQLConnection } from './sql-connection';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGjD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from './definitions';
|
|
2
|
-
export {
|
|
2
|
+
export { CapgoCapacitorFastSql } from './plugin';
|
|
3
3
|
// Re-export helper classes for convenience
|
|
4
|
-
export {
|
|
4
|
+
export { FastSQL } from './fast-sql';
|
|
5
5
|
export { SQLConnection } from './sql-connection';
|
package/dist/esm/plugin.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare const
|
|
1
|
+
import type { CapgoCapacitorFastSqlPlugin } from './definitions';
|
|
2
|
+
export declare const CapgoCapacitorFastSql: CapgoCapacitorFastSqlPlugin;
|
|
3
3
|
//# sourceMappingURL=plugin.d.ts.map
|
package/dist/esm/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAEjE,eAAO,MAAM,qBAAqB,6BAEhC,CAAC"}
|
package/dist/esm/plugin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { registerPlugin } from '@capacitor/core';
|
|
2
|
-
export const
|
|
3
|
-
web: () => import('./web').then((m) => new m.
|
|
2
|
+
export const CapgoCapacitorFastSql = registerPlugin('CapgoCapacitorFastSql', {
|
|
3
|
+
web: () => import('./web').then((m) => new m.CapgoCapacitorFastSqlWeb()),
|
|
4
4
|
});
|