anysql 0.3.0
anysql: ^0.3.0 copied to clipboard
A Firebase-style keyword API, setup generator, HTTP backend client, and driver layer for SQL and NoSQL databases.
import 'package:anysql/anysql.dart';
Future<void> main() async {
print('anysql example');
print('-------------');
final options = AnySqlOptions(
config: AnySqlConfig.postgres(
host: 'localhost',
database: 'app',
username: 'postgres',
password: const String.fromEnvironment('ANYSQL_PASSWORD'),
),
backendUri: Uri.parse('https://api.example.com/anysql'),
backendHeaders: const {'x-client': 'anysql-example'},
);
await runDirectAnySqlExample(options);
await runBackendAnySqlExample(options);
await runKeywordStoreExample();
}
Future<void> runDirectAnySqlExample(AnySqlOptions options) async {
print('\n1. Direct driver pattern for trusted Dart code');
final connection = await options.connect(driver: ExamplePostgresDriver());
try {
final result = await connection.query(
'select id, email from users where id = @id',
parameters: AnySqlParameters.named({'id': 1}),
);
print(result.firstOrNull);
} finally {
await connection.close();
}
}
Future<void> runBackendAnySqlExample(AnySqlOptions options) async {
print('\n2. Backend/proxy pattern for Flutter mobile apps');
final connection = await options.connectBackend(
client: ExampleBackendClient(),
);
try {
final result = await connection.query(
'users.findById',
parameters: AnySqlParameters.document({'id': 1}),
);
print(result.firstOrNull);
} finally {
await connection.close();
}
}
Future<void> runKeywordStoreExample() async {
print('\n3. Keyword store pattern over any connection');
final connection = _ExampleConnection(source: 'keyword store connection');
try {
final db = connection.store(dialect: AnySqlDialect.postgres);
final result = await db
.collection('users')
.where('active', isEqualTo: true)
.limit(10)
.get();
print(result.firstOrNull);
} finally {
await connection.close();
}
}
final class ExamplePostgresDriver extends AnySqlDriverBase {
ExamplePostgresDriver() : super('example_postgres', AnySqlDialect.postgres);
@override
Future<AnySqlConnection> connect(AnySqlConfig config) async {
checkSupported(config);
return _ExampleConnection(source: 'direct ${config.dialect.name} driver');
}
}
final class ExampleBackendClient implements AnySqlBackendClient {
@override
Future<AnySqlConnection> connect(AnySqlOptions options) async {
if (!options.hasBackend) {
throw const AnySqlException('Backend URL is required.');
}
return _ExampleConnection(source: 'backend proxy at ${options.backendUri}');
}
}
final class _ExampleConnection implements AnySqlConnection {
_ExampleConnection({required this.source});
final String source;
var _isOpen = true;
@override
bool get isOpen => _isOpen;
@override
Future<void> close() async {
_isOpen = false;
}
@override
Future<AnySqlResult> query(
String statement, {
Map<String, Object?> parameters = const {},
}) async {
if (!_isOpen) {
throw const AnySqlException('Connection is closed.');
}
return AnySqlResult.rows([
{'source': source, 'statement': statement, 'parameters': parameters},
]);
}
@override
Future<T> transaction<T>(
Future<T> Function(AnySqlTransaction transaction) action,
) async {
if (!_isOpen) {
throw const AnySqlException('Connection is closed.');
}
final transaction = _ExampleTransaction(this);
try {
final value = await action(transaction);
if (!transaction.isCompleted) {
await transaction.commit();
}
return value;
} catch (_) {
if (!transaction.isCompleted) {
await transaction.rollback();
}
rethrow;
}
}
}
final class _ExampleTransaction implements AnySqlTransaction {
_ExampleTransaction(this._connection);
final _ExampleConnection _connection;
var isCompleted = false;
@override
Future<void> commit() async {
_checkActive();
isCompleted = true;
}
@override
Future<AnySqlResult> query(
String statement, {
Map<String, Object?> parameters = const {},
}) {
_checkActive();
return _connection.query(statement, parameters: parameters);
}
@override
Future<void> rollback() async {
_checkActive();
isCompleted = true;
}
void _checkActive() {
if (isCompleted) {
throw const AnySqlException('Transaction is already completed.');
}
}
}