├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── rustfmt.toml └── src ├── catalog ├── catalog.rs ├── desc.rs └── mod.rs ├── core ├── context.rs ├── mod.rs └── planner.rs ├── main.rs ├── optimizer ├── builder.rs ├── expr.rs ├── implement.rs ├── metadata.rs └── mod.rs ├── parser ├── cypher.ebnf ├── expr.rs ├── mod.rs ├── parser.rs └── stmt.rs ├── runtime ├── executor.rs ├── expression │ ├── expr.rs │ ├── function.rs │ ├── mod.rs │ └── scalar.rs └── mod.rs ├── server ├── mod.rs └── query.rs ├── storage └── mod.rs ├── types ├── mod.rs └── types.rs └── util ├── error.rs ├── idgen.rs ├── mod.rs └── walker.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "actix-codec" 5 | version = "0.3.0" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "78d1833b3838dbe990df0f1f87baf640cf6146e898166afe401839d1b001e570" 8 | dependencies = [ 9 | "bitflags", 10 | "bytes 0.5.6", 11 | "futures-core", 12 | "futures-sink", 13 | "log", 14 | "pin-project 0.4.27", 15 | "tokio", 16 | "tokio-util", 17 | ] 18 | 19 | [[package]] 20 | name = "actix-connect" 21 | version = "2.0.0" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | checksum = "177837a10863f15ba8d3ae3ec12fac1099099529ed20083a27fdfe247381d0dc" 24 | dependencies = [ 25 | "actix-codec", 26 | "actix-rt", 27 | "actix-service", 28 | "actix-utils", 29 | "derive_more", 30 | "either", 31 | "futures-util", 32 | "http", 33 | "log", 34 | "trust-dns-proto", 35 | "trust-dns-resolver", 36 | ] 37 | 38 | [[package]] 39 | name = "actix-http" 40 | version = "2.2.0" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "452299e87817ae5673910e53c243484ca38be3828db819b6011736fc6982e874" 43 | dependencies = [ 44 | "actix-codec", 45 | "actix-connect", 46 | "actix-rt", 47 | "actix-service", 48 | "actix-threadpool", 49 | "actix-utils", 50 | "base64 0.13.0", 51 | "bitflags", 52 | "brotli2", 53 | "bytes 0.5.6", 54 | "cookie", 55 | "copyless", 56 | "derive_more", 57 | "either", 58 | "encoding_rs", 59 | "flate2", 60 | "futures-channel", 61 | "futures-core", 62 | "futures-util", 63 | "fxhash", 64 | "h2", 65 | "http", 66 | "httparse", 67 | "indexmap", 68 | "itoa", 69 | "language-tags", 70 | "lazy_static", 71 | "log", 72 | "mime", 73 | "percent-encoding", 74 | "pin-project 1.0.4", 75 | "rand 0.7.3", 76 | "regex", 77 | "serde", 78 | "serde_json", 79 | "serde_urlencoded", 80 | "sha-1", 81 | "slab", 82 | "time 0.2.24", 83 | ] 84 | 85 | [[package]] 86 | name = "actix-macros" 87 | version = "0.1.3" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655" 90 | dependencies = [ 91 | "quote", 92 | "syn", 93 | ] 94 | 95 | [[package]] 96 | name = "actix-router" 97 | version = "0.2.6" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "b8be584b3b6c705a18eabc11c4059cf83b255bdd8511673d1d569f4ce40c69de" 100 | dependencies = [ 101 | "bytestring", 102 | "http", 103 | "log", 104 | "regex", 105 | "serde", 106 | ] 107 | 108 | [[package]] 109 | name = "actix-rt" 110 | version = "1.1.1" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "143fcc2912e0d1de2bcf4e2f720d2a60c28652ab4179685a1ee159e0fb3db227" 113 | dependencies = [ 114 | "actix-macros", 115 | "actix-threadpool", 116 | "copyless", 117 | "futures-channel", 118 | "futures-util", 119 | "smallvec", 120 | "tokio", 121 | ] 122 | 123 | [[package]] 124 | name = "actix-server" 125 | version = "1.0.4" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "45407e6e672ca24784baa667c5d32ef109ccdd8d5e0b5ebb9ef8a67f4dfb708e" 128 | dependencies = [ 129 | "actix-codec", 130 | "actix-rt", 131 | "actix-service", 132 | "actix-utils", 133 | "futures-channel", 134 | "futures-util", 135 | "log", 136 | "mio", 137 | "mio-uds", 138 | "num_cpus", 139 | "slab", 140 | "socket2", 141 | ] 142 | 143 | [[package]] 144 | name = "actix-service" 145 | version = "1.0.6" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "0052435d581b5be835d11f4eb3bce417c8af18d87ddf8ace99f8e67e595882bb" 148 | dependencies = [ 149 | "futures-util", 150 | "pin-project 0.4.27", 151 | ] 152 | 153 | [[package]] 154 | name = "actix-testing" 155 | version = "1.0.1" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "47239ca38799ab74ee6a8a94d1ce857014b2ac36f242f70f3f75a66f691e791c" 158 | dependencies = [ 159 | "actix-macros", 160 | "actix-rt", 161 | "actix-server", 162 | "actix-service", 163 | "log", 164 | "socket2", 165 | ] 166 | 167 | [[package]] 168 | name = "actix-threadpool" 169 | version = "0.3.3" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "d209f04d002854b9afd3743032a27b066158817965bf5d036824d19ac2cc0e30" 172 | dependencies = [ 173 | "derive_more", 174 | "futures-channel", 175 | "lazy_static", 176 | "log", 177 | "num_cpus", 178 | "parking_lot", 179 | "threadpool", 180 | ] 181 | 182 | [[package]] 183 | name = "actix-tls" 184 | version = "2.0.0" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "24789b7d7361cf5503a504ebe1c10806896f61e96eca9a7350e23001aca715fb" 187 | dependencies = [ 188 | "actix-codec", 189 | "actix-service", 190 | "actix-utils", 191 | "futures-util", 192 | ] 193 | 194 | [[package]] 195 | name = "actix-utils" 196 | version = "2.0.0" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "2e9022dec56632d1d7979e59af14f0597a28a830a9c1c7fec8b2327eb9f16b5a" 199 | dependencies = [ 200 | "actix-codec", 201 | "actix-rt", 202 | "actix-service", 203 | "bitflags", 204 | "bytes 0.5.6", 205 | "either", 206 | "futures-channel", 207 | "futures-sink", 208 | "futures-util", 209 | "log", 210 | "pin-project 0.4.27", 211 | "slab", 212 | ] 213 | 214 | [[package]] 215 | name = "actix-web" 216 | version = "3.3.2" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "e641d4a172e7faa0862241a20ff4f1f5ab0ab7c279f00c2d4587b77483477b86" 219 | dependencies = [ 220 | "actix-codec", 221 | "actix-http", 222 | "actix-macros", 223 | "actix-router", 224 | "actix-rt", 225 | "actix-server", 226 | "actix-service", 227 | "actix-testing", 228 | "actix-threadpool", 229 | "actix-tls", 230 | "actix-utils", 231 | "actix-web-codegen", 232 | "awc", 233 | "bytes 0.5.6", 234 | "derive_more", 235 | "encoding_rs", 236 | "futures-channel", 237 | "futures-core", 238 | "futures-util", 239 | "fxhash", 240 | "log", 241 | "mime", 242 | "pin-project 1.0.4", 243 | "regex", 244 | "serde", 245 | "serde_json", 246 | "serde_urlencoded", 247 | "socket2", 248 | "time 0.2.24", 249 | "tinyvec", 250 | "url", 251 | ] 252 | 253 | [[package]] 254 | name = "actix-web-codegen" 255 | version = "0.4.0" 256 | source = "registry+https://github.com/rust-lang/crates.io-index" 257 | checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb" 258 | dependencies = [ 259 | "proc-macro2", 260 | "quote", 261 | "syn", 262 | ] 263 | 264 | [[package]] 265 | name = "addr2line" 266 | version = "0.14.1" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" 269 | dependencies = [ 270 | "gimli", 271 | ] 272 | 273 | [[package]] 274 | name = "adler" 275 | version = "0.2.3" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" 278 | 279 | [[package]] 280 | name = "ahash" 281 | version = "0.4.7" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" 284 | 285 | [[package]] 286 | name = "aho-corasick" 287 | version = "0.7.15" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" 290 | dependencies = [ 291 | "memchr", 292 | ] 293 | 294 | [[package]] 295 | name = "arrayvec" 296 | version = "0.5.2" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" 299 | 300 | [[package]] 301 | name = "async-trait" 302 | version = "0.1.42" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d" 305 | dependencies = [ 306 | "proc-macro2", 307 | "quote", 308 | "syn", 309 | ] 310 | 311 | [[package]] 312 | name = "autocfg" 313 | version = "1.0.1" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 316 | 317 | [[package]] 318 | name = "awc" 319 | version = "2.0.3" 320 | source = "registry+https://github.com/rust-lang/crates.io-index" 321 | checksum = "b381e490e7b0cfc37ebc54079b0413d8093ef43d14a4e4747083f7fa47a9e691" 322 | dependencies = [ 323 | "actix-codec", 324 | "actix-http", 325 | "actix-rt", 326 | "actix-service", 327 | "base64 0.13.0", 328 | "bytes 0.5.6", 329 | "cfg-if 1.0.0", 330 | "derive_more", 331 | "futures-core", 332 | "log", 333 | "mime", 334 | "percent-encoding", 335 | "rand 0.7.3", 336 | "serde", 337 | "serde_json", 338 | "serde_urlencoded", 339 | ] 340 | 341 | [[package]] 342 | name = "backtrace" 343 | version = "0.3.55" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "ef5140344c85b01f9bbb4d4b7288a8aa4b3287ccef913a14bcc78a1063623598" 346 | dependencies = [ 347 | "addr2line", 348 | "cfg-if 1.0.0", 349 | "libc", 350 | "miniz_oxide", 351 | "object", 352 | "rustc-demangle", 353 | ] 354 | 355 | [[package]] 356 | name = "base-x" 357 | version = "0.2.8" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" 360 | 361 | [[package]] 362 | name = "base64" 363 | version = "0.12.3" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" 366 | 367 | [[package]] 368 | name = "base64" 369 | version = "0.13.0" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 372 | 373 | [[package]] 374 | name = "bigdecimal" 375 | version = "0.1.2" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "1374191e2dd25f9ae02e3aa95041ed5d747fc77b3c102b49fe2dd9a8117a6244" 378 | dependencies = [ 379 | "num-bigint", 380 | "num-integer", 381 | "num-traits", 382 | "serde", 383 | ] 384 | 385 | [[package]] 386 | name = "bitflags" 387 | version = "1.2.1" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 390 | 391 | [[package]] 392 | name = "bitvec" 393 | version = "0.19.4" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81" 396 | dependencies = [ 397 | "funty", 398 | "radium", 399 | "tap", 400 | "wyz", 401 | ] 402 | 403 | [[package]] 404 | name = "block-buffer" 405 | version = "0.7.3" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" 408 | dependencies = [ 409 | "block-padding", 410 | "byte-tools", 411 | "byteorder", 412 | "generic-array 0.12.3", 413 | ] 414 | 415 | [[package]] 416 | name = "block-buffer" 417 | version = "0.9.0" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" 420 | dependencies = [ 421 | "generic-array 0.14.4", 422 | ] 423 | 424 | [[package]] 425 | name = "block-padding" 426 | version = "0.1.5" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" 429 | dependencies = [ 430 | "byte-tools", 431 | ] 432 | 433 | [[package]] 434 | name = "brotli-sys" 435 | version = "0.3.2" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" 438 | dependencies = [ 439 | "cc", 440 | "libc", 441 | ] 442 | 443 | [[package]] 444 | name = "brotli2" 445 | version = "0.3.2" 446 | source = "registry+https://github.com/rust-lang/crates.io-index" 447 | checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" 448 | dependencies = [ 449 | "brotli-sys", 450 | "libc", 451 | ] 452 | 453 | [[package]] 454 | name = "bufstream" 455 | version = "0.1.4" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" 458 | 459 | [[package]] 460 | name = "bumpalo" 461 | version = "3.4.0" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" 464 | 465 | [[package]] 466 | name = "byte-tools" 467 | version = "0.3.1" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" 470 | 471 | [[package]] 472 | name = "byteorder" 473 | version = "1.4.2" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" 476 | 477 | [[package]] 478 | name = "bytes" 479 | version = "0.5.6" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" 482 | 483 | [[package]] 484 | name = "bytes" 485 | version = "1.0.1" 486 | source = "registry+https://github.com/rust-lang/crates.io-index" 487 | checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" 488 | 489 | [[package]] 490 | name = "bytestring" 491 | version = "1.0.0" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "90706ba19e97b90786e19dc0d5e2abd80008d99d4c0c5d1ad0b5e72cec7c494d" 494 | dependencies = [ 495 | "bytes 1.0.1", 496 | ] 497 | 498 | [[package]] 499 | name = "cc" 500 | version = "1.0.66" 501 | source = "registry+https://github.com/rust-lang/crates.io-index" 502 | checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" 503 | 504 | [[package]] 505 | name = "cfg-if" 506 | version = "0.1.10" 507 | source = "registry+https://github.com/rust-lang/crates.io-index" 508 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 509 | 510 | [[package]] 511 | name = "cfg-if" 512 | version = "1.0.0" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 515 | 516 | [[package]] 517 | name = "chrono" 518 | version = "0.4.19" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" 521 | dependencies = [ 522 | "libc", 523 | "num-integer", 524 | "num-traits", 525 | "serde", 526 | "time 0.1.43", 527 | "winapi 0.3.9", 528 | ] 529 | 530 | [[package]] 531 | name = "const_fn" 532 | version = "0.4.5" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" 535 | 536 | [[package]] 537 | name = "cookie" 538 | version = "0.14.3" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | checksum = "784ad0fbab4f3e9cef09f20e0aea6000ae08d2cb98ac4c0abc53df18803d702f" 541 | dependencies = [ 542 | "percent-encoding", 543 | "time 0.2.24", 544 | "version_check", 545 | ] 546 | 547 | [[package]] 548 | name = "copyless" 549 | version = "0.1.5" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" 552 | 553 | [[package]] 554 | name = "core-foundation" 555 | version = "0.9.1" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" 558 | dependencies = [ 559 | "core-foundation-sys", 560 | "libc", 561 | ] 562 | 563 | [[package]] 564 | name = "core-foundation-sys" 565 | version = "0.8.2" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" 568 | 569 | [[package]] 570 | name = "cpuid-bool" 571 | version = "0.1.2" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" 574 | 575 | [[package]] 576 | name = "crc32fast" 577 | version = "1.2.1" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" 580 | dependencies = [ 581 | "cfg-if 1.0.0", 582 | ] 583 | 584 | [[package]] 585 | name = "derive_more" 586 | version = "0.99.11" 587 | source = "registry+https://github.com/rust-lang/crates.io-index" 588 | checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" 589 | dependencies = [ 590 | "proc-macro2", 591 | "quote", 592 | "syn", 593 | ] 594 | 595 | [[package]] 596 | name = "derive_utils" 597 | version = "0.11.2" 598 | source = "registry+https://github.com/rust-lang/crates.io-index" 599 | checksum = "532b4c15dccee12c7044f1fcad956e98410860b22231e44a3b827464797ca7bf" 600 | dependencies = [ 601 | "proc-macro2", 602 | "quote", 603 | "syn", 604 | ] 605 | 606 | [[package]] 607 | name = "digest" 608 | version = "0.8.1" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" 611 | dependencies = [ 612 | "generic-array 0.12.3", 613 | ] 614 | 615 | [[package]] 616 | name = "digest" 617 | version = "0.9.0" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" 620 | dependencies = [ 621 | "generic-array 0.14.4", 622 | ] 623 | 624 | [[package]] 625 | name = "discard" 626 | version = "1.0.4" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" 629 | 630 | [[package]] 631 | name = "either" 632 | version = "1.6.1" 633 | source = "registry+https://github.com/rust-lang/crates.io-index" 634 | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" 635 | 636 | [[package]] 637 | name = "encoding_rs" 638 | version = "0.8.26" 639 | source = "registry+https://github.com/rust-lang/crates.io-index" 640 | checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283" 641 | dependencies = [ 642 | "cfg-if 1.0.0", 643 | ] 644 | 645 | [[package]] 646 | name = "enum-as-inner" 647 | version = "0.3.3" 648 | source = "registry+https://github.com/rust-lang/crates.io-index" 649 | checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" 650 | dependencies = [ 651 | "heck", 652 | "proc-macro2", 653 | "quote", 654 | "syn", 655 | ] 656 | 657 | [[package]] 658 | name = "fake-simd" 659 | version = "0.1.2" 660 | source = "registry+https://github.com/rust-lang/crates.io-index" 661 | checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" 662 | 663 | [[package]] 664 | name = "flate2" 665 | version = "1.0.19" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129" 668 | dependencies = [ 669 | "cfg-if 1.0.0", 670 | "crc32fast", 671 | "libc", 672 | "libz-sys", 673 | "miniz_oxide", 674 | ] 675 | 676 | [[package]] 677 | name = "fnv" 678 | version = "1.0.7" 679 | source = "registry+https://github.com/rust-lang/crates.io-index" 680 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 681 | 682 | [[package]] 683 | name = "foreign-types" 684 | version = "0.3.2" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 687 | dependencies = [ 688 | "foreign-types-shared", 689 | ] 690 | 691 | [[package]] 692 | name = "foreign-types-shared" 693 | version = "0.1.1" 694 | source = "registry+https://github.com/rust-lang/crates.io-index" 695 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 696 | 697 | [[package]] 698 | name = "form_urlencoded" 699 | version = "1.0.0" 700 | source = "registry+https://github.com/rust-lang/crates.io-index" 701 | checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00" 702 | dependencies = [ 703 | "matches", 704 | "percent-encoding", 705 | ] 706 | 707 | [[package]] 708 | name = "fuchsia-zircon" 709 | version = "0.3.3" 710 | source = "registry+https://github.com/rust-lang/crates.io-index" 711 | checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 712 | dependencies = [ 713 | "bitflags", 714 | "fuchsia-zircon-sys", 715 | ] 716 | 717 | [[package]] 718 | name = "fuchsia-zircon-sys" 719 | version = "0.3.3" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 722 | 723 | [[package]] 724 | name = "funty" 725 | version = "1.1.0" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" 728 | 729 | [[package]] 730 | name = "futures" 731 | version = "0.3.12" 732 | source = "registry+https://github.com/rust-lang/crates.io-index" 733 | checksum = "da9052a1a50244d8d5aa9bf55cbc2fb6f357c86cc52e46c62ed390a7180cf150" 734 | dependencies = [ 735 | "futures-channel", 736 | "futures-core", 737 | "futures-io", 738 | "futures-sink", 739 | "futures-task", 740 | "futures-util", 741 | ] 742 | 743 | [[package]] 744 | name = "futures-channel" 745 | version = "0.3.12" 746 | source = "registry+https://github.com/rust-lang/crates.io-index" 747 | checksum = "f2d31b7ec7efab6eefc7c57233bb10b847986139d88cc2f5a02a1ae6871a1846" 748 | dependencies = [ 749 | "futures-core", 750 | "futures-sink", 751 | ] 752 | 753 | [[package]] 754 | name = "futures-core" 755 | version = "0.3.12" 756 | source = "registry+https://github.com/rust-lang/crates.io-index" 757 | checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65" 758 | 759 | [[package]] 760 | name = "futures-io" 761 | version = "0.3.12" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "28be053525281ad8259d47e4de5de657b25e7bac113458555bb4b70bc6870500" 764 | 765 | [[package]] 766 | name = "futures-macro" 767 | version = "0.3.12" 768 | source = "registry+https://github.com/rust-lang/crates.io-index" 769 | checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd" 770 | dependencies = [ 771 | "proc-macro-hack", 772 | "proc-macro2", 773 | "quote", 774 | "syn", 775 | ] 776 | 777 | [[package]] 778 | name = "futures-sink" 779 | version = "0.3.12" 780 | source = "registry+https://github.com/rust-lang/crates.io-index" 781 | checksum = "caf5c69029bda2e743fddd0582d1083951d65cc9539aebf8812f36c3491342d6" 782 | 783 | [[package]] 784 | name = "futures-task" 785 | version = "0.3.12" 786 | source = "registry+https://github.com/rust-lang/crates.io-index" 787 | checksum = "13de07eb8ea81ae445aca7b69f5f7bf15d7bf4912d8ca37d6645c77ae8a58d86" 788 | dependencies = [ 789 | "once_cell", 790 | ] 791 | 792 | [[package]] 793 | name = "futures-util" 794 | version = "0.3.12" 795 | source = "registry+https://github.com/rust-lang/crates.io-index" 796 | checksum = "632a8cd0f2a4b3fdea1657f08bde063848c3bd00f9bbf6e256b8be78802e624b" 797 | dependencies = [ 798 | "futures-channel", 799 | "futures-core", 800 | "futures-io", 801 | "futures-macro", 802 | "futures-sink", 803 | "futures-task", 804 | "memchr", 805 | "pin-project-lite 0.2.4", 806 | "pin-utils", 807 | "proc-macro-hack", 808 | "proc-macro-nested", 809 | "slab", 810 | ] 811 | 812 | [[package]] 813 | name = "fxhash" 814 | version = "0.2.1" 815 | source = "registry+https://github.com/rust-lang/crates.io-index" 816 | checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" 817 | dependencies = [ 818 | "byteorder", 819 | ] 820 | 821 | [[package]] 822 | name = "generic-array" 823 | version = "0.12.3" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" 826 | dependencies = [ 827 | "typenum", 828 | ] 829 | 830 | [[package]] 831 | name = "generic-array" 832 | version = "0.14.4" 833 | source = "registry+https://github.com/rust-lang/crates.io-index" 834 | checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" 835 | dependencies = [ 836 | "typenum", 837 | "version_check", 838 | ] 839 | 840 | [[package]] 841 | name = "getrandom" 842 | version = "0.1.16" 843 | source = "registry+https://github.com/rust-lang/crates.io-index" 844 | checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" 845 | dependencies = [ 846 | "cfg-if 1.0.0", 847 | "libc", 848 | "wasi 0.9.0+wasi-snapshot-preview1", 849 | ] 850 | 851 | [[package]] 852 | name = "getrandom" 853 | version = "0.2.1" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "4060f4657be78b8e766215b02b18a2e862d83745545de804638e2b545e81aee6" 856 | dependencies = [ 857 | "cfg-if 1.0.0", 858 | "libc", 859 | "wasi 0.10.1+wasi-snapshot-preview1", 860 | ] 861 | 862 | [[package]] 863 | name = "gimli" 864 | version = "0.23.0" 865 | source = "registry+https://github.com/rust-lang/crates.io-index" 866 | checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" 867 | 868 | [[package]] 869 | name = "h2" 870 | version = "0.2.7" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" 873 | dependencies = [ 874 | "bytes 0.5.6", 875 | "fnv", 876 | "futures-core", 877 | "futures-sink", 878 | "futures-util", 879 | "http", 880 | "indexmap", 881 | "slab", 882 | "tokio", 883 | "tokio-util", 884 | "tracing", 885 | "tracing-futures", 886 | ] 887 | 888 | [[package]] 889 | name = "hashbrown" 890 | version = "0.9.1" 891 | source = "registry+https://github.com/rust-lang/crates.io-index" 892 | checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" 893 | dependencies = [ 894 | "ahash", 895 | ] 896 | 897 | [[package]] 898 | name = "heck" 899 | version = "0.3.2" 900 | source = "registry+https://github.com/rust-lang/crates.io-index" 901 | checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" 902 | dependencies = [ 903 | "unicode-segmentation", 904 | ] 905 | 906 | [[package]] 907 | name = "hermit-abi" 908 | version = "0.1.17" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" 911 | dependencies = [ 912 | "libc", 913 | ] 914 | 915 | [[package]] 916 | name = "hostname" 917 | version = "0.3.1" 918 | source = "registry+https://github.com/rust-lang/crates.io-index" 919 | checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" 920 | dependencies = [ 921 | "libc", 922 | "match_cfg", 923 | "winapi 0.3.9", 924 | ] 925 | 926 | [[package]] 927 | name = "http" 928 | version = "0.2.3" 929 | source = "registry+https://github.com/rust-lang/crates.io-index" 930 | checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" 931 | dependencies = [ 932 | "bytes 1.0.1", 933 | "fnv", 934 | "itoa", 935 | ] 936 | 937 | [[package]] 938 | name = "httparse" 939 | version = "1.3.4" 940 | source = "registry+https://github.com/rust-lang/crates.io-index" 941 | checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" 942 | 943 | [[package]] 944 | name = "idna" 945 | version = "0.2.0" 946 | source = "registry+https://github.com/rust-lang/crates.io-index" 947 | checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" 948 | dependencies = [ 949 | "matches", 950 | "unicode-bidi", 951 | "unicode-normalization", 952 | ] 953 | 954 | [[package]] 955 | name = "indexmap" 956 | version = "1.6.1" 957 | source = "registry+https://github.com/rust-lang/crates.io-index" 958 | checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" 959 | dependencies = [ 960 | "autocfg", 961 | "hashbrown", 962 | ] 963 | 964 | [[package]] 965 | name = "instant" 966 | version = "0.1.9" 967 | source = "registry+https://github.com/rust-lang/crates.io-index" 968 | checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" 969 | dependencies = [ 970 | "cfg-if 1.0.0", 971 | ] 972 | 973 | [[package]] 974 | name = "io-enum" 975 | version = "0.2.6" 976 | source = "registry+https://github.com/rust-lang/crates.io-index" 977 | checksum = "94534fd32a986dd34d97ddefe5198630d5ed99efd4e9b9b9ed4359e6b23a9cf7" 978 | dependencies = [ 979 | "autocfg", 980 | "derive_utils", 981 | "quote", 982 | "syn", 983 | ] 984 | 985 | [[package]] 986 | name = "iovec" 987 | version = "0.1.4" 988 | source = "registry+https://github.com/rust-lang/crates.io-index" 989 | checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" 990 | dependencies = [ 991 | "libc", 992 | ] 993 | 994 | [[package]] 995 | name = "ipconfig" 996 | version = "0.2.2" 997 | source = "registry+https://github.com/rust-lang/crates.io-index" 998 | checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" 999 | dependencies = [ 1000 | "socket2", 1001 | "widestring", 1002 | "winapi 0.3.9", 1003 | "winreg", 1004 | ] 1005 | 1006 | [[package]] 1007 | name = "itoa" 1008 | version = "0.4.7" 1009 | source = "registry+https://github.com/rust-lang/crates.io-index" 1010 | checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" 1011 | 1012 | [[package]] 1013 | name = "kernel32-sys" 1014 | version = "0.2.2" 1015 | source = "registry+https://github.com/rust-lang/crates.io-index" 1016 | checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 1017 | dependencies = [ 1018 | "winapi 0.2.8", 1019 | "winapi-build", 1020 | ] 1021 | 1022 | [[package]] 1023 | name = "language-tags" 1024 | version = "0.2.2" 1025 | source = "registry+https://github.com/rust-lang/crates.io-index" 1026 | checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" 1027 | 1028 | [[package]] 1029 | name = "lazy_static" 1030 | version = "1.4.0" 1031 | source = "registry+https://github.com/rust-lang/crates.io-index" 1032 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 1033 | 1034 | [[package]] 1035 | name = "lexical" 1036 | version = "5.2.0" 1037 | source = "registry+https://github.com/rust-lang/crates.io-index" 1038 | checksum = "a28ff8a57641758c89a37b2d28556a68978b3ea3f709f39953e153acea3dbacf" 1039 | dependencies = [ 1040 | "cfg-if 0.1.10", 1041 | "lexical-core", 1042 | ] 1043 | 1044 | [[package]] 1045 | name = "lexical-core" 1046 | version = "0.7.4" 1047 | source = "registry+https://github.com/rust-lang/crates.io-index" 1048 | checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616" 1049 | dependencies = [ 1050 | "arrayvec", 1051 | "bitflags", 1052 | "cfg-if 0.1.10", 1053 | "ryu", 1054 | "static_assertions", 1055 | ] 1056 | 1057 | [[package]] 1058 | name = "libc" 1059 | version = "0.2.82" 1060 | source = "registry+https://github.com/rust-lang/crates.io-index" 1061 | checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" 1062 | 1063 | [[package]] 1064 | name = "libz-sys" 1065 | version = "1.1.2" 1066 | source = "registry+https://github.com/rust-lang/crates.io-index" 1067 | checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655" 1068 | dependencies = [ 1069 | "cc", 1070 | "pkg-config", 1071 | "vcpkg", 1072 | ] 1073 | 1074 | [[package]] 1075 | name = "linked-hash-map" 1076 | version = "0.5.4" 1077 | source = "registry+https://github.com/rust-lang/crates.io-index" 1078 | checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" 1079 | 1080 | [[package]] 1081 | name = "lock_api" 1082 | version = "0.4.2" 1083 | source = "registry+https://github.com/rust-lang/crates.io-index" 1084 | checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" 1085 | dependencies = [ 1086 | "scopeguard", 1087 | ] 1088 | 1089 | [[package]] 1090 | name = "log" 1091 | version = "0.4.13" 1092 | source = "registry+https://github.com/rust-lang/crates.io-index" 1093 | checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2" 1094 | dependencies = [ 1095 | "cfg-if 0.1.10", 1096 | ] 1097 | 1098 | [[package]] 1099 | name = "lru" 1100 | version = "0.6.3" 1101 | source = "registry+https://github.com/rust-lang/crates.io-index" 1102 | checksum = "3aae342b73d57ad0b8b364bd12584819f2c1fe9114285dfcf8b0722607671635" 1103 | dependencies = [ 1104 | "hashbrown", 1105 | ] 1106 | 1107 | [[package]] 1108 | name = "lru-cache" 1109 | version = "0.1.2" 1110 | source = "registry+https://github.com/rust-lang/crates.io-index" 1111 | checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" 1112 | dependencies = [ 1113 | "linked-hash-map", 1114 | ] 1115 | 1116 | [[package]] 1117 | name = "match_cfg" 1118 | version = "0.1.0" 1119 | source = "registry+https://github.com/rust-lang/crates.io-index" 1120 | checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" 1121 | 1122 | [[package]] 1123 | name = "matches" 1124 | version = "0.1.8" 1125 | source = "registry+https://github.com/rust-lang/crates.io-index" 1126 | checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" 1127 | 1128 | [[package]] 1129 | name = "memchr" 1130 | version = "2.3.4" 1131 | source = "registry+https://github.com/rust-lang/crates.io-index" 1132 | checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" 1133 | 1134 | [[package]] 1135 | name = "mime" 1136 | version = "0.3.16" 1137 | source = "registry+https://github.com/rust-lang/crates.io-index" 1138 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 1139 | 1140 | [[package]] 1141 | name = "miniz_oxide" 1142 | version = "0.4.3" 1143 | source = "registry+https://github.com/rust-lang/crates.io-index" 1144 | checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" 1145 | dependencies = [ 1146 | "adler", 1147 | "autocfg", 1148 | ] 1149 | 1150 | [[package]] 1151 | name = "mio" 1152 | version = "0.6.23" 1153 | source = "registry+https://github.com/rust-lang/crates.io-index" 1154 | checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" 1155 | dependencies = [ 1156 | "cfg-if 0.1.10", 1157 | "fuchsia-zircon", 1158 | "fuchsia-zircon-sys", 1159 | "iovec", 1160 | "kernel32-sys", 1161 | "libc", 1162 | "log", 1163 | "miow", 1164 | "net2", 1165 | "slab", 1166 | "winapi 0.2.8", 1167 | ] 1168 | 1169 | [[package]] 1170 | name = "mio-uds" 1171 | version = "0.6.8" 1172 | source = "registry+https://github.com/rust-lang/crates.io-index" 1173 | checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" 1174 | dependencies = [ 1175 | "iovec", 1176 | "libc", 1177 | "mio", 1178 | ] 1179 | 1180 | [[package]] 1181 | name = "miow" 1182 | version = "0.2.2" 1183 | source = "registry+https://github.com/rust-lang/crates.io-index" 1184 | checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" 1185 | dependencies = [ 1186 | "kernel32-sys", 1187 | "net2", 1188 | "winapi 0.2.8", 1189 | "ws2_32-sys", 1190 | ] 1191 | 1192 | [[package]] 1193 | name = "mysql" 1194 | version = "20.1.0" 1195 | source = "registry+https://github.com/rust-lang/crates.io-index" 1196 | checksum = "e5a8660184af84975ac1639aa692a539c37739cec8a22a414de3db9cb573c1aa" 1197 | dependencies = [ 1198 | "bufstream", 1199 | "io-enum", 1200 | "libc", 1201 | "lru", 1202 | "mysql_common", 1203 | "named_pipe", 1204 | "native-tls", 1205 | "nix", 1206 | "pem", 1207 | "percent-encoding", 1208 | "serde", 1209 | "serde_json", 1210 | "socket2", 1211 | "twox-hash", 1212 | "url", 1213 | ] 1214 | 1215 | [[package]] 1216 | name = "mysql_common" 1217 | version = "0.24.1" 1218 | source = "registry+https://github.com/rust-lang/crates.io-index" 1219 | checksum = "de63b87a5f24c5db252418a6f04abb2f62823bd838dc9b1d7fdb8ae972ef76cf" 1220 | dependencies = [ 1221 | "base64 0.12.3", 1222 | "bigdecimal", 1223 | "bitflags", 1224 | "byteorder", 1225 | "bytes 0.5.6", 1226 | "chrono", 1227 | "flate2", 1228 | "lazy_static", 1229 | "lexical", 1230 | "num-bigint", 1231 | "num-traits", 1232 | "rand 0.7.3", 1233 | "regex", 1234 | "rust_decimal", 1235 | "serde", 1236 | "serde_json", 1237 | "sha1", 1238 | "sha2", 1239 | "time 0.2.24", 1240 | "twox-hash", 1241 | "uuid", 1242 | ] 1243 | 1244 | [[package]] 1245 | name = "named_pipe" 1246 | version = "0.4.1" 1247 | source = "registry+https://github.com/rust-lang/crates.io-index" 1248 | checksum = "ad9c443cce91fc3e12f017290db75dde490d685cdaaf508d7159d7cf41f0eb2b" 1249 | dependencies = [ 1250 | "winapi 0.3.9", 1251 | ] 1252 | 1253 | [[package]] 1254 | name = "native-tls" 1255 | version = "0.2.7" 1256 | source = "registry+https://github.com/rust-lang/crates.io-index" 1257 | checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" 1258 | dependencies = [ 1259 | "lazy_static", 1260 | "libc", 1261 | "log", 1262 | "openssl", 1263 | "openssl-probe", 1264 | "openssl-sys", 1265 | "schannel", 1266 | "security-framework", 1267 | "security-framework-sys", 1268 | "tempfile", 1269 | ] 1270 | 1271 | [[package]] 1272 | name = "net2" 1273 | version = "0.2.37" 1274 | source = "registry+https://github.com/rust-lang/crates.io-index" 1275 | checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" 1276 | dependencies = [ 1277 | "cfg-if 0.1.10", 1278 | "libc", 1279 | "winapi 0.3.9", 1280 | ] 1281 | 1282 | [[package]] 1283 | name = "nix" 1284 | version = "0.19.1" 1285 | source = "registry+https://github.com/rust-lang/crates.io-index" 1286 | checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2" 1287 | dependencies = [ 1288 | "bitflags", 1289 | "cc", 1290 | "cfg-if 1.0.0", 1291 | "libc", 1292 | ] 1293 | 1294 | [[package]] 1295 | name = "nom" 1296 | version = "6.0.1" 1297 | source = "registry+https://github.com/rust-lang/crates.io-index" 1298 | checksum = "88034cfd6b4a0d54dd14f4a507eceee36c0b70e5a02236c4e4df571102be17f0" 1299 | dependencies = [ 1300 | "bitvec", 1301 | "lexical-core", 1302 | "memchr", 1303 | "version_check", 1304 | ] 1305 | 1306 | [[package]] 1307 | name = "num-bigint" 1308 | version = "0.2.6" 1309 | source = "registry+https://github.com/rust-lang/crates.io-index" 1310 | checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" 1311 | dependencies = [ 1312 | "autocfg", 1313 | "num-integer", 1314 | "num-traits", 1315 | ] 1316 | 1317 | [[package]] 1318 | name = "num-integer" 1319 | version = "0.1.44" 1320 | source = "registry+https://github.com/rust-lang/crates.io-index" 1321 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 1322 | dependencies = [ 1323 | "autocfg", 1324 | "num-traits", 1325 | ] 1326 | 1327 | [[package]] 1328 | name = "num-traits" 1329 | version = "0.2.14" 1330 | source = "registry+https://github.com/rust-lang/crates.io-index" 1331 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 1332 | dependencies = [ 1333 | "autocfg", 1334 | ] 1335 | 1336 | [[package]] 1337 | name = "num_cpus" 1338 | version = "1.13.0" 1339 | source = "registry+https://github.com/rust-lang/crates.io-index" 1340 | checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" 1341 | dependencies = [ 1342 | "hermit-abi", 1343 | "libc", 1344 | ] 1345 | 1346 | [[package]] 1347 | name = "object" 1348 | version = "0.22.0" 1349 | source = "registry+https://github.com/rust-lang/crates.io-index" 1350 | checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" 1351 | 1352 | [[package]] 1353 | name = "once_cell" 1354 | version = "1.5.2" 1355 | source = "registry+https://github.com/rust-lang/crates.io-index" 1356 | checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" 1357 | 1358 | [[package]] 1359 | name = "opaque-debug" 1360 | version = "0.2.3" 1361 | source = "registry+https://github.com/rust-lang/crates.io-index" 1362 | checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" 1363 | 1364 | [[package]] 1365 | name = "opaque-debug" 1366 | version = "0.3.0" 1367 | source = "registry+https://github.com/rust-lang/crates.io-index" 1368 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" 1369 | 1370 | [[package]] 1371 | name = "openssl" 1372 | version = "0.10.32" 1373 | source = "registry+https://github.com/rust-lang/crates.io-index" 1374 | checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70" 1375 | dependencies = [ 1376 | "bitflags", 1377 | "cfg-if 1.0.0", 1378 | "foreign-types", 1379 | "lazy_static", 1380 | "libc", 1381 | "openssl-sys", 1382 | ] 1383 | 1384 | [[package]] 1385 | name = "openssl-probe" 1386 | version = "0.1.2" 1387 | source = "registry+https://github.com/rust-lang/crates.io-index" 1388 | checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" 1389 | 1390 | [[package]] 1391 | name = "openssl-sys" 1392 | version = "0.9.60" 1393 | source = "registry+https://github.com/rust-lang/crates.io-index" 1394 | checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6" 1395 | dependencies = [ 1396 | "autocfg", 1397 | "cc", 1398 | "libc", 1399 | "pkg-config", 1400 | "vcpkg", 1401 | ] 1402 | 1403 | [[package]] 1404 | name = "parking_lot" 1405 | version = "0.11.1" 1406 | source = "registry+https://github.com/rust-lang/crates.io-index" 1407 | checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" 1408 | dependencies = [ 1409 | "instant", 1410 | "lock_api", 1411 | "parking_lot_core", 1412 | ] 1413 | 1414 | [[package]] 1415 | name = "parking_lot_core" 1416 | version = "0.8.2" 1417 | source = "registry+https://github.com/rust-lang/crates.io-index" 1418 | checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272" 1419 | dependencies = [ 1420 | "cfg-if 1.0.0", 1421 | "instant", 1422 | "libc", 1423 | "redox_syscall 0.1.57", 1424 | "smallvec", 1425 | "winapi 0.3.9", 1426 | ] 1427 | 1428 | [[package]] 1429 | name = "pem" 1430 | version = "0.8.2" 1431 | source = "registry+https://github.com/rust-lang/crates.io-index" 1432 | checksum = "f4c220d01f863d13d96ca82359d1e81e64a7c6bf0637bcde7b2349630addf0c6" 1433 | dependencies = [ 1434 | "base64 0.13.0", 1435 | "once_cell", 1436 | "regex", 1437 | ] 1438 | 1439 | [[package]] 1440 | name = "percent-encoding" 1441 | version = "2.1.0" 1442 | source = "registry+https://github.com/rust-lang/crates.io-index" 1443 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 1444 | 1445 | [[package]] 1446 | name = "pin-project" 1447 | version = "0.4.27" 1448 | source = "registry+https://github.com/rust-lang/crates.io-index" 1449 | checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15" 1450 | dependencies = [ 1451 | "pin-project-internal 0.4.27", 1452 | ] 1453 | 1454 | [[package]] 1455 | name = "pin-project" 1456 | version = "1.0.4" 1457 | source = "registry+https://github.com/rust-lang/crates.io-index" 1458 | checksum = "95b70b68509f17aa2857863b6fa00bf21fc93674c7a8893de2f469f6aa7ca2f2" 1459 | dependencies = [ 1460 | "pin-project-internal 1.0.4", 1461 | ] 1462 | 1463 | [[package]] 1464 | name = "pin-project-internal" 1465 | version = "0.4.27" 1466 | source = "registry+https://github.com/rust-lang/crates.io-index" 1467 | checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895" 1468 | dependencies = [ 1469 | "proc-macro2", 1470 | "quote", 1471 | "syn", 1472 | ] 1473 | 1474 | [[package]] 1475 | name = "pin-project-internal" 1476 | version = "1.0.4" 1477 | source = "registry+https://github.com/rust-lang/crates.io-index" 1478 | checksum = "caa25a6393f22ce819b0f50e0be89287292fda8d425be38ee0ca14c4931d9e71" 1479 | dependencies = [ 1480 | "proc-macro2", 1481 | "quote", 1482 | "syn", 1483 | ] 1484 | 1485 | [[package]] 1486 | name = "pin-project-lite" 1487 | version = "0.1.11" 1488 | source = "registry+https://github.com/rust-lang/crates.io-index" 1489 | checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" 1490 | 1491 | [[package]] 1492 | name = "pin-project-lite" 1493 | version = "0.2.4" 1494 | source = "registry+https://github.com/rust-lang/crates.io-index" 1495 | checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827" 1496 | 1497 | [[package]] 1498 | name = "pin-utils" 1499 | version = "0.1.0" 1500 | source = "registry+https://github.com/rust-lang/crates.io-index" 1501 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1502 | 1503 | [[package]] 1504 | name = "pkg-config" 1505 | version = "0.3.19" 1506 | source = "registry+https://github.com/rust-lang/crates.io-index" 1507 | checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" 1508 | 1509 | [[package]] 1510 | name = "ppv-lite86" 1511 | version = "0.2.10" 1512 | source = "registry+https://github.com/rust-lang/crates.io-index" 1513 | checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" 1514 | 1515 | [[package]] 1516 | name = "proc-macro-hack" 1517 | version = "0.5.19" 1518 | source = "registry+https://github.com/rust-lang/crates.io-index" 1519 | checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" 1520 | 1521 | [[package]] 1522 | name = "proc-macro-nested" 1523 | version = "0.1.7" 1524 | source = "registry+https://github.com/rust-lang/crates.io-index" 1525 | checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" 1526 | 1527 | [[package]] 1528 | name = "proc-macro2" 1529 | version = "1.0.24" 1530 | source = "registry+https://github.com/rust-lang/crates.io-index" 1531 | checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" 1532 | dependencies = [ 1533 | "unicode-xid", 1534 | ] 1535 | 1536 | [[package]] 1537 | name = "quick-error" 1538 | version = "1.2.3" 1539 | source = "registry+https://github.com/rust-lang/crates.io-index" 1540 | checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" 1541 | 1542 | [[package]] 1543 | name = "quote" 1544 | version = "1.0.8" 1545 | source = "registry+https://github.com/rust-lang/crates.io-index" 1546 | checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" 1547 | dependencies = [ 1548 | "proc-macro2", 1549 | ] 1550 | 1551 | [[package]] 1552 | name = "radium" 1553 | version = "0.5.3" 1554 | source = "registry+https://github.com/rust-lang/crates.io-index" 1555 | checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" 1556 | 1557 | [[package]] 1558 | name = "rand" 1559 | version = "0.7.3" 1560 | source = "registry+https://github.com/rust-lang/crates.io-index" 1561 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" 1562 | dependencies = [ 1563 | "getrandom 0.1.16", 1564 | "libc", 1565 | "rand_chacha 0.2.2", 1566 | "rand_core 0.5.1", 1567 | "rand_hc 0.2.0", 1568 | ] 1569 | 1570 | [[package]] 1571 | name = "rand" 1572 | version = "0.8.2" 1573 | source = "registry+https://github.com/rust-lang/crates.io-index" 1574 | checksum = "18519b42a40024d661e1714153e9ad0c3de27cd495760ceb09710920f1098b1e" 1575 | dependencies = [ 1576 | "libc", 1577 | "rand_chacha 0.3.0", 1578 | "rand_core 0.6.1", 1579 | "rand_hc 0.3.0", 1580 | ] 1581 | 1582 | [[package]] 1583 | name = "rand_chacha" 1584 | version = "0.2.2" 1585 | source = "registry+https://github.com/rust-lang/crates.io-index" 1586 | checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" 1587 | dependencies = [ 1588 | "ppv-lite86", 1589 | "rand_core 0.5.1", 1590 | ] 1591 | 1592 | [[package]] 1593 | name = "rand_chacha" 1594 | version = "0.3.0" 1595 | source = "registry+https://github.com/rust-lang/crates.io-index" 1596 | checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" 1597 | dependencies = [ 1598 | "ppv-lite86", 1599 | "rand_core 0.6.1", 1600 | ] 1601 | 1602 | [[package]] 1603 | name = "rand_core" 1604 | version = "0.5.1" 1605 | source = "registry+https://github.com/rust-lang/crates.io-index" 1606 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 1607 | dependencies = [ 1608 | "getrandom 0.1.16", 1609 | ] 1610 | 1611 | [[package]] 1612 | name = "rand_core" 1613 | version = "0.6.1" 1614 | source = "registry+https://github.com/rust-lang/crates.io-index" 1615 | checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5" 1616 | dependencies = [ 1617 | "getrandom 0.2.1", 1618 | ] 1619 | 1620 | [[package]] 1621 | name = "rand_hc" 1622 | version = "0.2.0" 1623 | source = "registry+https://github.com/rust-lang/crates.io-index" 1624 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 1625 | dependencies = [ 1626 | "rand_core 0.5.1", 1627 | ] 1628 | 1629 | [[package]] 1630 | name = "rand_hc" 1631 | version = "0.3.0" 1632 | source = "registry+https://github.com/rust-lang/crates.io-index" 1633 | checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" 1634 | dependencies = [ 1635 | "rand_core 0.6.1", 1636 | ] 1637 | 1638 | [[package]] 1639 | name = "redox_syscall" 1640 | version = "0.1.57" 1641 | source = "registry+https://github.com/rust-lang/crates.io-index" 1642 | checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" 1643 | 1644 | [[package]] 1645 | name = "redox_syscall" 1646 | version = "0.2.4" 1647 | source = "registry+https://github.com/rust-lang/crates.io-index" 1648 | checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570" 1649 | dependencies = [ 1650 | "bitflags", 1651 | ] 1652 | 1653 | [[package]] 1654 | name = "regex" 1655 | version = "1.4.3" 1656 | source = "registry+https://github.com/rust-lang/crates.io-index" 1657 | checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" 1658 | dependencies = [ 1659 | "aho-corasick", 1660 | "memchr", 1661 | "regex-syntax", 1662 | "thread_local", 1663 | ] 1664 | 1665 | [[package]] 1666 | name = "regex-syntax" 1667 | version = "0.6.22" 1668 | source = "registry+https://github.com/rust-lang/crates.io-index" 1669 | checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" 1670 | 1671 | [[package]] 1672 | name = "remove_dir_all" 1673 | version = "0.5.3" 1674 | source = "registry+https://github.com/rust-lang/crates.io-index" 1675 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 1676 | dependencies = [ 1677 | "winapi 0.3.9", 1678 | ] 1679 | 1680 | [[package]] 1681 | name = "resolv-conf" 1682 | version = "0.7.0" 1683 | source = "registry+https://github.com/rust-lang/crates.io-index" 1684 | checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" 1685 | dependencies = [ 1686 | "hostname", 1687 | "quick-error", 1688 | ] 1689 | 1690 | [[package]] 1691 | name = "rust_decimal" 1692 | version = "1.9.0" 1693 | source = "registry+https://github.com/rust-lang/crates.io-index" 1694 | checksum = "a5c739ba050709eae138f053356d27ff818d71fe54ce5a8d9f4c7a660bfb6684" 1695 | dependencies = [ 1696 | "num-traits", 1697 | "serde", 1698 | ] 1699 | 1700 | [[package]] 1701 | name = "rustc-demangle" 1702 | version = "0.1.18" 1703 | source = "registry+https://github.com/rust-lang/crates.io-index" 1704 | checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" 1705 | 1706 | [[package]] 1707 | name = "rustc_version" 1708 | version = "0.2.3" 1709 | source = "registry+https://github.com/rust-lang/crates.io-index" 1710 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 1711 | dependencies = [ 1712 | "semver", 1713 | ] 1714 | 1715 | [[package]] 1716 | name = "ryu" 1717 | version = "1.0.5" 1718 | source = "registry+https://github.com/rust-lang/crates.io-index" 1719 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" 1720 | 1721 | [[package]] 1722 | name = "schannel" 1723 | version = "0.1.19" 1724 | source = "registry+https://github.com/rust-lang/crates.io-index" 1725 | checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" 1726 | dependencies = [ 1727 | "lazy_static", 1728 | "winapi 0.3.9", 1729 | ] 1730 | 1731 | [[package]] 1732 | name = "scopeguard" 1733 | version = "1.1.0" 1734 | source = "registry+https://github.com/rust-lang/crates.io-index" 1735 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1736 | 1737 | [[package]] 1738 | name = "security-framework" 1739 | version = "2.0.0" 1740 | source = "registry+https://github.com/rust-lang/crates.io-index" 1741 | checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69" 1742 | dependencies = [ 1743 | "bitflags", 1744 | "core-foundation", 1745 | "core-foundation-sys", 1746 | "libc", 1747 | "security-framework-sys", 1748 | ] 1749 | 1750 | [[package]] 1751 | name = "security-framework-sys" 1752 | version = "2.0.0" 1753 | source = "registry+https://github.com/rust-lang/crates.io-index" 1754 | checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b" 1755 | dependencies = [ 1756 | "core-foundation-sys", 1757 | "libc", 1758 | ] 1759 | 1760 | [[package]] 1761 | name = "semver" 1762 | version = "0.9.0" 1763 | source = "registry+https://github.com/rust-lang/crates.io-index" 1764 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 1765 | dependencies = [ 1766 | "semver-parser", 1767 | ] 1768 | 1769 | [[package]] 1770 | name = "semver-parser" 1771 | version = "0.7.0" 1772 | source = "registry+https://github.com/rust-lang/crates.io-index" 1773 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 1774 | 1775 | [[package]] 1776 | name = "serde" 1777 | version = "1.0.118" 1778 | source = "registry+https://github.com/rust-lang/crates.io-index" 1779 | checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" 1780 | dependencies = [ 1781 | "serde_derive", 1782 | ] 1783 | 1784 | [[package]] 1785 | name = "serde_derive" 1786 | version = "1.0.118" 1787 | source = "registry+https://github.com/rust-lang/crates.io-index" 1788 | checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" 1789 | dependencies = [ 1790 | "proc-macro2", 1791 | "quote", 1792 | "syn", 1793 | ] 1794 | 1795 | [[package]] 1796 | name = "serde_json" 1797 | version = "1.0.61" 1798 | source = "registry+https://github.com/rust-lang/crates.io-index" 1799 | checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a" 1800 | dependencies = [ 1801 | "itoa", 1802 | "ryu", 1803 | "serde", 1804 | ] 1805 | 1806 | [[package]] 1807 | name = "serde_urlencoded" 1808 | version = "0.7.0" 1809 | source = "registry+https://github.com/rust-lang/crates.io-index" 1810 | checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" 1811 | dependencies = [ 1812 | "form_urlencoded", 1813 | "itoa", 1814 | "ryu", 1815 | "serde", 1816 | ] 1817 | 1818 | [[package]] 1819 | name = "sha-1" 1820 | version = "0.9.2" 1821 | source = "registry+https://github.com/rust-lang/crates.io-index" 1822 | checksum = "ce3cdf1b5e620a498ee6f2a171885ac7e22f0e12089ec4b3d22b84921792507c" 1823 | dependencies = [ 1824 | "block-buffer 0.9.0", 1825 | "cfg-if 1.0.0", 1826 | "cpuid-bool", 1827 | "digest 0.9.0", 1828 | "opaque-debug 0.3.0", 1829 | ] 1830 | 1831 | [[package]] 1832 | name = "sha1" 1833 | version = "0.6.0" 1834 | source = "registry+https://github.com/rust-lang/crates.io-index" 1835 | checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" 1836 | 1837 | [[package]] 1838 | name = "sha2" 1839 | version = "0.8.2" 1840 | source = "registry+https://github.com/rust-lang/crates.io-index" 1841 | checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" 1842 | dependencies = [ 1843 | "block-buffer 0.7.3", 1844 | "digest 0.8.1", 1845 | "fake-simd", 1846 | "opaque-debug 0.2.3", 1847 | ] 1848 | 1849 | [[package]] 1850 | name = "signal-hook-registry" 1851 | version = "1.3.0" 1852 | source = "registry+https://github.com/rust-lang/crates.io-index" 1853 | checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" 1854 | dependencies = [ 1855 | "libc", 1856 | ] 1857 | 1858 | [[package]] 1859 | name = "slab" 1860 | version = "0.4.2" 1861 | source = "registry+https://github.com/rust-lang/crates.io-index" 1862 | checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 1863 | 1864 | [[package]] 1865 | name = "smallvec" 1866 | version = "1.6.1" 1867 | source = "registry+https://github.com/rust-lang/crates.io-index" 1868 | checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" 1869 | 1870 | [[package]] 1871 | name = "socket2" 1872 | version = "0.3.19" 1873 | source = "registry+https://github.com/rust-lang/crates.io-index" 1874 | checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" 1875 | dependencies = [ 1876 | "cfg-if 1.0.0", 1877 | "libc", 1878 | "winapi 0.3.9", 1879 | ] 1880 | 1881 | [[package]] 1882 | name = "standback" 1883 | version = "0.2.14" 1884 | source = "registry+https://github.com/rust-lang/crates.io-index" 1885 | checksum = "c66a8cff4fa24853fdf6b51f75c6d7f8206d7c75cab4e467bcd7f25c2b1febe0" 1886 | dependencies = [ 1887 | "version_check", 1888 | ] 1889 | 1890 | [[package]] 1891 | name = "static_assertions" 1892 | version = "1.1.0" 1893 | source = "registry+https://github.com/rust-lang/crates.io-index" 1894 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 1895 | 1896 | [[package]] 1897 | name = "stdweb" 1898 | version = "0.4.20" 1899 | source = "registry+https://github.com/rust-lang/crates.io-index" 1900 | checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" 1901 | dependencies = [ 1902 | "discard", 1903 | "rustc_version", 1904 | "stdweb-derive", 1905 | "stdweb-internal-macros", 1906 | "stdweb-internal-runtime", 1907 | "wasm-bindgen", 1908 | ] 1909 | 1910 | [[package]] 1911 | name = "stdweb-derive" 1912 | version = "0.5.3" 1913 | source = "registry+https://github.com/rust-lang/crates.io-index" 1914 | checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" 1915 | dependencies = [ 1916 | "proc-macro2", 1917 | "quote", 1918 | "serde", 1919 | "serde_derive", 1920 | "syn", 1921 | ] 1922 | 1923 | [[package]] 1924 | name = "stdweb-internal-macros" 1925 | version = "0.2.9" 1926 | source = "registry+https://github.com/rust-lang/crates.io-index" 1927 | checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" 1928 | dependencies = [ 1929 | "base-x", 1930 | "proc-macro2", 1931 | "quote", 1932 | "serde", 1933 | "serde_derive", 1934 | "serde_json", 1935 | "sha1", 1936 | "syn", 1937 | ] 1938 | 1939 | [[package]] 1940 | name = "stdweb-internal-runtime" 1941 | version = "0.1.5" 1942 | source = "registry+https://github.com/rust-lang/crates.io-index" 1943 | checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" 1944 | 1945 | [[package]] 1946 | name = "syn" 1947 | version = "1.0.56" 1948 | source = "registry+https://github.com/rust-lang/crates.io-index" 1949 | checksum = "a9802ddde94170d186eeee5005b798d9c159fa970403f1be19976d0cfb939b72" 1950 | dependencies = [ 1951 | "proc-macro2", 1952 | "quote", 1953 | "unicode-xid", 1954 | ] 1955 | 1956 | [[package]] 1957 | name = "tap" 1958 | version = "1.0.0" 1959 | source = "registry+https://github.com/rust-lang/crates.io-index" 1960 | checksum = "36474e732d1affd3a6ed582781b3683df3d0563714c59c39591e8ff707cf078e" 1961 | 1962 | [[package]] 1963 | name = "tempfile" 1964 | version = "3.2.0" 1965 | source = "registry+https://github.com/rust-lang/crates.io-index" 1966 | checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" 1967 | dependencies = [ 1968 | "cfg-if 1.0.0", 1969 | "libc", 1970 | "rand 0.8.2", 1971 | "redox_syscall 0.2.4", 1972 | "remove_dir_all", 1973 | "winapi 0.3.9", 1974 | ] 1975 | 1976 | [[package]] 1977 | name = "thiserror" 1978 | version = "1.0.23" 1979 | source = "registry+https://github.com/rust-lang/crates.io-index" 1980 | checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146" 1981 | dependencies = [ 1982 | "thiserror-impl", 1983 | ] 1984 | 1985 | [[package]] 1986 | name = "thiserror-impl" 1987 | version = "1.0.23" 1988 | source = "registry+https://github.com/rust-lang/crates.io-index" 1989 | checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1" 1990 | dependencies = [ 1991 | "proc-macro2", 1992 | "quote", 1993 | "syn", 1994 | ] 1995 | 1996 | [[package]] 1997 | name = "thread_local" 1998 | version = "1.1.0" 1999 | source = "registry+https://github.com/rust-lang/crates.io-index" 2000 | checksum = "bb9bc092d0d51e76b2b19d9d85534ffc9ec2db959a2523cdae0697e2972cd447" 2001 | dependencies = [ 2002 | "lazy_static", 2003 | ] 2004 | 2005 | [[package]] 2006 | name = "threadpool" 2007 | version = "1.8.1" 2008 | source = "registry+https://github.com/rust-lang/crates.io-index" 2009 | checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" 2010 | dependencies = [ 2011 | "num_cpus", 2012 | ] 2013 | 2014 | [[package]] 2015 | name = "tigraph" 2016 | version = "0.1.0" 2017 | dependencies = [ 2018 | "actix-web", 2019 | "mysql", 2020 | "nom", 2021 | "serde", 2022 | "serde_json", 2023 | ] 2024 | 2025 | [[package]] 2026 | name = "time" 2027 | version = "0.1.43" 2028 | source = "registry+https://github.com/rust-lang/crates.io-index" 2029 | checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" 2030 | dependencies = [ 2031 | "libc", 2032 | "winapi 0.3.9", 2033 | ] 2034 | 2035 | [[package]] 2036 | name = "time" 2037 | version = "0.2.24" 2038 | source = "registry+https://github.com/rust-lang/crates.io-index" 2039 | checksum = "273d3ed44dca264b0d6b3665e8d48fb515042d42466fad93d2a45b90ec4058f7" 2040 | dependencies = [ 2041 | "const_fn", 2042 | "libc", 2043 | "standback", 2044 | "stdweb", 2045 | "time-macros", 2046 | "version_check", 2047 | "winapi 0.3.9", 2048 | ] 2049 | 2050 | [[package]] 2051 | name = "time-macros" 2052 | version = "0.1.1" 2053 | source = "registry+https://github.com/rust-lang/crates.io-index" 2054 | checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" 2055 | dependencies = [ 2056 | "proc-macro-hack", 2057 | "time-macros-impl", 2058 | ] 2059 | 2060 | [[package]] 2061 | name = "time-macros-impl" 2062 | version = "0.1.1" 2063 | source = "registry+https://github.com/rust-lang/crates.io-index" 2064 | checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa" 2065 | dependencies = [ 2066 | "proc-macro-hack", 2067 | "proc-macro2", 2068 | "quote", 2069 | "standback", 2070 | "syn", 2071 | ] 2072 | 2073 | [[package]] 2074 | name = "tinyvec" 2075 | version = "1.1.0" 2076 | source = "registry+https://github.com/rust-lang/crates.io-index" 2077 | checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f" 2078 | dependencies = [ 2079 | "tinyvec_macros", 2080 | ] 2081 | 2082 | [[package]] 2083 | name = "tinyvec_macros" 2084 | version = "0.1.0" 2085 | source = "registry+https://github.com/rust-lang/crates.io-index" 2086 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 2087 | 2088 | [[package]] 2089 | name = "tokio" 2090 | version = "0.2.24" 2091 | source = "registry+https://github.com/rust-lang/crates.io-index" 2092 | checksum = "099837d3464c16a808060bb3f02263b412f6fafcb5d01c533d309985fbeebe48" 2093 | dependencies = [ 2094 | "bytes 0.5.6", 2095 | "futures-core", 2096 | "iovec", 2097 | "lazy_static", 2098 | "libc", 2099 | "memchr", 2100 | "mio", 2101 | "mio-uds", 2102 | "pin-project-lite 0.1.11", 2103 | "signal-hook-registry", 2104 | "slab", 2105 | "winapi 0.3.9", 2106 | ] 2107 | 2108 | [[package]] 2109 | name = "tokio-util" 2110 | version = "0.3.1" 2111 | source = "registry+https://github.com/rust-lang/crates.io-index" 2112 | checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" 2113 | dependencies = [ 2114 | "bytes 0.5.6", 2115 | "futures-core", 2116 | "futures-sink", 2117 | "log", 2118 | "pin-project-lite 0.1.11", 2119 | "tokio", 2120 | ] 2121 | 2122 | [[package]] 2123 | name = "tracing" 2124 | version = "0.1.22" 2125 | source = "registry+https://github.com/rust-lang/crates.io-index" 2126 | checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3" 2127 | dependencies = [ 2128 | "cfg-if 1.0.0", 2129 | "log", 2130 | "pin-project-lite 0.2.4", 2131 | "tracing-core", 2132 | ] 2133 | 2134 | [[package]] 2135 | name = "tracing-core" 2136 | version = "0.1.17" 2137 | source = "registry+https://github.com/rust-lang/crates.io-index" 2138 | checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" 2139 | dependencies = [ 2140 | "lazy_static", 2141 | ] 2142 | 2143 | [[package]] 2144 | name = "tracing-futures" 2145 | version = "0.2.4" 2146 | source = "registry+https://github.com/rust-lang/crates.io-index" 2147 | checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c" 2148 | dependencies = [ 2149 | "pin-project 0.4.27", 2150 | "tracing", 2151 | ] 2152 | 2153 | [[package]] 2154 | name = "trust-dns-proto" 2155 | version = "0.19.6" 2156 | source = "registry+https://github.com/rust-lang/crates.io-index" 2157 | checksum = "53861fcb288a166aae4c508ae558ed18b53838db728d4d310aad08270a7d4c2b" 2158 | dependencies = [ 2159 | "async-trait", 2160 | "backtrace", 2161 | "enum-as-inner", 2162 | "futures", 2163 | "idna", 2164 | "lazy_static", 2165 | "log", 2166 | "rand 0.7.3", 2167 | "smallvec", 2168 | "thiserror", 2169 | "tokio", 2170 | "url", 2171 | ] 2172 | 2173 | [[package]] 2174 | name = "trust-dns-resolver" 2175 | version = "0.19.6" 2176 | source = "registry+https://github.com/rust-lang/crates.io-index" 2177 | checksum = "6759e8efc40465547b0dfce9500d733c65f969a4cbbfbe3ccf68daaa46ef179e" 2178 | dependencies = [ 2179 | "backtrace", 2180 | "cfg-if 0.1.10", 2181 | "futures", 2182 | "ipconfig", 2183 | "lazy_static", 2184 | "log", 2185 | "lru-cache", 2186 | "resolv-conf", 2187 | "smallvec", 2188 | "thiserror", 2189 | "tokio", 2190 | "trust-dns-proto", 2191 | ] 2192 | 2193 | [[package]] 2194 | name = "twox-hash" 2195 | version = "1.6.0" 2196 | source = "registry+https://github.com/rust-lang/crates.io-index" 2197 | checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59" 2198 | dependencies = [ 2199 | "cfg-if 0.1.10", 2200 | "rand 0.7.3", 2201 | "static_assertions", 2202 | ] 2203 | 2204 | [[package]] 2205 | name = "typenum" 2206 | version = "1.12.0" 2207 | source = "registry+https://github.com/rust-lang/crates.io-index" 2208 | checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" 2209 | 2210 | [[package]] 2211 | name = "unicode-bidi" 2212 | version = "0.3.4" 2213 | source = "registry+https://github.com/rust-lang/crates.io-index" 2214 | checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" 2215 | dependencies = [ 2216 | "matches", 2217 | ] 2218 | 2219 | [[package]] 2220 | name = "unicode-normalization" 2221 | version = "0.1.16" 2222 | source = "registry+https://github.com/rust-lang/crates.io-index" 2223 | checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606" 2224 | dependencies = [ 2225 | "tinyvec", 2226 | ] 2227 | 2228 | [[package]] 2229 | name = "unicode-segmentation" 2230 | version = "1.7.1" 2231 | source = "registry+https://github.com/rust-lang/crates.io-index" 2232 | checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" 2233 | 2234 | [[package]] 2235 | name = "unicode-xid" 2236 | version = "0.2.1" 2237 | source = "registry+https://github.com/rust-lang/crates.io-index" 2238 | checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" 2239 | 2240 | [[package]] 2241 | name = "url" 2242 | version = "2.2.0" 2243 | source = "registry+https://github.com/rust-lang/crates.io-index" 2244 | checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e" 2245 | dependencies = [ 2246 | "form_urlencoded", 2247 | "idna", 2248 | "matches", 2249 | "percent-encoding", 2250 | ] 2251 | 2252 | [[package]] 2253 | name = "uuid" 2254 | version = "0.8.2" 2255 | source = "registry+https://github.com/rust-lang/crates.io-index" 2256 | checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" 2257 | 2258 | [[package]] 2259 | name = "vcpkg" 2260 | version = "0.2.11" 2261 | source = "registry+https://github.com/rust-lang/crates.io-index" 2262 | checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" 2263 | 2264 | [[package]] 2265 | name = "version_check" 2266 | version = "0.9.2" 2267 | source = "registry+https://github.com/rust-lang/crates.io-index" 2268 | checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" 2269 | 2270 | [[package]] 2271 | name = "wasi" 2272 | version = "0.9.0+wasi-snapshot-preview1" 2273 | source = "registry+https://github.com/rust-lang/crates.io-index" 2274 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" 2275 | 2276 | [[package]] 2277 | name = "wasi" 2278 | version = "0.10.1+wasi-snapshot-preview1" 2279 | source = "registry+https://github.com/rust-lang/crates.io-index" 2280 | checksum = "93c6c3420963c5c64bca373b25e77acb562081b9bb4dd5bb864187742186cea9" 2281 | 2282 | [[package]] 2283 | name = "wasm-bindgen" 2284 | version = "0.2.69" 2285 | source = "registry+https://github.com/rust-lang/crates.io-index" 2286 | checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e" 2287 | dependencies = [ 2288 | "cfg-if 1.0.0", 2289 | "wasm-bindgen-macro", 2290 | ] 2291 | 2292 | [[package]] 2293 | name = "wasm-bindgen-backend" 2294 | version = "0.2.69" 2295 | source = "registry+https://github.com/rust-lang/crates.io-index" 2296 | checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62" 2297 | dependencies = [ 2298 | "bumpalo", 2299 | "lazy_static", 2300 | "log", 2301 | "proc-macro2", 2302 | "quote", 2303 | "syn", 2304 | "wasm-bindgen-shared", 2305 | ] 2306 | 2307 | [[package]] 2308 | name = "wasm-bindgen-macro" 2309 | version = "0.2.69" 2310 | source = "registry+https://github.com/rust-lang/crates.io-index" 2311 | checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084" 2312 | dependencies = [ 2313 | "quote", 2314 | "wasm-bindgen-macro-support", 2315 | ] 2316 | 2317 | [[package]] 2318 | name = "wasm-bindgen-macro-support" 2319 | version = "0.2.69" 2320 | source = "registry+https://github.com/rust-lang/crates.io-index" 2321 | checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549" 2322 | dependencies = [ 2323 | "proc-macro2", 2324 | "quote", 2325 | "syn", 2326 | "wasm-bindgen-backend", 2327 | "wasm-bindgen-shared", 2328 | ] 2329 | 2330 | [[package]] 2331 | name = "wasm-bindgen-shared" 2332 | version = "0.2.69" 2333 | source = "registry+https://github.com/rust-lang/crates.io-index" 2334 | checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158" 2335 | 2336 | [[package]] 2337 | name = "widestring" 2338 | version = "0.4.3" 2339 | source = "registry+https://github.com/rust-lang/crates.io-index" 2340 | checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" 2341 | 2342 | [[package]] 2343 | name = "winapi" 2344 | version = "0.2.8" 2345 | source = "registry+https://github.com/rust-lang/crates.io-index" 2346 | checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 2347 | 2348 | [[package]] 2349 | name = "winapi" 2350 | version = "0.3.9" 2351 | source = "registry+https://github.com/rust-lang/crates.io-index" 2352 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2353 | dependencies = [ 2354 | "winapi-i686-pc-windows-gnu", 2355 | "winapi-x86_64-pc-windows-gnu", 2356 | ] 2357 | 2358 | [[package]] 2359 | name = "winapi-build" 2360 | version = "0.1.1" 2361 | source = "registry+https://github.com/rust-lang/crates.io-index" 2362 | checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 2363 | 2364 | [[package]] 2365 | name = "winapi-i686-pc-windows-gnu" 2366 | version = "0.4.0" 2367 | source = "registry+https://github.com/rust-lang/crates.io-index" 2368 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2369 | 2370 | [[package]] 2371 | name = "winapi-x86_64-pc-windows-gnu" 2372 | version = "0.4.0" 2373 | source = "registry+https://github.com/rust-lang/crates.io-index" 2374 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2375 | 2376 | [[package]] 2377 | name = "winreg" 2378 | version = "0.6.2" 2379 | source = "registry+https://github.com/rust-lang/crates.io-index" 2380 | checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" 2381 | dependencies = [ 2382 | "winapi 0.3.9", 2383 | ] 2384 | 2385 | [[package]] 2386 | name = "ws2_32-sys" 2387 | version = "0.2.1" 2388 | source = "registry+https://github.com/rust-lang/crates.io-index" 2389 | checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" 2390 | dependencies = [ 2391 | "winapi 0.2.8", 2392 | "winapi-build", 2393 | ] 2394 | 2395 | [[package]] 2396 | name = "wyz" 2397 | version = "0.2.0" 2398 | source = "registry+https://github.com/rust-lang/crates.io-index" 2399 | checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" 2400 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tigraph" 3 | version = "0.1.0" 4 | authors = ["leiysky "] 5 | edition = "2018" 6 | default-run = "tigraph-server" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | [[bin]] 10 | path = "src/main.rs" 11 | name = "tigraph-server" 12 | 13 | [dependencies] 14 | nom = "6" 15 | mysql = "*" 16 | actix-web = "3" 17 | serde = { version = "1.0", features = ["derive"] } 18 | serde_json = "1.0" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TiGraph: Graph Database on TiDB 2 | 3 | > This is a failed project in [TiDB Hackathon 2020](https://pingcap.com/community/events/hackathon2020/) project. 4 | 5 | TiGraph is a graph database build with TiDB. 6 | 7 | Welcome to contribute. 8 | 9 | ## Architecture 10 | 11 | > TODO: 12 | 13 | contact: [leiysky](mailto://leiysky@outlook.com) -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leiysky/tigraph/3d612209f74251034913c253687778f796536b8e/rustfmt.toml -------------------------------------------------------------------------------- /src/catalog/catalog.rs: -------------------------------------------------------------------------------- 1 | use std::unimplemented; 2 | 3 | use super::desc::*; 4 | 5 | pub struct Catalog { 6 | version: u64, 7 | } 8 | 9 | #[derive(Debug)] 10 | 11 | pub enum CatalogError { 12 | ObjectNotExists, 13 | Unknown, 14 | } 15 | 16 | impl Catalog { 17 | pub fn resolve_label_by_id(&self, id: u64) -> Result { 18 | unimplemented!() 19 | } 20 | 21 | pub fn resolve_label_by_name( 22 | &self, 23 | name: Box, 24 | ) -> Result { 25 | unimplemented!() 26 | } 27 | 28 | pub fn create_label(&self, name: Box) -> Result { 29 | unimplemented!() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/catalog/desc.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Read, Write}; 2 | 3 | // Descriptor of metadata objects as follow: 4 | // - Label 5 | // - Property 6 | // - Index 7 | trait Desc { 8 | fn init(); 9 | 10 | fn object_type() -> ObjectType; 11 | 12 | fn object_id() -> u64; 13 | 14 | fn serialize(&self, w: dyn Write) -> Result<(), std::io::Error>; 15 | 16 | fn deserialize(&mut self, r: dyn Read) -> Result<(), std::io::Error>; 17 | } 18 | 19 | enum ObjectType { 20 | Label = 1, 21 | Property = 2, 22 | Index = 3, 23 | } 24 | 25 | pub trait LabelName { 26 | fn string(&self) -> &str; 27 | } 28 | 29 | pub struct LabelDesc { 30 | pub name: Box, 31 | } 32 | 33 | pub struct PropDesc { 34 | // pub name: Box< 35 | } 36 | -------------------------------------------------------------------------------- /src/catalog/mod.rs: -------------------------------------------------------------------------------- 1 | mod catalog; 2 | mod desc; 3 | 4 | pub use catalog::Catalog; 5 | -------------------------------------------------------------------------------- /src/core/context.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | pub struct Context { 4 | pub tidb_service: TiDBService, 5 | } 6 | 7 | pub struct TiDBService { 8 | pub host: String, 9 | pub port: String, 10 | pub username: String, 11 | pub password: String, 12 | pub database: String, 13 | 14 | pub label_table_map: HashMap, 15 | pub table_id_map: HashMap, 16 | } 17 | 18 | impl Context { 19 | pub fn new() -> Context { 20 | Context { 21 | tidb_service: TiDBService { 22 | host: String::from("localhost"), 23 | port: String::from("4000"), 24 | username: String::from("root"), 25 | password: String::from(""), 26 | database: String::from("test"), 27 | 28 | label_table_map: HashMap::new(), 29 | table_id_map: HashMap::new(), 30 | }, 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/core/mod.rs: -------------------------------------------------------------------------------- 1 | mod context; 2 | mod planner; 3 | 4 | pub use context::{Context, TiDBService}; 5 | pub use planner::Planner; 6 | -------------------------------------------------------------------------------- /src/core/planner.rs: -------------------------------------------------------------------------------- 1 | use crate::runtime::Executor; 2 | use crate::Error; 3 | use crate::{optimizer::default_implementation, parser::Query}; 4 | use crate::{optimizer::Builder, parser::Parser}; 5 | 6 | pub struct Planner {} 7 | 8 | impl Planner { 9 | pub fn plan(&self, ast: &Query) -> Result, Error> { 10 | let mut builder = Builder::new(); 11 | 12 | let rel_expr = builder.build(ast)?; 13 | // println!("{:#?}", rel_expr); 14 | 15 | let exec = default_implementation(&rel_expr)?; 16 | 17 | Ok(exec) 18 | } 19 | } 20 | 21 | #[test] 22 | fn test_planner() { 23 | let mut planner = Planner {}; 24 | let parser = Parser {}; 25 | let ast = parser 26 | .parse( 27 | r#" 28 | MATCH (a:Person)-[r:knows]->(b:Person) 29 | RETURN *; 30 | "#, 31 | ) 32 | .unwrap(); 33 | let mut exec = planner.plan(&ast).unwrap(); 34 | exec.open().unwrap(); 35 | let res = exec.next().unwrap(); 36 | // println!("{:#?}", res); 37 | exec.close().unwrap(); 38 | } 39 | 40 | #[test] 41 | fn test_scan() { 42 | let mut planner = Planner {}; 43 | let parser = Parser {}; 44 | let ast = parser 45 | .parse( 46 | r#" 47 | MATCH (a:Person) 48 | RETURN a; 49 | "#, 50 | ) 51 | .unwrap(); 52 | let mut exec = planner.plan(&ast).unwrap(); 53 | exec.open().unwrap(); 54 | while let Some(res) = exec.next().unwrap() { 55 | // println!("{:#?}", res); 56 | } 57 | exec.close().unwrap(); 58 | } 59 | 60 | #[test] 61 | fn test_selection() { 62 | let planner = Planner {}; 63 | let parser = Parser {}; 64 | let ast = parser 65 | .parse( 66 | r#" 67 | MATCH (a:Person) 68 | WHERE a.id = 1 69 | RETURN a; 70 | "#, 71 | ) 72 | .unwrap(); 73 | let mut exec = planner.plan(&ast).unwrap(); 74 | exec.open().unwrap(); 75 | while let Some(res) = exec.next().unwrap() { 76 | println!("{:#?}", res); 77 | } 78 | exec.close().unwrap(); 79 | } 80 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(iterator_fold_self)] 2 | 3 | mod catalog; 4 | mod core; 5 | mod optimizer; 6 | mod parser; 7 | mod runtime; 8 | mod server; 9 | mod types; 10 | mod util; 11 | 12 | use server::run; 13 | use util::{Error, ErrorKind}; 14 | 15 | extern crate nom; 16 | 17 | #[actix_web::main] 18 | async fn main() -> std::io::Result<()> { 19 | run().await 20 | } 21 | -------------------------------------------------------------------------------- /src/optimizer/builder.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | 3 | use nom::bitvec::vec; 4 | 5 | use super::expr::*; 6 | use super::metadata::*; 7 | use crate::parser::{Expr as ASTExpr, *}; 8 | 9 | use crate::Error; 10 | 11 | // Builder for logical plans 12 | pub struct Builder {} 13 | 14 | impl Builder { 15 | pub fn new() -> Builder { 16 | Builder {} 17 | } 18 | 19 | pub fn build(&mut self, ast: &Query) -> Result { 20 | let mut final_expr: RelExpr; 21 | let mut unions = Vec::new(); 22 | for expr in ast.unions.iter() { 23 | let u = self.build_union(expr)?; 24 | unions.push(u); 25 | } 26 | 27 | if unions.len() > 1 { 28 | unimplemented!(); 29 | } else { 30 | final_expr = unions.pop().unwrap(); 31 | } 32 | 33 | Ok(final_expr) 34 | } 35 | 36 | pub fn build_scalar(&mut self, expr: &ASTExpr) -> Result { 37 | let final_expr = match expr { 38 | ASTExpr::Variable(name) => ScalarExpr::Variable(name.to_owned()), 39 | ASTExpr::EqualExpr(equal) => { 40 | let lhs = self.build_scalar(equal.lhs.as_ref())?; 41 | let rhs = self.build_scalar(equal.rhs.as_ref())?; 42 | ScalarExpr::Equal(Box::new(lhs), Box::new(rhs)) 43 | } 44 | ASTExpr::PropertyLookup(prop_lookup) => { 45 | let child = self.build_scalar(prop_lookup.child.as_ref())?; 46 | ScalarExpr::PropertyLookup(Box::new(child), prop_lookup.prop_name.to_owned()) 47 | } 48 | ASTExpr::AndExpr(and) => { 49 | let lhs = self.build_scalar(and.lhs.as_ref())?; 50 | let rhs = self.build_scalar(and.rhs.as_ref())?; 51 | ScalarExpr::LogicAnd(Box::new(lhs), Box::new(rhs)) 52 | } 53 | ASTExpr::NumberLit(v) => ScalarExpr::NumberLiteral(v.to_owned()), 54 | ASTExpr::StringLit(v) => ScalarExpr::StringLiteral(v.to_owned()), 55 | _ => unimplemented!("{:#?}", expr), 56 | }; 57 | 58 | Ok(final_expr) 59 | } 60 | 61 | fn build_union(&mut self, union: &Union) -> Result { 62 | let mut final_expr = match union.reading_clause.as_ref().unwrap() { 63 | ReadingClause::Match(clause) => self.build_match(clause)?, 64 | _ => unimplemented!(), 65 | }; 66 | 67 | final_expr = self.build_projection(final_expr, &union.return_clause)?; 68 | 69 | Ok(final_expr) 70 | } 71 | 72 | fn build_match(&mut self, match_clause: &MatchClause) -> Result { 73 | let mut exprs = Vec::new(); 74 | for p in match_clause.pattern.iter() { 75 | exprs.push(self.build_pattern(p)?); 76 | } 77 | 78 | // If there are more than one patterns, join them 79 | let mut final_expr = if exprs.len() > 1 { 80 | exprs 81 | .into_iter() 82 | .map(|v| Result::::Ok(v)) 83 | .fold_first(|acc, expr| self.build_join(acc.unwrap(), expr.unwrap())) 84 | .unwrap()? 85 | } else { 86 | exprs.pop().unwrap() 87 | }; 88 | 89 | final_expr = if !match_clause.filter.is_empty() { 90 | let mut scalar = Vec::new(); 91 | for predicate in match_clause.filter.iter() { 92 | scalar.push(self.build_scalar(&predicate)?); 93 | } 94 | self.build_selection(final_expr, &scalar)? 95 | } else { 96 | final_expr 97 | }; 98 | 99 | Ok(final_expr) 100 | } 101 | 102 | fn build_selection( 103 | &mut self, 104 | expr: RelExpr, 105 | predicate: &Vec, 106 | ) -> Result { 107 | let final_expr = SelectExpr { 108 | filter: predicate.to_owned(), 109 | child: Box::new(expr), 110 | }; 111 | 112 | Ok(RelExpr::Selection(final_expr)) 113 | } 114 | 115 | fn build_projection( 116 | &mut self, 117 | expr: RelExpr, 118 | return_clause: &ReturnClause, 119 | ) -> Result { 120 | let mut projects = Vec::new(); 121 | for (p, alias) in return_clause.projections.iter() { 122 | let project = self.build_scalar(p)?; 123 | projects.push((project, alias.to_owned())); 124 | } 125 | 126 | let final_expr = ProjectExpr { 127 | projects: projects, 128 | star: return_clause.star, 129 | 130 | child: Box::new(expr), 131 | }; 132 | 133 | Ok(RelExpr::Projection(final_expr)) 134 | } 135 | 136 | fn build_pattern(&mut self, pattern: &Pattern) -> Result { 137 | // graph is an adjacent list, which stores topology of query graph pattern. 138 | // Elements of graph indicate index of NodePattern in pattern.nodes 139 | let mut graph = Vec::>::new(); 140 | graph.resize(pattern.nodes.len(), Vec::new()); 141 | for i in 0..pattern.rels.len() { 142 | let r = pattern.rels.get(i).unwrap(); 143 | match r.direction { 144 | Direction::Left => graph.get_mut(i + 1).unwrap().push(i), 145 | Direction::Right => graph.get_mut(i).unwrap().push(i + 1), 146 | }; 147 | } 148 | 149 | // Since a pattern is a path, we can assume that there is no cycle 150 | let mut start_nodes = Vec::::new(); 151 | let mut paths = Vec::>::new(); 152 | 153 | // First, find all starting nodes (node with no in-degree) 154 | { 155 | let mut set = HashSet::::new(); 156 | graph.iter().flatten().for_each(|v| { 157 | set.insert(v.to_owned()); 158 | }); 159 | for i in 0..graph.len() { 160 | if !set.contains(&i) { 161 | start_nodes.push(i); 162 | } 163 | } 164 | } 165 | 166 | // Second, resolve paths by DFS 167 | { 168 | fn resolve( 169 | graph: &Vec>, 170 | paths: &mut Vec>, 171 | current: usize, 172 | visited: &mut Vec, 173 | ) { 174 | visited.push(current); 175 | if graph.get(current).unwrap().len() == 0 { 176 | paths.push(visited.to_owned()); 177 | } else { 178 | graph.get(current).unwrap().into_iter().for_each(|v| { 179 | resolve(graph, paths, v.to_owned(), visited); 180 | }); 181 | } 182 | visited.pop(); 183 | } 184 | 185 | start_nodes.into_iter().for_each(|v| { 186 | resolve(&graph, &mut paths, v.to_owned(), Vec::new().as_mut()); 187 | }) 188 | } 189 | 190 | let mut final_expr: RelExpr; 191 | 192 | // Build paths 193 | let mut exprs = Vec::::new(); 194 | for path in paths.iter() { 195 | let nodes: Vec<&NodePattern> = path 196 | .into_iter() 197 | .map(|v| pattern.nodes.get(v.to_owned()).unwrap()) 198 | .collect(); 199 | let mut expr = self.build_scan(nodes.get(0).unwrap())?; 200 | for i in 1..nodes.len() { 201 | let start = path.get(i - 1).unwrap().to_owned(); 202 | let end = path.get(i).unwrap().to_owned(); 203 | assert!((start as i64 - end as i64).abs() == 1); 204 | // If start > end, then end <- start 205 | // If start < end, then start -> end 206 | // We know index of rel between start and end is the less index of start and end 207 | let rel = start.min(end); 208 | 209 | expr = self.build_expand( 210 | expr, 211 | pattern.nodes.get(start).unwrap(), 212 | pattern.nodes.get(end).unwrap(), 213 | pattern.rels.get(rel).unwrap(), 214 | )?; 215 | } 216 | 217 | exprs.push(expr); 218 | } 219 | 220 | // Join paths 221 | final_expr = if exprs.len() > 1 { 222 | exprs 223 | .into_iter() 224 | .map(|v| Result::::Ok(v)) 225 | .fold_first(|acc, expr| self.build_join(acc.unwrap(), expr.unwrap())) 226 | .unwrap()? 227 | } else { 228 | exprs.pop().unwrap() 229 | }; 230 | 231 | Ok(final_expr) 232 | } 233 | 234 | fn build_scan(&mut self, node_pattern: &NodePattern) -> Result { 235 | let scan = ScanExpr { 236 | binded_name: node_pattern.name.to_owned(), 237 | all: node_pattern.labels.len() == 0, 238 | label: node_pattern.labels.get(0).unwrap().to_owned(), 239 | }; 240 | 241 | Ok(RelExpr::NodeScan(scan)) 242 | } 243 | 244 | fn build_expand( 245 | &mut self, 246 | expr: RelExpr, 247 | start_node: &NodePattern, 248 | end_node: &NodePattern, 249 | rel: &RelationshipPattern, 250 | ) -> Result { 251 | let expand = ExpandExpr { 252 | start_name: start_node.name.to_owned(), 253 | end_name: end_node.name.to_owned(), 254 | rel_name: rel.name.to_owned(), 255 | rel_type: rel.types.get(0).unwrap().to_owned(), 256 | end_label: end_node.labels.get(0).unwrap().to_owned(), 257 | child: Box::new(expr), 258 | }; 259 | 260 | Ok(RelExpr::Expand(expand)) 261 | } 262 | 263 | fn build_join(&mut self, lhs: RelExpr, rhs: RelExpr) -> Result { 264 | let join = JoinExpr { 265 | join_type: JoinType::CartesianProduct, 266 | lhs: Box::new(lhs), 267 | rhs: Box::new(rhs), 268 | }; 269 | 270 | Ok(RelExpr::Join(join)) 271 | } 272 | } 273 | 274 | #[test] 275 | fn test_builder() { 276 | let parser = Parser {}; 277 | let ast = parser 278 | .parse( 279 | r#" 280 | MATCH (a:Label1)-[r:Type1]->(b:Label1)<-[r1:Type1]-(c:Label2) 281 | RETURN a.a, b, c AS d; 282 | "#, 283 | ) 284 | .unwrap(); 285 | 286 | let mut builder = Builder::new(); 287 | 288 | // println!("{:#?}", builder.build(&ast).unwrap()); 289 | } 290 | -------------------------------------------------------------------------------- /src/optimizer/expr.rs: -------------------------------------------------------------------------------- 1 | // pub trait Memo { 2 | // fn init(&mut self); 3 | // fn memonize(plan: Box) -> Box; 4 | // fn root(&self) -> Option<&Box>; 5 | // fn set_root(&mut self, root: Box); 6 | // } 7 | 8 | #[derive(Debug)] 9 | pub enum Expr { 10 | Relational(RelExpr), 11 | Scalar(ScalarExpr), 12 | } 13 | 14 | #[derive(Debug)] 15 | pub enum RelExpr { 16 | NodeScan(ScanExpr), 17 | Join(JoinExpr), 18 | Expand(ExpandExpr), 19 | Selection(SelectExpr), 20 | Projection(ProjectExpr), 21 | } 22 | 23 | #[derive(Debug, Clone)] 24 | pub enum ScalarExpr { 25 | // Add(AddExpr), 26 | // Sub(SubExpr), 27 | // Mult(MultiplyExpr), 28 | // Div(DivideExpr), 29 | Equal(Box, Box), 30 | LogicAnd(Box, Box), 31 | PropertyLookup(Box, String), 32 | Variable(String), 33 | NumberLiteral(f64), 34 | StringLiteral(String), 35 | } 36 | 37 | #[derive(Debug)] 38 | pub struct ScanExpr { 39 | pub binded_name: String, 40 | pub all: bool, 41 | pub label: String, 42 | } 43 | 44 | #[derive(Debug)] 45 | pub struct ExpandExpr { 46 | pub start_name: String, 47 | pub end_name: String, 48 | pub rel_name: String, 49 | pub rel_type: String, 50 | pub end_label: String, 51 | 52 | pub child: Box, 53 | } 54 | 55 | #[derive(Debug)] 56 | pub enum JoinType { 57 | CartesianProduct, 58 | } 59 | 60 | #[derive(Debug)] 61 | pub struct JoinExpr { 62 | pub join_type: JoinType, 63 | 64 | pub lhs: Box, 65 | pub rhs: Box, 66 | } 67 | 68 | #[derive(Debug)] 69 | pub struct SelectExpr { 70 | // Conjunctions 71 | pub filter: Vec, 72 | 73 | pub child: Box, 74 | } 75 | 76 | #[derive(Debug)] 77 | pub struct ProjectExpr { 78 | pub projects: Vec<(ScalarExpr, String)>, 79 | pub star: bool, 80 | 81 | pub child: Box, 82 | } 83 | 84 | // pub struct Memo { 85 | // root: Option, 86 | // rel_idgen: IdGen, 87 | // scalar_idgen: IdGen, 88 | // groups: HashMap, 89 | // scalars: HashMap>, 90 | // } 91 | 92 | // pub struct Group { 93 | // memo: Rc, 94 | // id: u32, 95 | // exprs: List, 96 | // } 97 | 98 | // impl Group { 99 | // pub fn new(memo: Rc, id: u32) -> Group { 100 | // Group { 101 | // memo: memo, 102 | // id: id, 103 | // exprs: List::new(), 104 | // } 105 | // } 106 | // } 107 | 108 | // pub trait Expr { 109 | // fn memo(&self) -> &Memo; 110 | // fn children_count(&self) -> usize; 111 | // fn child(&self, n: usize) -> Option<&Box>; 112 | // } 113 | 114 | // // Relational Expression 115 | // pub trait RelExpr: Expr { 116 | // fn group(&self) -> &Group; 117 | // fn get_cost(&self) -> f64; 118 | // fn get_type(&self) -> RelType; 119 | // fn next(&self) -> Option<&Box>; 120 | // } 121 | 122 | // pub trait ScalarExpr: Expr {} 123 | 124 | // impl Memo { 125 | // pub fn new() -> Memo { 126 | // Memo { 127 | // root: None, 128 | // scalar_idgen: IdGen::new(), 129 | // rel_idgen: IdGen::new(), 130 | // groups: HashMap::new(), 131 | // scalars: HashMap::new(), 132 | // } 133 | // } 134 | 135 | // pub fn init(&mut self) { 136 | // self.root = None; 137 | // } 138 | 139 | // pub fn root(&self) -> Option> { 140 | // self.root 141 | // } 142 | 143 | // pub fn set_root(&mut self, root: Box) { 144 | // self.root = Some(root); 145 | // } 146 | // } 147 | 148 | // pub struct ScanExpr { 149 | // group: Rc, 150 | // labels: Vec, 151 | // idx: usize, 152 | // } 153 | 154 | // impl Expr for ScanExpr { 155 | // fn memo(&self) -> &Memo { 156 | // self.group.memo.as_ref() 157 | // } 158 | 159 | // fn children_count(&self) -> usize { 160 | // 0 161 | // } 162 | 163 | // fn child(&self, n: usize) -> Option<&Box> { 164 | // None 165 | // } 166 | // } 167 | 168 | // impl RelExpr for ScanExpr { 169 | // fn group(&self) -> &Group { 170 | // self.group.as_ref() 171 | // } 172 | 173 | // fn next(&self) -> Option<&Box> { 174 | // self.group.exprs.get(self.idx + 1) 175 | // } 176 | 177 | // fn get_cost(&self) -> f64 { 178 | // unimplemented!() 179 | // } 180 | 181 | // fn get_type(&self) -> RelType { 182 | // RelType::DataSource 183 | // } 184 | // } 185 | 186 | // pub struct Selection { 187 | // group: Rc, 188 | // child: Box, 189 | // } 190 | 191 | // impl Expr for Selection { 192 | // fn memo(&self) -> &Memo { 193 | // self.group.memo.as_ref() 194 | // } 195 | 196 | // fn children_count(&self) -> usize { 197 | // 1 198 | // } 199 | 200 | // fn child(&self, n: usize) -> Option<&Box> { 201 | // if n == 1 { 202 | // Some(self.child.as_ref() as &Box) 203 | // } else { 204 | // None 205 | // } 206 | // } 207 | // } 208 | -------------------------------------------------------------------------------- /src/optimizer/implement.rs: -------------------------------------------------------------------------------- 1 | use crate::runtime::{Executor, FilterExec, ProjectExec, TiDBNestedLoopExpand, TiDBScanExec}; 2 | use crate::Error; 3 | 4 | use super::expr::RelExpr; 5 | 6 | pub fn default_implementation(rel_expr: &RelExpr) -> Result, Error> { 7 | match rel_expr { 8 | RelExpr::NodeScan(scan) => Ok(Box::new(TiDBScanExec::new(scan))), 9 | RelExpr::Expand(expand) => Ok(Box::new(TiDBNestedLoopExpand::new( 10 | default_implementation(expand.child.as_ref())?, 11 | expand, 12 | ))), 13 | RelExpr::Projection(project) => Ok(Box::new(ProjectExec::new( 14 | default_implementation(&project.child)?, 15 | project, 16 | ))), 17 | RelExpr::Selection(select) => Ok(Box::new(FilterExec::new( 18 | default_implementation(&select.child)?, 19 | select, 20 | ))), 21 | _ => unimplemented!(), 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/optimizer/metadata.rs: -------------------------------------------------------------------------------- 1 | use crate::catalog::*; 2 | 3 | pub struct Metadata { 4 | cat: Box, 5 | } 6 | 7 | impl Metadata { 8 | pub fn new(catalog: Box) -> Box { 9 | Box::new(Metadata { cat: catalog }) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/optimizer/mod.rs: -------------------------------------------------------------------------------- 1 | mod builder; 2 | mod expr; 3 | mod implement; 4 | mod metadata; 5 | 6 | pub use builder::Builder; 7 | 8 | pub use expr::*; 9 | 10 | pub use implement::*; -------------------------------------------------------------------------------- /src/parser/cypher.ebnf: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2015-2020 "Neo Technology," 3 | * Network Engine for Objects in Lund AB [http://neotechnology.com] 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Attribution Notice under the terms of the Apache License 2.0 18 | * 19 | * This work was created by the collective efforts of the openCypher community. 20 | * Without limiting the terms of Section 6, any Derivative Work that is not 21 | * approved by the public consensus process of the openCypher Implementers Group 22 | * should not be described as “Cypher” (and Cypher® is a registered trademark of 23 | * Neo4j Inc.) or as "openCypher". Extensions by implementers or prototypes or 24 | * proposals for change that have been documented or implemented should only be 25 | * described as "implementation extensions to Cypher" or as "proposed changes to 26 | * Cypher that are not yet approved by the openCypher community". 27 | *) 28 | Cypher = [SP], Statement, [[SP], ';'], [SP], EOI ; 29 | 30 | Statement = Query ; 31 | 32 | Query = RegularQuery 33 | | StandaloneCall 34 | ; 35 | 36 | RegularQuery = SingleQuery, { [SP], Union } ; 37 | 38 | Union = ((U,N,I,O,N), SP, (A,L,L), [SP], SingleQuery) 39 | | ((U,N,I,O,N), [SP], SingleQuery) 40 | ; 41 | 42 | SingleQuery = SinglePartQuery 43 | | MultiPartQuery 44 | ; 45 | 46 | SinglePartQuery = ({ ReadingClause, [SP] }, Return) 47 | | ({ ReadingClause, [SP] }, UpdatingClause, { [SP], UpdatingClause }, [[SP], Return]) 48 | ; 49 | 50 | MultiPartQuery = { { ReadingClause, [SP] }, { UpdatingClause, [SP] }, With, [SP] }-, SinglePartQuery ; 51 | 52 | UpdatingClause = Create 53 | | Merge 54 | | Delete 55 | | Set 56 | | Remove 57 | ; 58 | 59 | ReadingClause = Match 60 | | Unwind 61 | | InQueryCall 62 | ; 63 | 64 | Match = [(O,P,T,I,O,N,A,L), SP], (M,A,T,C,H), [SP], Pattern, [[SP], Where] ; 65 | 66 | Unwind = (U,N,W,I,N,D), [SP], Expression, SP, (A,S), SP, Variable ; 67 | 68 | Merge = (M,E,R,G,E), [SP], PatternPart, { SP, MergeAction } ; 69 | 70 | MergeAction = ((O,N), SP, (M,A,T,C,H), SP, Set) 71 | | ((O,N), SP, (C,R,E,A,T,E), SP, Set) 72 | ; 73 | 74 | Create = (C,R,E,A,T,E), [SP], Pattern ; 75 | 76 | Set = (S,E,T), [SP], SetItem, { ',', SetItem } ; 77 | 78 | SetItem = (PropertyExpression, [SP], '=', [SP], Expression) 79 | | (Variable, [SP], '=', [SP], Expression) 80 | | (Variable, [SP], '+=', [SP], Expression) 81 | | (Variable, [SP], NodeLabels) 82 | ; 83 | 84 | Delete = [(D,E,T,A,C,H), SP], (D,E,L,E,T,E), [SP], Expression, { [SP], ',', [SP], Expression } ; 85 | 86 | Remove = (R,E,M,O,V,E), SP, RemoveItem, { [SP], ',', [SP], RemoveItem } ; 87 | 88 | RemoveItem = (Variable, NodeLabels) 89 | | PropertyExpression 90 | ; 91 | 92 | InQueryCall = (C,A,L,L), SP, ExplicitProcedureInvocation, [[SP], (Y,I,E,L,D), SP, YieldItems] ; 93 | 94 | StandaloneCall = (C,A,L,L), SP, (ExplicitProcedureInvocation | ImplicitProcedureInvocation), [SP, (Y,I,E,L,D), SP, YieldItems] ; 95 | 96 | YieldItems = ('*' | (YieldItem, { [SP], ',', [SP], YieldItem })), [[SP], Where] ; 97 | 98 | YieldItem = [ProcedureResultField, SP, (A,S), SP], Variable ; 99 | 100 | With = (W,I,T,H), ProjectionBody, [[SP], Where] ; 101 | 102 | Return = (R,E,T,U,R,N), ProjectionBody ; 103 | 104 | ProjectionBody = [[SP], (D,I,S,T,I,N,C,T)], SP, ProjectionItems, [SP, Order], [SP, Skip], [SP, Limit] ; 105 | 106 | ProjectionItems = ('*', { [SP], ',', [SP], ProjectionItem }) 107 | | (ProjectionItem, { [SP], ',', [SP], ProjectionItem }) 108 | ; 109 | 110 | ProjectionItem = (Expression, SP, (A,S), SP, Variable) 111 | | Expression 112 | ; 113 | 114 | Order = (O,R,D,E,R), SP, (B,Y), SP, SortItem, { ',', [SP], SortItem } ; 115 | 116 | Skip = (S,K,I,P), SP, Expression ; 117 | 118 | Limit = (L,I,M,I,T), SP, Expression ; 119 | 120 | SortItem = Expression, [[SP], ((A,S,C,E,N,D,I,N,G) | (A,S,C) | (D,E,S,C,E,N,D,I,N,G) | (D,E,S,C))] ; 121 | 122 | Where = (W,H,E,R,E), SP, Expression ; 123 | 124 | Pattern = PatternPart, { [SP], ',', [SP], PatternPart } ; 125 | 126 | PatternPart = (Variable, [SP], '=', [SP], AnonymousPatternPart) 127 | | AnonymousPatternPart 128 | ; 129 | 130 | AnonymousPatternPart = PatternElement ; 131 | 132 | PatternElement = (NodePattern, { [SP], PatternElementChain }) 133 | | ('(', PatternElement, ')') 134 | ; 135 | 136 | NodePattern = '(', [SP], [Variable, [SP]], [NodeLabels, [SP]], [Properties, [SP]], ')' ; 137 | 138 | PatternElementChain = RelationshipPattern, [SP], NodePattern ; 139 | 140 | RelationshipPattern = (LeftArrowHead, [SP], Dash, [SP], [RelationshipDetail], [SP], Dash, [SP], RightArrowHead) 141 | | (LeftArrowHead, [SP], Dash, [SP], [RelationshipDetail], [SP], Dash) 142 | | (Dash, [SP], [RelationshipDetail], [SP], Dash, [SP], RightArrowHead) 143 | | (Dash, [SP], [RelationshipDetail], [SP], Dash) 144 | ; 145 | 146 | RelationshipDetail = '[', [SP], [Variable, [SP]], [RelationshipTypes, [SP]], [RangeLiteral], [Properties, [SP]], ']' ; 147 | 148 | Properties = MapLiteral 149 | | Parameter 150 | ; 151 | 152 | RelationshipTypes = ':', [SP], RelTypeName, { [SP], '|', [':'], [SP], RelTypeName } ; 153 | 154 | NodeLabels = NodeLabel, { [SP], NodeLabel } ; 155 | 156 | NodeLabel = ':', [SP], LabelName ; 157 | 158 | RangeLiteral = '*', [SP], [IntegerLiteral, [SP]], ['..', [SP], [IntegerLiteral, [SP]]] ; 159 | 160 | LabelName = SchemaName ; 161 | 162 | RelTypeName = SchemaName ; 163 | 164 | Expression = OrExpression ; 165 | 166 | OrExpression = XorExpression, { SP, (O,R), SP, XorExpression } ; 167 | 168 | XorExpression = AndExpression, { SP, (X,O,R), SP, AndExpression } ; 169 | 170 | AndExpression = NotExpression, { SP, (A,N,D), SP, NotExpression } ; 171 | 172 | NotExpression = { (N,O,T), [SP] }, ComparisonExpression ; 173 | 174 | ComparisonExpression = AddOrSubtractExpression, { [SP], PartialComparisonExpression } ; 175 | 176 | AddOrSubtractExpression = MultiplyDivideModuloExpression, { ([SP], '+', [SP], MultiplyDivideModuloExpression) | ([SP], '-', [SP], MultiplyDivideModuloExpression) } ; 177 | 178 | MultiplyDivideModuloExpression = PowerOfExpression, { ([SP], '*', [SP], PowerOfExpression) | ([SP], '/', [SP], PowerOfExpression) | ([SP], '%', [SP], PowerOfExpression) } ; 179 | 180 | PowerOfExpression = UnaryAddOrSubtractExpression, { [SP], '^', [SP], UnaryAddOrSubtractExpression } ; 181 | 182 | UnaryAddOrSubtractExpression = { ('+' | '-'), [SP] }, StringListNullOperatorExpression ; 183 | 184 | StringListNullOperatorExpression = PropertyOrLabelsExpression, { StringOperatorExpression | ListOperatorExpression | NullOperatorExpression } ; 185 | 186 | ListOperatorExpression = (SP, (I,N), [SP], PropertyOrLabelsExpression) 187 | | ([SP], '[', Expression, ']') 188 | | ([SP], '[', [Expression], '..', [Expression], ']') 189 | ; 190 | 191 | StringOperatorExpression = ((SP, (S,T,A,R,T,S), SP, (W,I,T,H)) | (SP, (E,N,D,S), SP, (W,I,T,H)) | (SP, (C,O,N,T,A,I,N,S))), [SP], PropertyOrLabelsExpression ; 192 | 193 | NullOperatorExpression = (SP, (I,S), SP, (N,U,L,L)) 194 | | (SP, (I,S), SP, (N,O,T), SP, (N,U,L,L)) 195 | ; 196 | 197 | PropertyOrLabelsExpression = Atom, { [SP], PropertyLookup }, [[SP], NodeLabels] ; 198 | 199 | Atom = Literal 200 | | Parameter 201 | | CaseExpression 202 | | ((C,O,U,N,T), [SP], '(', [SP], '*', [SP], ')') 203 | | ListComprehension 204 | | PatternComprehension 205 | | ((A,L,L), [SP], '(', [SP], FilterExpression, [SP], ')') 206 | | ((A,N,Y), [SP], '(', [SP], FilterExpression, [SP], ')') 207 | | ((N,O,N,E), [SP], '(', [SP], FilterExpression, [SP], ')') 208 | | ((S,I,N,G,L,E), [SP], '(', [SP], FilterExpression, [SP], ')') 209 | | RelationshipsPattern 210 | | ParenthesizedExpression 211 | | FunctionInvocation 212 | | Variable 213 | ; 214 | 215 | Literal = NumberLiteral 216 | | StringLiteral 217 | | BooleanLiteral 218 | | (N,U,L,L) 219 | | MapLiteral 220 | | ListLiteral 221 | ; 222 | 223 | BooleanLiteral = (T,R,U,E) 224 | | (F,A,L,S,E) 225 | ; 226 | 227 | ListLiteral = '[', [SP], [Expression, [SP], { ',', [SP], Expression, [SP] }], ']' ; 228 | 229 | PartialComparisonExpression = ('=', [SP], AddOrSubtractExpression) 230 | | ('<>', [SP], AddOrSubtractExpression) 231 | | ('<', [SP], AddOrSubtractExpression) 232 | | ('>', [SP], AddOrSubtractExpression) 233 | | ('<=', [SP], AddOrSubtractExpression) 234 | | ('>=', [SP], AddOrSubtractExpression) 235 | ; 236 | 237 | ParenthesizedExpression = '(', [SP], Expression, [SP], ')' ; 238 | 239 | RelationshipsPattern = NodePattern, { [SP], PatternElementChain }- ; 240 | 241 | FilterExpression = IdInColl, [[SP], Where] ; 242 | 243 | IdInColl = Variable, SP, (I,N), SP, Expression ; 244 | 245 | FunctionInvocation = FunctionName, [SP], '(', [SP], [(D,I,S,T,I,N,C,T), [SP]], [Expression, [SP], { ',', [SP], Expression, [SP] }], ')' ; 246 | 247 | FunctionName = (Namespace, SymbolicName) 248 | | (E,X,I,S,T,S) 249 | ; 250 | 251 | ExplicitProcedureInvocation = ProcedureName, [SP], '(', [SP], [Expression, [SP], { ',', [SP], Expression, [SP] }], ')' ; 252 | 253 | ImplicitProcedureInvocation = ProcedureName ; 254 | 255 | ProcedureResultField = SymbolicName ; 256 | 257 | ProcedureName = Namespace, SymbolicName ; 258 | 259 | Namespace = { SymbolicName, '.' } ; 260 | 261 | ListComprehension = '[', [SP], FilterExpression, [[SP], '|', [SP], Expression], [SP], ']' ; 262 | 263 | PatternComprehension = '[', [SP], [Variable, [SP], '=', [SP]], RelationshipsPattern, [SP], [(W,H,E,R,E), [SP], Expression, [SP]], '|', [SP], Expression, [SP], ']' ; 264 | 265 | PropertyLookup = '.', [SP], (PropertyKeyName) ; 266 | 267 | CaseExpression = (((C,A,S,E), { [SP], CaseAlternatives }-) | ((C,A,S,E), [SP], Expression, { [SP], CaseAlternatives }-)), [[SP], (E,L,S,E), [SP], Expression], [SP], (E,N,D) ; 268 | 269 | CaseAlternatives = (W,H,E,N), [SP], Expression, [SP], (T,H,E,N), [SP], Expression ; 270 | 271 | Variable = SymbolicName ; 272 | 273 | StringLiteral = ('"', { ANY - ('"' | '\') | EscapedChar }, '"') 274 | | ("'", { ANY - ("'" | '\') | EscapedChar }, "'") 275 | ; 276 | 277 | EscapedChar = '\', ('\' | "'" | '"' | (B) | (F) | (N) | (R) | (T) | ((U), 4 * HexDigit) | ((U), 8 * HexDigit)) ; 278 | 279 | NumberLiteral = DoubleLiteral 280 | | IntegerLiteral 281 | ; 282 | 283 | MapLiteral = '{', [SP], [PropertyKeyName, [SP], ':', [SP], Expression, [SP], { ',', [SP], PropertyKeyName, [SP], ':', [SP], Expression, [SP] }], '}' ; 284 | 285 | Parameter = '$', (SymbolicName | DecimalInteger) ; 286 | 287 | PropertyExpression = Atom, { [SP], PropertyLookup }- ; 288 | 289 | PropertyKeyName = SchemaName ; 290 | 291 | IntegerLiteral = HexInteger 292 | | OctalInteger 293 | | DecimalInteger 294 | ; 295 | 296 | HexInteger = '0x', { HexDigit }- ; 297 | 298 | DecimalInteger = ZeroDigit 299 | | (NonZeroDigit, { Digit }) 300 | ; 301 | 302 | OctalInteger = ZeroDigit, { OctDigit }- ; 303 | 304 | HexLetter = (A) 305 | | (B) 306 | | (C) 307 | | (D) 308 | | (E) 309 | | (F) 310 | ; 311 | 312 | HexDigit = Digit 313 | | HexLetter 314 | ; 315 | 316 | Digit = ZeroDigit 317 | | NonZeroDigit 318 | ; 319 | 320 | NonZeroDigit = NonZeroOctDigit 321 | | '8' 322 | | '9' 323 | ; 324 | 325 | NonZeroOctDigit = '1' 326 | | '2' 327 | | '3' 328 | | '4' 329 | | '5' 330 | | '6' 331 | | '7' 332 | ; 333 | 334 | OctDigit = ZeroDigit 335 | | NonZeroOctDigit 336 | ; 337 | 338 | ZeroDigit = '0' ; 339 | 340 | DoubleLiteral = ExponentDecimalReal 341 | | RegularDecimalReal 342 | ; 343 | 344 | ExponentDecimalReal = ({ Digit }- | ({ Digit }-, '.', { Digit }-) | ('.', { Digit }-)), (E), ['-'], { Digit }- ; 345 | 346 | RegularDecimalReal = { Digit }, '.', { Digit }- ; 347 | 348 | SchemaName = SymbolicName 349 | | ReservedWord 350 | ; 351 | 352 | ReservedWord = (A,L,L) 353 | | (A,S,C) 354 | | (A,S,C,E,N,D,I,N,G) 355 | | (B,Y) 356 | | (C,R,E,A,T,E) 357 | | (D,E,L,E,T,E) 358 | | (D,E,S,C) 359 | | (D,E,S,C,E,N,D,I,N,G) 360 | | (D,E,T,A,C,H) 361 | | (E,X,I,S,T,S) 362 | | (L,I,M,I,T) 363 | | (M,A,T,C,H) 364 | | (M,E,R,G,E) 365 | | (O,N) 366 | | (O,P,T,I,O,N,A,L) 367 | | (O,R,D,E,R) 368 | | (R,E,M,O,V,E) 369 | | (R,E,T,U,R,N) 370 | | (S,E,T) 371 | | (S,K,I,P) 372 | | (W,H,E,R,E) 373 | | (W,I,T,H) 374 | | (U,N,I,O,N) 375 | | (U,N,W,I,N,D) 376 | | (A,N,D) 377 | | (A,S) 378 | | (C,O,N,T,A,I,N,S) 379 | | (D,I,S,T,I,N,C,T) 380 | | (E,N,D,S) 381 | | (I,N) 382 | | (I,S) 383 | | (N,O,T) 384 | | (O,R) 385 | | (S,T,A,R,T,S) 386 | | (X,O,R) 387 | | (F,A,L,S,E) 388 | | (T,R,U,E) 389 | | (N,U,L,L) 390 | | (C,O,N,S,T,R,A,I,N,T) 391 | | (D,O) 392 | | (F,O,R) 393 | | (R,E,Q,U,I,R,E) 394 | | (U,N,I,Q,U,E) 395 | | (C,A,S,E) 396 | | (W,H,E,N) 397 | | (T,H,E,N) 398 | | (E,L,S,E) 399 | | (E,N,D) 400 | | (M,A,N,D,A,T,O,R,Y) 401 | | (S,C,A,L,A,R) 402 | | (O,F) 403 | | (A,D,D) 404 | | (D,R,O,P) 405 | ; 406 | 407 | SymbolicName = UnescapedSymbolicName 408 | | EscapedSymbolicName 409 | | HexLetter 410 | | (C,O,U,N,T) 411 | | (F,I,L,T,E,R) 412 | | (E,X,T,R,A,C,T) 413 | | (A,N,Y) 414 | | (N,O,N,E) 415 | | (S,I,N,G,L,E) 416 | ; 417 | 418 | UnescapedSymbolicName = IdentifierStart, { IdentifierPart } ; 419 | 420 | (* Based on the unicode identifier and pattern syntax 421 | * (http://www.unicode.org/reports/tr31/) 422 | * And extended with a few characters. 423 | *)IdentifierStart = ID_Start 424 | | Pc 425 | ; 426 | 427 | (* Based on the unicode identifier and pattern syntax 428 | * (http://www.unicode.org/reports/tr31/) 429 | * And extended with a few characters. 430 | *)IdentifierPart = ID_Continue 431 | | Sc 432 | ; 433 | 434 | (* Any character except "`", enclosed within `backticks`. Backticks are escaped with double backticks. 435 | *)EscapedSymbolicName = { '`', { ANY - ('`') }, '`' }- ; 436 | 437 | SP = { whitespace }- ; 438 | 439 | whitespace = SPACE 440 | | TAB 441 | | LF 442 | | VT 443 | | FF 444 | | CR 445 | | FS 446 | | GS 447 | | RS 448 | | US 449 | | ' ' 450 | | '᠎' 451 | | ' ' 452 | | ' ' 453 | | ' ' 454 | | ' ' 455 | | ' ' 456 | | ' ' 457 | | ' ' 458 | | ' ' 459 | | ' ' 460 | | ' ' 461 | | '' 462 | | '' 463 | | ' ' 464 | | ' ' 465 | | ' ' 466 | | ' ' 467 | | ' ' 468 | | Comment 469 | ; 470 | 471 | Comment = ('/*', { ANY - ('*') | ('*', ANY - ('/')) }, '*/') 472 | | ('//', { ANY - (LF | CR) }, [CR], (LF | EOI)) 473 | ; 474 | 475 | LeftArrowHead = '<' 476 | | '⟨' 477 | | '〈' 478 | | '﹤' 479 | | '<' 480 | ; 481 | 482 | RightArrowHead = '>' 483 | | '⟩' 484 | | '〉' 485 | | '﹥' 486 | | '>' 487 | ; 488 | 489 | Dash = '-' 490 | | '­' 491 | | '‐' 492 | | '‑' 493 | | '‒' 494 | | '–' 495 | | '—' 496 | | '―' 497 | | '−' 498 | | '﹘' 499 | | '﹣' 500 | | '-' 501 | ; 502 | 503 | A = 'A' | 'a' ; 504 | 505 | B = 'B' | 'b' ; 506 | 507 | C = 'C' | 'c' ; 508 | 509 | D = 'D' | 'd' ; 510 | 511 | E = 'E' | 'e' ; 512 | 513 | F = 'F' | 'f' ; 514 | 515 | G = 'G' | 'g' ; 516 | 517 | H = 'H' | 'h' ; 518 | 519 | I = 'I' | 'i' ; 520 | 521 | K = 'K' | 'k' ; 522 | 523 | L = 'L' | 'l' ; 524 | 525 | M = 'M' | 'm' ; 526 | 527 | N = 'N' | 'n' ; 528 | 529 | O = 'O' | 'o' ; 530 | 531 | P = 'P' | 'p' ; 532 | 533 | Q = 'Q' | 'q' ; 534 | 535 | R = 'R' | 'r' ; 536 | 537 | S = 'S' | 's' ; 538 | 539 | T = 'T' | 't' ; 540 | 541 | U = 'U' | 'u' ; 542 | 543 | V = 'V' | 'v' ; 544 | 545 | W = 'W' | 'w' ; 546 | 547 | X = 'X' | 'x' ; 548 | 549 | Y = 'Y' | 'y' ; 550 | 551 | -------------------------------------------------------------------------------- /src/parser/expr.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | #[derive(Debug)] 4 | pub enum Expr { 5 | EqualExpr(EqualExpr), 6 | NotEqualExpr(NotEqualExpr), 7 | LessExpr(LessExpr), 8 | GreaterExpr(GreaterExpr), 9 | LessEqualExpr(LessEqualExpr), 10 | GreaterEqualExpr(GreaterEqualExpr), 11 | 12 | AndExpr(AndExpr), 13 | XorExpr(XorExpr), 14 | OrExpr(OrExpr), 15 | NotExpr(NotExpr), 16 | 17 | AddExpr(AddExpr), 18 | SubExpr(SubExpr), 19 | MultExpr(MultExpr), 20 | DivExpr(DivExpr), 21 | PowerExpr(PowerExpr), 22 | UnarySubExpr(UnarySubExpr), 23 | 24 | NumberLit(f64), 25 | StringLit(String), 26 | BooleanLit(bool), 27 | 28 | Variable(String), 29 | PropertyLookup(PropertyLookup), 30 | } 31 | 32 | impl fmt::Display for Expr { 33 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 34 | match self { 35 | Self::EqualExpr(expr) => write!(fmt, "{}={}", expr.lhs, expr.rhs), 36 | Self::NotEqualExpr(expr) => write!(fmt, "{}!={}", expr.lhs, expr.rhs), 37 | Self::LessExpr(expr) => write!(fmt, "{}<{}", expr.lhs, expr.rhs), 38 | Self::LessEqualExpr(expr) => write!(fmt, "{}<={}", expr.lhs, expr.rhs), 39 | Self::GreaterExpr(expr) => write!(fmt, "{}>{}", expr.lhs, expr.rhs), 40 | Self::GreaterEqualExpr(expr) => write!(fmt, "{}>={}", expr.lhs, expr.rhs), 41 | Self::AndExpr(expr) => write!(fmt, "{} AND {}", expr.lhs, expr.rhs), 42 | Self::XorExpr(expr) => write!(fmt, "{} XOR {}", expr.lhs, expr.rhs), 43 | Self::OrExpr(expr) => write!(fmt, "{} OR {}", expr.lhs, expr.rhs), 44 | Self::NotExpr(expr) => write!(fmt, "NOT {}", expr.child), 45 | Self::AddExpr(expr) => write!(fmt, "{}+{}", expr.lhs, expr.rhs), 46 | Self::SubExpr(expr) => write!(fmt, "{}-{}", expr.lhs, expr.rhs), 47 | Self::MultExpr(expr) => write!(fmt, "{}*{}", expr.lhs, expr.rhs), 48 | Self::DivExpr(expr) => write!(fmt, "{}/{}", expr.lhs, expr.rhs), 49 | Self::PowerExpr(expr) => write!(fmt, "{}^{}", expr.lhs, expr.rhs), 50 | Self::UnarySubExpr(expr) => write!(fmt, "-{}", expr.child), 51 | Self::NumberLit(expr) => write!(fmt, "{}", expr), 52 | Self::StringLit(expr) => write!(fmt, "{}", expr), 53 | Self::BooleanLit(expr) => write!(fmt, "{}", expr), 54 | Self::Variable(expr) => write!(fmt, "{}", expr), 55 | Self::PropertyLookup(expr) => write!(fmt, "{}.{}", expr.child, expr.prop_name), 56 | } 57 | } 58 | } 59 | 60 | #[derive(Debug)] 61 | pub struct EqualExpr { 62 | pub lhs: Box, 63 | pub rhs: Box, 64 | } 65 | 66 | #[derive(Debug)] 67 | pub struct NotEqualExpr { 68 | pub lhs: Box, 69 | pub rhs: Box, 70 | } 71 | 72 | #[derive(Debug)] 73 | pub struct LessExpr { 74 | pub lhs: Box, 75 | pub rhs: Box, 76 | } 77 | 78 | #[derive(Debug)] 79 | pub struct LessEqualExpr { 80 | pub lhs: Box, 81 | pub rhs: Box, 82 | } 83 | 84 | #[derive(Debug)] 85 | pub struct GreaterExpr { 86 | pub lhs: Box, 87 | pub rhs: Box, 88 | } 89 | 90 | #[derive(Debug)] 91 | pub struct GreaterEqualExpr { 92 | pub lhs: Box, 93 | pub rhs: Box, 94 | } 95 | 96 | #[derive(Debug)] 97 | pub struct AndExpr { 98 | pub lhs: Box, 99 | pub rhs: Box, 100 | } 101 | 102 | #[derive(Debug)] 103 | pub struct OrExpr { 104 | pub lhs: Box, 105 | pub rhs: Box, 106 | } 107 | 108 | #[derive(Debug)] 109 | pub struct XorExpr { 110 | pub lhs: Box, 111 | pub rhs: Box, 112 | } 113 | 114 | #[derive(Debug)] 115 | pub struct NotExpr { 116 | pub child: Box, 117 | } 118 | 119 | #[derive(Debug)] 120 | pub struct AddExpr { 121 | pub lhs: Box, 122 | pub rhs: Box, 123 | } 124 | 125 | #[derive(Debug)] 126 | pub struct SubExpr { 127 | pub lhs: Box, 128 | pub rhs: Box, 129 | } 130 | 131 | #[derive(Debug)] 132 | pub struct MultExpr { 133 | pub lhs: Box, 134 | pub rhs: Box, 135 | } 136 | 137 | #[derive(Debug)] 138 | pub struct DivExpr { 139 | pub lhs: Box, 140 | pub rhs: Box, 141 | } 142 | 143 | #[derive(Debug)] 144 | pub struct PowerExpr { 145 | pub lhs: Box, 146 | pub rhs: Box, 147 | } 148 | 149 | #[derive(Debug)] 150 | pub struct UnarySubExpr { 151 | pub child: Box, 152 | } 153 | 154 | #[derive(Debug)] 155 | pub struct PropertyLookup { 156 | pub child: Box, 157 | pub prop_name: String, 158 | } 159 | -------------------------------------------------------------------------------- /src/parser/mod.rs: -------------------------------------------------------------------------------- 1 | mod expr; 2 | mod parser; 3 | mod stmt; 4 | 5 | pub use expr::*; 6 | pub use parser::Parser; 7 | pub use stmt::*; 8 | -------------------------------------------------------------------------------- /src/parser/parser.rs: -------------------------------------------------------------------------------- 1 | use core::f64; 2 | 3 | use super::expr::*; 4 | use super::stmt::*; 5 | use nom::{ 6 | branch::alt, 7 | bytes::complete::{tag, tag_no_case, take_while, take_while1}, 8 | character::complete::{char as c, digit1, hex_digit1, multispace0, multispace1, one_of}, 9 | combinator::{map, opt}, 10 | multi::many0, 11 | number::complete::double, 12 | sequence::{delimited, pair, terminated, tuple}, 13 | IResult, 14 | }; 15 | 16 | use crate::{util::ErrorKind, Error}; 17 | 18 | pub struct Parser {} 19 | 20 | impl Parser { 21 | pub fn new() -> Parser { 22 | Parser {} 23 | } 24 | 25 | pub fn parse(&self, input: &str) -> Result { 26 | Self::parse_impl(input).map(|v| v.1).map_err(|e| Error { 27 | msg: e.map(|e| e.code.description().to_owned()).to_string(), 28 | kind: ErrorKind::Parse, 29 | }) 30 | } 31 | 32 | fn parse_impl(input: &str) -> IResult<&str, Query> { 33 | map(terminated(tuple((sp0, query, sp0)), opt(tag(";"))), |v| v.1)(input) 34 | } 35 | } 36 | 37 | fn query(input: &str) -> IResult<&str, Query> { 38 | map(tuple((reading_clause, sp0, return_clause)), |v| Query { 39 | unions: Vec::from([Union { 40 | reading_clause: Some(v.0), 41 | updating_clauses: Vec::new(), 42 | return_clause: v.2, 43 | }]), 44 | sort_items: Vec::new(), 45 | ordering: None, 46 | skip: None, 47 | limit: None, 48 | })(input) 49 | } 50 | 51 | fn reading_clause(input: &str) -> IResult<&str, ReadingClause> { 52 | match_clause(input) 53 | } 54 | 55 | fn match_clause(input: &str) -> IResult<&str, ReadingClause> { 56 | map( 57 | tuple(( 58 | tag_no_case("MATCH"), 59 | sp1, 60 | pattern, 61 | many0(tuple((tag(","), sp0, pattern))), 62 | opt(tuple((sp1, tag_no_case("WHERE"), sp1, expr))), 63 | )), 64 | |v| { 65 | let mut patterns = Vec::new(); 66 | patterns.push(v.2); 67 | for i in v.3.into_iter() { 68 | patterns.push(i.2); 69 | } 70 | let mut predicate = Vec::new(); 71 | match v.4 { 72 | Some((_, _, _, e)) => predicate.push(e), 73 | None => {} 74 | }; 75 | ReadingClause::Match(MatchClause { 76 | pattern: patterns, 77 | filter: predicate, 78 | }) 79 | }, 80 | )(input) 81 | } 82 | 83 | fn return_clause(input: &str) -> IResult<&str, ReturnClause> { 84 | map( 85 | tuple(( 86 | tag_no_case("RETURN"), 87 | sp1, 88 | alt(( 89 | map( 90 | tuple(( 91 | tag("*"), 92 | many0(tuple((sp0, tag(","), sp0, projection_item))), 93 | )), 94 | |v| ReturnClause { 95 | star: true, 96 | projections: v.1.into_iter().map(|v| v.3).collect(), 97 | }, 98 | ), 99 | map( 100 | tuple(( 101 | projection_item, 102 | many0(tuple((sp0, tag(","), sp0, projection_item))), 103 | )), 104 | |v| { 105 | let mut projections = Vec::new(); 106 | projections.push(v.0); 107 | v.1.into_iter().for_each(|v| projections.push(v.3)); 108 | ReturnClause { 109 | star: false, 110 | projections: projections, 111 | } 112 | }, 113 | ), 114 | )), 115 | )), 116 | |v| v.2, 117 | )(input) 118 | } 119 | 120 | fn projection_item(input: &str) -> IResult<&str, (Expr, String)> { 121 | alt(( 122 | map(expr, |v| { 123 | let s = format!("{}", &v); 124 | (v, s) 125 | }), 126 | map( 127 | tuple((expr, sp0, tag_no_case("AS"), sp0, symbolic_name)), 128 | |v| (v.0, v.4), 129 | ), 130 | ))(input) 131 | } 132 | 133 | fn pattern(input: &str) -> IResult<&str, Pattern> { 134 | map( 135 | tuple(( 136 | node_pattern, 137 | many0(tuple((sp0, relationship_pattern, sp0, node_pattern))), 138 | )), 139 | |v| { 140 | let mut pattern = Pattern { 141 | nodes: Vec::new(), 142 | rels: Vec::new(), 143 | }; 144 | pattern.nodes.push(v.0); 145 | v.1.into_iter().for_each(|v| { 146 | pattern.rels.push(v.1); 147 | pattern.nodes.push(v.3); 148 | }); 149 | pattern 150 | }, 151 | )(input) 152 | } 153 | 154 | fn node_pattern(input: &str) -> IResult<&str, NodePattern> { 155 | map( 156 | tuple(( 157 | c('('), 158 | sp0, 159 | symbolic_name, 160 | sp0, // Variable 161 | many0(tuple((c(':'), symbolic_name))), // labels 162 | sp0, 163 | c(')'), 164 | )), 165 | |v| NodePattern { 166 | name: v.2, 167 | labels: v.4.into_iter().map(|v| v.1).collect(), 168 | }, 169 | )(input) 170 | } 171 | 172 | fn relationship_pattern(input: &str) -> IResult<&str, RelationshipPattern> { 173 | alt(( 174 | map( 175 | tuple(( 176 | left_arrow, 177 | sp0, 178 | dash, 179 | sp0, 180 | c('['), 181 | symbolic_name, 182 | sp0, 183 | many0(tuple((c(':'), symbolic_name))), 184 | sp0, 185 | c(']'), 186 | sp0, 187 | dash, 188 | sp0, 189 | )), 190 | |v| RelationshipPattern { 191 | name: v.5, 192 | direction: Direction::Left, 193 | types: v.7.into_iter().map(|v| v.1).collect(), 194 | }, 195 | ), 196 | map( 197 | tuple(( 198 | sp0, 199 | dash, 200 | sp0, 201 | c('['), 202 | symbolic_name, 203 | sp0, 204 | many0(tuple((c(':'), symbolic_name))), 205 | sp0, 206 | c(']'), 207 | sp0, 208 | dash, 209 | sp0, 210 | right_arrow, 211 | )), 212 | |v| RelationshipPattern { 213 | name: v.4, 214 | direction: Direction::Right, 215 | types: v.6.into_iter().map(|v| v.1).collect(), 216 | }, 217 | ), 218 | ))(input) 219 | } 220 | 221 | fn updating_clause(input: &str) -> IResult<&str, UpdatingClause> { 222 | unimplemented!() 223 | } 224 | 225 | fn expr(input: &str) -> IResult<&str, Expr> { 226 | or_expr(input) 227 | } 228 | 229 | fn or_expr(input: &str) -> IResult<&str, Expr> { 230 | map( 231 | tuple(( 232 | xor_expr, 233 | opt(tuple((sp1, tag_no_case("OR"), sp1, xor_expr))), 234 | )), 235 | |v| match v.1 { 236 | Some(e) => Expr::OrExpr(OrExpr { 237 | lhs: Box::new(v.0), 238 | rhs: Box::new(e.3), 239 | }), 240 | None => v.0, 241 | }, 242 | )(input) 243 | } 244 | 245 | fn xor_expr(input: &str) -> IResult<&str, Expr> { 246 | map( 247 | tuple(( 248 | and_expr, 249 | opt(tuple((sp1, tag_no_case("XOR"), sp1, and_expr))), 250 | )), 251 | |v| match v.1 { 252 | Some(e) => Expr::XorExpr(XorExpr { 253 | lhs: Box::new(v.0), 254 | rhs: Box::new(e.3), 255 | }), 256 | None => v.0, 257 | }, 258 | )(input) 259 | } 260 | 261 | fn and_expr(input: &str) -> IResult<&str, Expr> { 262 | map( 263 | tuple(( 264 | not_expr, 265 | opt(tuple((sp1, tag_no_case("AND"), sp1, not_expr))), 266 | )), 267 | |v| match v.1 { 268 | Some(e) => Expr::AndExpr(AndExpr { 269 | lhs: Box::new(v.0), 270 | rhs: Box::new(e.3), 271 | }), 272 | None => v.0, 273 | }, 274 | )(input) 275 | } 276 | 277 | fn not_expr(input: &str) -> IResult<&str, Expr> { 278 | map( 279 | tuple((opt(pair(tag_no_case("NOT"), sp1)), comp_expr)), 280 | |v| match v.0 { 281 | Some(_) => Expr::NotExpr(NotExpr { 282 | child: Box::new(v.1), 283 | }), 284 | None => v.1, 285 | }, 286 | )(input) 287 | } 288 | 289 | fn comp_expr(input: &str) -> IResult<&str, Expr> { 290 | map( 291 | tuple((add_sub_expr, opt(pair(sp1, partial_comp_expr)))), 292 | |v| match v.1 { 293 | Some(e) => match e.1 { 294 | ("=", r) => Expr::EqualExpr(EqualExpr { 295 | lhs: Box::new(v.0), 296 | rhs: Box::new(r), 297 | }), 298 | ("!=", r) => Expr::NotEqualExpr(NotEqualExpr { 299 | lhs: Box::new(v.0), 300 | rhs: Box::new(r), 301 | }), 302 | ("<", r) => Expr::LessExpr(LessExpr { 303 | lhs: Box::new(v.0), 304 | rhs: Box::new(r), 305 | }), 306 | ("<=", r) => Expr::LessEqualExpr(LessEqualExpr { 307 | lhs: Box::new(v.0), 308 | rhs: Box::new(r), 309 | }), 310 | (">", r) => Expr::GreaterExpr(GreaterExpr { 311 | lhs: Box::new(v.0), 312 | rhs: Box::new(r), 313 | }), 314 | (">=", r) => Expr::GreaterEqualExpr(GreaterEqualExpr { 315 | lhs: Box::new(v.0), 316 | rhs: Box::new(r), 317 | }), 318 | _ => panic!("unexpected"), 319 | }, 320 | None => v.0, 321 | }, 322 | )(input) 323 | } 324 | 325 | fn partial_comp_expr(input: &str) -> IResult<&str, (&str, Expr)> { 326 | map( 327 | tuple(( 328 | alt((tag("="), tag("<"), tag("<="), tag(">"), tag(">="))), 329 | sp0, 330 | add_sub_expr, 331 | )), 332 | |v| (v.0, v.2), 333 | )(input) 334 | } 335 | 336 | fn add_sub_expr(input: &str) -> IResult<&str, Expr> { 337 | map( 338 | tuple(( 339 | mul_div_expr, 340 | opt(tuple((sp1, one_of("+-"), sp1, mul_div_expr))), 341 | )), 342 | |v| match v.1 { 343 | Some(e) => match e.1 { 344 | '+' => Expr::AddExpr(AddExpr { 345 | lhs: Box::new(v.0), 346 | rhs: Box::new(e.3), 347 | }), 348 | '-' => Expr::SubExpr(SubExpr { 349 | lhs: Box::new(v.0), 350 | rhs: Box::new(e.3), 351 | }), 352 | _ => panic!("unexpected"), 353 | }, 354 | None => v.0, 355 | }, 356 | )(input) 357 | } 358 | 359 | fn mul_div_expr(input: &str) -> IResult<&str, Expr> { 360 | map( 361 | tuple((power_expr, opt(tuple((sp1, one_of("*/"), sp1, power_expr))))), 362 | |v| match v.1 { 363 | Some(e) => match e.1 { 364 | '*' => Expr::MultExpr(MultExpr { 365 | lhs: Box::new(v.0), 366 | rhs: Box::new(e.3), 367 | }), 368 | '/' => Expr::DivExpr(DivExpr { 369 | lhs: Box::new(v.0), 370 | rhs: Box::new(e.3), 371 | }), 372 | _ => panic!("unexpected"), 373 | }, 374 | None => v.0, 375 | }, 376 | )(input) 377 | } 378 | 379 | fn power_expr(input: &str) -> IResult<&str, Expr> { 380 | map( 381 | tuple(( 382 | unary_add_sub_expr, 383 | opt(tuple((sp1, tag("^"), sp1, unary_add_sub_expr))), 384 | )), 385 | |v| match v.1 { 386 | Some(e) => Expr::PowerExpr(PowerExpr { 387 | lhs: Box::new(v.0), 388 | rhs: Box::new(e.3), 389 | }), 390 | None => v.0, 391 | }, 392 | )(input) 393 | } 394 | 395 | fn unary_add_sub_expr(input: &str) -> IResult<&str, Expr> { 396 | map( 397 | tuple((opt(tuple((one_of("+-"), sp0))), property_lookup_expr)), 398 | |v| match v.0 { 399 | Some(e) => Expr::UnarySubExpr(UnarySubExpr { 400 | child: Box::new(v.1), 401 | }), 402 | None => v.1, 403 | }, 404 | )(input) 405 | } 406 | 407 | fn property_lookup_expr(input: &str) -> IResult<&str, Expr> { 408 | map( 409 | tuple((atom_expr, opt(tuple((sp0, tag("."), sp0, symbolic_name))))), 410 | |v| match v.1 { 411 | Some(e) => Expr::PropertyLookup(PropertyLookup { 412 | child: Box::new(v.0), 413 | prop_name: e.3, 414 | }), 415 | None => v.0, 416 | }, 417 | )(input) 418 | } 419 | 420 | fn atom_expr(input: &str) -> IResult<&str, Expr> { 421 | alt((literal, map(symbolic_name, |v| Expr::Variable(v))))(input) 422 | } 423 | 424 | fn literal(input: &str) -> IResult<&str, Expr> { 425 | alt((number_literal, string_literal, boolean_literal))(input) 426 | } 427 | 428 | fn number_literal(input: &str) -> IResult<&str, Expr> { 429 | alt(( 430 | map(double, |v| Expr::NumberLit(v)), 431 | map(pair(tag_no_case("0X"), hex_digit1), |v| { 432 | Expr::NumberLit(i64::from_str_radix(v.1, 16).unwrap() as f64) 433 | }), 434 | map(digit1, |v| { 435 | Expr::NumberLit(i64::from_str_radix(v, 10).unwrap() as f64) 436 | }), 437 | ))(input) 438 | } 439 | 440 | fn string_literal(input: &str) -> IResult<&str, Expr> { 441 | alt(( 442 | delimited( 443 | tag("\""), 444 | map(take_while(|v| v != '\"'), |v| { 445 | Expr::StringLit(String::from(v)) 446 | }), 447 | tag("\""), 448 | ), 449 | delimited( 450 | tag("\'"), 451 | map(take_while(|v| v != '\''), |v| { 452 | Expr::StringLit(String::from(v)) 453 | }), 454 | tag("\'"), 455 | ), 456 | ))(input) 457 | } 458 | 459 | fn boolean_literal(input: &str) -> IResult<&str, Expr> { 460 | alt(( 461 | map(tag_no_case("TRUE"), |_| Expr::BooleanLit(true)), 462 | map(tag_no_case("FALSE"), |_| Expr::BooleanLit(false)), 463 | ))(input) 464 | } 465 | 466 | fn sp0(input: &str) -> IResult<&str, ()> { 467 | map(multispace0, |_| ())(input) 468 | } 469 | 470 | fn sp1(input: &str) -> IResult<&str, ()> { 471 | map(multispace1, |_| ())(input) 472 | } 473 | 474 | fn symbolic_name(input: &str) -> IResult<&str, String> { 475 | map( 476 | take_while1(|v: char| v.is_alphabetic() || v.is_numeric() || v == '_'), 477 | |v| String::from(v), 478 | )(input) 479 | } 480 | 481 | fn dash(input: &str) -> IResult<&str, ()> { 482 | map(one_of("-­‐‑‒–—―−﹘﹣-"), |v| ())(input) 483 | } 484 | 485 | fn left_arrow(input: &str) -> IResult<&str, ()> { 486 | map(c('<'), |_| ())(input) 487 | } 488 | 489 | fn right_arrow(input: &str) -> IResult<&str, ()> { 490 | map(c('>'), |_| ())(input) 491 | } 492 | 493 | #[test] 494 | fn test_parse() { 495 | let query = r#" 496 | MATCH (a:Label1)-[r:Type1]->(b:Label2) 497 | WHERE a = 1 498 | RETURN *, a, b;"#; 499 | let parser = Parser::new(); 500 | // println!("{:#?}", parser.parse(query)); 501 | } 502 | 503 | #[test] 504 | fn test_parse_multiple_pattern() { 505 | let query = r#" 506 | MATCH (a:Label1)-[r:Type1]->(b:Label2), (c:Label1)<-[r1:Type1]-(d:Label2) 507 | WHERE a = 1 508 | RETURN *, a, b;"#; 509 | let parser = Parser::new(); 510 | // println!("{:#?}", parser.parse(query)); 511 | } 512 | -------------------------------------------------------------------------------- /src/parser/stmt.rs: -------------------------------------------------------------------------------- 1 | use super::expr::*; 2 | 3 | #[derive(Debug)] 4 | pub enum Stmt { 5 | CypherQuery(Query), 6 | } 7 | 8 | #[derive(Debug)] 9 | pub enum SortOrdering { 10 | Ascending, 11 | Descending, 12 | } 13 | 14 | #[derive(Debug)] 15 | pub struct Query { 16 | pub unions: Vec, 17 | pub sort_items: Vec, 18 | pub ordering: Option, 19 | pub skip: Option, 20 | pub limit: Option, 21 | } 22 | 23 | #[derive(Debug)] 24 | pub struct Union { 25 | pub reading_clause: Option, 26 | pub updating_clauses: Vec, 27 | pub return_clause: ReturnClause, 28 | } 29 | 30 | #[derive(Debug)] 31 | pub enum ReadingClause { 32 | Match(MatchClause), 33 | Unwind, 34 | } 35 | 36 | #[derive(Debug)] 37 | pub struct MatchClause { 38 | pub pattern: Vec, 39 | pub filter: Vec, 40 | } 41 | 42 | #[derive(Debug)] 43 | pub struct NodePattern { 44 | pub name: String, 45 | pub labels: Vec, 46 | } 47 | 48 | #[derive(Debug)] 49 | pub enum Direction { 50 | Left, 51 | Right, 52 | } 53 | 54 | #[derive(Debug)] 55 | pub struct RelationshipPattern { 56 | pub name: String, 57 | pub direction: Direction, 58 | pub types: Vec, 59 | } 60 | 61 | #[derive(Debug)] 62 | pub struct Pattern { 63 | pub nodes: Vec, 64 | pub rels: Vec, 65 | } 66 | 67 | #[derive(Debug)] 68 | pub enum UpdatingClause { 69 | Create, 70 | Merge, 71 | Remove, 72 | Set, 73 | } 74 | 75 | #[derive(Debug)] 76 | pub struct ReturnClause { 77 | pub star: bool, 78 | pub projections: Vec<(Expr, String)>, 79 | } 80 | -------------------------------------------------------------------------------- /src/runtime/executor.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | core::Context, 3 | optimizer::{ExpandExpr, ProjectExpr, RelExpr, ScalarExpr, SelectExpr}, 4 | types::Object, 5 | }; 6 | use crate::{core::TiDBService, types::Value}; 7 | use crate::{optimizer::ScanExpr, Error}; 8 | use mysql::{ 9 | prelude::{FromRow, Queryable}, 10 | Pool, PooledConn, Row, 11 | }; 12 | use std::collections::{HashMap, VecDeque}; 13 | 14 | use super::expression::eval; 15 | 16 | #[derive(Clone, Debug)] 17 | pub struct ExecutionContext { 18 | pub values: HashMap, 19 | } 20 | 21 | impl ExecutionContext { 22 | pub fn new() -> ExecutionContext { 23 | ExecutionContext { 24 | values: HashMap::new(), 25 | } 26 | } 27 | 28 | pub fn get(&self, name: &str) -> Option<&Value> { 29 | self.values.get(name) 30 | } 31 | 32 | pub fn set(&mut self, name: &str, value: Value) { 33 | self.values.insert(String::from(name), value); 34 | } 35 | 36 | pub fn clear(&mut self) { 37 | self.values.clear(); 38 | } 39 | } 40 | 41 | pub trait Executor { 42 | fn open(&mut self) -> Result<(), Error>; 43 | fn next(&mut self) -> Result, Error>; 44 | fn close(&mut self) -> Result<(), Error>; 45 | } 46 | 47 | pub struct TiDBScanExec { 48 | context: Context, 49 | result: VecDeque, 50 | 51 | binded_name: String, 52 | all: bool, 53 | label: String, 54 | } 55 | 56 | impl Executor for TiDBScanExec { 57 | fn open(&mut self) -> Result<(), Error> { 58 | let mut conn = prepare_tidb_connection(&self.context)?; 59 | let res = scan_table(&self.table_name(), &self.binded_name, &mut conn)?; 60 | self.result = VecDeque::from(res); 61 | 62 | Ok(()) 63 | } 64 | 65 | fn close(&mut self) -> Result<(), Error> { 66 | Ok(()) 67 | } 68 | 69 | fn next(&mut self) -> Result, Error> { 70 | Ok(self.result.pop_front()) 71 | } 72 | } 73 | 74 | impl TiDBScanExec { 75 | pub fn new(expr: &ScanExpr) -> TiDBScanExec { 76 | TiDBScanExec { 77 | binded_name: expr.binded_name.to_owned(), 78 | all: expr.all, 79 | label: expr.label.to_owned(), 80 | context: Context::new(), 81 | result: VecDeque::new(), 82 | } 83 | } 84 | 85 | fn table_name(&self) -> String { 86 | match self.context.tidb_service.label_table_map.get(&self.label) { 87 | Some(name) => name.to_owned(), 88 | None => self.label.to_owned(), 89 | } 90 | } 91 | 92 | fn scan_sql(&self, table_name: String) -> String { 93 | format!(r#"select * from {};"#, table_name) 94 | } 95 | } 96 | 97 | pub struct ProjectExec { 98 | projects: Vec<(ScalarExpr, String)>, 99 | star: bool, 100 | 101 | child: Box, 102 | } 103 | 104 | impl Executor for ProjectExec { 105 | fn open(&mut self) -> Result<(), Error> { 106 | self.child.open() 107 | } 108 | 109 | fn next(&mut self) -> Result, Error> { 110 | match self.child.next() { 111 | Ok(Some(mut ctx)) => { 112 | if self.star { 113 | for p in self.projects.iter() { 114 | let v = eval(&p.0, &ctx)?; 115 | ctx.set(&p.1, v); 116 | } 117 | Ok(Some(ctx)) 118 | } else { 119 | let mut res = ExecutionContext::new(); 120 | for p in self.projects.iter() { 121 | let v = eval(&p.0, &ctx)?; 122 | res.set(&p.1, v); 123 | } 124 | Ok(Some(res)) 125 | } 126 | } 127 | v @ _ => v, 128 | } 129 | } 130 | 131 | fn close(&mut self) -> Result<(), Error> { 132 | self.child.close() 133 | } 134 | } 135 | 136 | impl ProjectExec { 137 | pub fn new(child: Box, project: &ProjectExpr) -> ProjectExec { 138 | ProjectExec { 139 | projects: project.projects.to_owned(), 140 | star: project.star, 141 | child: child, 142 | } 143 | } 144 | } 145 | 146 | pub struct TiDBNestedLoopExpand { 147 | context: Context, 148 | result: VecDeque, 149 | start_name: String, 150 | end_name: String, 151 | rel_name: String, 152 | rel_type: String, 153 | end_label: String, 154 | 155 | child: Box, 156 | } 157 | 158 | impl Executor for TiDBNestedLoopExpand { 159 | fn open(&mut self) -> Result<(), Error> { 160 | self.child.open()?; 161 | let mut conn = prepare_tidb_connection(&self.context)?; 162 | let rels = self.fetch_relationships(&mut conn)?; 163 | let end_nodes = self.fetch_end_nodes(&mut conn)?; 164 | let start_id = "id"; 165 | let end_id = "id"; 166 | let rel_id = ("start", "end"); 167 | 168 | let mut result = Vec::new(); 169 | 170 | // println!("Relationships: {:#?}", rels); 171 | // println!("End Nodes: {:#?}", end_nodes); 172 | 173 | // Join with rels 174 | while let Ok(Some(ref ctx)) = self.child.next() { 175 | for rel in rels.iter() { 176 | match ( 177 | ctx.get(self.start_name.as_str()), 178 | rel.get(self.rel_name.as_str()), 179 | ) { 180 | (Some(Value::Object(l)), Some(Value::Object(r))) => { 181 | if match (l.get(start_id), r.get(rel_id.0)) { 182 | (Some(l), Some(r)) => l == r, 183 | _ => false, 184 | } { 185 | let mut res = ctx.clone(); 186 | res.set(&self.rel_name, Value::Object(r.to_owned())); 187 | result.push(res); 188 | } 189 | } 190 | _ => {} 191 | } 192 | } 193 | } 194 | 195 | // Join with end 196 | for ctx in result.iter() { 197 | for end in end_nodes.iter() { 198 | match ( 199 | ctx.get(self.rel_name.as_str()), 200 | end.get(self.end_name.as_str()), 201 | ) { 202 | (Some(Value::Object(l)), Some(Value::Object(r))) => { 203 | if match (l.get(rel_id.1), r.get(end_id)) { 204 | (Some(l), Some(r)) => l == r, 205 | _ => false, 206 | } { 207 | let mut res = ctx.clone(); 208 | res.set(&self.end_name, Value::Object(r.to_owned())); 209 | self.result.push_back(res); 210 | } 211 | } 212 | _ => {} 213 | } 214 | } 215 | } 216 | 217 | Ok(()) 218 | } 219 | 220 | fn close(&mut self) -> Result<(), Error> { 221 | self.child.close() 222 | } 223 | 224 | fn next(&mut self) -> Result, Error> { 225 | Ok(self.result.pop_front()) 226 | } 227 | } 228 | 229 | impl TiDBNestedLoopExpand { 230 | pub fn new(child: Box, expand: &ExpandExpr) -> TiDBNestedLoopExpand { 231 | TiDBNestedLoopExpand { 232 | context: Context::new(), 233 | result: VecDeque::new(), 234 | start_name: expand.start_name.to_owned(), 235 | end_name: expand.end_name.to_owned(), 236 | rel_name: expand.rel_name.to_owned(), 237 | rel_type: expand.rel_type.to_owned(), 238 | end_label: expand.end_label.to_owned(), 239 | 240 | child: child, 241 | } 242 | } 243 | 244 | fn fetch_relationships( 245 | &mut self, 246 | conn: &mut PooledConn, 247 | ) -> Result, Error> { 248 | let res = scan_table(self.rel_table_name(), &self.rel_name, conn)?; 249 | Ok(res) 250 | } 251 | 252 | fn fetch_end_nodes(&mut self, conn: &mut PooledConn) -> Result, Error> { 253 | let res = scan_table(self.end_node_table_name(), &self.end_name, conn)?; 254 | Ok(res) 255 | } 256 | 257 | fn rel_table_name(&self) -> &String { 258 | match self 259 | .context 260 | .tidb_service 261 | .label_table_map 262 | .get(&self.rel_type) 263 | { 264 | Some(name) => name, 265 | None => &self.rel_type, 266 | } 267 | } 268 | 269 | fn end_node_table_name(&self) -> &String { 270 | match self 271 | .context 272 | .tidb_service 273 | .label_table_map 274 | .get(&self.end_label) 275 | { 276 | Some(name) => name, 277 | None => &self.end_label, 278 | } 279 | } 280 | } 281 | 282 | pub struct FilterExec { 283 | filter: Vec, 284 | child: Box, 285 | } 286 | 287 | impl Executor for FilterExec { 288 | fn open(&mut self) -> Result<(), Error> { 289 | self.child.open() 290 | } 291 | 292 | fn close(&mut self) -> Result<(), Error> { 293 | self.child.close() 294 | } 295 | 296 | fn next(&mut self) -> Result, Error> { 297 | match self.child.next() { 298 | Ok(Some(ctx)) => { 299 | let mut result = true; 300 | for filter in self.filter.iter() { 301 | if !result { 302 | break; 303 | }; 304 | // println!("{:#?}", ctx); 305 | match eval(filter, &ctx)? { 306 | Value::Boolean(v) if v => result = true, 307 | _ => result = false, 308 | }; 309 | } 310 | if result { 311 | Ok(Some(ctx)) 312 | } else { 313 | self.next() 314 | } 315 | } 316 | v @ _ => v, 317 | } 318 | } 319 | } 320 | 321 | impl FilterExec { 322 | pub fn new(child: Box, expr: &SelectExpr) -> FilterExec { 323 | FilterExec { 324 | filter: expr.filter.to_owned(), 325 | child: child, 326 | } 327 | } 328 | } 329 | 330 | fn prepare_tidb_connection(context: &Context) -> Result { 331 | let TiDBService { 332 | ref host, 333 | ref port, 334 | ref username, 335 | ref password, 336 | ref database, 337 | .. 338 | } = context.tidb_service; 339 | 340 | let url = format!( 341 | "mysql://{}:{}@{}:{}/{}", 342 | username, password, host, port, database, 343 | ); 344 | 345 | let pool = Pool::new(url)?; 346 | Ok(pool.get_conn()?) 347 | } 348 | 349 | fn scan_table( 350 | table_name: &String, 351 | variable_name: &String, 352 | conn: &mut PooledConn, 353 | ) -> Result, Error> { 354 | let sql = format!("select * from {}", table_name); 355 | let mut result = conn.query_iter(sql)?; 356 | 357 | let mut res = Vec::new(); 358 | 359 | while let Some(result_set) = result.next_set() { 360 | let result_set = result_set?; 361 | 362 | let column_names: Vec = result_set 363 | .columns() 364 | .as_ref() 365 | .into_iter() 366 | .map(|v| String::from_utf8(Vec::from(v.name_ref())).unwrap()) 367 | .collect(); 368 | 369 | for row in result_set { 370 | let mut ctx = ExecutionContext::new(); 371 | let mut obj = Object::new(); 372 | let mut row = row?; 373 | for i in 0..row.len() { 374 | // println!("Row: {:#?}", row); 375 | let v: Value = row.take(i).unwrap(); 376 | obj.set(column_names.get(i).unwrap(), &v); 377 | } 378 | ctx.set(variable_name, Value::Object(obj)); 379 | res.push(ctx); 380 | } 381 | } 382 | 383 | Ok(res) 384 | } 385 | -------------------------------------------------------------------------------- /src/runtime/expression/expr.rs: -------------------------------------------------------------------------------- 1 | use crate::Error; 2 | use crate::{optimizer::ScalarExpr, runtime::executor::ExecutionContext, types::Value}; 3 | 4 | pub fn eval(expr: &ScalarExpr, ctx: &ExecutionContext) -> Result { 5 | match expr { 6 | ScalarExpr::PropertyLookup(child, name) => eval_property_lookup(child, name, ctx), 7 | ScalarExpr::Variable(name) => eval_variable(name, ctx), 8 | ScalarExpr::Equal(lhs, rhs) => eval_equal(lhs, rhs, ctx), 9 | ScalarExpr::NumberLiteral(v) => eval_number_literal(v.to_owned(), ctx), 10 | ScalarExpr::StringLiteral(v) => eval_string_literal(v.to_owned(), ctx), 11 | _ => unimplemented!(), 12 | } 13 | } 14 | 15 | fn eval_equal(lhs: &ScalarExpr, rhs: &ScalarExpr, ctx: &ExecutionContext) -> Result { 16 | let res = (eval(lhs, ctx)?, eval(rhs, ctx)?); 17 | match res { 18 | (Value::Int(l), Value::Int(r)) => Ok(Value::Boolean(l == r)), 19 | (Value::Double(l), Value::Double(r)) => Ok(Value::Boolean(l == r)), 20 | (Value::String(l), Value::String(r)) => Ok(Value::Boolean(l == r)), 21 | (Value::Int(l), Value::Double(r)) => Ok(Value::Boolean(l as f64 == r)), 22 | (Value::Double(l), Value::Int(r)) => Ok(Value::Boolean(l == r as f64)), 23 | _ => Ok(Value::Boolean(false)), 24 | } 25 | } 26 | 27 | fn eval_property_lookup( 28 | child: &ScalarExpr, 29 | prop_name: &String, 30 | ctx: &ExecutionContext, 31 | ) -> Result { 32 | let res = eval(child, ctx)?; 33 | match res { 34 | Value::Object(obj) => Ok(obj.get(prop_name).unwrap_or(&Value::Null).to_owned()), 35 | _ => Ok(Value::Null), 36 | } 37 | } 38 | 39 | fn eval_variable(name: &String, ctx: &ExecutionContext) -> Result { 40 | match ctx.get(name) { 41 | Some(v) => Ok(v.to_owned()), 42 | _ => Ok(Value::Null), 43 | } 44 | } 45 | 46 | fn eval_number_literal(value: f64, _: &ExecutionContext) -> Result { 47 | Ok(Value::Double(value)) 48 | } 49 | 50 | fn eval_string_literal(value: String, _: &ExecutionContext) -> Result { 51 | Ok(Value::String(value)) 52 | } 53 | -------------------------------------------------------------------------------- /src/runtime/expression/function.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leiysky/tigraph/3d612209f74251034913c253687778f796536b8e/src/runtime/expression/function.rs -------------------------------------------------------------------------------- /src/runtime/expression/mod.rs: -------------------------------------------------------------------------------- 1 | mod expr; 2 | mod function; 3 | 4 | mod scalar; 5 | 6 | pub use expr::*; -------------------------------------------------------------------------------- /src/runtime/expression/scalar.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leiysky/tigraph/3d612209f74251034913c253687778f796536b8e/src/runtime/expression/scalar.rs -------------------------------------------------------------------------------- /src/runtime/mod.rs: -------------------------------------------------------------------------------- 1 | mod executor; 2 | mod expression; 3 | 4 | pub use executor::Executor; 5 | pub use executor::*; 6 | -------------------------------------------------------------------------------- /src/server/mod.rs: -------------------------------------------------------------------------------- 1 | mod query; 2 | 3 | use actix_web::{post, web, App, HttpServer, Responder, Result}; 4 | use query::query as query_handler; 5 | use serde::{Deserialize, Serialize}; 6 | 7 | pub async fn run() -> std::io::Result<()> { 8 | HttpServer::new(|| App::new().service(query_handler)) 9 | .bind("0.0.0.0:8080")? 10 | .run() 11 | .await 12 | } 13 | -------------------------------------------------------------------------------- /src/server/query.rs: -------------------------------------------------------------------------------- 1 | use crate::types; 2 | use crate::Error; 3 | use crate::{core::Planner, parser::Parser}; 4 | use actix_web::{post, web, App, HttpResponse, HttpServer, Responder, Result}; 5 | use serde::{Deserialize, Serialize}; 6 | 7 | #[derive(Deserialize)] 8 | pub struct Query { 9 | query: String, 10 | } 11 | 12 | #[derive(Serialize, Deserialize)] 13 | pub struct QueryResult { 14 | docs: Vec, 15 | } 16 | 17 | impl From for serde_json::Value { 18 | fn from(value: types::Value) -> Self { 19 | use types::Value; 20 | match value { 21 | Value::Null => serde_json::Value::Null, 22 | Value::Int(v) => serde_json::Value::Number(serde_json::Number::from(v)), 23 | Value::Double(v) => serde_json::Number::from_f64(v) 24 | .map(|v| serde_json::Value::Number(v)) 25 | .unwrap_or(serde_json::Value::Null), 26 | Value::String(v) => serde_json::Value::String(v), 27 | Value::Boolean(v) => serde_json::Value::Bool(v), 28 | Value::Object(v) => serde_json::Value::Object(serde_json::Map::from(v)), 29 | Value::Array(v) => serde_json::Value::Array( 30 | v.elements 31 | .into_iter() 32 | .map(|v| serde_json::Value::from(v)) 33 | .collect(), 34 | ), 35 | } 36 | } 37 | } 38 | 39 | impl From for serde_json::Map { 40 | fn from(v: types::Object) -> Self { 41 | v.props 42 | .into_iter() 43 | .map(|v| (v.0, serde_json::Value::from(v.1))) 44 | .collect() 45 | } 46 | } 47 | 48 | fn run_query(q: String) -> Result { 49 | let planner = Planner {}; 50 | let parser = Parser::new(); 51 | let ast = parser.parse(q.as_str())?; 52 | let mut exec = planner.plan(&ast)?; 53 | 54 | let mut query_result = QueryResult { docs: Vec::new() }; 55 | 56 | exec.open()?; 57 | while let Some(ctx) = exec.next()? { 58 | let mut map = serde_json::Map::new(); 59 | for v in ctx.values { 60 | map.insert(v.0, serde_json::Value::from(v.1)); 61 | } 62 | query_result.docs.push(serde_json::Value::Object(map)) 63 | } 64 | 65 | Ok(query_result) 66 | } 67 | 68 | #[post("/query")] 69 | pub async fn query(query: web::Json) -> impl Responder { 70 | match run_query(query.query.to_owned()) { 71 | Ok(query_result) => HttpResponse::Ok() 72 | .content_type("application/json") 73 | .body(serde_json::to_string(&query_result).unwrap_or(String::from("{}"))), 74 | Err(err) => HttpResponse::InternalServerError().body(err.msg), 75 | } 76 | } 77 | 78 | #[test] 79 | fn test_run_query() { 80 | let result = run_query(String::from( 81 | r#" 82 | MATCH (n:Person)-[r:knows]->(n1:Person) 83 | RETURN n, r, n1 84 | "#, 85 | )) 86 | .unwrap(); 87 | 88 | // println!("{}", serde_json::to_string(&result).unwrap()); 89 | } 90 | -------------------------------------------------------------------------------- /src/storage/mod.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leiysky/tigraph/3d612209f74251034913c253687778f796536b8e/src/storage/mod.rs -------------------------------------------------------------------------------- /src/types/mod.rs: -------------------------------------------------------------------------------- 1 | mod types; 2 | 3 | pub use types::*; 4 | -------------------------------------------------------------------------------- /src/types/types.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use mysql::{ 4 | prelude::{ConvIr, FromValue}, 5 | FromValueError, Value as V, 6 | }; 7 | 8 | pub enum Type { 9 | Integer, 10 | Double, 11 | // Decimal(u32, u32), // Decimal(Scale, Precision) 12 | String, 13 | // Datetime, 14 | // Array, 15 | // Map, 16 | // Blob, 17 | Null, 18 | } 19 | 20 | #[derive(Clone, Debug, PartialEq)] 21 | pub enum Value { 22 | Int(i64), 23 | Double(f64), 24 | String(String), 25 | Boolean(bool), 26 | Null, 27 | 28 | Object(Object), 29 | Array(Array), 30 | } 31 | 32 | impl FromValue for Value { 33 | type Intermediate = Value; 34 | 35 | fn from_value(v: V) -> Value { 36 | Value::from(v) 37 | } 38 | 39 | fn from_value_opt(v: V) -> Result { 40 | Ok(Value::from(v)) 41 | } 42 | 43 | fn get_intermediate(v: V) -> Result { 44 | Ok(Value::from(v)) 45 | } 46 | } 47 | 48 | impl ConvIr for Value { 49 | fn new(v: V) -> Result { 50 | Ok(Value::from(v)) 51 | } 52 | 53 | fn commit(self) -> Value { 54 | Value::from(self) 55 | } 56 | 57 | fn rollback(self) -> V { 58 | V::NULL 59 | } 60 | } 61 | 62 | impl From for Value { 63 | fn from(value: V) -> Value { 64 | match value { 65 | V::Int(v) => Value::Int(v), 66 | V::Double(v) => Value::Double(v), 67 | V::Bytes(v) => { 68 | let string = String::from_utf8(v).unwrap(); 69 | 70 | if let Ok(v) = i64::from_str_radix(&string, 10) { 71 | Value::Int(v) 72 | } else if let Ok(v) = string.parse::() { 73 | Value::Double(v) 74 | } else { 75 | Value::String(string) 76 | } 77 | } 78 | V::NULL => Value::Null, 79 | _ => Value::Null, 80 | } 81 | } 82 | } 83 | 84 | #[derive(Clone, Debug, PartialEq)] 85 | pub struct Object { 86 | pub props: HashMap, 87 | } 88 | 89 | impl Object { 90 | pub fn new() -> Object { 91 | Object { 92 | props: HashMap::new(), 93 | } 94 | } 95 | 96 | pub fn clear(&mut self) { 97 | self.props.clear(); 98 | } 99 | 100 | pub fn get(&self, prop_name: &str) -> Option<&Value> { 101 | self.props.get(prop_name) 102 | } 103 | 104 | pub fn set(&mut self, prop_name: &str, value: &Value) { 105 | self.props.insert(String::from(prop_name), value.to_owned()); 106 | } 107 | } 108 | 109 | #[derive(Clone, Debug, PartialEq)] 110 | pub struct Array { 111 | pub elements: Vec, 112 | } 113 | 114 | impl Array { 115 | pub fn new() -> Array { 116 | Array { 117 | elements: Vec::new(), 118 | } 119 | } 120 | 121 | pub fn clear(&mut self) { 122 | self.elements.clear(); 123 | } 124 | 125 | pub fn get(&self, index: usize) -> Option<&Value> { 126 | self.elements.get(index) 127 | } 128 | 129 | pub fn set(&mut self, index: usize, value: &Value) { 130 | self.elements.insert(index, value.to_owned()); 131 | } 132 | 133 | pub fn push_back(&mut self, value: &Value) { 134 | self.elements.push(value.to_owned()); 135 | } 136 | 137 | pub fn pop_back(&mut self) { 138 | self.elements.pop(); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/util/error.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | #[derive(Debug)] 4 | pub struct Error { 5 | pub msg: String, 6 | pub kind: ErrorKind, 7 | } 8 | 9 | impl fmt::Display for Error { 10 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 11 | write!(f, "{}: {}", self.kind, self.msg) 12 | } 13 | } 14 | 15 | impl From for Error { 16 | fn from(err: mysql::Error) -> Error { 17 | Error { 18 | msg: err.to_string(), 19 | kind: ErrorKind::Mysql, 20 | } 21 | } 22 | } 23 | 24 | impl std::error::Error for Error {} 25 | 26 | #[derive(Debug)] 27 | pub enum ErrorKind { 28 | Parse, 29 | Internal, 30 | Mysql, 31 | Unknown, 32 | } 33 | 34 | impl fmt::Display for ErrorKind { 35 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 36 | match self { 37 | ErrorKind::Parse => write!(f, "ParseError"), 38 | ErrorKind::Internal => write!(f, "InternalError"), 39 | ErrorKind::Mysql => write!(f, "MysqlError"), 40 | ErrorKind::Unknown => write!(f, "UnknownError"), 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/util/idgen.rs: -------------------------------------------------------------------------------- 1 | use std::sync::atomic::*; 2 | 3 | pub struct IdGen { 4 | current: u64, 5 | } 6 | 7 | impl IdGen { 8 | pub fn new() -> IdGen { 9 | IdGen { current: 0 } 10 | } 11 | 12 | pub fn next(&mut self) -> u64 { 13 | self.current += 1; 14 | 15 | self.current - 1 16 | } 17 | } 18 | 19 | pub struct IdGenSync { 20 | current: AtomicU64, 21 | } 22 | 23 | impl IdGenSync { 24 | pub fn new() -> IdGenSync { 25 | IdGenSync { 26 | current: AtomicU64::new(0), 27 | } 28 | } 29 | 30 | pub fn next(&mut self) -> u64 { 31 | self.current.fetch_add(1, Ordering::Acquire) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/util/mod.rs: -------------------------------------------------------------------------------- 1 | mod error; 2 | mod idgen; 3 | mod walker; 4 | 5 | pub use error::{Error, ErrorKind}; 6 | pub use idgen::{IdGen, IdGenSync}; 7 | pub use walker::Walker; 8 | -------------------------------------------------------------------------------- /src/util/walker.rs: -------------------------------------------------------------------------------- 1 | pub trait Walker { 2 | fn walk(&mut self, _: T) -> T; 3 | } 4 | --------------------------------------------------------------------------------