diff --git a/bin/jadb.dart b/bin/jadb.dart index c18f930..7ac2dfc 100644 --- a/bin/jadb.dart +++ b/bin/jadb.dart @@ -88,6 +88,41 @@ class QueryKanji extends Command { } } +class QueryWord extends Command { + final name = "query-word"; + final description = "Query the database for word data"; + + QueryWord() { + addLibsqliteArg(argParser); + addJadbArg(argParser); + } + + Future run() async { + if (argResults!.option('libsqlite') == null || + !argResults!.wasParsed('jadb')) { + print(argParser.usage); + exit(64); + } + + final db = await createDatabaseFactoryFfi(ffiInit: () { + open.overrideForAll( + () => DynamicLibrary.open(argResults!.option('libsqlite')!)); + }).openDatabase( + Directory.current.uri.resolve(argResults!.option('jadb')!).path); + + final result = await JaDBConnection(db).searchWord('かな'); + + if (result == null) { + print("Invalid search"); + } else if (result.isEmpty) { + print("No matches"); + } else { + print(JsonEncoder.withIndent(' ') + .convert(result.map((e) => e.toJson()).toList())); + } + } +} + Future main(List args) async { final runner = CommandRunner( 'jadb', @@ -96,6 +131,7 @@ Future main(List args) async { runner.addCommand(CreateDb()); runner.addCommand(QueryKanji()); + runner.addCommand(QueryWord()); runner.run(args); } diff --git a/lib/models/common/jlpt_level.dart b/lib/models/common/jlpt_level.dart new file mode 100644 index 0000000..6d1712f --- /dev/null +++ b/lib/models/common/jlpt_level.dart @@ -0,0 +1 @@ +enum JlptLevel { none, n5, n4, n3, n2, n1 } diff --git a/lib/models/jmdict/word_search_result.dart b/lib/models/jmdict/word_search_result.dart index f7dbec1..1cd012b 100644 --- a/lib/models/jmdict/word_search_result.dart +++ b/lib/models/jmdict/word_search_result.dart @@ -1,3 +1,5 @@ class WordSearchResult { // TODO: implement me + + Map toJson() => {}; } diff --git a/lib/search.dart b/lib/search.dart index 2fe5713..8f88f56 100644 --- a/lib/search.dart +++ b/lib/search.dart @@ -1,6 +1,7 @@ import 'package:jadb/models/jmdict/word_search_result.dart'; import 'package:jadb/models/kanjidic/kanji_search_result.dart'; import 'package:jadb/models/radkfile/radicals_search_result.dart'; +import 'package:jadb/search/jmdict.dart'; import 'package:jadb/search/kanji.dart'; @@ -14,11 +15,11 @@ class JaDBConnection { Future searchKanji(String kanji) async => searchKanjiWithDbConnection(this._connection, kanji); - Future searchKanjiByRadicals(List radicals) { + Future searchKanjiByRadicals( + List radicals) async { throw UnimplementedError(); } - Future searchWord(String word) async { - throw UnimplementedError(); - } + Future?> searchWord(String word) async => + searchWordWithDbConnection(this._connection, word); } diff --git a/lib/search/jmdict.dart b/lib/search/jmdict.dart new file mode 100644 index 0000000..1f9fbc5 --- /dev/null +++ b/lib/search/jmdict.dart @@ -0,0 +1,105 @@ +import 'package:jadb/models/jmdict/word_search_result.dart'; +import 'package:sqflite_common/sqlite_api.dart'; + +// TODO: Support globs + +// TODO: Support tags + +// TODO: Prefer original kana type when sorting results + +// TODO: Support mixing kana and romaji + +Future?> searchWordWithDbConnection( + DatabaseExecutor connection, + String word, { + bool isKana = true, +}) async { + if (word.isEmpty) { + return null; + } + + late final List matches; + if (isKana) { + matches = (await connection.query( + 'JMdict_EntryByKana', + where: 'kana LIKE ?', + whereArgs: ['%$word%'], + )) + .map((row) => row['id'] as int) + .toList(); + } else { + matches = (await connection.query( + 'JMdict_EntryByEnglish', + where: 'english LIKE ?', + whereArgs: ['%$word%'], + )) + .map((row) => row['id'] as int) + .toList(); + } + + if (matches.isEmpty) { + return []; + } + + late final List senseIds; + final Future> senseIds_query = connection + .query( + 'JMdict_Sense', + where: 'id IN (${matches.join(',')})', + ) + .then((rows) => rows.map((row) => row['id'] as int).toList()); + + late final List> readingElements; + final Future>> readingElements_query = + connection.query( + 'JMdict_ReadingElement', + where: 'entry_id IN (${matches.join(',')})', + ); + + late final List> kanjiElements; + final Future>> kanjiElements_query = + connection.query( + 'JMdict_KanjiElement', + where: 'entry_id IN (${matches.join(',')})', + ); + + Future.wait([ + senseIds_query.then((value) => senseIds = value), + readingElements_query.then((value) => readingElements = value), + kanjiElements_query.then((value) => kanjiElements = value), + ]); + + print(senseIds); + print(readingElements); + print(kanjiElements); + + // JMdict_EntryByEnglish + // JMdict_EntryByKana + // + // JMdict_ExampleSentence + // JMdict_InfoDialect + // JMdict_InfoField + // JMdict_InfoKanji + // JMdict_InfoMisc + // JMdict_InfoPOS + // JMdict_InfoReading + // JMdict_KanjiElement + // JMdict_KanjiElementInfo + // JMdict_ReadingElement + // JMdict_ReadingElementInfo + // JMdict_ReadingElementRestriction + // JMdict_Sense + // JMdict_SenseAntonym + // JMdict_SenseDialect + // JMdict_SenseField + // JMdict_SenseGlossary + // JMdict_SenseInfo + // JMdict_SenseLanguageSource + // JMdict_SenseMisc + // JMdict_SensePOS + // JMdict_SenseRestrictedToKanji + // JMdict_SenseRestrictedToReading + // JMdict_SenseSeeAlso + + throw UnimplementedError(); +}