294 Commits
Author SHA1 Message Date
adrien 0484b15d9c Update README.md
mkdocs / deploy (push) Successful in 6m24s
2025-07-21 19:38:52 +00:00
adrien 6573f39692 Update README
mkdocs / deploy (push) Failing after 1m55s
2025-05-29 08:20:15 +00:00
adrien 958f0842a2 Renamed .github to .gitea
mkdocs / deploy (push) Failing after 1m50s
2025-05-29 08:18:33 +02:00
adrien 281e77ea64 Use specific version of 0.14 because stuff changed, to switch to just 0.14 when release
mkdocs / deploy (push) Failing after 2m1s
2025-02-12 17:08:02 +01:00
adrien f0fc12d1b8 Remove test from auto release because it is buggy, to check later 2025-02-12 17:04:50 +01:00
adrien 1bfdad9a28 Update release action 2025-02-12 17:02:50 +01:00
adrien 2021f95ffd Update roadmap 2025-02-12 16:51:07 +01:00
adrien fe2f407b7f Added empty test for later 2025-02-12 16:42:14 +01:00
adrien ca5d806f0b Changed a bit test and removed comments 2025-02-12 16:39:35 +01:00
adrien d7b8dec378 Fix
Start index still change if the member name is not right, otherwise run
in loop forever
2025-02-12 16:39:18 +01:00
adrien 7352ec45c7 Removed old comment and move an array a bit later in function 2025-02-12 14:54:10 +01:00
adrien 84f5749aa2 Fix
Now str array don't take ' on both side when creating the array,
otherwise I compare Bob with 'Bob' and it don't work
2025-02-12 14:53:39 +01:00
adrien 3e234396bf Fix
Now delete .new file if Йfind one when I shouldn't in allFileIndex
2025-02-12 14:52:48 +01:00
adrien b480cff079 Fix
I wasn't flushing writter buffer if the limit is reached as I return
early
2025-02-12 14:36:02 +01:00
adrien b7878227e9 Better readme and docs 2025-02-12 10:19:34 +01:00
adrien 45622e3d3a Update readme 2025-01-04 18:38:40 +01:00
adrien 24fccc6487 Update readme 2025-01-04 18:37:20 +01:00
adrien 19c097717a a 2025-02-10 11:53:19 +01:00
adrien adf39be133 2 small fix 2025-01-31 18:49:44 +01:00
adrien b757e01b64 Array and link are empty by default if not in ADD action. Also can use * to return everything execpt link
The * is to be use like that GRAB User [*, friends]
Because if I just do GRAB User [friends], I only get friends
So I would of need to specify all of them like GRAB User [name, age,
email, .., friends]
2025-01-31 10:05:55 +01:00
adrien 30a7a83e56 Update some docs 2025-01-30 21:21:02 +01:00
adrien b28970f26a Added some bullshit in about 2025-01-30 20:28:03 +01:00
adrien f02a1e3e01 Squeleton for single file 2025-01-30 20:22:49 +01:00
adrien e0d4840123 Moved quickstart doc out of learn 2025-01-30 20:22:24 +01:00
adrien b2d05edbee Added REMOVE and REMOVEAT test 2025-01-30 20:22:07 +01:00
adrien 8c6a6188dd Working REMOVE and REMOVEAT 2025-01-30 20:21:50 +01:00
adrien cd178ce53d Working CLEAR command, now checking REMOVE 2025-01-30 20:15:07 +01:00
adrien 005631ac76 Removed a FIXME tested 2025-01-30 20:12:02 +01:00
adrien d819281fe4 Fix
If the array is empty, I still ne to append 8 bytes to hold the array
len
2025-01-30 20:11:51 +01:00
adrien b1ce5e9923 Working POP command, now doing CLEAR 2025-01-30 20:01:18 +01:00
adrien 44ea7efbb0 Updated APPEND function to remove duplicate code 2025-01-29 22:22:25 +01:00
adrien cb250bbcd0 Small opti 2025-01-27 20:38:14 +01:00
adrien 15ec304fe1 APPEND work, need to check next array manipulation 2025-01-27 20:38:03 +01:00
adrien baf6cd2284 Added some log and started testing array manip. Fixed some errors already 2025-01-25 21:15:04 +01:00
adrien 4066803ecd Small update on index and README 2025-01-25 19:13:04 +01:00
adrien 78e8b67b80 Moved benchmark and test to src. Implemented array without testing yet 2025-01-25 19:11:01 +01:00
adrien a476cef2df Changed release github action to use release Small and stop making a .zip, it is small enough 2025-01-25 19:09:59 +01:00
adrien c3db03fe4c Small doc update 2025-01-23 17:31:55 +01:00
adrien b2bd1e373b Updated lib config and small stuff 2025-01-23 17:31:41 +01:00
adrien 6fa8d6b7c6 Opti
Bring test back

Removed useless arena, making like 40% perf improv

Removed shared Loc
2025-01-23 17:31:14 +01:00
adrien 98f0c69e61 SOLVED THREAD BUG
Needed a thread safe alloc. Will need to update other part as I just did
parseEntities and deleteEntities
2025-01-22 22:34:46 +01:00
adrien f05696a924 Removed max_file from SyncContext to use work group
Now instead of create a context with the number of file to parse and
check every x millisecond if it is complete, I use work group. For each
file, I spawn a thread in the group and then I call wg.wait()
2025-01-22 18:24:02 +01:00
adrien 7c34431702 Error found!!
Got an error that I could find for a while. It was when parsing a lot of
files.

Turn out it was the Thread Pool or something because if I run on 1 core,
it's ok.

Different thing in this commit, I just want to freeze a state that
benchmark work.
2025-01-22 11:34:00 +01:00
adrien ebf91bb61c If config.CPU_CORE == 0, use the cpu count of processor 2025-01-22 10:29:54 +01:00
adrien 1ca2fc5470 Updated docs and roadmap 2025-01-20 19:56:44 +01:00
adrien abe9445d72 Compilable array manipulation, still some errors 2025-01-20 19:56:29 +01:00
adrien 14ea22dad6 Added a map with just the zero UUID in memory
So I dont need to create a map everytime I have a orders=none
2025-01-16 22:49:36 +01:00
adrien 6bd3782e1e Now string with \n are written in triple quote 2025-01-16 22:34:39 +01:00
adrien a09a368528 Removed useless code and old comment 2025-01-16 22:34:19 +01:00
adrien d1b430a3d5 Removed some TODO and changer so now it parse all existing file
Before I was parsing all files, getting the max index then parsing from
0 to the max.

Byt now that I delete empty files, I need to parse only existing one.
2025-01-16 22:17:42 +01:00
adrien a16c9b29c1 Update README and doc 2025-01-16 20:45:58 +01:00
adrien 154a146678 Missing from previous commit 2025-01-16 20:45:50 +01:00
adrien a9c39d9aa5 Renamed paarser.core to ziql.parser 2025-01-16 20:45:30 +01:00
adrien 6338cb6364 NewData ordered by default 2025-01-15 19:59:13 +01:00
adrien e848be94c1 Good docs update, stillo need some work. Need to take a step back and think 2025-01-14 22:48:50 +01:00
adrien 9ae9b65f1e Rename ziql to parser 2025-01-14 22:42:11 +01:00
adrien dff7ead5b1 . 2025-01-14 22:33:01 +01:00
adrien 26bbe0d0f9 . 2025-01-14 22:32:42 +01:00
adrien 672d79cbea Add config and schema for benchmark 2025-01-14 22:32:31 +01:00
adrien 173b302976 Add number of file to db metrics 2025-01-14 22:31:55 +01:00
adrien 77e1197894 Custom color for docs 2025-01-14 15:15:26 +01:00
adrien 425401d764 Change image and doc name 2025-01-14 13:43:48 +01:00
adrien 3a6a0e202b Update image 2025-01-14 13:42:22 +01:00
adrien 58bbc44119 Add transparent logo 2025-01-14 10:58:48 +01:00
adrien a5e957c05a Release for every tag now 2025-01-14 10:54:32 +01:00
adrien e818700905 Use try 2025-01-13 20:06:16 +01:00
adrien 1031e767bc Deleted logo dir and moved new logo to docs images 2025-01-13 20:04:05 +01:00
adrien bfb7533ef9 Merge branch 'main' into v0.1.8 2025-01-13 20:01:50 +01:00
adrien eb0389464d Update logo 2025-01-13 20:01:22 +01:00
adrien e18a12aefe Add simple SQL comparison 2025-01-13 10:56:53 +00:00
adrien 57f97e50ab Remove extension from zip name 2025-01-12 20:35:43 +01:00
adrien c6725f6b54 Fix stdout error 2025-01-12 20:28:35 +01:00
adrien 6ccfc7feb9 Send back to true and remove .pdb from release 2025-01-12 19:08:34 +01:00
adrien 35ca253dad Test 2025-01-12 18:32:25 +01:00
adrien d35b7a5e3e Fix ? 2025-01-12 18:27:12 +01:00
adrien c7024d70c4 Update release flow 2025-01-12 18:21:52 +01:00
adrien bd4cc98797 Release test 2025-01-12 17:16:16 +01:00
adrien 0b871ecc93 Add permision 2025-01-12 17:05:40 +01:00
adrien 374d724bba Update workflow 2025-01-12 16:52:26 +01:00
adrien d4d03f1b2c Typo 2025-01-12 16:42:38 +01:00
adrien f1a37648d3 Typo 2025-01-12 16:41:05 +01:00
adrien 574c616929 Rename workflow and remove arm in build release 2025-01-12 16:39:07 +01:00
adrien 7db5c5329a Update workflow 2025-01-12 16:34:59 +01:00
adrien 9b547e594e Update github action 2025-01-12 16:28:02 +01:00
adrien ff92cacc7c Auto release github action 2025-01-12 16:24:18 +01:00
adrien c070723baa ziql moved into a dir and splited 2025-01-12 15:33:15 +01:00
adrien 1f5da7a74b Created cli struct and dir 2025-01-12 12:37:07 +01:00
adrien 1c8384dec6 Moved stuff into a schema dir and created empty dir 2025-01-12 11:50:22 +01:00
adrien 83ff27c3f2 A bit better docs README 2025-01-12 01:41:42 +01:00
adrien 67546d69a9 Splited fileEngine into multiple files 2025-01-12 01:25:09 +01:00
adrien 955aff0d09 Moved global error to lib and fuse to a unique one 2025-01-12 00:37:57 +01:00
adrien c0e8b07025 Moved thread stuff into a directory 2025-01-12 00:11:03 +01:00
adrien d775ff1d0a Deleted stuffs dir for a dataStructure one 2025-01-11 23:41:03 +01:00
adrien bc0c0cbe1d Update benchmark and some stuff 2025-01-11 19:26:06 +01:00
adrien 13caff2fd7 Dump csv
Can now use command dump csv

Will see later to add json and zid format as well as loading it
2025-01-11 19:25:03 +01:00
adrien ee9d5c92f2 Some data struct now use file instead of = struct { 2025-01-11 19:24:15 +01:00
adrien 78213df3ff And other 2025-01-11 18:03:36 +01:00
adrien 90edb94f7a Same for schemaEngine 2025-01-11 17:58:52 +01:00
adrien d5f7309869 Same for ziqlParser 2025-01-11 17:57:19 +01:00
adrien 0f6f34e706 Moved fileEngine to use the root as struct 2025-01-11 17:55:56 +01:00
adrien bd4f0aab7f Removed some TODO, fix and typo 2025-01-11 16:52:19 +01:00
adrien 54146b9495 Add and remove UUID from index map
Now remove and add UUID in the sstruct map UUID -> File index
2025-01-11 16:08:46 +01:00
adrien 1495e779c9 Speed up date
Date was taking a long time for parsing when using ADD in batch, speeded
up by like x50
2025-01-11 15:27:17 +01:00
adrien 7d012b527f Write every 1000 map
Now if I run a big ADD query, write every 1000 entities to prevent a
maps array too big and go OOM
2025-01-11 13:50:32 +01:00
adrien 5300f932d5 Update README 2025-01-08 23:53:56 +01:00
adrien d533eaff98 Working multi struct schema with relationship!
Noce
2025-01-08 23:53:41 +01:00
adrien 71e5f6eb1e Started to debug schema with multiple struct and some time keyword
Added NOW already and now debuging some stuff regarding filter and
parsing file of one struct when it should be another

Also moved query test into a seperated test file.
And some fix and changed in docs
2025-01-08 10:09:15 +01:00
adrien a712fe3e83 Save schema file when using new 2025-01-07 17:15:09 +01:00
adrien 65fa7ccfc4 Now delete empty file when deleting entities exept 0.zid 2025-01-07 14:09:22 +01:00
adrien 2a4842432d Speed up batch ADD and better bechmark
Now I flush only when the file is full and I check the the currently
used file if it is big enough.

So I dont get stat of all files and flush everytime like before
2025-01-07 13:55:02 +01:00
adrien e3264d8553 Random ADD for benchmark 2025-01-06 20:45:16 +00:00
adrien 900b9e5305 Moved benchmark outside of src and making it better 2025-01-02 13:28:23 +00:00
adrien b075f8b89a Moved config to libs 2025-01-02 12:19:05 +00:00
adrien 4f421f7977 Added ADD in batch 2024-12-30 15:31:16 +01:00
adrien a535ce5283 Basic benchmark command 2024-12-30 14:09:59 +01:00
adrien a7d076ec80 Added !IN 2024-12-30 12:08:25 +01:00
adrien 2e2dae3df1 Some typo 2024-12-29 10:19:04 +01:00
adrien b2dd6fe627 Basic working relationship
It is working !

The basic GRAB [name, best_friend] work and do return the best friend
infos.

I added more test and some do not work yet, working on it now
2024-12-28 20:12:20 +01:00
adrien 3b47007ca4 Base reparsing
This dosnt work yet but I implemented the reparsing of the files to
return relationship.

So GRAB User [name, friends] should return all infos of all friends and
not just the UUID of those friends like before
2024-12-27 12:42:51 +01:00
adrien 0127daa330 Push before leaving for christmas 2024-12-21 15:13:50 +01:00
adrien e7056efec9 Now query with relationship will write the UUID bytes betwen {|<>|}
So then I can parse the file again, create a map of UUID sub json and
just iterate over the first json looking for UUID and update with new
data from map
2024-12-20 22:29:02 +01:00
adrien 7fb0b5f63e Changed memory in AdditionalData
Now it need to use an arena because there is no deinit function.

And additionalData of member are null by default instead of an empty
list.
2024-11-30 10:33:28 +01:00
adrien 57a9eecdb3 Renamed members of AdditionalData 2024-11-30 09:49:54 +01:00
adrien c901ec2b06 Added some docs 2024-11-29 21:57:04 +01:00
adrien c6fe428270 Dont send link if not in AdditionalData 2024-11-29 21:56:52 +01:00
adrien 4ee79c9629 Created an EntityWriter responsable for writing into JSON and table into a writer 2024-11-29 21:38:05 +01:00
adrien 7f27557ca2 Fix parsing array
Before if the array is [ 1 ] I get [ 0, 1, 0] because I get 2 empty
string that when I try to make into int, it become 0
2024-11-29 21:20:12 +01:00
adrien ae2fa848b4 Added docs 2024-11-28 19:21:09 +01:00
adrien 3f53da5220 Making link_array working, now can do query with filter for array of ofther struct 2024-11-28 19:20:44 +01:00
adrien 12ae7f9a62 Added db state command and fixed printError
I was using the same buffer at 2 place :/
2024-11-26 22:59:36 +01:00
adrien 3c01150e33 Update Docs 2024-11-26 21:31:53 +01:00
adrien e41f53b692 Update commands docs 2024-11-26 20:10:22 +01:00
adrien 5141df3429 Added pygments in ci workslow 2024-11-26 19:49:57 +01:00
adrien 481fee27bf Added code highlit 2024-11-26 19:43:02 +01:00
adrien 874550a77d Added git repo to docs 2024-11-26 19:37:57 +01:00
adrien 2e3e89d3db Update docs 2024-11-26 19:34:44 +01:00
adrien 75a8e822a1 Test material theme 2024-11-26 19:17:29 +01:00
adrien 9c460b5ab4 Update docs 2024-11-26 19:14:22 +01:00
adrien 7e5abcedea Update Docs
Shoud added them on docs and added images
2024-11-26 18:59:12 +01:00
adrien cc32eff1da Added doc website complete as Roadmap 2024-11-26 07:19:52 +01:00
adrien c35b559a60 Update docs 2024-11-25 23:40:42 +01:00
adrien a40670a0c6 Update to trigger github action 2024-11-25 23:35:43 +01:00
adrien ed43a4b0ce Update url in mkdocs 2024-11-25 23:31:01 +01:00
adrien acef72b319 Delete Dockerfile
It is useless, it was just a quick test
2024-11-25 23:25:19 +01:00
adrien fcc0cd71f2 Update ci 2024-11-25 23:24:23 +01:00
adrien 95f23449d6 Update Docs 2024-11-25 23:09:02 +01:00
adrien 401b40bb8f Added glightbox 2024-11-25 22:49:59 +01:00
adrien b54c25fdb8 Fix 2024-11-25 22:48:10 +01:00
adrien 2338cb6549 Added docs 2024-11-25 22:43:03 +01:00
adrien 08cae48cbc Added a writeEntityTable and fixed date and time 2024-11-24 22:26:54 +01:00
adrien 1333b75981 Dont trow and error on basic relationship query 2024-11-24 20:10:21 +01:00
adrien bf1f5916d7 Can now ADD using a filter 2024-11-24 16:55:54 +01:00
adrien ceab51da27 NewData map now use ConditionValue 2024-11-24 16:26:26 +01:00
adrien 23e8ed8709 Changed a bit how the memory work
Now SchemaEngine have an arena at the root of the file. So UUIDFileIndex
can be as big as we want. The idea is nice, maybe I will use it for the
FileEngine too.
2024-11-22 11:03:39 +01:00
adrien 3f5c929a11 Big memory improvement
Started to use fixed buffer at the root of each file. I like that
because that mean I can estimate the amount of memory that the app use.

The only thing that still use an non fixed allocator is the
UUIDFileIndex, but I dont like it. I think it should also use a fixed
lenght buffer. But then how can I be sure it is enough ? :/

I mean I get it, I need an allocator here. But if this is the only place
I use one, this a shame
2024-11-20 23:52:36 +01:00
adrien 979690fec4 IN filter working
Now if I do like GRAB User { best_friends IN {name = 'Bob'}} it should
work

At least now the condition value is a hashmap with key as UUID.
2024-11-17 21:52:11 +01:00
adrien 7b2a754d81 Check if additional data count is reached at each iteration
Before I was checking after the filter.evaluate is true. So I can end up
with the limit reach, but the thread will continue parsing until it find
one that is true, add it and then check if the limit is reach.

Which mean I endup with more than what I want and the thread could stop
before, making things faster.
2024-11-17 20:45:58 +01:00
adrien 65ba0263cc Condition value now can have a HashMap of UUID/void 2024-11-17 18:11:54 +01:00
adrien ca5de646d6 Populate the UUIDFileIndex
Now each SchemaStruct have a UUIDFileIndex that allow to find the file
index of where an entity is based on it's UUID
2024-11-17 16:40:12 +01:00
adrien 5c8d2b6dc7 Create ThreadEngine
Now the DBEngine have a ThreadEngine that have a pool. Like that it is
always the same pool and I dont create one everytime I run a parseing
methods of the FileEngine
2024-11-17 15:25:54 +01:00
adrien 303dc81e2a Created an unused UUIDFileIndex
Created a RadixTree but it is too slow and doest provide that much
reduced memory, mostly because I did it badly. So I will juste use a
small wrapper around an AutoHashMap UUID usize
2024-11-17 00:11:34 +01:00
adrien f1c2bea5c1 Update Docs 2024-11-14 22:32:22 +01:00
adrien ef84200b34 Parsing filter can now parse sub filter, waiting to be use with the parsing to find relationship 2024-11-14 20:39:04 +01:00
adrien 6e7d1d150c Pass test with added stuffs for relationship 2024-11-13 22:44:27 +01:00
adrien 13cba58dbc Fix 2024-11-12 21:57:13 +01:00
adrien 5e9c64caf6 Removed useless code 2024-11-12 21:18:19 +01:00
adrien 3a61e81024 Added not in keyword 2024-11-12 21:17:49 +01:00
adrien b1de4a40c3 Moved ZipponData to lib 2024-11-12 21:17:33 +01:00
adrien f5d93c94f6 Created a ThreadSyncContext
This keep the atomic value that are shared by thread
2024-11-12 21:17:06 +01:00
adrien 268010fe37 Removed log in testing for now 2024-11-10 17:10:56 +01:00
adrien 91b1f61e66 Working new SchemaEngine 2024-11-10 17:10:42 +01:00
adrien dd65f5f03e Typo in docs 2024-11-10 11:41:06 +01:00
adrien e1c957b3b6 Started cleaning by creating a SchemaEngine 2024-11-10 11:38:37 +01:00
adrien 1d365adff6 Moved charts inside the python dir 2024-11-09 16:42:21 +01:00
adrien 18c55194d5 Moved stuffs to new dir 2024-11-09 16:41:28 +01:00
adrien 9fa6f25459 Removed CSV_DELIMITER and some old comment 2024-11-09 16:39:40 +01:00
adrien e5d0a122e1 Added multi threading to delete 2024-11-06 16:04:07 +01:00
adrien 65be757440 Added multithreading to update 2024-11-06 16:01:55 +01:00
adrien fbbeb2f40d Updqte Benchmqrk.md 2024-11-04 23:24:49 +01:00
adrien 48a3ae4a5d Update Benchmark.md 2024-11-04 23:20:24 +01:00
adrien 900b6c5f54 Replace some path_buff to utils.preintOpenDir/File 2024-11-04 23:18:49 +01:00
adrien 96e77a5ad4 Removed last trace of null 2024-11-04 22:57:19 +01:00
adrien 280b3b3c3a Update docs 2024-11-04 22:52:44 +01:00
adrien b12116c005 Removed uuid_file_index 2024-11-04 22:52:19 +01:00
adrien 463df1dc6c Added time for 1 000 000 2024-11-04 22:38:17 +01:00
adrien 3cf33fe4f8 Fixed url of chart 2024-11-04 22:13:33 +01:00
adrien 2af9f68c5e Added small benchmark 2024-11-04 22:11:56 +01:00
adrien c500c2a23c Fixed wrong condition
Superior was inferior and reverse
2024-11-03 22:43:02 +01:00
adrien 3539dd685c Fix, perf ect
- Added a new data type self, that represent the id of the intity itself
- Fixed multi threading for parsing, now each thread use it's own writer
and I concat them at the end
- Added a schemaStruct id to the list
- Other fixe and stuff to go with the rest

New step, multi threading for all function then finally relationship
2024-11-03 19:18:25 +01:00
adrien 72b001b72c I think I just added multithreading for GRAB :o
This look like it work, maybe I need to start using a unique Pool for
everything. Maybe keeping it directly inside the FileEngine
2024-11-02 23:47:41 +01:00
adrien dba73ce113 Started to use fixed lenght alloc for performance
For very importatnt stuff like the writter that write data when parsing,
started to use fixed length because it take the majority of the time to
write, not to parse =/

Gonna need to improve that
2024-11-02 22:12:47 +01:00
adrien aaa1cb2589 Added bach updateEntities using zid 2024-11-02 00:22:13 +01:00
adrien 0920927bc3 Removed sendUUIDs
Removed the different sendUUIDs and sendUUID function. new writeEntity
use a buffer to write inside like the other stuffs.
2024-11-01 22:23:04 +01:00
adrien a20a60e566 Delete Entities now use ZipponData
Also stopped to parse then delete, now I parse and delete at the same
time for perf issue
2024-11-01 21:17:31 +01:00
adrien bead52df5a Fix 2024-11-01 20:40:18 +01:00
adrien 557e4ab064 Return slice when parsing individual value
When I use s2t, or string to type. Like to transform a string array into
an array. "[1 4 21]" to []i32{ 1, 4, 21}.

Before I return an ArrayList, now it use toOwnedSlice
2024-11-01 20:37:19 +01:00
adrien f5a692558b Fixed the bug with additional data 2024-11-01 20:22:37 +01:00
adrien 5e1ac7a0d7 Parse and write at the same time
Created a new function to replace parseAndFindUUIDWithFilter.

Now it parse the file, evaluate with the filter and write directly to a
buffer. There is no UUID that is return, then file are parse again.
Should be a huge perf improve.

Some bugs with additionData tho, got a name: "<UUID>" =(
2024-11-01 20:17:45 +01:00
adrien 1bcc4465c5 getAllUUIDList now use the index_file_map map 2024-11-01 17:19:24 +01:00
adrien c37999cbfc Added UUID -> File index hash map
SchemaStruct member now are [] and not ArrayList. Started to use and
understand toOwnedSlice.

Implemented the hashmap that keep all UUID -> File index. Inside each
SchemaStruct
2024-11-01 17:10:13 +01:00
adrien aff8fac0af FileEngine struct_array no longer an ArrayList
Started to use toOwnedSlice to replace members that are arrayList
2024-11-01 12:31:46 +01:00
adrien dbf5a255a9 writeEntity working with new ZipponData package 2024-10-30 23:50:37 +01:00
adrien 294d4f7a2c Condition with index instead of member_name
Condition now store the index of the value in the file instead of the
member_name. So when I parse, I can just use the list array []Data and
the index to compare both value
2024-10-27 22:34:17 +01:00
adrien 304ec89167 Put back all test
I removed some test while implementing the new Filter
2024-10-27 22:17:15 +01:00
adrien 2a946eafd0 Working new filter parse
Now the parseFilter function return a Filter struct.

It is a tree of Condition and Logic operator  that will then be use when
parsing row. Need to do the evaluate function with the []Data and test
some error
2024-10-27 21:56:57 +01:00
adrien 15171f73c6 Update README 2024-10-27 19:56:43 +01:00
adrien 334c738ac1 New Filter start to work
Changing how condition are handle to create a tree of condition to only
parse once.

So far the basic work, need more testing.
2024-10-27 19:55:07 +01:00
adrien 5756e3a530 Fixed build so test use dependencies 2024-10-27 15:04:30 +01:00
adrien fd21d9bd65 Fix and now schema are saved with name schema and not schema.zipponschema 2024-10-27 14:46:19 +01:00
adrien 24c204f435 Added an option to reset or not the logs and some typo 2024-10-27 13:18:26 +01:00
adrien debc646738 Moved the custom types to a library 2024-10-27 12:59:28 +01:00
adrien 4df151ea85 Moved help message to config 2024-10-27 11:20:02 +01:00
adrien 99871ddc73 Deleted test data 2024-10-27 11:07:07 +01:00
adrien e5f2f7c5e5 Changed some print to log 2024-10-26 18:52:10 +02:00
adrien c5f931cf04 Better logs
Now log are managed by the std log, did a custom log to print either
into a file or into the default io strout.

The plan is to create a scope in each file and log depending of stuff,
can also use it in library I think, if should still base by the custom
function.

Next step is logging a lot of stuff a bit everywhere.
2024-10-26 17:30:58 +02:00
adrien 9d39d47c3b Removed some test and fixed some synthax 2024-10-26 13:47:52 +02:00
adrien 9c36fec517 Removed duplicate code
Changed the expected new value in parseNewData to remove code duplicate
2024-10-22 00:29:01 +02:00
adrien 696498d7ed Removed duplicate code
Changed how I check data type in parseCondition to prevent code
duplicate
2024-10-22 00:20:25 +02:00
adrien 2b9ad08abf Cleaned ZiQlParser
Removed 4 members to be variable, includding; state, struct_name, action
and additional_data.

Also make it so it only return ZipponEError
2024-10-22 00:03:38 +02:00
adrien 62e4f53477 Automatically create all folder if env var provided
If ZIPPONDB_PATH is found, it will try to create and ur the directory.

If ZIPPONDB_SCHEMA is found, it will try to init the schema using it.
2024-10-20 21:19:25 +02:00
adrien 08869e5e3d Added links to schema struct
Added a hash map that contain the name of the struct corresponding to
the link.

So the member "best_friend: User" is an entry key: "best_friend" value:
"User"
2024-10-20 18:01:17 +02:00
adrien 9d2948d686 SchemaStruct use []const u8
Before it was link that and I changed to use Loc as I throught that I
would save memory.

But a slice is just a pointer and a leng, so it should be better. As
long as I keep the original string in memory. The query and schema
2024-10-20 17:51:40 +02:00
adrien 6b1d3d7495 Renamed id and id_array to link and link_array 2024-10-20 17:36:05 +02:00
adrien c7d7a01fa8 Log now print always the same length
When printing 12:03 it was 12;3 before, now it's fix and use the
DateTime.format function
2024-10-20 10:15:25 +02:00
adrien 34688a0180 Changed a bit how log work 2024-10-20 09:50:44 +02:00
adrien a6a3c092cc Added logging, all Token use the same Loc 2024-10-20 01:35:12 +02:00
adrien ebb3eec4f4 Switched to csv 2024-10-19 23:24:55 +02:00
adrien d851c8f908 DELETE UPDATE and ADD now send the list of affected uuid 2024-10-19 18:43:39 +02:00
adrien 49853458ce Fixed the json output for GRAB 2024-10-19 18:12:16 +02:00
adrien 6bcb369cbc Date, clean and errors
Added the datatype date, time and datetime

Moved all custom erros to a single file

Cleaned code to be more readable and created some small utils

Other stuffs that I dont recall. Basically preparing for the
relationship implementation
2024-10-19 14:42:13 +02:00
adrien 673148ba77 Update tokenizer
Added time and datetime to the schema tokenizer

Added date, time and datetime literal to the ziqltokenizer
2024-10-17 23:06:59 +02:00
adrien 69069d39db Base date type 2024-10-17 21:43:50 +02:00
adrien 783697d4df Created config.zig and BUFFERSIZE 2024-10-17 19:38:08 +02:00
adrien be9d4cb63d Create Technical docs.md 2024-10-17 16:49:17 +02:00
adrien 4069c7d85b Back to CLI in a loop 2024-10-17 01:49:54 +02:00
adrien edfd00f939 Updated gitignore 2024-10-17 00:37:27 +02:00
adrien 2b1deca452 Cleaning session
Removed the loop for the CLI, now just take some argument using the
binary. May come back to while loop if I need to keep like the file
engine between session. To run query in parallel.

Moved printError and send to utils and removed duplicate of them.

Organized FileEngine better.

Put the function that convert string to value in a seperate file.

Fix some synthax and make it smaller. Removed unused functions too
2024-10-16 22:36:21 +02:00
adrien 29af5a7ac0 Start cleaning before working one 0.2 2024-10-16 20:26:40 +02:00
adrien c93538f4b0 Update README.md 2024-10-14 18:01:40 +02:00
adrien d15a494fb8 Create LICENSE 2024-10-14 14:35:14 +02:00
adrien d099353509 Update README.md 2024-10-14 11:24:15 +02:00
adrien e67b5afa0a Update README.md 2024-10-14 11:20:17 +02:00
adrien 8f1ce5462f Checked spelling of REDME and ZiQL.md 2024-10-14 00:15:18 +02:00
adrien 7d2400b257 Update README and small stuff
Changed the zipponschema example   to have friends as list of string

Better README, created ZiQL.md for more details on query

Added fast build option
2024-10-13 23:40:30 +02:00
adrien 04263493db Fixed some memory errors and synthax 2024-10-13 23:38:50 +02:00
adrien 0fe3eb5560 Can send string array in JSON 2024-10-13 13:32:58 +02:00
adrien 68e91a62fd Clean a bit ZiQL parser and add condition check
Added a check at the end of parse Condition to check if the condition is
valid. Like < between string is not for example.

Also removed the state send_all to check inside filter_and_send instead
so update and delete can do the same.

And some small bugs/erros
2024-10-13 13:30:30 +02:00
adrien 78d7ed2c0a Fix environment variable
I was freeing the path just after getting it, changed that
2024-10-13 13:28:26 +02:00
adrien e45d8579a9 Added the db metrics, use and init command
Now the DataEngine is deinit and init again everytime the user swap
database using db use. If a db is not selected, it will display an error
2024-10-13 11:26:44 +02:00
adrien ac4186529d Implement send all and send JSON
Now send the JSON using the additional data.

Also implemented the empty filter and the no filter like GRAB User {}
and GRAB User
2024-10-12 19:02:23 +02:00
adrien e6357c4d74 Added DELETE
Basically use the same function as update but instead of rewiting an
updated row, I skip it
2024-10-12 16:20:34 +02:00
adrien 94e3905009 Implemented UPDATE and error for ZiQL Parser
Created a function that is use by UPDATE to take a list of uuids and a
map of new value. Can be optimize later but work rn.

Also started to creat more proper error handeling with custom error
starting with ZiQLError
2024-10-12 15:26:24 +02:00
adrien fbcca0dc09 Implemented dynamic schema
Started by doing a SchemaEngine but at the end I just put everything
inside the FileEngine.

Now you can use 'schema init path/to/schema' to initialize the struct
folders and first data file, Also save a copy of the schema in a file in
the ZipponDB folder.
2024-10-11 17:51:45 +02:00
adrien e2e8bc4d80 Created the engines folder
Created a new folder to clean a bit the repo, put the file and schema
engine inside. As those and Parser depend on the types.zig, I also add
this folder inside the new engines folder
2024-10-09 23:32:37 +02:00
adrien b008f434a6 Passed to one tabular file for each struct
Created a new Parser unique for the FileEngine to read each line.
It is slower as I need to parser character by character because their is
no fixed len for the data in files. Before I was just reading until the
end of the file.

Im gonna need to find some tricks to improve the parsing of data. I am
thinking using the stream directly instead of doing streamUntilDelimiter
2024-10-09 23:20:28 +02:00
adrien 8c8b10ef2a Changed command schema build to schema init 2024-10-09 20:19:20 +02:00
adrien cda2ee16a8 Passe basic GRAB query ! 2024-10-09 20:12:07 +02:00
adrien 84495e831f Update README.md 2024-10-09 14:16:49 +02:00
adrien 1012255c6b Update README.md 2024-10-09 13:56:25 +02:00
adrien 25843ec7d2 Update README.md 2024-10-09 12:32:12 +02:00
adrien 59b29816d5 Update README 2024-10-08 23:41:14 +02:00
adrien 1840dea70b Update README.md 2024-10-08 15:57:13 +02:00
adrien f937fafcca Update README.md 2024-10-08 14:28:17 +02:00
adrien 907aeef35b Update README.md 2024-10-08 14:24:23 +02:00
adrien 4586b8493a Update dataParser.zig 2024-10-08 09:44:56 +02:00
adrien 0bb27027a0 Update README.md 2024-10-08 09:40:26 +02:00
adrien 67fb49ded5 Working new ZiQL pqrser for basic ADD and GRAB !!! 2024-10-08 00:18:25 +02:00
adrien 9829cb24b0 fix README 2024-10-08 00:18:00 +02:00
adrien 7646927a00 fix 2024-10-07 23:38:15 +02:00
adrien 406ef1de48 fix 2024-10-07 23:34:04 +02:00
adrien 6d72997165 fix 2024-10-07 23:27:38 +02:00
adrien 817ba4de2f Better root organization 2024-10-07 23:27:05 +02:00
adrien 3c3d40a019 Better banner 2024-10-07 19:13:26 +02:00
adrien 02606a54ef fix 2024-10-07 18:54:42 +02:00
adrien 2fc29a5a24 fix 2024-10-07 18:46:00 +02:00
adrien 2c664c54c1 fix 2024-10-07 18:45:29 +02:00
adrien 9ace7cb382 Readmap to 1.0 =o 2024-10-07 18:44:55 +02:00
adrien 44e48a5276 Big rework - Now use global ziql parser - still buggy, need to debug the tests 2024-10-07 00:40:24 +02:00
adrien ed1d879aef Update README 2024-10-04 00:17:35 +02:00
adrien 1d1de51d99 Added banner 2024-10-04 00:16:47 +02:00
adrien 9b773588e7 Function to get a list of UUID based on a condition is working, need to finish the GRAB parser to then use AND / OR on left / right array 2024-10-04 00:06:55 +02:00
adrien c66bfe285a Readme update 2024-10-02 20:03:34 +02:00
adrien 61f2363f8f Readme update 2024-10-02 20:00:19 +02:00
adrien 87f070231e Commit to continue working in the car to europa park 2024-09-29 06:30:45 +02:00
adrien a40a57df3d Added a small tech docs 2024-09-28 17:15:32 +02:00
adrien 475e00b13e Moved temporally everything to the root for testing test. Also small changes 2024-09-22 22:58:13 +02:00
adrien 0ee197b564 Small README update 2024-09-20 17:58:16 +02:00
adrien bd198e6a94 Deleted file that shouldnt be on github and added them to gitignore 2024-09-20 17:45:37 +02:00
adrien 07f09e463d Update readme 2024-09-12 20:20:49 +02:00
adrien 87e11188d2 Basic ADD working, started the GRAB parser 2024-09-12 20:13:44 +02:00
adrien dacc9fea67 logo change 2024-09-08 18:15:36 +02:00
adrien b5669e9c2d Some progress, have a good part of the schema and engine building working. Now starting to do the query parser part 2024-09-08 18:11:39 +02:00
adrien be84a8e481 Simple cli and ziql tokenizer 2024-09-02 20:22:46 +02:00
adrien e3f0ff1d84 first commit 2024-09-02 11:02:33 +02:00
158 changed files with 11568 additions and 37927 deletions
+30
View File
@@ -0,0 +1,30 @@
name: mkdocs
on:
push:
branches:
- main
permissions:
contents: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure Git Credentials
run: |
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
- uses: actions/setup-python@v5
with:
python-version: 3.x
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- uses: actions/cache@v4
with:
key: mkdocs-material-${{ env.cache_id }}
path: .cache
restore-keys: |
mkdocs-material-
- run: pip install mkdocs-material
- run: pip install mkdocs-glightbox
- run: pip install Pygments
- run: mkdocs gh-deploy --force
+44
View File
@@ -0,0 +1,44 @@
name: Build and Release
on:
push:
tags:
- '*'
permissions:
contents: write
jobs:
build-and-release:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Zig
uses: mlugg/setup-zig@v1
with:
version: 0.14.0-dev.1510+fb0028a0d
- name: Build release artifacts
run: |
zig build -Doptimize=ReleaseSmall release
# The think is 300kb, I dont need to compress it
#- name: Create zip files for release artifacts
# run: |
# mkdir -p zig-out/release/zips
# for file in zig-out/release/*; do
# if [ -f "$file" ] && [[ "$(basename "$file")" != *.pdb ]]; then
# filename=$(basename "$file")
# zipname="${filename%.*}"
# zip -j "zig-out/release/zips/${zipname}.zip" "$file"
# fi
# done
- name: Upload release artifacts
uses: ncipollo/release-action@v1
with:
name: "Release ${{ github.ref_name }}"
body: "Base release. Most ZipponQL features are here but stuffs around is missing."
artifacts: zig-out/release/*
+13
View File
@@ -0,0 +1,13 @@
.zig-cache
.venv
ZipponDB
data
benchmarkDB
engine
engine.o
zig-out
test1
test2
fly.toml
dockerfile
.dockerignore
-1100
View File
File diff suppressed because it is too large Load Diff
-1438
View File
File diff suppressed because it is too large Load Diff
-1297
View File
File diff suppressed because it is too large Load Diff
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Adrien Bouvais
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
File diff suppressed because it is too large Load Diff
+136
View File
@@ -0,0 +1,136 @@
<p align="center">
<a href="/ZipponDB"><img src="https://mrbounty.github.io/ZipponDB/images/banner.png" alt="ZipponDB"></a>
</p>
<p align="center">
<em>Minimalist Lightweight General Purpose Database written in Zig</em>
</p>
---
**Documentation**: <a href="https://mrbounty.github.io/ZipponDB/" target="_blank">https://mrbounty.github.io/ZipponDB (TODO: Host myself)</a>
**Source Code**: <a href="https://git.bouvais.lu/adrien/ZipponDB" target="_blank">https://git.bouvais.lu/adrien/ZipponDB</a>
---
ZipponDB is a database built from the ground up in Zig, with zero external dependencies. Designed for simplicity,
performance, and portability, it's almost usable for small to
medium applications that want a quick and simple database.
## Key Features
* **Small Binary:** ~300kb.
* **Fast:** Parse millions of entities in milliseconds.*
* **Relationship:** Build with focus on easy relationship.
* **Query Language:** Use it's own stupid query language.
* **No dependencies:** Depend on nothing, every line of code running is in the codebase and written for ZipponDB.
* **Open-source:** Open-source under MIT licence.
<small>* Check <a href="https://mrbounty.github.io/ZipponDB/Benchmark/">benchmark</a>.</small>
# Declare a schema
In ZipponDB, you use structures, or structs for short, and not tables to organize how your data is stored and manipulated. A struct has a name like `User` and members like `name` and `age`.
Create a file that contains a schema that describes all structs. Compared to SQL, you can see it as a file where you declare all table names, column names, data types, and relationships.
All structs have an id of the type UUID by default.
Here an example of a file:
```lua
User (
name: str,
age: int,
email: str,
Parent: User,
childrens: []User,
orders: []Order,
)
Order (
at: datetime,
items: []Item,
)
Item (
name: str,
category: str,
)
```
Note that parent is a link to another `User` and can be `none`, `[]` mean an array. You can find more examples [here](https://github.com/MrBounty/ZipponDB/tree/main/schema).
# ZipponQL
ZipponDB uses its own query language, ZipponQL or ZiQL for short. Here are the key points to remember:
- 4 actions available: `GRAB`, `ADD`, `UPDATE`, `DELETE`
- All queries start with an action followed by a struct name
- `{}` are filters
- `[]` specify how much and what data
- `()` contain new or updated data (not already in the file)
## GRAB
The main action is `GRAB`, it parse files and return data.
```js
GRAB User {name = 'Bob' AND (age > 30 OR age < 10)}
```
Using `[]` before the filter tell what to return.
```js
GRAB User [id, email] {name = 'Bob'}
```
Relationship use filter within filter.
```js
GRAB User {best_friend IN {name = 'Bob'}}
```
GRAB queries return a list of JSON objects, e.g:
```
[{id:"1e170a80-84c9-429a-be25-ab4657894653", name: "Gwendolyn Ray", age: 70, email: "austin92@example.org", scores: [ 77 ], friends: [], }, ]
```
## ADD
The `ADD` action adds one entity to the database. The syntax is similar to `GRAB`, but uses `()`. This signifies that the data is not yet in the database.
```js
ADD User (name = 'Bob', age = 30)
```
## DELETE
Similar to `GRAB` but deletes all entities found using the filter and returns a list of deleted UUIDs.
```js
DELETE User {name = 'Bob'}
```
## UPDATE
A mix of `GRAB` and `ADD`. It takes a filter first, then the new data.
Here, we update the first 5 `User` entities named 'bob' to capitalize the name and become 'Bob':
```js
UPDATE User [5] {name='bob'} TO (name = 'Bob')
```
## Link query - Not yet implemented
You can also link query. Each query returns a list of UUID of a specific struct. You can use it in the next query.
Here an example where I create a new `Comment` that I then append to the list of comment of one specific `User`.
```js
ADD Comment (content='Hello world', at=NOW, like_by=[]) => added_comment => UPDATE User {id = '000'} TO (comments APPEND added_comment)
```
The name between `=>` is the variable name of the list of UUID used for the next queries, you can have multiple one if the link has more than 2 queries.
You can also just use one `=>` but the list of UUID is discarded in that case.
This can be use with GRAB too. So you can create variable before making the query. Here an example:
```js
GRAB User {name = 'Bob'} => bobs =>
GRAB User {age > 18} => adults =>
GRAB User {IN adults AND !IN bobs}
```
Which is the same as:
```js
GRAB User {name != 'Bob' AND age > 18}
```
-1432
View File
File diff suppressed because it is too large Load Diff
-1323
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-1162
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-1290
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-18
View File
@@ -1,18 +0,0 @@
/*!
* Lunr languages, `Danish` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.da=function(){this.pipeline.reset(),this.pipeline.add(e.da.trimmer,e.da.stopWordFilter,e.da.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.da.stemmer))},e.da.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.da.trimmer=e.trimmerSupport.generateTrimmer(e.da.wordCharacters),e.Pipeline.registerFunction(e.da.trimmer,"trimmer-da"),e.da.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){var e,r=f.cursor+3;if(d=f.limit,0<=r&&r<=f.limit){for(a=r;;){if(e=f.cursor,f.in_grouping(w,97,248)){f.cursor=e;break}if(f.cursor=e,e>=f.limit)return;f.cursor++}for(;!f.out_grouping(w,97,248);){if(f.cursor>=f.limit)return;f.cursor++}d=f.cursor,d<a&&(d=a)}}function n(){var e,r;if(f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(c,32),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del();break;case 2:f.in_grouping_b(p,97,229)&&f.slice_del()}}function t(){var e,r=f.limit-f.cursor;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.find_among_b(l,4)?(f.bra=f.cursor,f.limit_backward=e,f.cursor=f.limit-r,f.cursor>f.limit_backward&&(f.cursor--,f.bra=f.cursor,f.slice_del())):f.limit_backward=e)}function s(){var e,r,i,n=f.limit-f.cursor;if(f.ket=f.cursor,f.eq_s_b(2,"st")&&(f.bra=f.cursor,f.eq_s_b(2,"ig")&&f.slice_del()),f.cursor=f.limit-n,f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(m,5),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del(),i=f.limit-f.cursor,t(),f.cursor=f.limit-i;break;case 2:f.slice_from("løs")}}function o(){var e;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.out_grouping_b(w,97,248)?(f.bra=f.cursor,u=f.slice_to(u),f.limit_backward=e,f.eq_v_b(u)&&f.slice_del()):f.limit_backward=e)}var a,d,u,c=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],l=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],w=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],p=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],f=new i;this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var r=f.cursor;return e(),f.limit_backward=r,f.cursor=f.limit,n(),f.cursor=f.limit,t(),f.cursor=f.limit,s(),f.cursor=f.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}});
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hi=function(){this.pipeline.reset(),this.pipeline.add(e.hi.trimmer,e.hi.stopWordFilter,e.hi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hi.stemmer))},e.hi.wordCharacters="ऀ-ःऄ-एऐ-टठ-यर-िी-ॏॐ-य़ॠ-९॰-ॿa-zA-Za-zA-Z0-90-9",e.hi.trimmer=e.trimmerSupport.generateTrimmer(e.hi.wordCharacters),e.Pipeline.registerFunction(e.hi.trimmer,"trimmer-hi"),e.hi.stopWordFilter=e.generateStopWordFilter("अत अपना अपनी अपने अभी अंदर आदि आप इत्यादि इन इनका इन्हीं इन्हें इन्हों इस इसका इसकी इसके इसमें इसी इसे उन उनका उनकी उनके उनको उन्हीं उन्हें उन्हों उस उसके उसी उसे एक एवं एस ऐसे और कई कर करता करते करना करने करें कहते कहा का काफ़ी कि कितना किन्हें किन्हों किया किर किस किसी किसे की कुछ कुल के को कोई कौन कौनसा गया घर जब जहाँ जा जितना जिन जिन्हें जिन्हों जिस जिसे जीधर जैसा जैसे जो तक तब तरह तिन तिन्हें तिन्हों तिस तिसे तो था थी थे दबारा दिया दुसरा दूसरे दो द्वारा न नके नहीं ना निहायत नीचे ने पर पहले पूरा पे फिर बनी बही बहुत बाद बाला बिलकुल भी भीतर मगर मानो मे में यदि यह यहाँ यही या यिह ये रखें रहा रहे ऱ्वासा लिए लिये लेकिन व वग़ैरह वर्ग वह वहाँ वहीं वाले वुह वे वो सकता सकते सबसे सभी साथ साबुत साभ सारा से सो संग ही हुआ हुई हुए है हैं हो होता होती होते होना होने".split(" ")),e.hi.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.hi.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var t=i.toString().toLowerCase().replace(/^\s+/,"");return r.cut(t).split("|")},e.Pipeline.registerFunction(e.hi.stemmer,"stemmer-hi"),e.Pipeline.registerFunction(e.hi.stopWordFilter,"stopWordFilter-hi")}});
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hy=function(){this.pipeline.reset(),this.pipeline.add(e.hy.trimmer,e.hy.stopWordFilter)},e.hy.wordCharacters="[A-Za-z԰-֏ff-ﭏ]",e.hy.trimmer=e.trimmerSupport.generateTrimmer(e.hy.wordCharacters),e.Pipeline.registerFunction(e.hy.trimmer,"trimmer-hy"),e.hy.stopWordFilter=e.generateStopWordFilter("դու և եք էիր էիք հետո նաև նրանք որը վրա է որ պիտի են այս մեջ ն իր ու ի այդ որոնք այն կամ էր մի ես համար այլ իսկ էին ենք հետ ին թ էինք մենք նրա նա դուք եմ էի ըստ որպես ում".split(" ")),e.Pipeline.registerFunction(e.hy.stopWordFilter,"stopWordFilter-hy"),e.hy.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}(),e.Pipeline.registerFunction(e.hy.stemmer,"stemmer-hy")}});
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.ja=function(){this.pipeline.reset(),this.pipeline.add(e.ja.trimmer,e.ja.stopWordFilter,e.ja.stemmer),r?this.tokenizer=e.ja.tokenizer:(e.tokenizer&&(e.tokenizer=e.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.ja.tokenizer))};var t=new e.TinySegmenter;e.ja.tokenizer=function(i){var n,o,s,p,a,u,m,l,c,f;if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t.toLowerCase()):t.toLowerCase()});for(o=i.toString().toLowerCase().replace(/^\s+/,""),n=o.length-1;n>=0;n--)if(/\S/.test(o.charAt(n))){o=o.substring(0,n+1);break}for(a=[],s=o.length,c=0,l=0;c<=s;c++)if(u=o.charAt(c),m=c-l,u.match(/\s/)||c==s){if(m>0)for(p=t.segment(o.slice(l,c)).filter(function(e){return!!e}),f=l,n=0;n<p.length;n++)r?a.push(new e.Token(p[n],{position:[f,p[n].length],index:a.length})):a.push(p[n]),f+=p[n].length;l=c+1}return a},e.ja.stemmer=function(){return function(e){return e}}(),e.Pipeline.registerFunction(e.ja.stemmer,"stemmer-ja"),e.ja.wordCharacters="一二三四五六七八九十百千万億兆一-龠々〆ヵヶぁ-んァ-ヴーア-ン゙a-zA-Za-zA-Z0-90-9",e.ja.trimmer=e.trimmerSupport.generateTrimmer(e.ja.wordCharacters),e.Pipeline.registerFunction(e.ja.trimmer,"trimmer-ja"),e.ja.stopWordFilter=e.generateStopWordFilter("これ それ あれ この その あの ここ そこ あそこ こちら どこ だれ なに なん 何 私 貴方 貴方方 我々 私達 あの人 あのかた 彼女 彼 です あります おります います は が の に を で え から まで より も どの と し それで しかし".split(" ")),e.Pipeline.registerFunction(e.ja.stopWordFilter,"stopWordFilter-ja"),e.jp=e.ja,e.Pipeline.registerFunction(e.jp.stemmer,"stemmer-jp"),e.Pipeline.registerFunction(e.jp.trimmer,"trimmer-jp"),e.Pipeline.registerFunction(e.jp.stopWordFilter,"stopWordFilter-jp")}});
-1
View File
@@ -1 +0,0 @@
module.exports=require("./lunr.ja");
-1
View File
@@ -1 +0,0 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.kn=function(){this.pipeline.reset(),this.pipeline.add(e.kn.trimmer,e.kn.stopWordFilter,e.kn.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.kn.stemmer))},e.kn.wordCharacters="ಀ-಄ಅ-ಔಕ-ಹಾ-ೌ಼-ಽೕ-ೖೝ-ೞೠ-ೡೢ-ೣ೤೥೦-೯ೱ-ೳ",e.kn.trimmer=e.trimmerSupport.generateTrimmer(e.kn.wordCharacters),e.Pipeline.registerFunction(e.kn.trimmer,"trimmer-kn"),e.kn.stopWordFilter=e.generateStopWordFilter("ಮತ್ತು ಈ ಒಂದು ರಲ್ಲಿ ಹಾಗೂ ಎಂದು ಅಥವಾ ಇದು ರ ಅವರು ಎಂಬ ಮೇಲೆ ಅವರ ತನ್ನ ಆದರೆ ತಮ್ಮ ನಂತರ ಮೂಲಕ ಹೆಚ್ಚು ನ ಆ ಕೆಲವು ಅನೇಕ ಎರಡು ಹಾಗು ಪ್ರಮುಖ ಇದನ್ನು ಇದರ ಸುಮಾರು ಅದರ ಅದು ಮೊದಲ ಬಗ್ಗೆ ನಲ್ಲಿ ರಂದು ಇತರ ಅತ್ಯಂತ ಹೆಚ್ಚಿನ ಸಹ ಸಾಮಾನ್ಯವಾಗಿ ನೇ ಹಲವಾರು ಹೊಸ ದಿ ಕಡಿಮೆ ಯಾವುದೇ ಹೊಂದಿದೆ ದೊಡ್ಡ ಅನ್ನು ಇವರು ಪ್ರಕಾರ ಇದೆ ಮಾತ್ರ ಕೂಡ ಇಲ್ಲಿ ಎಲ್ಲಾ ವಿವಿಧ ಅದನ್ನು ಹಲವು ರಿಂದ ಕೇವಲ ದ ದಕ್ಷಿಣ ಗೆ ಅವನ ಅತಿ ನೆಯ ಬಹಳ ಕೆಲಸ ಎಲ್ಲ ಪ್ರತಿ ಇತ್ಯಾದಿ ಇವು ಬೇರೆ ಹೀಗೆ ನಡುವೆ ಇದಕ್ಕೆ ಎಸ್ ಇವರ ಮೊದಲು ಶ್ರೀ ಮಾಡುವ ಇದರಲ್ಲಿ ರೀತಿಯ ಮಾಡಿದ ಕಾಲ ಅಲ್ಲಿ ಮಾಡಲು ಅದೇ ಈಗ ಅವು ಗಳು ಎ ಎಂಬುದು ಅವನು ಅಂದರೆ ಅವರಿಗೆ ಇರುವ ವಿಶೇಷ ಮುಂದೆ ಅವುಗಳ ಮುಂತಾದ ಮೂಲ ಬಿ ಮೀ ಒಂದೇ ಇನ್ನೂ ಹೆಚ್ಚಾಗಿ ಮಾಡಿ ಅವರನ್ನು ಇದೇ ಯ ರೀತಿಯಲ್ಲಿ ಜೊತೆ ಅದರಲ್ಲಿ ಮಾಡಿದರು ನಡೆದ ಆಗ ಮತ್ತೆ ಪೂರ್ವ ಆತ ಬಂದ ಯಾವ ಒಟ್ಟು ಇತರೆ ಹಿಂದೆ ಪ್ರಮಾಣದ ಗಳನ್ನು ಕುರಿತು ಯು ಆದ್ದರಿಂದ ಅಲ್ಲದೆ ನಗರದ ಮೇಲಿನ ಏಕೆಂದರೆ ರಷ್ಟು ಎಂಬುದನ್ನು ಬಾರಿ ಎಂದರೆ ಹಿಂದಿನ ಆದರೂ ಆದ ಸಂಬಂಧಿಸಿದ ಮತ್ತೊಂದು ಸಿ ಆತನ ".split(" ")),e.kn.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.kn.tokenizer=function(t){if(!arguments.length||null==t||void 0==t)return[];if(Array.isArray(t))return t.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var n=t.toString().toLowerCase().replace(/^\s+/,"");return r.cut(n).split("|")},e.Pipeline.registerFunction(e.kn.stemmer,"stemmer-kn"),e.Pipeline.registerFunction(e.kn.stopWordFilter,"stopWordFilter-kn")}});
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){e.multiLanguage=function(){for(var t=Array.prototype.slice.call(arguments),i=t.join("-"),r="",n=[],s=[],p=0;p<t.length;++p)"en"==t[p]?(r+="\\w",n.unshift(e.stopWordFilter),n.push(e.stemmer),s.push(e.stemmer)):(r+=e[t[p]].wordCharacters,e[t[p]].stopWordFilter&&n.unshift(e[t[p]].stopWordFilter),e[t[p]].stemmer&&(n.push(e[t[p]].stemmer),s.push(e[t[p]].stemmer)));var o=e.trimmerSupport.generateTrimmer(r);return e.Pipeline.registerFunction(o,"lunr-multi-trimmer-"+i),n.unshift(o),function(){this.pipeline.reset(),this.pipeline.add.apply(this.pipeline,n),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add.apply(this.searchPipeline,s))}}}});
File diff suppressed because one or more lines are too long
-18
View File
@@ -1,18 +0,0 @@
/*!
* Lunr languages, `Norwegian` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,r=w.cursor+3;if(a=w.limit,0<=r||r<=w.limit){for(s=r;;){if(e=w.cursor,w.in_grouping(d,97,248)){w.cursor=e;break}if(e>=w.limit)return;w.cursor=e+1}for(;!w.out_grouping(d,97,248);){if(w.cursor>=w.limit)return;w.cursor++}a=w.cursor,a<s&&(a=s)}}function i(){var e,r,n;if(w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(m,29),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:n=w.limit-w.cursor,w.in_grouping_b(c,98,122)?w.slice_del():(w.cursor=w.limit-n,w.eq_s_b(1,"k")&&w.out_grouping_b(d,97,248)&&w.slice_del());break;case 3:w.slice_from("er")}}function t(){var e,r=w.limit-w.cursor;w.cursor>=a&&(e=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,w.find_among_b(u,2)?(w.bra=w.cursor,w.limit_backward=e,w.cursor=w.limit-r,w.cursor>w.limit_backward&&(w.cursor--,w.bra=w.cursor,w.slice_del())):w.limit_backward=e)}function o(){var e,r;w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(l,11),e?(w.bra=w.cursor,w.limit_backward=r,1==e&&w.slice_del()):w.limit_backward=r)}var s,a,m=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],u=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],c=[119,125,149,1],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,i(),w.cursor=w.limit,t(),w.cursor=w.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}});
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sa=function(){this.pipeline.reset(),this.pipeline.add(e.sa.trimmer,e.sa.stopWordFilter,e.sa.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sa.stemmer))},e.sa.wordCharacters="ऀ-ःऄ-एऐ-टठ-यर-िी-ॏॐ-य़ॠ-९॰-ॿ꣠-꣱ꣲ-ꣷ꣸-ꣻ꣼-ꣽꣾ-ꣿᆰ0-ᆰ9",e.sa.trimmer=e.trimmerSupport.generateTrimmer(e.sa.wordCharacters),e.Pipeline.registerFunction(e.sa.trimmer,"trimmer-sa"),e.sa.stopWordFilter=e.generateStopWordFilter('तथा अयम्‌ एकम्‌ इत्यस्मिन्‌ तथा तत्‌ वा अयम्‌ इत्यस्य ते आहूत उपरि तेषाम्‌ किन्तु तेषाम्‌ तदा इत्यनेन अधिकः इत्यस्य तत्‌ केचन बहवः द्वि तथा महत्वपूर्णः अयम्‌ अस्य विषये अयं अस्ति तत्‌ प्रथमः विषये इत्युपरि इत्युपरि इतर अधिकतमः अधिकः अपि सामान्यतया ठ इतरेतर नूतनम्‌ द न्यूनम्‌ कश्चित्‌ वा विशालः द सः अस्ति तदनुसारम् तत्र अस्ति केवलम्‌ अपि अत्र सर्वे विविधाः तत्‌ बहवः यतः इदानीम्‌ द दक्षिण इत्यस्मै तस्य उपरि नथ अतीव कार्यम्‌ सर्वे एकैकम्‌ इत्यादि। एते सन्ति उत इत्थम्‌ मध्ये एतदर्थं . स कस्य प्रथमः श्री. करोति अस्मिन् प्रकारः निर्मिता कालः तत्र कर्तुं समान अधुना ते सन्ति स एकः अस्ति सः अर्थात् तेषां कृते . स्थितम् विशेषः अग्रिम तेषाम्‌ समान स्रोतः ख म समान इदानीमपि अधिकतया करोतु ते समान इत्यस्य वीथी सह यस्मिन् कृतवान्‌ धृतः तदा पुनः पूर्वं सः आगतः किम्‌ कुल इतर पुरा मात्रा स विषये उ अतएव अपि नगरस्य उपरि यतः प्रतिशतं कतरः कालः साधनानि भूत तथापि जात सम्बन्धि अन्यत्‌ ग अतः अस्माकं स्वकीयाः अस्माकं इदानीं अन्तः इत्यादयः भवन्तः इत्यादयः एते एताः तस्य अस्य इदम् एते तेषां तेषां तेषां तान् तेषां तेषां तेषां समानः सः एकः च तादृशाः बहवः अन्ये च वदन्ति यत् कियत् कस्मै कस्मै यस्मै यस्मै यस्मै यस्मै न अतिनीचः किन्तु प्रथमं सम्पूर्णतया ततः चिरकालानन्तरं पुस्तकं सम्पूर्णतया अन्तः किन्तु अत्र वा इह इव श्रद्धाय अवशिष्यते परन्तु अन्ये वर्गाः सन्ति ते सन्ति शक्नुवन्ति सर्वे मिलित्वा सर्वे एकत्र"'.split(" ")),e.sa.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.sa.tokenizer=function(t){if(!arguments.length||null==t||void 0==t)return[];if(Array.isArray(t))return t.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var i=t.toString().toLowerCase().replace(/^\s+/,"");return r.cut(i).split("|")},e.Pipeline.registerFunction(e.sa.stemmer,"stemmer-sa"),e.Pipeline.registerFunction(e.sa.stopWordFilter,"stopWordFilter-sa")}});
@@ -1 +0,0 @@
!function(r,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(r.lunr)}(this,function(){return function(r){r.stemmerSupport={Among:function(r,t,i,s){if(this.toCharArray=function(r){for(var t=r.length,i=new Array(t),s=0;s<t;s++)i[s]=r.charCodeAt(s);return i},!r&&""!=r||!t&&0!=t||!i)throw"Bad Among initialisation: s:"+r+", substring_i: "+t+", result: "+i;this.s_size=r.length,this.s=this.toCharArray(r),this.substring_i=t,this.result=i,this.method=s},SnowballProgram:function(){var r;return{bra:0,ket:0,limit:0,cursor:0,limit_backward:0,setCurrent:function(t){r=t,this.cursor=0,this.limit=t.length,this.limit_backward=0,this.bra=this.cursor,this.ket=this.limit},getCurrent:function(){var t=r;return r=null,t},in_grouping:function(t,i,s){if(this.cursor<this.limit){var e=r.charCodeAt(this.cursor);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},in_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},out_grouping:function(t,i,s){if(this.cursor<this.limit){var e=r.charCodeAt(this.cursor);if(e>s||e<i)return this.cursor++,!0;if(e-=i,!(t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},out_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e>s||e<i)return this.cursor--,!0;if(e-=i,!(t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},eq_s:function(t,i){if(this.limit-this.cursor<t)return!1;for(var s=0;s<t;s++)if(r.charCodeAt(this.cursor+s)!=i.charCodeAt(s))return!1;return this.cursor+=t,!0},eq_s_b:function(t,i){if(this.cursor-this.limit_backward<t)return!1;for(var s=0;s<t;s++)if(r.charCodeAt(this.cursor-t+s)!=i.charCodeAt(s))return!1;return this.cursor-=t,!0},find_among:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o<h?o:h,_=t[a],m=l;m<_.s_size;m++){if(n+l==u){f=-1;break}if(f=r.charCodeAt(n+l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n+_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n+_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},find_among_b:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit_backward,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o<h?o:h,_=t[a],m=_.s_size-1-l;m>=0;m--){if(n-l==u){f=-1;break}if(f=r.charCodeAt(n-1-l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n-_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n-_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},replace_s:function(t,i,s){var e=s.length-(i-t),n=r.substring(0,t),u=r.substring(i);return r=n+s+u,this.limit+=e,this.cursor>=i?this.cursor+=e:this.cursor>t&&(this.cursor=t),e},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>r.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),r.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}});
-18
View File
@@ -1,18 +0,0 @@
/*!
* Lunr languages, `Swedish` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){function e(){var e,r=w.cursor+3;if(o=w.limit,0<=r||r<=w.limit){for(a=r;;){if(e=w.cursor,w.in_grouping(l,97,246)){w.cursor=e;break}if(w.cursor=e,w.cursor>=w.limit)return;w.cursor++}for(;!w.out_grouping(l,97,246);){if(w.cursor>=w.limit)return;w.cursor++}o=w.cursor,o<a&&(o=a)}}function t(){var e,r=w.limit_backward;if(w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(u,37),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.in_grouping_b(d,98,121)&&w.slice_del()}}function i(){var e=w.limit_backward;w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.find_among_b(c,7)&&(w.cursor=w.limit,w.ket=w.cursor,w.cursor>w.limit_backward&&(w.bra=--w.cursor,w.slice_del())),w.limit_backward=e)}function s(){var e,r;if(w.cursor>=o){if(r=w.limit_backward,w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(m,5))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.slice_from("lös");break;case 3:w.slice_from("full")}w.limit_backward=r}}var a,o,u=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],c=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],l=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],d=[119,127,149],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,t(),w.cursor=w.limit,i(),w.cursor=w.limit,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}}(),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}});
-1
View File
@@ -1 +0,0 @@
!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ta=function(){this.pipeline.reset(),this.pipeline.add(e.ta.trimmer,e.ta.stopWordFilter,e.ta.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ta.stemmer))},e.ta.wordCharacters="஀-உஊ-ஏஐ-ஙச-ட஠-னப-யர-ஹ஺-ிீ-௉ொ-௏ௐ-௙௚-௟௠-௩௪-௯௰-௹௺-௿a-zA-Za-zA-Z0-90-9",e.ta.trimmer=e.trimmerSupport.generateTrimmer(e.ta.wordCharacters),e.Pipeline.registerFunction(e.ta.trimmer,"trimmer-ta"),e.ta.stopWordFilter=e.generateStopWordFilter("அங்கு அங்கே அது அதை அந்த அவர் அவர்கள் அவள் அவன் அவை ஆக ஆகவே ஆகையால் ஆதலால் ஆதலினால் ஆனாலும் ஆனால் இங்கு இங்கே இது இதை இந்த இப்படி இவர் இவர்கள் இவள் இவன் இவை இவ்வளவு உனக்கு உனது உன் உன்னால் எங்கு எங்கே எது எதை எந்த எப்படி எவர் எவர்கள் எவள் எவன் எவை எவ்வளவு எனக்கு எனது எனவே என் என்ன என்னால் ஏது ஏன் தனது தன்னால் தானே தான் நாங்கள் நாம் நான் நீ நீங்கள்".split(" ")),e.ta.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var t=e.wordcut;t.init(),e.ta.tokenizer=function(r){if(!arguments.length||null==r||void 0==r)return[];if(Array.isArray(r))return r.map(function(t){return isLunr2?new e.Token(t.toLowerCase()):t.toLowerCase()});var i=r.toString().toLowerCase().replace(/^\s+/,"");return t.cut(i).split("|")},e.Pipeline.registerFunction(e.ta.stemmer,"stemmer-ta"),e.Pipeline.registerFunction(e.ta.stopWordFilter,"stopWordFilter-ta")}});
-1
View File
@@ -1 +0,0 @@
!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.te=function(){this.pipeline.reset(),this.pipeline.add(e.te.trimmer,e.te.stopWordFilter,e.te.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.te.stemmer))},e.te.wordCharacters="ఀ-ఄఅ-ఔక-హా-ౌౕ-ౖౘ-ౚౠ-ౡౢ-ౣ౦-౯౸-౿఼ఽ్ౝ౷౤౥",e.te.trimmer=e.trimmerSupport.generateTrimmer(e.te.wordCharacters),e.Pipeline.registerFunction(e.te.trimmer,"trimmer-te"),e.te.stopWordFilter=e.generateStopWordFilter("అందరూ అందుబాటులో అడగండి అడగడం అడ్డంగా అనుగుణంగా అనుమతించు అనుమతిస్తుంది అయితే ఇప్పటికే ఉన్నారు ఎక్కడైనా ఎప్పుడు ఎవరైనా ఎవరో ఏ ఏదైనా ఏమైనప్పటికి ఒక ఒకరు కనిపిస్తాయి కాదు కూడా గా గురించి చుట్టూ చేయగలిగింది తగిన తర్వాత దాదాపు దూరంగా నిజంగా పై ప్రకారం ప్రక్కన మధ్య మరియు మరొక మళ్ళీ మాత్రమే మెచ్చుకో వద్ద వెంట వేరుగా వ్యతిరేకంగా సంబంధం".split(" ")),e.te.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var t=e.wordcut;t.init(),e.te.tokenizer=function(r){if(!arguments.length||null==r||void 0==r)return[];if(Array.isArray(r))return r.map(function(t){return isLunr2?new e.Token(t.toLowerCase()):t.toLowerCase()});var i=r.toString().toLowerCase().replace(/^\s+/,"");return t.cut(i).split("|")},e.Pipeline.registerFunction(e.te.stemmer,"stemmer-te"),e.Pipeline.registerFunction(e.te.stopWordFilter,"stopWordFilter-te")}});
-1
View File
@@ -1 +0,0 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.th=function(){this.pipeline.reset(),this.pipeline.add(e.th.trimmer),r?this.tokenizer=e.th.tokenizer:(e.tokenizer&&(e.tokenizer=e.th.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.th.tokenizer))},e.th.wordCharacters="[฀-๿]",e.th.trimmer=e.trimmerSupport.generateTrimmer(e.th.wordCharacters),e.Pipeline.registerFunction(e.th.trimmer,"trimmer-th");var t=e.wordcut;t.init(),e.th.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t):t});var n=i.toString().replace(/^\s+/,"");return t.cut(n).split("|")}}});
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.vi=function(){this.pipeline.reset(),this.pipeline.add(e.vi.stopWordFilter,e.vi.trimmer)},e.vi.wordCharacters="[A-Za-ẓ̀͐́͑̉̃̓ÂâÊêÔôĂ-ăĐ-đƠ-ơƯ-ư]",e.vi.trimmer=e.trimmerSupport.generateTrimmer(e.vi.wordCharacters),e.Pipeline.registerFunction(e.vi.trimmer,"trimmer-vi"),e.vi.stopWordFilter=e.generateStopWordFilter("là cái nhưng mà".split(" "))}});
-1
View File
@@ -1 +0,0 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r(require("@node-rs/jieba")):r()(e.lunr)}(this,function(e){return function(r,t){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var i="2"==r.version[0];r.zh=function(){this.pipeline.reset(),this.pipeline.add(r.zh.trimmer,r.zh.stopWordFilter,r.zh.stemmer),i?this.tokenizer=r.zh.tokenizer:(r.tokenizer&&(r.tokenizer=r.zh.tokenizer),this.tokenizerFn&&(this.tokenizerFn=r.zh.tokenizer))},r.zh.tokenizer=function(n){if(!arguments.length||null==n||void 0==n)return[];if(Array.isArray(n))return n.map(function(e){return i?new r.Token(e.toLowerCase()):e.toLowerCase()});t&&e.load(t);var o=n.toString().trim().toLowerCase(),s=[];e.cut(o,!0).forEach(function(e){s=s.concat(e.split(" "))}),s=s.filter(function(e){return!!e});var u=0;return s.map(function(e,t){if(i){var n=o.indexOf(e,u),s={};return s.position=[n,e.length],s.index=t,u=n,new r.Token(e,s)}return e})},r.zh.wordCharacters="\\w一-龥",r.zh.trimmer=r.trimmerSupport.generateTrimmer(r.zh.wordCharacters),r.Pipeline.registerFunction(r.zh.trimmer,"trimmer-zh"),r.zh.stemmer=function(){return function(e){return e}}(),r.Pipeline.registerFunction(r.zh.stemmer,"stemmer-zh"),r.zh.stopWordFilter=r.generateStopWordFilter("的 一 不 在 人 有 是 为 為 以 于 於 上 他 而 后 後 之 来 來 及 了 因 下 可 到 由 这 這 与 與 也 此 但 并 並 个 個 其 已 无 無 小 我 们 們 起 最 再 今 去 好 只 又 或 很 亦 某 把 那 你 乃 它 吧 被 比 别 趁 当 當 从 從 得 打 凡 儿 兒 尔 爾 该 該 各 给 給 跟 和 何 还 還 即 几 幾 既 看 据 據 距 靠 啦 另 么 麽 每 嘛 拿 哪 您 凭 憑 且 却 卻 让 讓 仍 啥 如 若 使 谁 誰 虽 雖 随 隨 同 所 她 哇 嗡 往 些 向 沿 哟 喲 用 咱 则 則 怎 曾 至 致 着 著 诸 諸 自".split(" ")),r.Pipeline.registerFunction(r.zh.stopWordFilter,"stopWordFilter-zh")}});
-206
View File
@@ -1,206 +0,0 @@
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function () {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
// TinySegmenter 0.1 -- Super compact Japanese tokenizer in Javascript
// (c) 2008 Taku Kudo <taku@chasen.org>
// TinySegmenter is freely distributable under the terms of a new BSD licence.
// For details, see http://chasen.org/~taku/software/TinySegmenter/LICENCE.txt
function TinySegmenter() {
var patterns = {
"[一二三四五六七八九十百千万億兆]":"M",
"[一-龠々〆ヵヶ]":"H",
"[ぁ-ん]":"I",
"[ァ-ヴーア-ン゙ー]":"K",
"[a-zA-Za-zA-Z]":"A",
"[0-90-9]":"N"
}
this.chartype_ = [];
for (var i in patterns) {
var regexp = new RegExp(i);
this.chartype_.push([regexp, patterns[i]]);
}
this.BIAS__ = -332
this.BC1__ = {"HH":6,"II":2461,"KH":406,"OH":-1378};
this.BC2__ = {"AA":-3267,"AI":2744,"AN":-878,"HH":-4070,"HM":-1711,"HN":4012,"HO":3761,"IA":1327,"IH":-1184,"II":-1332,"IK":1721,"IO":5492,"KI":3831,"KK":-8741,"MH":-3132,"MK":3334,"OO":-2920};
this.BC3__ = {"HH":996,"HI":626,"HK":-721,"HN":-1307,"HO":-836,"IH":-301,"KK":2762,"MK":1079,"MM":4034,"OA":-1652,"OH":266};
this.BP1__ = {"BB":295,"OB":304,"OO":-125,"UB":352};
this.BP2__ = {"BO":60,"OO":-1762};
this.BQ1__ = {"BHH":1150,"BHM":1521,"BII":-1158,"BIM":886,"BMH":1208,"BNH":449,"BOH":-91,"BOO":-2597,"OHI":451,"OIH":-296,"OKA":1851,"OKH":-1020,"OKK":904,"OOO":2965};
this.BQ2__ = {"BHH":118,"BHI":-1159,"BHM":466,"BIH":-919,"BKK":-1720,"BKO":864,"OHH":-1139,"OHM":-181,"OIH":153,"UHI":-1146};
this.BQ3__ = {"BHH":-792,"BHI":2664,"BII":-299,"BKI":419,"BMH":937,"BMM":8335,"BNN":998,"BOH":775,"OHH":2174,"OHM":439,"OII":280,"OKH":1798,"OKI":-793,"OKO":-2242,"OMH":-2402,"OOO":11699};
this.BQ4__ = {"BHH":-3895,"BIH":3761,"BII":-4654,"BIK":1348,"BKK":-1806,"BMI":-3385,"BOO":-12396,"OAH":926,"OHH":266,"OHK":-2036,"ONN":-973};
this.BW1__ = {",と":660,",同":727,"B1あ":1404,"B1同":542,"、と":660,"、同":727,"」と":1682,"あっ":1505,"いう":1743,"いっ":-2055,"いる":672,"うし":-4817,"うん":665,"から":3472,"がら":600,"こう":-790,"こと":2083,"こん":-1262,"さら":-4143,"さん":4573,"した":2641,"して":1104,"すで":-3399,"そこ":1977,"それ":-871,"たち":1122,"ため":601,"った":3463,"つい":-802,"てい":805,"てき":1249,"でき":1127,"です":3445,"では":844,"とい":-4915,"とみ":1922,"どこ":3887,"ない":5713,"なっ":3015,"など":7379,"なん":-1113,"にし":2468,"には":1498,"にも":1671,"に対":-912,"の一":-501,"の中":741,"ませ":2448,"まで":1711,"まま":2600,"まる":-2155,"やむ":-1947,"よっ":-2565,"れた":2369,"れで":-913,"をし":1860,"を見":731,"亡く":-1886,"京都":2558,"取り":-2784,"大き":-2604,"大阪":1497,"平方":-2314,"引き":-1336,"日本":-195,"本当":-2423,"毎日":-2113,"目指":-724,"B1あ":1404,"B1同":542,"」と":1682};
this.BW2__ = {"..":-11822,"11":-669,"――":-5730,"−−":-13175,"いう":-1609,"うか":2490,"かし":-1350,"かも":-602,"から":-7194,"かれ":4612,"がい":853,"がら":-3198,"きた":1941,"くな":-1597,"こと":-8392,"この":-4193,"させ":4533,"され":13168,"さん":-3977,"しい":-1819,"しか":-545,"した":5078,"して":972,"しな":939,"その":-3744,"たい":-1253,"たた":-662,"ただ":-3857,"たち":-786,"たと":1224,"たは":-939,"った":4589,"って":1647,"っと":-2094,"てい":6144,"てき":3640,"てく":2551,"ては":-3110,"ても":-3065,"でい":2666,"でき":-1528,"でし":-3828,"です":-4761,"でも":-4203,"とい":1890,"とこ":-1746,"とと":-2279,"との":720,"とみ":5168,"とも":-3941,"ない":-2488,"なが":-1313,"など":-6509,"なの":2614,"なん":3099,"にお":-1615,"にし":2748,"にな":2454,"によ":-7236,"に対":-14943,"に従":-4688,"に関":-11388,"のか":2093,"ので":-7059,"のに":-6041,"のの":-6125,"はい":1073,"はが":-1033,"はず":-2532,"ばれ":1813,"まし":-1316,"まで":-6621,"まれ":5409,"めて":-3153,"もい":2230,"もの":-10713,"らか":-944,"らし":-1611,"らに":-1897,"りし":651,"りま":1620,"れた":4270,"れて":849,"れば":4114,"ろう":6067,"われ":7901,"を通":-11877,"んだ":728,"んな":-4115,"一人":602,"一方":-1375,"一日":970,"一部":-1051,"上が":-4479,"会社":-1116,"出て":2163,"分の":-7758,"同党":970,"同日":-913,"大阪":-2471,"委員":-1250,"少な":-1050,"年度":-8669,"年間":-1626,"府県":-2363,"手権":-1982,"新聞":-4066,"日新":-722,"日本":-7068,"日米":3372,"曜日":-601,"朝鮮":-2355,"本人":-2697,"東京":-1543,"然と":-1384,"社会":-1276,"立て":-990,"第に":-1612,"米国":-4268,"11":-669};
this.BW3__ = {"あた":-2194,"あり":719,"ある":3846,"い.":-1185,"い。":-1185,"いい":5308,"いえ":2079,"いく":3029,"いた":2056,"いっ":1883,"いる":5600,"いわ":1527,"うち":1117,"うと":4798,"えと":1454,"か.":2857,"か。":2857,"かけ":-743,"かっ":-4098,"かに":-669,"から":6520,"かり":-2670,"が,":1816,"が、":1816,"がき":-4855,"がけ":-1127,"がっ":-913,"がら":-4977,"がり":-2064,"きた":1645,"けど":1374,"こと":7397,"この":1542,"ころ":-2757,"さい":-714,"さを":976,"し,":1557,"し、":1557,"しい":-3714,"した":3562,"して":1449,"しな":2608,"しま":1200,"す.":-1310,"す。":-1310,"する":6521,"ず,":3426,"ず、":3426,"ずに":841,"そう":428,"た.":8875,"た。":8875,"たい":-594,"たの":812,"たり":-1183,"たる":-853,"だ.":4098,"だ。":4098,"だっ":1004,"った":-4748,"って":300,"てい":6240,"てお":855,"ても":302,"です":1437,"でに":-1482,"では":2295,"とう":-1387,"とし":2266,"との":541,"とも":-3543,"どう":4664,"ない":1796,"なく":-903,"など":2135,"に,":-1021,"に、":-1021,"にし":1771,"にな":1906,"には":2644,"の,":-724,"の、":-724,"の子":-1000,"は,":1337,"は、":1337,"べき":2181,"まし":1113,"ます":6943,"まっ":-1549,"まで":6154,"まれ":-793,"らし":1479,"られ":6820,"るる":3818,"れ,":854,"れ、":854,"れた":1850,"れて":1375,"れば":-3246,"れる":1091,"われ":-605,"んだ":606,"んで":798,"カ月":990,"会議":860,"入り":1232,"大会":2217,"始め":1681,"市":965,"新聞":-5055,"日,":974,"日、":974,"社会":2024,"カ月":990};
this.TC1__ = {"AAA":1093,"HHH":1029,"HHM":580,"HII":998,"HOH":-390,"HOM":-331,"IHI":1169,"IOH":-142,"IOI":-1015,"IOM":467,"MMH":187,"OOI":-1832};
this.TC2__ = {"HHO":2088,"HII":-1023,"HMM":-1154,"IHI":-1965,"KKH":703,"OII":-2649};
this.TC3__ = {"AAA":-294,"HHH":346,"HHI":-341,"HII":-1088,"HIK":731,"HOH":-1486,"IHH":128,"IHI":-3041,"IHO":-1935,"IIH":-825,"IIM":-1035,"IOI":-542,"KHH":-1216,"KKA":491,"KKH":-1217,"KOK":-1009,"MHH":-2694,"MHM":-457,"MHO":123,"MMH":-471,"NNH":-1689,"NNO":662,"OHO":-3393};
this.TC4__ = {"HHH":-203,"HHI":1344,"HHK":365,"HHM":-122,"HHN":182,"HHO":669,"HIH":804,"HII":679,"HOH":446,"IHH":695,"IHO":-2324,"IIH":321,"III":1497,"IIO":656,"IOO":54,"KAK":4845,"KKA":3386,"KKK":3065,"MHH":-405,"MHI":201,"MMH":-241,"MMM":661,"MOM":841};
this.TQ1__ = {"BHHH":-227,"BHHI":316,"BHIH":-132,"BIHH":60,"BIII":1595,"BNHH":-744,"BOHH":225,"BOOO":-908,"OAKK":482,"OHHH":281,"OHIH":249,"OIHI":200,"OIIH":-68};
this.TQ2__ = {"BIHH":-1401,"BIII":-1033,"BKAK":-543,"BOOO":-5591};
this.TQ3__ = {"BHHH":478,"BHHM":-1073,"BHIH":222,"BHII":-504,"BIIH":-116,"BIII":-105,"BMHI":-863,"BMHM":-464,"BOMH":620,"OHHH":346,"OHHI":1729,"OHII":997,"OHMH":481,"OIHH":623,"OIIH":1344,"OKAK":2792,"OKHH":587,"OKKA":679,"OOHH":110,"OOII":-685};
this.TQ4__ = {"BHHH":-721,"BHHM":-3604,"BHII":-966,"BIIH":-607,"BIII":-2181,"OAAA":-2763,"OAKK":180,"OHHH":-294,"OHHI":2446,"OHHO":480,"OHIH":-1573,"OIHH":1935,"OIHI":-493,"OIIH":626,"OIII":-4007,"OKAK":-8156};
this.TW1__ = {"につい":-4681,"東京都":2026};
this.TW2__ = {"ある程":-2049,"いった":-1256,"ころが":-2434,"しょう":3873,"その後":-4430,"だって":-1049,"ていた":1833,"として":-4657,"ともに":-4517,"もので":1882,"一気に":-792,"初めて":-1512,"同時に":-8097,"大きな":-1255,"対して":-2721,"社会党":-3216};
this.TW3__ = {"いただ":-1734,"してい":1314,"として":-4314,"につい":-5483,"にとっ":-5989,"に当た":-6247,"ので,":-727,"ので、":-727,"のもの":-600,"れから":-3752,"十二月":-2287};
this.TW4__ = {"いう.":8576,"いう。":8576,"からな":-2348,"してい":2958,"たが,":1516,"たが、":1516,"ている":1538,"という":1349,"ました":5543,"ません":1097,"ようと":-4258,"よると":5865};
this.UC1__ = {"A":484,"K":93,"M":645,"O":-505};
this.UC2__ = {"A":819,"H":1059,"I":409,"M":3987,"N":5775,"O":646};
this.UC3__ = {"A":-1370,"I":2311};
this.UC4__ = {"A":-2643,"H":1809,"I":-1032,"K":-3450,"M":3565,"N":3876,"O":6646};
this.UC5__ = {"H":313,"I":-1238,"K":-799,"M":539,"O":-831};
this.UC6__ = {"H":-506,"I":-253,"K":87,"M":247,"O":-387};
this.UP1__ = {"O":-214};
this.UP2__ = {"B":69,"O":935};
this.UP3__ = {"B":189};
this.UQ1__ = {"BH":21,"BI":-12,"BK":-99,"BN":142,"BO":-56,"OH":-95,"OI":477,"OK":410,"OO":-2422};
this.UQ2__ = {"BH":216,"BI":113,"OK":1759};
this.UQ3__ = {"BA":-479,"BH":42,"BI":1913,"BK":-7198,"BM":3160,"BN":6427,"BO":14761,"OI":-827,"ON":-3212};
this.UW1__ = {",":156,"、":156,"「":-463,"あ":-941,"う":-127,"が":-553,"き":121,"こ":505,"で":-201,"と":-547,"ど":-123,"に":-789,"の":-185,"は":-847,"も":-466,"や":-470,"よ":182,"ら":-292,"り":208,"れ":169,"を":-446,"ん":-137,"・":-135,"主":-402,"京":-268,"区":-912,"午":871,"国":-460,"大":561,"委":729,"市":-411,"日":-141,"理":361,"生":-408,"県":-386,"都":-718,"「":-463,"・":-135};
this.UW2__ = {",":-829,"、":-829,"〇":892,"「":-645,"」":3145,"あ":-538,"い":505,"う":134,"お":-502,"か":1454,"が":-856,"く":-412,"こ":1141,"さ":878,"ざ":540,"し":1529,"す":-675,"せ":300,"そ":-1011,"た":188,"だ":1837,"つ":-949,"て":-291,"で":-268,"と":-981,"ど":1273,"な":1063,"に":-1764,"の":130,"は":-409,"ひ":-1273,"べ":1261,"ま":600,"も":-1263,"や":-402,"よ":1639,"り":-579,"る":-694,"れ":571,"を":-2516,"ん":2095,"ア":-587,"カ":306,"キ":568,"ッ":831,"三":-758,"不":-2150,"世":-302,"中":-968,"主":-861,"事":492,"人":-123,"会":978,"保":362,"入":548,"初":-3025,"副":-1566,"北":-3414,"区":-422,"大":-1769,"天":-865,"太":-483,"子":-1519,"学":760,"実":1023,"小":-2009,"市":-813,"年":-1060,"強":1067,"手":-1519,"揺":-1033,"政":1522,"文":-1355,"新":-1682,"日":-1815,"明":-1462,"最":-630,"朝":-1843,"本":-1650,"東":-931,"果":-665,"次":-2378,"民":-180,"気":-1740,"理":752,"発":529,"目":-1584,"相":-242,"県":-1165,"立":-763,"第":810,"米":509,"自":-1353,"行":838,"西":-744,"見":-3874,"調":1010,"議":1198,"込":3041,"開":1758,"間":-1257,"「":-645,"」":3145,"ッ":831,"ア":-587,"カ":306,"キ":568};
this.UW3__ = {",":4889,"1":-800,"−":-1723,"、":4889,"々":-2311,"〇":5827,"」":2670,"〓":-3573,"あ":-2696,"い":1006,"う":2342,"え":1983,"お":-4864,"か":-1163,"が":3271,"く":1004,"け":388,"げ":401,"こ":-3552,"ご":-3116,"さ":-1058,"し":-395,"す":584,"せ":3685,"そ":-5228,"た":842,"ち":-521,"っ":-1444,"つ":-1081,"て":6167,"で":2318,"と":1691,"ど":-899,"な":-2788,"に":2745,"の":4056,"は":4555,"ひ":-2171,"ふ":-1798,"へ":1199,"ほ":-5516,"ま":-4384,"み":-120,"め":1205,"も":2323,"や":-788,"よ":-202,"ら":727,"り":649,"る":5905,"れ":2773,"わ":-1207,"を":6620,"ん":-518,"ア":551,"グ":1319,"ス":874,"ッ":-1350,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278,"・":-3794,"一":-1619,"下":-1759,"世":-2087,"両":3815,"中":653,"主":-758,"予":-1193,"二":974,"人":2742,"今":792,"他":1889,"以":-1368,"低":811,"何":4265,"作":-361,"保":-2439,"元":4858,"党":3593,"全":1574,"公":-3030,"六":755,"共":-1880,"円":5807,"再":3095,"分":457,"初":2475,"別":1129,"前":2286,"副":4437,"力":365,"動":-949,"務":-1872,"化":1327,"北":-1038,"区":4646,"千":-2309,"午":-783,"協":-1006,"口":483,"右":1233,"各":3588,"合":-241,"同":3906,"和":-837,"員":4513,"国":642,"型":1389,"場":1219,"外":-241,"妻":2016,"学":-1356,"安":-423,"実":-1008,"家":1078,"小":-513,"少":-3102,"州":1155,"市":3197,"平":-1804,"年":2416,"広":-1030,"府":1605,"度":1452,"建":-2352,"当":-3885,"得":1905,"思":-1291,"性":1822,"戸":-488,"指":-3973,"政":-2013,"教":-1479,"数":3222,"文":-1489,"新":1764,"日":2099,"旧":5792,"昨":-661,"時":-1248,"曜":-951,"最":-937,"月":4125,"期":360,"李":3094,"村":364,"東":-805,"核":5156,"森":2438,"業":484,"氏":2613,"民":-1694,"決":-1073,"法":1868,"海":-495,"無":979,"物":461,"特":-3850,"生":-273,"用":914,"町":1215,"的":7313,"直":-1835,"省":792,"県":6293,"知":-1528,"私":4231,"税":401,"立":-960,"第":1201,"米":7767,"系":3066,"約":3663,"級":1384,"統":-4229,"総":1163,"線":1255,"者":6457,"能":725,"自":-2869,"英":785,"見":1044,"調":-562,"財":-733,"費":1777,"車":1835,"軍":1375,"込":-1504,"通":-1136,"選":-681,"郎":1026,"郡":4404,"部":1200,"金":2163,"長":421,"開":-1432,"間":1302,"関":-1282,"雨":2009,"電":-1045,"非":2066,"駅":1620,"1":-800,"」":2670,"・":-3794,"ッ":-1350,"ア":551,"グ":1319,"ス":874,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278};
this.UW4__ = {",":3930,".":3508,"―":-4841,"、":3930,"。":3508,"〇":4999,"「":1895,"」":3798,"〓":-5156,"あ":4752,"い":-3435,"う":-640,"え":-2514,"お":2405,"か":530,"が":6006,"き":-4482,"ぎ":-3821,"く":-3788,"け":-4376,"げ":-4734,"こ":2255,"ご":1979,"さ":2864,"し":-843,"じ":-2506,"す":-731,"ず":1251,"せ":181,"そ":4091,"た":5034,"だ":5408,"ち":-3654,"っ":-5882,"つ":-1659,"て":3994,"で":7410,"と":4547,"な":5433,"に":6499,"ぬ":1853,"ね":1413,"の":7396,"は":8578,"ば":1940,"ひ":4249,"び":-4134,"ふ":1345,"へ":6665,"べ":-744,"ほ":1464,"ま":1051,"み":-2082,"む":-882,"め":-5046,"も":4169,"ゃ":-2666,"や":2795,"ょ":-1544,"よ":3351,"ら":-2922,"り":-9726,"る":-14896,"れ":-2613,"ろ":-4570,"わ":-1783,"を":13150,"ん":-2352,"カ":2145,"コ":1789,"セ":1287,"ッ":-724,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637,"・":-4371,"ー":-11870,"一":-2069,"中":2210,"予":782,"事":-190,"井":-1768,"人":1036,"以":544,"会":950,"体":-1286,"作":530,"側":4292,"先":601,"党":-2006,"共":-1212,"内":584,"円":788,"初":1347,"前":1623,"副":3879,"力":-302,"動":-740,"務":-2715,"化":776,"区":4517,"協":1013,"参":1555,"合":-1834,"和":-681,"員":-910,"器":-851,"回":1500,"国":-619,"園":-1200,"地":866,"場":-1410,"塁":-2094,"士":-1413,"多":1067,"大":571,"子":-4802,"学":-1397,"定":-1057,"寺":-809,"小":1910,"屋":-1328,"山":-1500,"島":-2056,"川":-2667,"市":2771,"年":374,"庁":-4556,"後":456,"性":553,"感":916,"所":-1566,"支":856,"改":787,"政":2182,"教":704,"文":522,"方":-856,"日":1798,"時":1829,"最":845,"月":-9066,"木":-485,"来":-442,"校":-360,"業":-1043,"氏":5388,"民":-2716,"気":-910,"沢":-939,"済":-543,"物":-735,"率":672,"球":-1267,"生":-1286,"産":-1101,"田":-2900,"町":1826,"的":2586,"目":922,"省":-3485,"県":2997,"空":-867,"立":-2112,"第":788,"米":2937,"系":786,"約":2171,"経":1146,"統":-1169,"総":940,"線":-994,"署":749,"者":2145,"能":-730,"般":-852,"行":-792,"規":792,"警":-1184,"議":-244,"谷":-1000,"賞":730,"車":-1481,"軍":1158,"輪":-1433,"込":-3370,"近":929,"道":-1291,"選":2596,"郎":-4866,"都":1192,"野":-1100,"銀":-2213,"長":357,"間":-2344,"院":-2297,"際":-2604,"電":-878,"領":-1659,"題":-792,"館":-1984,"首":1749,"高":2120,"「":1895,"」":3798,"・":-4371,"ッ":-724,"ー":-11870,"カ":2145,"コ":1789,"セ":1287,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637};
this.UW5__ = {",":465,".":-299,"1":-514,"E2":-32768,"]":-2762,"、":465,"。":-299,"「":363,"あ":1655,"い":331,"う":-503,"え":1199,"お":527,"か":647,"が":-421,"き":1624,"ぎ":1971,"く":312,"げ":-983,"さ":-1537,"し":-1371,"す":-852,"だ":-1186,"ち":1093,"っ":52,"つ":921,"て":-18,"で":-850,"と":-127,"ど":1682,"な":-787,"に":-1224,"の":-635,"は":-578,"べ":1001,"み":502,"め":865,"ゃ":3350,"ょ":854,"り":-208,"る":429,"れ":504,"わ":419,"を":-1264,"ん":327,"イ":241,"ル":451,"ン":-343,"中":-871,"京":722,"会":-1153,"党":-654,"務":3519,"区":-901,"告":848,"員":2104,"大":-1296,"学":-548,"定":1785,"嵐":-1304,"市":-2991,"席":921,"年":1763,"思":872,"所":-814,"挙":1618,"新":-1682,"日":218,"月":-4353,"査":932,"格":1356,"機":-1508,"氏":-1347,"田":240,"町":-3912,"的":-3149,"相":1319,"省":-1052,"県":-4003,"研":-997,"社":-278,"空":-813,"統":1955,"者":-2233,"表":663,"語":-1073,"議":1219,"選":-1018,"郎":-368,"長":786,"間":1191,"題":2368,"館":-689,"1":-514,"E2":-32768,"「":363,"イ":241,"ル":451,"ン":-343};
this.UW6__ = {",":227,".":808,"1":-270,"E1":306,"、":227,"。":808,"あ":-307,"う":189,"か":241,"が":-73,"く":-121,"こ":-200,"じ":1782,"す":383,"た":-428,"っ":573,"て":-1014,"で":101,"と":-105,"な":-253,"に":-149,"の":-417,"は":-236,"も":-206,"り":187,"る":-135,"を":195,"ル":-673,"ン":-496,"一":-277,"中":201,"件":-800,"会":624,"前":302,"区":1792,"員":-1212,"委":798,"学":-960,"市":887,"広":-695,"後":535,"業":-697,"相":753,"社":-507,"福":974,"空":-822,"者":1811,"連":463,"郎":1082,"1":-270,"E1":306,"ル":-673,"ン":-496};
return this;
}
TinySegmenter.prototype.ctype_ = function(str) {
for (var i in this.chartype_) {
if (str.match(this.chartype_[i][0])) {
return this.chartype_[i][1];
}
}
return "O";
}
TinySegmenter.prototype.ts_ = function(v) {
if (v) { return v; }
return 0;
}
TinySegmenter.prototype.segment = function(input) {
if (input == null || input == undefined || input == "") {
return [];
}
var result = [];
var seg = ["B3","B2","B1"];
var ctype = ["O","O","O"];
var o = input.split("");
for (i = 0; i < o.length; ++i) {
seg.push(o[i]);
ctype.push(this.ctype_(o[i]))
}
seg.push("E1");
seg.push("E2");
seg.push("E3");
ctype.push("O");
ctype.push("O");
ctype.push("O");
var word = seg[3];
var p1 = "U";
var p2 = "U";
var p3 = "U";
for (var i = 4; i < seg.length - 3; ++i) {
var score = this.BIAS__;
var w1 = seg[i-3];
var w2 = seg[i-2];
var w3 = seg[i-1];
var w4 = seg[i];
var w5 = seg[i+1];
var w6 = seg[i+2];
var c1 = ctype[i-3];
var c2 = ctype[i-2];
var c3 = ctype[i-1];
var c4 = ctype[i];
var c5 = ctype[i+1];
var c6 = ctype[i+2];
score += this.ts_(this.UP1__[p1]);
score += this.ts_(this.UP2__[p2]);
score += this.ts_(this.UP3__[p3]);
score += this.ts_(this.BP1__[p1 + p2]);
score += this.ts_(this.BP2__[p2 + p3]);
score += this.ts_(this.UW1__[w1]);
score += this.ts_(this.UW2__[w2]);
score += this.ts_(this.UW3__[w3]);
score += this.ts_(this.UW4__[w4]);
score += this.ts_(this.UW5__[w5]);
score += this.ts_(this.UW6__[w6]);
score += this.ts_(this.BW1__[w2 + w3]);
score += this.ts_(this.BW2__[w3 + w4]);
score += this.ts_(this.BW3__[w4 + w5]);
score += this.ts_(this.TW1__[w1 + w2 + w3]);
score += this.ts_(this.TW2__[w2 + w3 + w4]);
score += this.ts_(this.TW3__[w3 + w4 + w5]);
score += this.ts_(this.TW4__[w4 + w5 + w6]);
score += this.ts_(this.UC1__[c1]);
score += this.ts_(this.UC2__[c2]);
score += this.ts_(this.UC3__[c3]);
score += this.ts_(this.UC4__[c4]);
score += this.ts_(this.UC5__[c5]);
score += this.ts_(this.UC6__[c6]);
score += this.ts_(this.BC1__[c2 + c3]);
score += this.ts_(this.BC2__[c3 + c4]);
score += this.ts_(this.BC3__[c4 + c5]);
score += this.ts_(this.TC1__[c1 + c2 + c3]);
score += this.ts_(this.TC2__[c2 + c3 + c4]);
score += this.ts_(this.TC3__[c3 + c4 + c5]);
score += this.ts_(this.TC4__[c4 + c5 + c6]);
// score += this.ts_(this.TC5__[c4 + c5 + c6]);
score += this.ts_(this.UQ1__[p1 + c1]);
score += this.ts_(this.UQ2__[p2 + c2]);
score += this.ts_(this.UQ3__[p3 + c3]);
score += this.ts_(this.BQ1__[p2 + c2 + c3]);
score += this.ts_(this.BQ2__[p2 + c3 + c4]);
score += this.ts_(this.BQ3__[p3 + c2 + c3]);
score += this.ts_(this.BQ4__[p3 + c3 + c4]);
score += this.ts_(this.TQ1__[p2 + c1 + c2 + c3]);
score += this.ts_(this.TQ2__[p2 + c2 + c3 + c4]);
score += this.ts_(this.TQ3__[p3 + c1 + c2 + c3]);
score += this.ts_(this.TQ4__[p3 + c2 + c3 + c4]);
var p = "O";
if (score > 0) {
result.push(word);
word = "";
p = "B";
}
p1 = p2;
p2 = p3;
p3 = p;
word += seg[i];
}
result.push(word);
return result;
}
lunr.TinySegmenter = TinySegmenter;
};
}));
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
{"version":3,"sources":["src/templates/assets/stylesheets/palette/_scheme.scss","../../../../src/templates/assets/stylesheets/palette.scss","src/templates/assets/stylesheets/palette/_accent.scss","src/templates/assets/stylesheets/palette/_primary.scss","src/templates/assets/stylesheets/utilities/_break.scss"],"names":[],"mappings":"AA2BA,cAGE,6BAME,sDAAA,CACA,6DAAA,CACA,+DAAA,CACA,gEAAA,CACA,mDAAA,CACA,6DAAA,CACA,+DAAA,CACA,gEAAA,CAGA,mDAAA,CACA,gDAAA,CAGA,0BAAA,CACA,mCAAA,CAGA,iCAAA,CACA,kCAAA,CACA,mCAAA,CACA,mCAAA,CACA,kCAAA,CACA,iCAAA,CACA,+CAAA,CACA,6DAAA,CACA,gEAAA,CACA,4DAAA,CACA,4DAAA,CACA,6DAAA,CAGA,6CAAA,CAGA,+CAAA,CAGA,uDAAA,CACA,6DAAA,CACA,2DAAA,CAGA,iCAAA,CAGA,yDAAA,CACA,iEAAA,CAGA,mDAAA,CACA,mDAAA,CAGA,qDAAA,CACA,uDAAA,CAGA,8DAAA,CAKA,8DAAA,CAKA,0DAAA,CAvEA,iBCeF,CD6DE,kHAEE,YC3DJ,CDkFE,yDACE,4BChFJ,CD+EE,2DACE,4BC7EJ,CD4EE,gEACE,4BC1EJ,CDyEE,2DACE,4BCvEJ,CDsEE,yDACE,4BCpEJ,CDmEE,0DACE,4BCjEJ,CDgEE,gEACE,4BC9DJ,CD6DE,0DACE,4BC3DJ,CD0DE,2OACE,4BC/CJ,CDsDA,+FAGE,iCCpDF,CACF,CC/CE,2BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD2CN,CCrDE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDkDN,CC5DE,8BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDyDN,CCnEE,mCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDgEN,CC1EE,8BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDuEN,CCjFE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD8EN,CCxFE,kCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDqFN,CC/FE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD4FN,CCtGE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDmGN,CC7GE,6BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD0GN,CCpHE,mCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDiHN,CC3HE,4BACE,4BAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCD2HN,CClIE,8BACE,4BAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCDkIN,CCzIE,6BACE,yBAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCDyIN,CChJE,8BACE,4BAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCDgJN,CCvJE,mCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDoJN,CEzJE,4BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsJN,CEjKE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8JN,CEzKE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsKN,CEjLE,oCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8KN,CEzLE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsLN,CEjME,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8LN,CEzME,mCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsMN,CEjNE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8MN,CEzNE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsNN,CEjOE,8BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8NN,CEzOE,oCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsON,CEjPE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFiPN,CEzPE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFyPN,CEjQE,8BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFiQN,CEzQE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFyQN,CEjRE,oCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8QN,CEzRE,8BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsRN,CEjSE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCAAA,CAKA,4BF0RN,CE1SE,kCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCAAA,CAKA,4BFmSN,CEpRE,sEACE,4BFuRJ,CExRE,+DACE,4BF2RJ,CE5RE,iEACE,4BF+RJ,CEhSE,gEACE,4BFmSJ,CEpSE,iEACE,4BFuSJ,CE9RA,8BACE,mDAAA,CACA,4DAAA,CACA,0DAAA,CACA,oDAAA,CACA,2DAAA,CAGA,4BF+RF,CE5RE,yCACE,+BF8RJ,CE3RI,kDAEE,0CAAA,CACA,sCAAA,CAFA,mCF+RN,CG3MI,mCD1EA,+CACE,8CFwRJ,CErRI,qDACE,8CFuRN,CElRE,iEACE,mCFoRJ,CACF,CGtNI,sCDvDA,uCACE,oCFgRJ,CACF,CEvQA,8BACE,kDAAA,CACA,4DAAA,CACA,wDAAA,CACA,oDAAA,CACA,6DAAA,CAGA,4BFwQF,CErQE,yCACE,+BFuQJ,CEpQI,kDAEE,0CAAA,CACA,sCAAA,CAFA,mCFwQN,CEjQE,yCACE,6CFmQJ,CG5NI,0CDhCA,8CACE,gDF+PJ,CACF,CGjOI,0CDvBA,iFACE,6CF2PJ,CACF,CGzPI,sCDKA,uCACE,6CFuPJ,CACF","file":"palette.css"}
+186
View File
@@ -0,0 +1,186 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Run
// -----------------------------------------------
{
const exe = b.addExecutable(.{
.name = "zippondb",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
exe.root_module.addImport("dtype", b.createModule(.{ .root_source_file = b.path("lib/types/out.zig") }));
exe.root_module.addImport("config", b.createModule(.{ .root_source_file = b.path("lib/config.zig") }));
exe.root_module.addImport("ZipponData", b.createModule(.{ .root_source_file = b.path("lib/zid.zig") }));
exe.root_module.addImport("error", b.createModule(.{ .root_source_file = b.path("lib/errors.zig") }));
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
// Test
// -----------------------------------------------
{
const tests1 = b.addTest(.{
.root_source_file = b.path("src/dataStructure/UUIDFileIndex.zig"),
.target = target,
.optimize = optimize,
.name = "CLI tokenizer",
.test_runner = b.path("src/test_runner.zig"),
});
tests1.root_module.addImport("dtype", b.createModule(.{ .root_source_file = b.path("lib/types/out.zig") }));
const run_tests1 = b.addRunArtifact(tests1);
const tests2 = b.addTest(.{
.root_source_file = b.path("src/cli/tokenizer.zig"),
.target = target,
.optimize = optimize,
.name = "CLI tokenizer",
.test_runner = b.path("src/test_runner.zig"),
});
const run_tests2 = b.addRunArtifact(tests2);
const tests3 = b.addTest(.{
.root_source_file = b.path("src/ziql/tokenizer.zig"),
.target = target,
.optimize = optimize,
.name = "ZiQL tokenizer",
.test_runner = b.path("src/test_runner.zig"),
});
const run_tests3 = b.addRunArtifact(tests3);
const tests4 = b.addTest(.{
.root_source_file = b.path("src/schema/tokenizer.zig"),
.target = target,
.optimize = optimize,
.name = "Schema tokenizer",
.test_runner = b.path("src/test_runner.zig"),
});
tests4.root_module.addImport("config", b.createModule(.{ .root_source_file = b.path("lib/config.zig") }));
tests4.root_module.addImport("dtype", b.createModule(.{ .root_source_file = b.path("lib/types/out.zig") }));
const run_tests4 = b.addRunArtifact(tests4);
const tests5 = b.addTest(.{
.root_source_file = b.path("src/test.zig"),
.target = target,
.optimize = optimize,
.name = "ZiQL parser",
.test_runner = b.path("src/test_runner.zig"),
});
tests5.root_module.addImport("dtype", b.createModule(.{ .root_source_file = b.path("lib/types/out.zig") }));
tests5.root_module.addImport("config", b.createModule(.{ .root_source_file = b.path("lib/config.zig") }));
tests5.root_module.addImport("ZipponData", b.createModule(.{ .root_source_file = b.path("lib/zid.zig") }));
tests5.root_module.addImport("error", b.createModule(.{ .root_source_file = b.path("lib/errors.zig") }));
const run_tests5 = b.addRunArtifact(tests5);
const tests6 = b.addTest(.{
.root_source_file = b.path("src/dataStructure/filter.zig"),
.target = target,
.optimize = optimize,
.name = "Filter tree",
.test_runner = b.path("src/test_runner.zig"),
});
tests6.root_module.addImport("dtype", b.createModule(.{ .root_source_file = b.path("lib/types/out.zig") }));
tests6.root_module.addImport("config", b.createModule(.{ .root_source_file = b.path("lib/config.zig") }));
tests6.root_module.addImport("ZipponData", b.createModule(.{ .root_source_file = b.path("lib/zid.zig") }));
tests6.root_module.addImport("error", b.createModule(.{ .root_source_file = b.path("lib/errors.zig") }));
const run_tests6 = b.addRunArtifact(tests6);
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_tests1.step);
test_step.dependOn(&run_tests2.step);
test_step.dependOn(&run_tests3.step);
test_step.dependOn(&run_tests4.step);
test_step.dependOn(&run_tests5.step);
test_step.dependOn(&run_tests6.step);
}
// Test zid
// -----------------------------------------------
{
const tests1 = b.addTest(.{
.root_source_file = b.path("lib/zid.zig"),
.target = target,
.optimize = optimize,
.name = "File parsing",
.test_runner = b.path("src/test_runner.zig"),
});
const run_tests1 = b.addRunArtifact(tests1);
const test_step = b.step("benchmark-parsing", "Run the benchmark of ZipponData (Single thread).");
test_step.dependOn(&run_tests1.step);
}
// Benchmark
// -----------------------------------------------
{
const benchmark = b.addExecutable(.{
.name = "benchmark",
.root_source_file = b.path("src/benchmark.zig"),
.target = target,
.optimize = optimize,
});
benchmark.root_module.addImport("dtype", b.createModule(.{ .root_source_file = b.path("lib/types/out.zig") }));
benchmark.root_module.addImport("config", b.createModule(.{ .root_source_file = b.path("lib/config_benchmark.zig") }));
benchmark.root_module.addImport("ZipponData", b.createModule(.{ .root_source_file = b.path("lib/zid.zig") }));
benchmark.root_module.addImport("error", b.createModule(.{ .root_source_file = b.path("lib/errors.zig") }));
b.installArtifact(benchmark);
const run_benchmark = b.addRunArtifact(benchmark);
run_benchmark.step.dependOn(b.getInstallStep());
const benchmark_step = b.step("benchmark", "Run benchmarks");
benchmark_step.dependOn(&run_benchmark.step);
}
// Release
// -----------------------------------------------
{
const release_step = b.step("release", "Create release binaries for multiple platforms");
const targets = [_]std.Build.ResolvedTarget{
b.resolveTargetQuery(.{ .os_tag = .windows, .cpu_arch = .x86_64 }),
//b.resolveTargetQuery(.{ .os_tag = .windows, .cpu_arch = .arm }),
b.resolveTargetQuery(.{ .os_tag = .macos, .cpu_arch = .x86_64 }),
b.resolveTargetQuery(.{ .os_tag = .macos, .cpu_arch = .aarch64 }),
b.resolveTargetQuery(.{ .os_tag = .linux, .cpu_arch = .x86_64 }),
b.resolveTargetQuery(.{ .os_tag = .linux, .cpu_arch = .aarch64 }),
//b.resolveTargetQuery(.{ .os_tag = .linux, .cpu_arch = .arm }),
b.resolveTargetQuery(.{ .os_tag = .linux, .cpu_arch = .riscv64 }),
};
for (targets) |tar| {
const exe_name = b.fmt("zippondb-{s}-{s}", .{
@tagName(tar.query.cpu_arch.?),
@tagName(tar.query.os_tag.?),
});
const exe = b.addExecutable(.{
.name = exe_name,
.root_source_file = b.path("src/main.zig"),
.target = tar,
.optimize = optimize,
});
// Add the same imports as your main executable
exe.root_module.addImport("dtype", b.createModule(.{ .root_source_file = b.path("lib/types/out.zig") }));
exe.root_module.addImport("config", b.createModule(.{ .root_source_file = b.path("lib/config.zig") }));
exe.root_module.addImport("ZipponData", b.createModule(.{ .root_source_file = b.path("lib/zid.zig") }));
exe.root_module.addImport("error", b.createModule(.{ .root_source_file = b.path("lib/errors.zig") }));
const install_exe = b.addInstallArtifact(exe, .{
.dest_dir = .{ .override = .{ .custom = "release" } },
});
release_step.dependOn(&install_exe.step);
}
}
}
+8
View File
@@ -0,0 +1,8 @@
.{
.name = "ZipponDB",
.version = "0.1.4",
.dependencies = .{},
.paths = .{
"",
},
}
-1387
View File
File diff suppressed because it is too large Load Diff
-1498
View File
File diff suppressed because it is too large Load Diff
+233
View File
@@ -0,0 +1,233 @@
# Benchmark
***Benchmark are set to evolve. I have currently multiple ideas to improve performance.***
ZipponDB is fairly fast and can easely query millions of entities.
Current limitation is around 5GB I would say, depending of CPU cores, usage and kind of data saved.
After that query can start to become slow as optimizations are still missing.
Most of query's time is writing entities into a JSON format. Parsing the file itself take little time.
For example in the benchmark report bellow, I parse 100 000 users in around 40ms if there is no entities to send and 130ms if all 100 000 entities are to send.
I choosed to release ZipponDB binary with the small release.
Zig has a fast and safe release, but the fast release isn't that much faster in my case, if not at all.
If you want you can build it with it.
## Command
You can run `zig build benchmark`, if you clone the repo to benchmark your machine.
[More info on how to build from source.](/ZipponDB/build)
Here an example on my machine with 16 core:
```
=====================================
Populating with 5000 users.
Populate duration: 0.035698 seconds
Database path: benchmarkDB
Total size: 0.36Mb
CPU core: 16
Max file size: 5.00Mb
LOG: 0.02Mb
BACKUP: 0.00Mb
DATA: 0.33Mb
Item: 0.00Mb | 19 entities | 1 files
User: 0.33Mb | 5000 entities | 1 files
Order: 0.00Mb | 0 entities | 1 files
Category: 0.00Mb | 4 entities | 1 files
--------------------------------------
Query: GRAB User {}
Time: 16.90 ± 25.22 ms | Min 8.25ms | Max 92.55ms
Query: GRAB User {name='asd'}
Time: 2.62 ± 0.10 ms | Min 2.52ms | Max 2.85ms
Query: GRAB User [1] {}
Time: 0.16 ± 0.01 ms | Min 0.15ms | Max 0.18ms
Query: GRAB User [name] {}
Time: 7.88 ± 11.69 ms | Min 3.91ms | Max 42.94ms
Query: GRAB User {name = 'Charlie'}
Time: 3.87 ± 0.16 ms | Min 3.70ms | Max 4.17ms
Query: GRAB Category {}
Time: 0.20 ± 0.07 ms | Min 0.17ms | Max 0.41ms
Query: GRAB Item {}
Time: 0.21 ± 0.02 ms | Min 0.19ms | Max 0.25ms
Query: GRAB Order {}
Time: 0.14 ± 0.01 ms | Min 0.13ms | Max 0.18ms
Query: GRAB Order [from, items, quantity, at] {}
Time: 4.18 ± 12.01 ms | Min 0.15ms | Max 40.21ms
Query: DELETE User {}
Time: 0.64 ± 1.13 ms | Min 0.23ms | Max 4.04ms
Read: 1907698 Entity/second *Include small condition
Write: 350200 Entity/second
=====================================
Populating with 100000 users.
Populate duration: 0.707605 seconds
Database path: benchmarkDB
Total size: 6.62Mb
CPU core: 16
Max file size: 5.00Mb
LOG: 0.02Mb
BACKUP: 0.00Mb
DATA: 6.59Mb
Item: 0.00Mb | 19 entities | 1 files
User: 6.59Mb | 100000 entities | 2 files
Order: 0.00Mb | 0 entities | 1 files
Category: 0.00Mb | 4 entities | 1 files
--------------------------------------
Query: GRAB User {}
Time: 126.99 ± 3.05 ms | Min 123.37ms | Max 133.56ms
Query: GRAB User {name='asd'}
Time: 38.12 ± 1.60 ms | Min 36.48ms | Max 41.88ms
Query: GRAB User [1] {}
Time: 0.19 ± 0.02 ms | Min 0.16ms | Max 0.22ms
Query: GRAB User [name] {}
Time: 59.33 ± 1.29 ms | Min 58.02ms | Max 61.47ms
Query: GRAB User {name = 'Charlie'}
Time: 53.29 ± 1.00 ms | Min 51.50ms | Max 54.78ms
Query: GRAB Category {}
Time: 0.19 ± 0.01 ms | Min 0.18ms | Max 0.22ms
Query: GRAB Item {}
Time: 5.51 ± 13.43 ms | Min 0.22ms | Max 45.22ms
Query: GRAB Order {}
Time: 0.16 ± 0.01 ms | Min 0.15ms | Max 0.18ms
Query: GRAB Order [from, items, quantity, at] {}
Time: 0.17 ± 0.02 ms | Min 0.15ms | Max 0.21ms
Query: DELETE User {}
Time: 5.96 ± 17.04 ms | Min 0.26ms | Max 57.07ms
Read: 2623338 Entity/second *Include small condition
Write: 1125278 Entity/second
=====================================
Populating with 1000000 users.
Populate duration: 7.029142 seconds
Database path: benchmarkDB
Total size: 65.96Mb
CPU core: 16
Max file size: 5.00Mb
LOG: 0.02Mb
BACKUP: 0.00Mb
DATA: 65.93Mb
Item: 0.00Mb | 19 entities | 1 files
User: 65.93Mb | 1000000 entities | 14 files
Order: 0.00Mb | 0 entities | 1 files
Category: 0.00Mb | 4 entities | 1 files
--------------------------------------
Query: GRAB User {}
Time: 250.77 ± 6.74 ms | Min 247.08ms | Max 270.61ms
Query: GRAB User {name='asd'}
Time: 67.90 ± 0.42 ms | Min 67.31ms | Max 68.78ms
Query: GRAB User [1] {}
Time: 8.92 ± 24.86 ms | Min 0.55ms | Max 83.51ms
Query: GRAB User [name] {}
Time: 110.08 ± 5.27 ms | Min 106.86ms | Max 125.21ms
Query: GRAB User {name = 'Charlie'}
Time: 73.65 ± 2.79 ms | Min 69.24ms | Max 79.22ms
Query: GRAB Category {}
Time: 0.19 ± 0.04 ms | Min 0.16ms | Max 0.33ms
Query: GRAB Item {}
Time: 0.21 ± 0.02 ms | Min 0.19ms | Max 0.26ms
Query: GRAB Order {}
Time: 0.15 ± 0.01 ms | Min 0.14ms | Max 0.17ms
Query: GRAB Order [from, items, quantity, at] {}
Time: 0.17 ± 0.01 ms | Min 0.16ms | Max 0.18ms
Query: DELETE User {}
Time: 11.74 ± 34.19 ms | Min 0.29ms | Max 114.30ms
Read: 14727354 Entity/second *Include small condition
Write: 5468517 Entity/second
=====================================
Populating with 10000000 users.
Populate duration: 72.675680 seconds
Database path: benchmarkDB
Total size: 659.33Mb
CPU core: 16
Max file size: 5.00Mb
LOG: 0.02Mb
BACKUP: 0.00Mb
DATA: 659.30Mb
Item: 0.00Mb | 19 entities | 1 files
User: 659.30Mb | 10000000 entities | 132 files
Order: 0.00Mb | 0 entities | 1 files
Category: 0.00Mb | 4 entities | 1 files
--------------------------------------
Query: GRAB User {}
Time: 2535.29 ± 86.92 ms | Min 2448.39ms | Max 2712.78ms
Query: GRAB User {name='asd'}
Time: 684.75 ± 39.96 ms | Min 649.09ms | Max 797.13ms
Query: GRAB User [1] {}
Time: 6.65 ± 1.00 ms | Min 5.36ms | Max 8.75ms
Query: GRAB User [name] {}
Time: 1106.21 ± 33.57 ms | Min 1056.57ms | Max 1172.61ms
Query: GRAB User {name = 'Charlie'}
Time: 690.56 ± 20.41 ms | Min 661.51ms | Max 718.07ms
Query: GRAB Category {}
Time: 0.21 ± 0.03 ms | Min 0.18ms | Max 0.31ms
Query: GRAB Item {}
Time: 0.23 ± 0.04 ms | Min 0.19ms | Max 0.32ms
Query: GRAB Order {}
Time: 0.15 ± 0.01 ms | Min 0.13ms | Max 0.17ms
Query: GRAB Order [from, items, quantity, at] {}
Time: 0.17 ± 0.02 ms | Min 0.15ms | Max 0.21ms
Query: DELETE User {}
Time: 109.55 ± 326.64ms | Min 0.47ms | Max 1089.46ms
Read: 14603810 Entity/second *Include small condition
Write: 5403847 Entity/second
=====================================
```
+25
View File
@@ -0,0 +1,25 @@
# Data types
ZipponDB have a little set of types. This is on purpose, to keep the database simple and fast. But more type may be added in the future.
## Primary Data Types
ZipponDB supports 8 primary data types:
| Type | Description | Example |
|------|-------------|---------|
| int | 32-bit integer | 42 |
| float | 64-bit float (must include a decimal point) | 3.14 |
| bool | Boolean value | true or false |
| string | Character array enclosed in single quotes | 'Hello, World!' |
| UUID | Universally Unique Identifier | 123e4567-e89b-12d3-a456-426614174000 |
| date | Date in yyyy/mm/dd format | 2024/10/19 |
| time | Time in hh:mm:ss.mmmm format | 12:45:00.0000 |
| datetime | Combined date and time | 2024/10/19-12:45:00.0000 |
## Array Types
Any of these data types can be used as an array by prefixing it with `[]`. For example:
- `[]int`: An array of integers
- `[]string`: An array of strings
+47
View File
@@ -0,0 +1,47 @@
# Quickstart
This guide will help you set up and start using ZipponDB quickly.
## Step 1: Get a Binary
Obtain a binary for your architecture by:
- Downloading a pre-built binary from the [releases page](https://github.com/MrBounty/ZipponDB/releases)
- Building from [source code](https://mrbounty.github.io/ZipponDB/build)
Once with the binary, run it to get access to the CLI.
## Step 2: Select a Database
Once in the CLI, create a database by running:
```bash
db use path/to/dir
```
Alternatively, set the `ZIPPONDB_PATH` environment variable.
## Step 3: Attach a Schema
Define a [schema](/ZipponDB/Schema) and attach it to the database by running:
```bash
schema use path/to/schema.txt
```
This will create the necessary directories and empty files for data storage. Test the current database schema by running:
```bash
schema describe
```
Alternatively, set the `ZIPPONDB_SCHEMA` environment variable.
## Step 4: Use the Database
Start using the database by sending queries, such as:
```bash
run "ADD User (name = 'Bob')"
```
[Learn more about ZiQL.](/ZipponDB/ziql/intro)
+58
View File
@@ -0,0 +1,58 @@
# Roadmap
***Note: This will probably evolve over time.***
### Alpha
#### v0.1 - Base
- [X] UUID
- [X] CLI
- [X] Tokenizers
- [X] ZiQL parser
- [X] Schema engine
- [X] File engine
#### v0.2 - Usable
- [X] Relationships
- [X] Custom data file
- [X] Date
- [X] Logs
- [X] Query multi threading
- [X] Arrays manipulation
#### v0.3 - QoL
- [X] Docs website
- [ ] Ordering
- [ ] Dot operator
- [ ] Linked query
- [ ] Schema migration
- [ ] Dump/Bump data
- [ ] Recovery
- [ ] Better CLI
#### v0.4 - Usability
- [ ] Single file
- [ ] Docker
- [ ] YAML config file
- [ ] Python interface
- [ ] Go interface
#### v0.5 - In memory
- [ ] In memory option
- [ ] Cache
#### v0.6 - Performance
- [ ] Transaction
- [ ] Other multi threading
- [ ] Query optimization
- [ ] Index
#### v0.7 - Safety
- [ ] Metrics
- [ ] Durability
#### v0.8 - Docs
- [ ] ZiQL tuto
- [ ] Deployment tuto
- [ ] Code docs
- [ ] CLI help
+71
View File
@@ -0,0 +1,71 @@
# Schema
In ZipponDB, data is organized and manipulated using structures, or structs, rather than traditional tables. A struct is defined by a name, such as `User`, and members, such as `name` and `age`.
## Defining a Schema
To declare structs for use in your database, create a separate file containing the schema definitions. Below is an example of a simple schema file:
```lua
User (
name: str,
email: str,
best_friend: User,
)
```
In this example, the `best_friend` member is a reference to another `User`.
Here's a more complex example featuring multiple structs:
```lua
User (
name: str,
email: str,
friends: []User,
posts: []Post,
comments: []Comment,
)
Post (
title: str,
image: str,
at: date,
like_by: []User,
comments: []Comment,
)
Comment (
content: str,
at: date,
like_by: []User,
)
```
*Note: The [] symbol preceding a type indicates an array of that type. For example, []User represents an array of User structs.*
## Schema Migration - Not yet implemented
In future releases, ZipponDB will support schema updates, allowing you to modify existing structs or add new ones, and then apply these changes to your database. Currently, schema modifications are not possible once the database has been initialized.
I will add commands or query to add, delete and update struct in the schema. Maybe the schema will be a Struct itself with a schema like that:
```lua
Struct (
name: str,
members: []Member,
)
Member (
name: str,
type: int,
)
```
Like that can just do ZiQL query directly on it.
### Planned Migration Features
- Add new members to existing structs
- Modify or remove existing members
- Rename structs or members
- Update relationships between structs
- More...
+15
View File
@@ -0,0 +1,15 @@
# Single file
In the future I will migrate into a single file database like SQLite.
## FileBlok
A blok is like memory but for file. It has a starting point and a size and can hold entities or FileVar.
Everything I will save will be linked into a Blok and I can create and delete them at will. The size is in the config and can't change.
In SQLite, it is what they call it a page I think. Similare thing.
## FileVar
A FileVar is a single value but saved in a file. This have a Blok, a position, a size and a type.
For string, I will create something different I think, with a size max and a len, and can request more if needed.
+8
View File
@@ -0,0 +1,8 @@
- [ ] Array manipulation
- [ ] Some time keyword like NOW
- [X] Benchmark command
## Run in WASM for a demo
This could be fun, make a small demo where you get a wasm that run the database locally in the browser.
+243
View File
@@ -0,0 +1,243 @@
# Intro
TODO
***Note: Code snippets in this documentation are simplified examples and may not represent the actual codebase.***
## Tokenizers
Tokenizers are responsible for converting a buffer string into a list of tokens. Each token has a `Tag` enum that represents its type, such as `equal` for the `=` symbol, and a `Loc` struct with start and end indices that represent its position in the buffer.
All tokenizers work similarly and are based on the [zig tokenizer.](https://github.com/ziglang/zig/blob/master/lib/std/zig/tokenizer.zig) They have two main methods: next, which returns the next token, and getTokenSlice, which returns the slice of the buffer that represents the token.
Here's an example of how to use a tokenizer:
```zig
const toker = Tokenizer.init(buff);
const token = toker.next();
std.debug.print("{s}", .{toker.getTokenSlice(token)});
```
Tokenizers are often used in a loop until the `end` tag is reached. In each iteration, the next token is retrieved and processed based on its tag. Here's a simple example:
```zig
const toker = Tokenizer.init(buff);
var token = toker.next();
while (token.tag != .end) : (token = toker.next()) switch (token.tag) {
.equal => std.debug.print("{s}", .{toker.getTokenSlice(token)}),
else => {},
}
```
### Available Tokenizers
There are four different tokenizers in ZipponDB:
- **ZiQL:** Tokenizer for the query language.
- **cli:** Tokenizer the commands.
- **schema:** Tokenizer for the schema file.
Each tokenizer has its own set of tags and parsing rules, but they all work similarly.
## Parser
Parsers are the next step after tokenization. They take tokens and perform actions or raise errors. There are three parsers in ZipponDB: one for ZiQL, one for schema files, and one for CLI commands.
A parser has a `State` enum and a `Tokenizer` instance as members, and a parse method that processes tokens until the `end` state is reached.
Here's an example of how a parser works:
```zig
var state = .start;
var token = self.toker.next();
while (state != .end) : (token = self.toker.next()) switch (state) {
.start => switch (token.tag) {
.identifier => self.addStruct(token),
else => printError("Error: Expected a struct name.", token),
},
else => {},
}
```
The parser's state is updated based on the combination of the current state and token tag. This process continues until the `end` state is reached.
The ZiQL parser uses different methods for parsing:
- `parse`: The main parsing method that calls other methods.
- `parseFilter`: Creates a filter tree from the query.
- `parseCondition`: Creates a condition from a part of the query.
- `parseAdditionalData`: Populates additional data from the query.
- `parseNewData`: Returns a string map with key-value pairs from the query.
- `parseOption`: Not implemented yet.
## File parsing
File parsing is done through a small library that I did named [ZipponData](https://github.com/MrBounty/ZipponData).
It is minimal and fast, it can parse 1_000_000 entity in 0.3s on one thread
on a 7 7800X3D at around 4.5GHz with a Samsung SSD 980 PRO 2TB (up to 7,000/5,100MB/s for read/write speed).
To read a file, you create an iterator for a single file and then you can iterate with `.next()`. It will return an array of `Data`. This make everything very easy to use.
```zig
const std = @import("std");
pub fn main() !void {
const allocator = std.testing.allocator;
// 0. Make a temporary directory
try std.fs.cwd().makeDir("tmp");
const dir = try std.fs.cwd().openDir("tmp", .{});
// 1. Create a file
try createFile("test", dir);
// 2. Create some Data
const data = [_]Data{
Data.initInt(1),
Data.initFloat(3.14159),
Data.initInt(-5),
Data.initStr("Hello world"),
Data.initBool(true),
Data.initUnix(2021),
};
// 3. Create a DataWriter
var dwriter = try DataWriter.init("test", dir);
defer dwriter.deinit(); // This just close the file
// 4. Write some data
try dwriter.write(&data);
try dwriter.write(&data);
try dwriter.flush(); // Dont forget to flush !
// 5. Create a schema
// A schema is how the iterator will parse the file.
// If you are wrong here, it will return wrong/random data
// And most likely an error when iterating in the while loop
const schema = &[_]DType{
.Int,
.Float,
.Int,
.Str,
.Bool,
.Unix,
};
// 6. Create a DataIterator
var iter = try DataIterator.init(allocator, "test", dir, schema);
defer iter.deinit();
// 7. Iterate over data
while (try iter.next()) |row| {
std.debug.print("Row: {any}\n", .{ row });
}
// 8. Delete the file (Optional ofc)
try deleteFile("test", dir);
try std.fs.cwd().deleteDir("tmp");
}
```
## Engines
ZipponDB segregate responsability with Engines.
For example the `FileEngine` is the only place where files used, for both writting and reading. This simplify refactoring, testing, etc.
### DBEngine
This is just a wrapper around all other Engines to keep them at the same place. This doesnt do anything except storing other Engines.
This can be find in `main.zig`, in the `main` function.
### FileEngine
The `FileEngine` is responsible for managing files, including reading and writing.
Most methods will parse all files of a struct and evaluate them with a filter and do stuff if `true`. For example `parseEntities` will parse all entities and if the filter return `true`,
will write using the writer argument a JSON object with the entity's data.
Those methods are usually sperated into 2 methods. The main one and a `OneFile` version, e.g. `parseEntitiesOneFile`. The main one will call a thread for each file using multiple `OneFile` version.
This is how multi-threading is done.
### SchemaEngine
The `SchemaEngine` manage everything related to schemas.
This is mostly used to store a list of `SchemaStruct`, with is just one struct as defined in the schema. With all member names, data types, links, etc.
This is also here that I store the `UUIDFileIndex`, that is a map of UUID to file index. So I can quickly check if a UUID exist and in which file it is store.
This work well but use a bit too much memory for me, around 220MB for 1_000_000 entities. I tried doing a Radix Trie but it doesn't use that much less memory, maybe I did a mistake somewhere.
### ThreadEngine
The `ThreadEngine` manage the thread pool of the database.
This is also where is stored the `ThreadSyncContext` that is use for each `OneFile` version of parsing methods in the `FileEngine`. This is the only atomix value currently used in the database.
## Multi-threading
ZipponDB uses multi-threading to improve performance. Each struct is saved in multiple `.zid` files, and a thread pool is used to process files concurrently. Each thread has its own buffered writer, and the results are concatenated and sent once all threads finish.
The only shared atomic values between threads are the number of found structs and the number of finished threads. This approach keeps things simple and easy to implement, avoiding parallel threads accessing the same file.
## Data Structures
### AdditionalData
AdditionalData keep what is between `[]`. It is composed of 2 struct `AdditionalData` and `AdditionalDataMember`.
`AdditionalDataMember` have the name of the member, it's position in the schema file and an `AdditionalData`.
`AdditionalData` have a limit (the first part `[100]`), and a list of `AdditionalDataMember`.
### Filters
A filter is a series of condition. It use a tree approach, by that I mean the filter have a root node that is either a condition or have 2 others nodes (left and right).
For example the filter `{name = 'Bob'}` have one root node that is the condition. So when I evaluate the struct, I just check this condition.
Now for like `{name = 'Bob' AND age > 0}`, the root node have as left node the condition `name = 'Bob'` and right node the condition `age > 0`.
To look like that:
```
AND
/ \
OR OR
/ \ / \
name name age age
='A' ='B' >80 <20
```
### Condition
A condition is part of filters. It is one 'unit of condition'. For example `name = 'Bob'` is one condition.
`name = 'Bob' and age > 0` are 2 conditions and one filter. It is created inside `parseCondition` in the `ziqlParser`.
A condition have those infos:
- value: ConditionValue. E.g. `32`
- operation: ComparisonOperator. E.g. `equal` or `in`
- data_type: DataType. E.g. `int` or `str`
- data_index: usize. This is the index in when parsing returned by zid `DataIterator`
### NewData
NewData is a map with member name as key and ConditionValue as value, it is created when parsing and is use to add data into a file.
I transform ConditionValue into Zid Data. Maybe I can directly do a map member name -> zid Data ?
### RelationMap
A `RelationMap` is use when I need to return relationship. Let's say we have this query `GRAB User [orders [date]]`.
The `RelationMap` have a struct_name, here Order. A member name, here orders. A map with UUID as key and a string as value.
When I first init the map, I am parsing the first struct (here User). So it populate the map with empty string for entities that I want to return.
Here it will be UUID of Order.
Then I parse Order file and add the string to the right UUID, skipping UUID that are not in the map.
Once that done, I parse the JSON response that I generated when parsing User. Where a relationship should be, there is `{<|[16]u8|>}`, where `[16]u8` is the UUID of the entity that shoud be here.
So now I can just replace it by the right key in the map.
## EntityWriter
This is responsable to transform the raw Data into a JSON, Table or other output format to send send to end user.
Basically the last step before sending.
+195
View File
@@ -0,0 +1,195 @@
# ZipponData
ZipponData is a library developped in the context of [ZipponDB](https://github.com/MrBounty/ZipponDB/tree/v0.1.3).
The library intent to create a simple way to store and parse data from a file in the most efficient and fast way possible.
There is 6 data type available in ZipponData:
| Type | Zig type | Bytes in file |
| --- | --- | --- |
| int | i32 | 4 |
| float | f64 | 8 |
| bool | bool | 1 |
| str | []u8 | 4 + len |
| uuid | [16]u8 | 16 |
| unix | u64 | 8 |
Each type have its array equivalent.
## Quickstart
1. Create a file with `createFile`
2. Create some `Data`
3. Create a `DataWriter`
4. Write the data
5. Create a schema
6. Create an iterator with `DataIterator`
7. Iterate over all value
8. Delete the file with `deleteFile`
Here an example of how to use it:
``` zig
const std = @import("std");
pub fn main() !void {
const allocator = std.testing.allocator;
// 0. Make a temporary directory
try std.fs.cwd().makeDir("tmp");
const dir = try std.fs.cwd().openDir("tmp", .{});
// 1. Create a file
try createFile("test", dir);
// 2. Create some Data
const data = [_]Data{
Data.initInt(1),
Data.initFloat(3.14159),
Data.initInt(-5),
Data.initStr("Hello world"),
Data.initBool(true),
Data.initUnix(2021),
};
// 3. Create a DataWriter
var dwriter = try DataWriter.init("test", dir);
defer dwriter.deinit(); // This just close the file
// 4. Write some data
try dwriter.write(&data);
try dwriter.write(&data);
try dwriter.write(&data);
try dwriter.write(&data);
try dwriter.write(&data);
try dwriter.write(&data);
try dwriter.flush(); // Dont forget to flush !
// 5. Create a schema
// A schema is how the iterator will parse the file.
// If you are wrong here, it will return wrong/random data
// And most likely an error when iterating in the while loop
const schema = &[_]DType{
.Int,
.Float,
.Int,
.Str,
.Bool,
.Unix,
};
// 6. Create a DataIterator
var iter = try DataIterator.init(allocator, "test", dir, schema);
defer iter.deinit();
// 7. Iterate over data
while (try iter.next()) |row| {
std.debug.print("Row: {any}\n", .{ row });
}
// 8. Delete the file (Optional ofc)
try deleteFile("test", dir);
try std.fs.cwd().deleteDir("tmp");
}
```
***Note: The dir can be null and it will use cwd.***
## Array
All data type have an array equivalent. To write an array, you need to first encode it using `allocEncodArray` before writing it.
This use an allocator so you need to free what it return.
When read, an array is just the raw bytes. To get the data itself, you need to create an `ArrayIterator`. Here an example:
```zig
pub fn main() !void {
const allocator = std.testing.allocator;
// 0. Make a temporary directory
try std.fs.cwd().makeDir("array_tmp");
const dir = try std.fs.cwd().openDir("array_tmp", .{});
// 1. Create a file
try createFile("test", dir);
// 2. Create and encode some Data
const int_array = [4]i32{ 32, 11, 15, 99 };
const data = [_]Data{
Data.initIntArray(try allocEncodArray.Int(allocator, &int_array)), // Encode
};
defer allocator.free(data[0].IntArray); // DOnt forget to free it
// 3. Create a DataWriter
var dwriter = try DataWriter.init("test", dir);
defer dwriter.deinit();
// 4. Write some data
try dwriter.write(&data);
try dwriter.flush();
// 5. Create a schema
const schema = &[_]DType{
.IntArray,
};
// 6. Create a DataIterator
var iter = try DataIterator.init(allocator, "test", dir, schema);
defer iter.deinit();
// 7. Iterate over data
var i: usize = 0;
if (try iter.next()) |row| {
// 8. Iterate over array
var array_iter = ArrayIterator.init(&row[0]); // Sub array iterator
while (array_iter.next()) |d| {
try std.testing.expectEqual(int_array[i], d.Int);
i += 1;
}
}
try deleteFile("test", dir);
try std.fs.cwd().deleteDir("array_tmp");
}
```
## Benchmark
Done on a AMD Ryzen 7 7800X3D with a Samsung SSD 980 PRO 2TB (up to 7,000/5,100MB/s for read/write speed) on one thread.
Data use:
```zig
const schema = &[_]DType{
.Int,
.Float,
.Int,
.Str,
.Bool,
.Unix,
};
const data = &[_]Data{
Data.initInt(1),
Data.initFloat(3.14159),
Data.initInt(-5),
Data.initStr("Hello world"),
Data.initBool(true),
Data.initUnix(2021),
};
```
Result:
| Number of Entity | Total Write Time (ms) | Average Write Time / entity (μs) | Total Read Time (ms) | Average Read Time / entity (μs) | File Size (kB) |
| --- | --- | --- | --- | --- | --- |
| 1 | 0.01 | 13.63 | 0.025 | 25.0 | 0.04 |
| 10 | 0.01 | 1.69 | 0.03 | 3.28 | 0.4 |
| 100 | 0.04 | 0.49 | 0.07 | 0.67 | 4.0 |
| 1_000 | 0.36 | 0.36 | 0.48 | 0.48 | 40 |
| 10_000 | 3.42 | 0.34 | 4.67 | 0.47 | 400 |
| 100_000 | 36.39 | 0.36 | 48.00 | 0.49 | 4_000 |
| 1_000_000 | 361.41 | 0.36 | 481.00 | 0.48 | 40_000 |
***Note: You can check [benchmark](/ZipponDB/Benchmark) to see performance of the real database using multi-threading. Was able to parse 1_000_000 users in less than 100ms***
+40
View File
@@ -0,0 +1,40 @@
# About
## Me
ZipponDB is developped by a single person, [Adrien Bouvais](https://github.com/MrBounty).
I started this project because I wanted to learn a lot of things:
* Database
* Zig
* CI/CD
* Data structures
* Algorithms
* Documentation
* Memory management
* High performance
* Low level programming
* ...
### Why
I wanted to create a "real" project, not just some TODO app. But something original with actually everything.
That's why I added automatic documentation update when push in main. Or automatic build and release when I push a new tag. And why I make it look like a proper open-source project.
I didn't research that much how other db do stuff. I wanted to just do it, figure it out and make silly mistake. That how you learn.
I may take this knowledge and try to do more niche database, something maybe a bit more through upfront.
Because here I just wrote the simpliest query I could think of that can do easy relationship.
But let's be honest, that's kind of a mess. I more want to do like a vector db or tigerbeetle and there transaction database.
Or just just simply a SQL db. I mean I don't think it would be that difficult based on what I already did.
### How
I came into this project with 0 real knowledge of how a database work and a small week-end of coding zig. I didn't read that much about how other people make databases.
My goal was more to learn by mistake, doing it myself. I spended a lot of time at the beguining planing how the database will work inside, before coding.
For the how itself, I solved one small problem at the time. 'How to open a file ?', 'How to read and write bytes ?', 'How to do a tokenizer ?', etc... And litle by litle,
you go closer and closer to your objectif.
I learned a lot of thing with this project. And even if I would do some part differently if I do it again, I think it is a fairly decent piece of software.
+60
View File
@@ -0,0 +1,60 @@
# Build
On this page, I will show you how to build ZipponDB from source.
## 1. Get Zig
First thing first, <a href="https://ziglang.org/" target="_blank">go get zig</a>.
## 2. Clone repo
Simple enough, clone ZipponDB repository and cd into it.
```bash
git clone https://github.com/MrBounty/ZipponDB
cd ZipponDB
```
## 3. Config
In `lib/config.zig` you will find a config file. There is few parameters and they are comptime for now (can't change from cli). But more will be added.
Parameter | Default | Description
----- | ----- | ---------------
MAX_FILE_SIZE | 1Mb | Max size of each individual file where data is store.
CPU_CORE | 16 | Number of thread the pool will use. (At least 4 recommended for db > 100Mb)
## 4. build
```
zig build
```
Create 2 binaries in `zig-out/bin`:
* **zippondb:** The database CLI.
* **benchmark:** Run and print a benchmark.
### build run
```
zig build run
```
Build and run the CLI.
### build benchmark
```
zig build benchmark
```
Build and run the benchmark.
### build test
```
zig build test
```
Build and run tests.
+111
View File
@@ -0,0 +1,111 @@
# Command Line Interface
ZipponDB use a CLI to interact, there is few commands available for now as focus was given to ZiQL. But more commands will be added in the future.
## run
Run a ZiQL query on the selected database.
**Usage:**
```go
run "QUERY" // (1)!
```
1. Note that query need to be between ""
## db
### db metrics
Print some metrics from the db, including: Size on disk and number of entities stored.
**Usage:**
```
db metrics
```
### db new
Create a new empty directory that can be then initialize with a schema.
**Usage:**
```
db new path/to/dir
```
### db use
Select an already created database with `db new`.
**Usage:**
```
db use path/to/dir
```
### db state
Return the state of the database, either `Ok` or `MissingDatabase` if no database selected or `MissingSchema` if no schema was initialize.
**Usage:**
```
db state
```
## schema
### schema use
Attach a schema to the database using a schema file.
**Usage:**
```
schema use path/to/schema.file
```
### schema describe
Print the schema use by the selected database.
**Usage:**
```
schema describe
```
## dump
Export the entier database in a specific format.
**Usage:**
```
dump [FORMAT] [PATH]
```
FORMAT options: `csv`, `json`, `zid`
## quit
Quit the CLI.
**Usage:**
```
quit
```
## help
Write an help message.
**Usage:**
```
help
```

Before

Width:  |  Height:  |  Size: 740 KiB

After

Width:  |  Height:  |  Size: 740 KiB

Before

Width:  |  Height:  |  Size: 488 KiB

After

Width:  |  Height:  |  Size: 488 KiB

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

+57
View File
@@ -0,0 +1,57 @@
# ZipponDB: A Minimalist Lightweight General Purpose Database in Zig
<style>
.md-content .md-typeset h1 { display: none; }
</style>
<p align="center">
<a href="/ZipponDB"><img src="images/banner.png" alt="ZipponDB"></a>
</p>
<p align="center">
<em>Minimalist Lightweight General Purpose Database written in Zig</em>
</p>
---
**Documentation**: <a href="/ZipponDB" target="_blank">https://mrbounty.github.io/ZipponDB</a>
**Source Code**: <a href="https://github.com/MrBounty/ZipponDB" target="_blank">https://github.com/MrBounty/ZipponDB</a>
---
ZipponDB is a database built from the ground up in Zig, with zero external dependencies. Designed for simplicity,
performance, and portability, it's almost usable for small to
medium applications that want a quick and simple database.
## Key Features
* **Small Binary:** ~300kb.
* **Fast:** Parse millions of entities in milliseconds.*
* **Relationship:** Build with focus on easy relationship.
* **Query Language:** Use it's own stupid query language.
* **No dependencies:** Depend on nothing, every line of code running is in the codebase and written for ZipponDB.
* **Open-source:** Open-source under MIT licence.
<small>* Check <a href="/Benchmark">benchmark</a>.</small>
### Planned
* **Interface:** Small package to interact with ZipponDB from different programming language.
* **Single file:** Like SQLite, ZipponDB's database aim to be a single file.
* **Schema migration:** Update dynamically database schema.
* **Custom index:** Speed up query with custom indexing.
* **Better QL:** Improving ZiQL and adding features.
* **Safety and Performance:** Improve general safty and performance.
<small>More info in the Roadmap.</small>
### Maybe
Those are idea for very long term with 0 promesse, maybe as extension.
* **Web interface:** Similare to EdgeDB, getting a webapp to query and config the DB.
* **HTTP server:** Be able to start a simple HTTP server and send json.
* **Auth:** Be able to auth users, maybe third-party OAuth.
* **Per user database:** Like Turso.
* **Performace:** I'm sure I can do better.
* **Client side database:** Run it on the client side with WASM.
+35
View File
@@ -0,0 +1,35 @@
# Interface
Interfaces are way to use ZipponDB from other programming language.
## Python
**Not yet implemented, to give a general idea. Exact code may change.**
```python
from zippondb import Client
db = Client("data")
db.run("ADD User (name='Bob')")
```
### Pydantic
I will most likely implement with Pydantic. Something like that:
```python
from zippondb import Client, Model
class User(Model):
name: str
age: int
db = Client("data")
users = db.run("GRAB User {}", model=User)
```
`Model` is like `BaseModel` from pydantic but all member are optional. If no model provided, return a list of dict.
## Golang
TODO
+3
View File
@@ -0,0 +1,3 @@
# Log
I have logging implemented but badly and I don't log enough. I need to check this part.
+11
View File
@@ -0,0 +1,11 @@
# Release
## 0.1.8
First release.
Mostly to test the release pipeline with Github actions.
Only include CLI, most ZiQL features here but still missing some part.
Mostly missing thing around the database to make it usable.
[Link](https://github.com/MrBounty/ZipponDB/releases/tag/0.1.8)
+33
View File
@@ -0,0 +1,33 @@
# ADD
The `ADD` action adds entities to the database. The syntax is similar to `GRAB`, but uses `()`. This signifies that the data is not yet in the database.
Here's an example:
```lua
ADD User (name = 'Bob', age = 30, email = 'bob@email.com', scores = [1 100 44 82])
```
You need to specify all members when adding an entity (default values comming).
The `ADD` query will return a list of added IDs, e.g.:
```
["1e170a80-84c9-429a-be25-ab4657894653", "1e170a80-84c9-429a-be25-ab4657894654", ]
```
And you can also add them in batch
```
ADD User (name = 'Bob', age = 30, email = 'bob@email.com', scores = [1 100 44 82]) (name = 'Bob2', age = 33, email = 'bob2@email.com', scores = [])
```
You don't need to specify member's name for the second entity as long as the order is respected:
```
ADD User
(name = 'Bob', age = 30, email = 'bob@email.com', scores = [1 100 44 82])
('Bob2', 33, 'bob2@email.com', [])
```
* Default value
* Array default is empty
* Link default is none
+11
View File
@@ -0,0 +1,11 @@
# DELETE
Similar to `GRAB` but deletes all entities found using the filter and returns a list of deleted UUIDs.
```js
DELETE User {name = 'Bob'}
```
The `DELETE` query will return a list of deleted IDs, e.g.:
```
["1e170a80-84c9-429a-be25-ab4657894653", "1e170a80-84c9-429a-be25-ab4657894654", ]
```
+130
View File
@@ -0,0 +1,130 @@
# GRAB
The main action is `GRAB`, this will parse files and return data.
## Basic
Here's how to return all `User` without any filtering:
```
GRAB User
```
---
To get all `User` above 30 years old:
```
GRAB User {age > 30}
```
---
To return only the member `name` of `User`:
```
GRAB User [name] {age > 30}
```
---
To return the 10 first `User`:
```
GRAB User [10] {age > 30}
```
---
You can combine these options:
```
GRAB User [10; name] {age > 30}
```
---
Use multiple conditions:
```
GRAB User {name = 'Bob' AND (age > 30 OR age < 10)}
```
---
GRAB queries return a list of JSON objects with the data inside, e.g:
```
[{id:"1e170a80-84c9-429a-be25-ab4657894653", name: "Gwendolyn Ray", age: 70, email: "austin92@example.org", scores: [ 77 ], friends: [], }, ]
```
---
## Ordering - Not yet implemented
To order the results by `name`:
```js
GRAB User [10; name] {age > 10} |ASC name|
```
## Array
You can use the `IN` operator to check if something is in an array:
```js
GRAB User { age > 10 AND name IN ['Adrien' 'Bob']}
```
---
## Relationship
2 main things to remember with relationship:
* You can use filter inside filter.
* You can use the dot `.` to refer to a relationship. (Not yet implemented)
Get `User` that have a best friend named Adrien:
```js
GRAB User { bestfriend IN { name = 'Adrien' } }
```
---
You can specify how much data to return and which members to include, even for links. In this example, I get 1 friend's name for 10 `User`:
```js
GRAB User [10; friends [1; name]]
```
---
When using `IN`, it return all `User` that have AT LEAST one friend named Adrien:
```js
GRAB User { friends IN { name = 'Adrien' } }
```
---
To get `User` with all friends named Adrien:
```js
GRAB User { friends ALLIN { name = 'Adrien' } }
```
---
You can use `!` to say not in:
```js
GRAB User { friends !IN { name = 'Adrien' } }
```
---
## Dot - Not yet implemented
You can use `.` if you just want to do one comparison. Here I get all `User` that ordered at least one book:
```js
GRAB User { orders.products.category.name = 'Book' }
```
Same as:
```
GRAB User {orders IN { products IN { category IN { name = 'Book'} } } }
```
---
You can also use the dot like that:
```js
GRAB User.orders {name = 'Bob'}
```
The filter is done on User but it return Order.
It return all Order from User named 'Bob'.
+211
View File
@@ -0,0 +1,211 @@
# ZipponQL
ZipponDB uses its own query language, ZipponQL or ZiQL for short.
The language goal is to be minimal, small and simple.
Yet allowing powerful relationship.
Here are the key points to remember:
* 4 actions available: `GRAB`, `ADD`, `UPDATE`, `DELETE`
* All queries start with an action followed by a struct name
* `{}` are filters
* `[]` specify how much and what data
* `()` contain new or updated data (not already in files)
* `||` for ordering
* By default, all members that are not links are returned
***Disclaimer: The language may change a bit over time.***
---
## Making errors
When you make an error writing ZiQL, you should see something like this to help you understand where you made a mistake:
```lua
Error: Expected string
GRAB User {name = Bob}
^^^
```
```
Error: Expected ( or member name.
GRAB User {name = 'Bob' AND {age > 10}}
^
```
---
## To return
What is between `[]` are what data to return. You can see it as the column name after `SELECT` in SQL and number after `LIMIT`.
Here I return just the name of all users:
```
GRAB User [name] {}
```
Here the 100 first users:
```
GRAB User [100] {}
```
Here the name of the 100 first users:
```
GRAB User [100; name]
```
You can also specify what data to return for each relationship returned. By default, query do not return any relationship.
This will return the name and best friend of all users:
```
GRAB User [name, best_friend] {}
```
You can also specify what the best friend return:
```
GRAB User [name, best_friend [name, age]] {}
```
---
## Filters
What is between `{}` are filters, basically as a list of condition. This filter is use when parsing files and evaluate entities. You can see it as `WHERE` in SQL.
For example `{ name = 'Bob' }` will return `true` if the member `name` of the evaluated entity is equal to `Bob`. This is the most important thing in ZipponDB.
Here an example in a query:
```
GRAB User {name = 'Bob' AND age > 44}
```
---
## Relationship
Filter can be use inside filter. This allow simple yet powerfull relationship.
This query will return all users that have a best friend named 'Bob'.
```
GRAB User {best_friend IN {name = 'Bob'}}
```
You are obviously not limited to one depth. This will return all users that ordered at least one book in 2024:
```go
GRAB User {
orders IN {
products IN {
category IN {
name = 'Book'
}
},
date > 2024/01/01
}
}
```
Same as:
```go
GRAB User {orders IN { products.category.name = 'Book' AND date > 2024/01/01} } // (1)!
```
1. Dot not yet implemented
---
## Link query - Not yet implemented
You can also link query. Each query returns a list of UUID of a specific struct. You can use it in the next query.
Here an example where I create a new `Comment` that I then append to the list of comment of one specific `User`.
```
ADD Comment (content='Hello world', at=NOW, like_by=[], by={id='000'})
=> added_comment =>
UPDATE User {id = '000'} TO (comments APPEND added_comment)
```
The name between `=>` is the variable name of the list of UUID used for the next queries, you can have multiple one if the link has more than 2 queries.
You can also just use one `=>` but the list of UUID is discarded in that case.
This can be use with GRAB too. So you can create variable before making the query. Here an example:
```
GRAB User {name = 'Bob'} => bobs =>
GRAB User {age > 18} => adults =>
GRAB User {IN adults AND !IN bobs}
```
Which is the same as:
```
GRAB User {name != 'Bob' AND age > 18}
```
<small>Note that the query are completly isolated, so files will be parse 3 times.</small>
Another example:
```
GRAB Product [1] {category.name = 'Book'} => book =>
GRAB Order {date > 2024/01/01 AND products IN book} => book_orders =>
GRAB User [100] {orders IN book_orders}
```
---
## Actions
### [GRAB](/ZipponDB/ziql/grab)
The main action is `GRAB`, it parse files and return data.
```js
GRAB User {name = 'Bob' AND (age > 30 OR age < 10)}
```
Using `[]` before the filter tell what to return.
```js
GRAB User [id, email] {name = 'Bob'}
```
Relationship use filter within filter.
```js
GRAB User {best_friend IN {name = 'Bob'}}
```
GRAB queries return a list of JSON objects, e.g:
```
[{id:"1e170a80-84c9-429a-be25-ab4657894653", name: "Gwendolyn Ray", age: 70, email: "austin92@example.org", scores: [ 77 ], friends: [], }, ]
```
[More info.](/ZipponDB/ziql/grab)
### [ADD](/ZipponDB/ziql/add)
The `ADD` action adds one entity to the database. The syntax is similar to `GRAB`, but uses `()`. This signifies that the data is not yet in the database.
```js
ADD User (name = 'Bob', age = 30)
```
[More info.](/ZipponDB/ziql/add)
### [DELETE](/ZipponDB/ziql/delete)
Similar to `GRAB` but deletes all entities found using the filter and returns a list of deleted UUIDs.
```js
DELETE User {name = 'Bob'}
```
[More info.](/ZipponDB/ziql/delete)
### [UPDATE](/ZipponDB/ziql/update)
A mix of `GRAB` and `ADD`. It takes a filter first, then the new data.
Here, we update the first 5 `User` entities named 'bob' to capitalize the name and become 'Bob':
```js
UPDATE User [5] {name='bob'} TO (name = 'Bob')
```
[More info.](/ZipponDB/ziql/update)
+48
View File
@@ -0,0 +1,48 @@
# UPDATE
A mix of `GRAB` and `ADD`. It takes a filter first, then the new data.
Here, we update the first 5 `User` entities named 'adrien' to capitalize the name and become 'Adrien':
```js
UPDATE User [5] {name='adrien'} TO (name = 'Adrien')
```
Note that, compared to `ADD`, you don't need to specify all members between `()`. Only the ones specified will be updated.
The `UPDATE` query will return a list of updated IDs, e.g.:
```
["1e170a80-84c9-429a-be25-ab4657894653", "1e170a80-84c9-429a-be25-ab4657894654", ]
```
## Not yet implemented
You can use operations on values themselves when updating:
```js
UPDATE User {name = 'Bob'} TO (age += 1)
```
## Array - Not yet implemented
You can also manipulate arrays, like adding or removing values:
```js
UPDATE User {name='Bob'} TO (scores APPEND 45)
UPDATE User {name='Bob'} TO (scores APPEND [45 99])
UPDATE User {name='Bob'} TO (scores REMOVEAT [0 1 2])
```
Currently, there will be four keywords for manipulating lists:
- `APPEND`: Adds a value to the end of the list.
- `REMOVE`: Checks the list, and if the value is found, deletes it.
- `REMOVEAT`: Deletes the value at a specific index.
- `CLEAR`: Removes all values from the array.
- `POP`: Remove the last value.
Except for `CLEAR` and `POP`, which takes no value, each keyword can use one value or an array of values. If you choose an array, it will perform the operation on all values in the array.
For relationships, you can use filters:
```js
UPDATE User {name='Bob'} TO (comments APPEND {id = '000'})
UPDATE User {name='Bob'} TO (comments REMOVE [1] { at < '2023/12/31'})
```
I may include more options later.
+136
View File
@@ -0,0 +1,136 @@
# Vs SQL
A good way to see how ZipponQl work is to compare it to SQL.
## Select everything
```
SELECT * FROM User
```
```
GRAB User {}
```
---
## Selection on condition
```
SELECT *
FROM Users
WHERE name = 'Bob'
AND (age > 30 OR age < 10);
```
```go
GRAB User {name = 'Bob' AND (age > 30 OR age < 10)}
```
---
## Select something
```
SELECT name, age
FROM Users
LIMIT 100
```
```go
GRAB User [100; name, age] {}
```
---
## Relationship
```
SELECT u1.name AS user_name, GROUP_CONCAT(u2.name || ' (' || u2.age || ')') AS friends_list
FROM Users u1
LEFT JOIN User u2 ON ',' || u1.friends || ',' LIKE '%,' || u2.id || ',%'
WHERE u1.age > 30
GROUP BY u1.name;
```
```go
GRAB User [name, friends [name, age]] {age > 30}
```
---
SQL:
```
SELECT Users.name, Orders.orderID, Orders.orderDate
FROM Users
INNER JOIN Orders ON Users.UserID = Orders.UserID;
```
ZiQL:
```go
GRAB User [name, order [id, date]] {}
```
---
SQL:
```
SELECT
U.name AS UserName,
O.orderID,
O.orderDate,
P.productName,
C.categoryName,
OD.quantity,
FROM
Users U
INNER JOIN Orders O ON U.UserID = O.UserID
INNER JOIN OrderDetails OD ON O.OrderID = OD.OrderID
INNER JOIN Products P ON OD.ProductID = P.ProductID
INNER JOIN Categories C ON P.CategoryID = C.CategoryID
WHERE
O.orderDate >= '2023-01-01'
AND C.categoryName != 'Accessories'
ORDER BY
O.orderDate DESC;
```
ZiQL:
```go
GRAB User
[ name, orders [id, date, details [quantity, products [name, category [name]]]]]
{ orders IN {date >= 2023/01/01 AND details.products.category.name != 'Accessories' } } // (1)!
| orders.date DESC | // (2)!
```
1. Dot not yet implemented. But you can do it with:
```
details IN { products IN {category IN {name != 'Accessories'}}}
```
2. Ordering not yet implemented
---
SQL:
```
UPDATE orders o
JOIN customers c ON o.customer_id = c.customer_id
SET o.status = 'Priority'
WHERE c.membership_level = 'Premium' AND o.order_date > '2023-01-01';
```
ZiQL:
```go
GRAB User.orders { membership_level = 'Premium' } // (1)!
=> premium_order => // (2)!
UPDATE Order {id IN premium_order AND date > 2023/01/01}
TO (status = 'Priority')
```
1. Not yet implemented. Can't do it now.
Here that mean filter are done on User but it return Order.
It return all order of User with a premium membership.
2. Linked query not implemented
-1307
View File
File diff suppressed because it is too large Load Diff
-1289
View File
File diff suppressed because it is too large Load Diff
+73
View File
@@ -0,0 +1,73 @@
pub const BUFFER_SIZE = 1024 * 10; // Used a bit everywhere. The size for the schema for example. 10kB
pub const MAX_FILE_SIZE = 1024 * 1024 * 5; // Tried multiple MAX_FILE_SIZE and found 5Mb is good
pub const CPU_CORE = 0; // If 0, take maximum using std.Thread.getCpuCount()
// Debug
pub const PRINT_STATE = false;
pub const DONT_SEND = false;
pub const DONT_SEND_ERROR = false;
pub const RESET_LOG_AT_RESTART = false; // If true, will reset the log file at the start of the db, otherwise just keep adding to it
// Help message
pub const HELP_MESSAGE = struct {
pub const main: []const u8 =
\\Welcome to ZipponDB v0.2!
\\
\\Available commands:
\\run To run a query.
\\db Create or chose a database.
\\schema Initialize the database schema.
\\dump To export data in other format and backup.
\\quit Stop the CLI with memory safety.
\\
\\For more informations: https://mrbounty.github.io/ZipponDB/cli
\\
;
pub const db: []const u8 =
\\Available commands:
\\use Select or create a folder to use as database.
\\metrics Print some metrics of the current database.
\\state Print the current db state (Ok, MissingSchemaEngine, MissingFileEngine).
\\
\\For more informations: https://mrbounty.github.io/ZipponDB/cli
\\
;
pub const schema: []const u8 =
\\Available commands:
\\describe Print the schema use by the currently database.
\\use Take the path to a schema file and initialize the database.
\\
\\For more informations: https://mrbounty.github.io/ZipponDB/cli
\\
;
pub const dump: []const u8 =
\\Available commands:
\\csv Export all database in a csv format.
\\json Export all database in a json format. (Not implemented)
\\zid Export all database in a zid format. (Not implemented)
\\
\\For more informations: https://mrbounty.github.io/ZipponDB/cli
\\
;
pub const no_engine: []const u8 =
\\To start using ZipponDB you need to create a new database.
\\This is a directory/folder that will be use to store data, logs, backup, ect.
\\To create one use 'db new path/to/directory'. E.g. 'db new data'.
\\Or use an existing one with 'db use'.
\\
\\You can also set the environment variable ZIPPONDB_PATH to the desire path.
\\
\\For more informations: https://mrbounty.github.io/ZipponDB/cli
\\
;
pub const no_schema: []const u8 =
\\A database was found here `{s}` but no schema find inside.
\\To start a database, you need to attach it a schema using a schema file.
\\By using 'schema use path/to/schema'. For more informations on how to create a schema: TODO add link
\\
\\You can also set the environment variable ZIPPONDB_SCHEMA to the path to a schema file.
\\
\\For more informations: https://mrbounty.github.io/ZipponDB/Schema
\\
;
};
+73
View File
@@ -0,0 +1,73 @@
pub const BUFFER_SIZE = 1024 * 1024; // Used a bit everywhere. The size for the schema for example. 10kB
pub const MAX_FILE_SIZE = 1024 * 1024 * 5; // Tried multiple MAX_FILE_SIZE and found 5Mb is good
pub const CPU_CORE = 16;
// Debug
pub const PRINT_STATE = false;
pub const DONT_SEND = true;
pub const DONT_SEND_ERROR = false;
pub const RESET_LOG_AT_RESTART = false; // If true, will reset the log file at the start of the db, otherwise just keep adding to it
// Help message
pub const HELP_MESSAGE = struct {
pub const main: []const u8 =
\\Welcome to ZipponDB v0.2!
\\
\\Available commands:
\\run To run a query.
\\db Create or chose a database.
\\schema Initialize the database schema.
\\dump To export data in other format and backup. (experimental)
\\quit Stop the CLI with memory safety.
\\
\\For more informations: https://mrbounty.github.io/ZipponDB/cli
\\
;
pub const db: []const u8 =
\\Available commands:
\\use Select or create a folder to use as database.
\\metrics Print some metrics of the current database.
\\state Print the current db state (Ok, MissingSchemaEngine, MissingFileEngine).
\\
\\For more informations: https://mrbounty.github.io/ZipponDB/cli
\\
;
pub const schema: []const u8 =
\\Available commands:
\\describe Print the schema use by the currently database.
\\use Take the path to a schema file and initialize the database.
\\
\\For more informations: https://mrbounty.github.io/ZipponDB/cli
\\
;
pub const dump: []const u8 =
\\Available commands:
\\csv Export all database in a csv format.
\\json Export all database in a json format. (Not implemented)
\\zid Export all database in a zid format. (Not implemented)
\\
\\For more informations: https://mrbounty.github.io/ZipponDB/cli
\\
;
pub const no_engine: []const u8 =
\\To start using ZipponDB you need to create a new database.
\\This is a directory/folder that will be use to store data, logs, backup, ect.
\\To create one use 'db new path/to/directory'. E.g. 'db new data'.
\\Or use an existing one with 'db use'.
\\
\\You can also set the environment variable ZIPPONDB_PATH to the desire path.
\\
\\For more informations: https://mrbounty.github.io/ZipponDB/cli
\\
;
pub const no_schema: []const u8 =
\\A database was found here `{s}` but no schema find inside.
\\To start a database, you need to attach it a schema using a schema file.
\\By using 'schema init path/to/schema'. For more informations on how to create a schema: TODO add link
\\
\\You can also set the environment variable ZIPPONDB_SCHEMA to the path to a schema file.
\\
\\For more informations: https://mrbounty.github.io/ZipponDB/Schema
\\
;
};
+31
View File
@@ -0,0 +1,31 @@
pub const ZipponError = error{
SchemaFileNotFound,
SchemaNotConform,
DATAFolderNotFound,
StructFolderNotFound,
CantMakeDir,
CantMakeFile,
CantOpenDir,
CantOpenFile,
StreamError,
ReadError,
InvalidUUID,
InvalidDate,
InvalidFileIndex,
DirIterError,
FileStatError,
DeleteFileError,
RenameFileError,
ZipponDataError,
AllocEncodError,
MemoryError,
SynthaxError,
ThreadError,
CantWriteEntity,
WriteError,
ConditionError,
ParsingValueError,
MemberNotFound,
MemberMissing,
StructNotFound,
};
+466
View File
@@ -0,0 +1,466 @@
// Thanks to: https://github.com/nektro/zig-time/blob/master/time.zig
const std = @import("std");
const string = []const u8;
const time = @This();
pub const DateTime = struct {
ms: u16,
seconds: u8,
minutes: u8,
hours: u8,
days: u8,
months: u8,
years: u16,
const Self = @This(); // Pas mal ca
pub fn initUnixMs(unix: u64) Self {
return epoch_unix.addMs(unix);
}
pub fn initUnix(unix: u64) Self {
return epoch_unix.addSecs(unix);
}
pub fn now() Self {
return epoch_unix.addMs(@as(u64, @intCast(std.time.milliTimestamp())));
}
/// Caller asserts that this is > epoch
pub fn init(year: u16, month: u8, day: u8, hr: u8, min: u8, sec: u8, ms: u16) Self {
return Self{
.years = if (year < 1970) 1970 else year,
.months = month,
.days = day,
.hours = hr,
.minutes = min,
.seconds = sec,
.ms = ms,
};
}
pub const epoch_unix = Self{
.ms = 0,
.seconds = 0,
.minutes = 0,
.hours = 0,
.days = 0,
.months = 0,
.years = 1970,
};
pub fn eql(self: Self, other: Self) bool {
return self.ms == other.ms and
self.seconds == other.seconds and
self.minutes == other.minutes and
self.hours == other.hours and
self.days == other.days and
self.months == other.months and
self.years == other.years;
}
pub fn compareDate(self: Self, other: Self) bool {
return self.days == other.days and
self.months == other.months and
self.years == other.years;
}
pub fn compareTime(self: Self, other: Self) bool {
return self.ms == other.ms and
self.seconds == other.seconds and
self.minutes == other.minutes and
self.hours == other.hours;
}
pub fn compareDatetime(self: Self, other: Self) bool {
return self.ms == other.ms and
self.seconds == other.seconds and
self.minutes == other.minutes and
self.hours == other.hours and
self.days == other.days and
self.months == other.months and
self.years == other.years;
}
// So as long as the count / unit, it continue adding the next unit, smart
pub fn addMs(self: Self, count: u64) Self {
if (count == 0) return self;
var result = self;
result.ms += @intCast(count % 1000);
return result.addSecs(count / 1000);
}
pub fn addSecs(self: Self, count: u64) Self {
if (count == 0) return self;
var result = self;
result.seconds += @intCast(count % 60);
return result.addMins(count / 60);
}
pub fn addMins(self: Self, count: u64) Self {
if (count == 0) return self;
var result = self;
result.minutes += @intCast(count % 60);
return result.addHours(count / 60);
}
pub fn addHours(self: Self, count: u64) Self {
if (count == 0) return self;
var result = self;
result.hours += @intCast(count % 24);
return result.addDays(count / 24);
}
pub fn addDays(self: Self, count: u64) Self {
if (count == 0) return self;
var result = self;
var input = count;
while (true) {
const year_len = result.daysThisYear();
if (input >= year_len) {
result.years += 1;
input -= year_len;
continue;
}
break;
}
while (true) {
const month_len = result.daysThisMonth();
if (input >= month_len) {
result.months += 1;
input -= month_len;
if (result.months == 12) {
result.years += 1;
result.months = 0;
}
continue;
}
break;
}
{
const month_len = result.daysThisMonth();
if (result.days + input > month_len) {
const left = month_len - result.days;
input -= left;
result.months += 1;
result.days = 0;
}
result.days += @intCast(input);
if (result.days == result.daysThisMonth()) {
result.months += 1;
result.days = 0;
}
if (result.months == 12) {
result.years += 1;
result.months = 0;
}
}
std.debug.assert(result.ms < 1000);
std.debug.assert(result.seconds < 60);
std.debug.assert(result.minutes < 60);
std.debug.assert(result.hours < 24);
std.debug.assert(result.days < result.daysThisMonth());
std.debug.assert(result.months < 12);
return result;
}
pub fn addMonths(self: Self, count: u64) Self {
if (count == 0) return self;
var result = self;
var input = count;
while (input > 0) {
const new = result.addDays(result.daysThisMonth());
result = new;
input -= 1;
}
return result;
}
pub fn addYears(self: Self, count: u64) Self {
var result = self;
for (0..count) |_| {
result = result.addDays(result.daysThisYear());
}
return result;
}
pub fn isLeapYear(self: Self) bool {
return time.isLeapYear(self.years);
}
pub fn daysThisYear(self: Self) u16 {
return time.daysInYear(self.years);
}
pub fn daysThisMonth(self: Self) u16 {
return self.daysInMonth(self.months);
}
fn daysInMonth(self: Self, month: u16) u16 {
return time.daysInMonth(self.years, month);
}
pub fn dayOfThisYear(self: Self) u16 {
var ret: u16 = 0;
for (0..self.months) |item| {
ret += self.daysInMonth(@intCast(item));
}
ret += self.days;
return ret;
}
pub fn toUnix(self: Self) u64 {
const x = self.toUnixMilli();
return x / 1000;
}
pub fn toUnixMilli(self: Self) u64 {
var res: u64 = 0;
res += self.ms;
res += @as(u64, self.seconds) * std.time.ms_per_s;
res += @as(u64, self.minutes) * std.time.ms_per_min;
res += @as(u64, self.hours) * std.time.ms_per_hour;
res += self.daysSinceEpoch() * std.time.ms_per_day;
return res;
}
fn daysSinceEpoch(self: Self) u64 {
var res: u64 = 0;
res += self.days;
for (0..self.years - epoch_unix.years) |i| res += time.daysInYear(@intCast(i));
for (0..self.months) |i| res += self.daysInMonth(@intCast(i));
return res;
}
/// fmt is based on https://momentjs.com/docs/#/displaying/format/
pub fn format(self: Self, comptime fmt: string, writer: anytype) !void {
if (fmt.len == 0) @compileError("DateTime: format string can't be empty");
@setEvalBranchQuota(100000);
comptime var s = 0;
comptime var e = 0;
comptime var next: ?FormatSeq = null;
inline for (fmt, 0..) |c, i| {
e = i + 1;
if (comptime std.meta.stringToEnum(FormatSeq, fmt[s..e])) |tag| {
next = tag;
if (i < fmt.len - 1) continue;
}
if (next) |tag| {
switch (tag) {
.MM => try writer.print("{:0>2}", .{self.months + 1}),
.M => try writer.print("{}", .{self.months + 1}),
.Mo => try printOrdinal(writer, self.months + 1),
.MMM => try printLongName(writer, self.months, &[_]string{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }),
.MMMM => try printLongName(writer, self.months, &[_]string{ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }),
.Q => try writer.print("{}", .{self.months / 3 + 1}),
.Qo => try printOrdinal(writer, self.months / 3 + 1),
.D => try writer.print("{}", .{self.days + 1}),
.Do => try printOrdinal(writer, self.days + 1),
.DD => try writer.print("{:0>2}", .{self.days + 1}),
.DDD => try writer.print("{}", .{self.dayOfThisYear() + 1}),
.DDDo => try printOrdinal(writer, self.dayOfThisYear() + 1),
.DDDD => try writer.print("{:0>3}", .{self.dayOfThisYear() + 1}),
.d => try writer.print("{}", .{@intFromEnum(self.weekday())}),
.do => try printOrdinal(writer, @intFromEnum(self.weekday())),
.dd => try writer.writeAll(@tagName(self.weekday())[0..2]),
.ddd => try writer.writeAll(@tagName(self.weekday())),
.dddd => try printLongName(writer, @intFromEnum(self.weekday()), &[_]string{ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }),
.e => try writer.print("{}", .{@intFromEnum(self.weekday())}),
.E => try writer.print("{}", .{@intFromEnum(self.weekday()) + 1}),
.w => try writer.print("{}", .{self.dayOfThisYear() / 7 + 1}),
.wo => try printOrdinal(writer, self.dayOfThisYear() / 7 + 1),
.ww => try writer.print("{:0>2}", .{self.dayOfThisYear() / 7 + 1}),
.Y => try writer.print("{}", .{self.years + 10000}),
.YY => try writer.print("{:0>2}", .{self.years % 100}),
.YYY => try writer.print("{}", .{self.years}),
.YYYY => try writer.print("{:0>4}", .{self.years}),
.N => try writer.writeAll(@tagName(self.era())),
.NN => try writer.writeAll("Anno Domini"),
.A => try printLongName(writer, self.hours / 12, &[_]string{ "AM", "PM" }),
.a => try printLongName(writer, self.hours / 12, &[_]string{ "am", "pm" }),
.H => try writer.print("{}", .{self.hours}),
.HH => try writer.print("{:0>2}", .{self.hours}),
.h => try writer.print("{}", .{wrap(self.hours, 12)}),
.hh => try writer.print("{:0>2}", .{wrap(self.hours, 12)}),
.k => try writer.print("{}", .{wrap(self.hours, 24)}),
.kk => try writer.print("{:0>2}", .{wrap(self.hours, 24)}),
.m => try writer.print("{}", .{self.minutes}),
.mm => try writer.print("{:0>2}", .{self.minutes}),
.s => try writer.print("{}", .{self.seconds}),
.ss => try writer.print("{:0>2}", .{self.seconds}),
.S => try writer.print("{}", .{self.ms / 100}),
.SS => try writer.print("{:0>2}", .{self.ms / 10}),
.SSS => try writer.print("{:0>3}", .{self.ms}),
.z => try writer.writeAll(@tagName(self.timezone)),
.Z => try writer.writeAll("+00:00"),
.ZZ => try writer.writeAll("+0000"),
.x => try writer.print("{}", .{self.toUnixMilli()}),
.X => try writer.print("{}", .{self.toUnix()}),
}
next = null;
s = i;
}
switch (c) {
',',
' ',
':',
'-',
'.',
'T',
'W',
'/',
=> {
try writer.writeAll(&.{c});
s = i + 1;
continue;
},
else => {},
}
}
}
pub fn formatAlloc(self: Self, alloc: std.mem.Allocator, comptime fmt: string) !string {
var list = std.ArrayList(u8).init(alloc);
defer list.deinit();
try self.format(fmt, .{}, list.writer());
return list.toOwnedSlice();
}
const FormatSeq = enum {
M, // 1 2 ... 11 12
Mo, // 1st 2nd ... 11th 12th
MM, // 01 02 ... 11 12
MMM, // Jan Feb ... Nov Dec
MMMM, // January February ... November December
Q, // 1 2 3 4
Qo, // 1st 2nd 3rd 4th
D, // 1 2 ... 30 31
Do, // 1st 2nd ... 30th 31st
DD, // 01 02 ... 30 31
DDD, // 1 2 ... 364 365
DDDo, // 1st 2nd ... 364th 365th
DDDD, // 001 002 ... 364 365
d, // 0 1 ... 5 6
do, // 0th 1st ... 5th 6th
dd, // Su Mo ... Fr Sa
ddd, // Sun Mon ... Fri Sat
dddd, // Sunday Monday ... Friday Saturday
e, // 0 1 ... 5 6 (locale)
E, // 1 2 ... 6 7 (ISO)
w, // 1 2 ... 52 53
wo, // 1st 2nd ... 52nd 53rd
ww, // 01 02 ... 52 53
Y, // 11970 11971 ... 19999 20000 20001 (Holocene calendar)
YY, // 70 71 ... 29 30
YYY, // 1 2 ... 1970 1971 ... 2029 2030
YYYY, // 0001 0002 ... 1970 1971 ... 2029 2030
N, // BC AD
NN, // Before Christ ... Anno Domini
A, // AM PM
a, // am pm
H, // 0 1 ... 22 23
HH, // 00 01 ... 22 23
h, // 1 2 ... 11 12
hh, // 01 02 ... 11 12
k, // 1 2 ... 23 24
kk, // 01 02 ... 23 24
m, // 0 1 ... 58 59
mm, // 00 01 ... 58 59
s, // 0 1 ... 58 59
ss, // 00 01 ... 58 59
S, // 0 1 ... 8 9 (second fraction)
SS, // 00 01 ... 98 99
SSS, // 000 001 ... 998 999
z, // EST CST ... MST PST
Z, // -07:00 -06:00 ... +06:00 +07:00
ZZ, // -0700 -0600 ... +0600 +0700
x, // unix milli
X, // unix
};
pub fn since(self: Self, other_in_the_past: Self) Duration {
return Duration{
.ms = self.toUnixMilli() - other_in_the_past.toUnixMilli(),
};
}
};
pub const format = struct {
pub const LT = "h:mm A";
pub const LTS = "h:mm:ss A";
pub const L = "MM/DD/YYYY";
pub const l = "M/D/YYY";
pub const LL = "MMMM D, YYYY";
pub const ll = "MMM D, YYY";
pub const LLL = LL ++ " " ++ LT;
pub const lll = ll ++ " " ++ LT;
pub const LLLL = "dddd, " ++ LLL;
pub const llll = "ddd, " ++ lll;
};
pub fn isLeapYear(year: u16) bool {
var ret = false;
if (year % 4 == 0) ret = true;
if (year % 100 == 0) ret = false;
if (year % 400 == 0) ret = true;
return ret;
}
pub fn daysInYear(year: u16) u16 {
return if (isLeapYear(year)) 366 else 365;
}
fn daysInMonth(year: u16, month: u16) u16 {
const norm = [12]u16{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
const leap = [12]u16{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
const month_days = if (!isLeapYear(year)) norm else leap;
return month_days[month];
}
fn printOrdinal(writer: anytype, num: u16) !void {
try writer.print("{}", .{num});
try writer.writeAll(switch (num) {
1 => "st",
2 => "nd",
3 => "rd",
else => "th",
});
}
fn printLongName(writer: anytype, index: u16, names: []const string) !void {
try writer.writeAll(names[index]);
}
fn wrap(val: u16, at: u16) u16 {
const tmp = val % at;
return if (tmp == 0) at else tmp;
}
pub const Duration = struct {
ms: u64,
};
+37
View File
@@ -0,0 +1,37 @@
// This file is just to expose what I need to grab
pub const UUID = @import("uuid.zig").UUID;
pub const Zero = @import("uuid.zig").zero;
pub const DateTime = @import("date.zig").DateTime;
pub const OR = @import("uuid.zig").OR;
pub const AND = @import("uuid.zig").AND;
pub const s2t = @import("stringToType.zig");
/// Suported dataType for the DB
/// Maybe start using a unionenum
pub const DataType = enum {
int,
float,
str,
bool,
link,
self, // self represent itself, it is the id
date,
time,
datetime,
int_array,
float_array,
str_array,
bool_array,
date_array,
time_array,
datetime_array,
link_array,
pub fn is_array(self: DataType) bool {
return switch (self) {
.int_array, .float_array, .str_array, .bool_array, .date_array, .time_array, .datetime_array, .link_array => true,
else => false,
};
}
};

Some files were not shown because too many files have changed in this diff Show More