cocoindex 0.1.61__tar.gz → 0.1.63__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) hide show
  1. {cocoindex-0.1.61 → cocoindex-0.1.63}/Cargo.lock +1 -1
  2. {cocoindex-0.1.61 → cocoindex-0.1.63}/Cargo.toml +1 -1
  3. {cocoindex-0.1.61 → cocoindex-0.1.63}/PKG-INFO +2 -1
  4. {cocoindex-0.1.61 → cocoindex-0.1.63}/README.md +1 -0
  5. cocoindex-0.1.63/examples/paper_metadata/.gitignore +1 -0
  6. cocoindex-0.1.63/examples/paper_metadata/README.md +60 -0
  7. cocoindex-0.1.63/examples/paper_metadata/main.py +183 -0
  8. cocoindex-0.1.63/examples/paper_metadata/papers/2502.06786v3.pdf +0 -0
  9. cocoindex-0.1.63/examples/paper_metadata/papers/2502.20346v1.pdf +0 -0
  10. cocoindex-0.1.63/examples/paper_metadata/pyproject.toml +13 -0
  11. cocoindex-0.1.63/examples/patient_intake_extraction/.env.example +4 -0
  12. cocoindex-0.1.63/examples/pdf_embedding/pdf_files/1706.03762v7.pdf +0 -0
  13. cocoindex-0.1.63/examples/pdf_embedding/pdf_files/1810.04805v2.pdf +0 -0
  14. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/cli.py +40 -10
  15. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/targets/postgres.rs +8 -9
  16. {cocoindex-0.1.61 → cocoindex-0.1.63}/.cargo/config.toml +0 -0
  17. {cocoindex-0.1.61 → cocoindex-0.1.63}/.env.lib_debug +0 -0
  18. {cocoindex-0.1.61 → cocoindex-0.1.63}/.github/ISSUE_TEMPLATE//360/237/220/233-bug-report.md" +0 -0
  19. {cocoindex-0.1.61 → cocoindex-0.1.63}/.github/ISSUE_TEMPLATE//360/237/222/241-feature-request.md" +0 -0
  20. {cocoindex-0.1.61 → cocoindex-0.1.63}/.github/scripts/update_version.sh +0 -0
  21. {cocoindex-0.1.61 → cocoindex-0.1.63}/.github/workflows/CI.yml +0 -0
  22. {cocoindex-0.1.61 → cocoindex-0.1.63}/.github/workflows/_doc_release.yml +0 -0
  23. {cocoindex-0.1.61 → cocoindex-0.1.63}/.github/workflows/_test.yml +0 -0
  24. {cocoindex-0.1.61 → cocoindex-0.1.63}/.github/workflows/docs.yml +0 -0
  25. {cocoindex-0.1.61 → cocoindex-0.1.63}/.github/workflows/format.yml +0 -0
  26. {cocoindex-0.1.61 → cocoindex-0.1.63}/.github/workflows/release.yml +0 -0
  27. {cocoindex-0.1.61 → cocoindex-0.1.63}/.gitignore +0 -0
  28. {cocoindex-0.1.61 → cocoindex-0.1.63}/.pre-commit-config.yaml +0 -0
  29. {cocoindex-0.1.61 → cocoindex-0.1.63}/CODE_OF_CONDUCT.md +0 -0
  30. {cocoindex-0.1.61 → cocoindex-0.1.63}/CONTRIBUTING.md +0 -0
  31. {cocoindex-0.1.61 → cocoindex-0.1.63}/LICENSE +0 -0
  32. {cocoindex-0.1.61 → cocoindex-0.1.63}/dev/neo4j.yaml +0 -0
  33. {cocoindex-0.1.61 → cocoindex-0.1.63}/dev/postgres.yaml +0 -0
  34. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/.gitignore +0 -0
  35. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/README.md +0 -0
  36. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/about/community.md +0 -0
  37. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/about/contributing.md +0 -0
  38. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/ai/llm.mdx +0 -0
  39. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/core/basics.md +0 -0
  40. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/core/cli.mdx +0 -0
  41. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/core/custom_function.mdx +0 -0
  42. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/core/data_example.svg +0 -0
  43. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/core/data_types.mdx +0 -0
  44. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/core/flow_def.mdx +0 -0
  45. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/core/flow_example.svg +0 -0
  46. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/core/flow_methods.mdx +0 -0
  47. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/core/settings.mdx +0 -0
  48. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/getting_started/installation.md +0 -0
  49. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/getting_started/markdown_files.zip +0 -0
  50. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/getting_started/overview.md +0 -0
  51. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/getting_started/quickstart.md +0 -0
  52. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/ops/functions.md +0 -0
  53. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/ops/sources.md +0 -0
  54. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/ops/targets.md +0 -0
  55. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docs/query.mdx +0 -0
  56. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/docusaurus.config.ts +0 -0
  57. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/package.json +0 -0
  58. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/sidebars.ts +0 -0
  59. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/src/components/HomepageFeatures/index.tsx +0 -0
  60. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/src/components/HomepageFeatures/styles.module.css +0 -0
  61. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/src/css/custom.css +0 -0
  62. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/src/theme/Root.js +0 -0
  63. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/static/.nojekyll +0 -0
  64. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/static/img/docusaurus.png +0 -0
  65. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/static/img/favicon.ico +0 -0
  66. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/static/img/icon.svg +0 -0
  67. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/static/img/incremental-etl.gif +0 -0
  68. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/static/robots.txt +0 -0
  69. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/tsconfig.json +0 -0
  70. {cocoindex-0.1.61 → cocoindex-0.1.63}/docs/yarn.lock +0 -0
  71. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/amazon_s3_embedding/.env.example +0 -0
  72. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/amazon_s3_embedding/.gitignore +0 -0
  73. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/amazon_s3_embedding/README.md +0 -0
  74. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/amazon_s3_embedding/main.py +0 -0
  75. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/amazon_s3_embedding/pyproject.toml +0 -0
  76. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/code_embedding/.env +0 -0
  77. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/code_embedding/README.md +0 -0
  78. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/code_embedding/main.py +0 -0
  79. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/code_embedding/pyproject.toml +0 -0
  80. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/docs_to_knowledge_graph/.env +0 -0
  81. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/docs_to_knowledge_graph/README.md +0 -0
  82. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/docs_to_knowledge_graph/main.py +0 -0
  83. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/docs_to_knowledge_graph/pyproject.toml +0 -0
  84. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/fastapi_server_docker/.dockerignore +0 -0
  85. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/fastapi_server_docker/.env +0 -0
  86. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/fastapi_server_docker/README.md +0 -0
  87. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/fastapi_server_docker/compose.yaml +0 -0
  88. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/fastapi_server_docker/dockerfile +0 -0
  89. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/fastapi_server_docker/files/1810.04805v2.md +0 -0
  90. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/fastapi_server_docker/main.py +0 -0
  91. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/fastapi_server_docker/requirements.txt +0 -0
  92. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/gdrive_text_embedding/.env.example +0 -0
  93. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/gdrive_text_embedding/.gitignore +0 -0
  94. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/gdrive_text_embedding/README.md +0 -0
  95. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/gdrive_text_embedding/main.py +0 -0
  96. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/gdrive_text_embedding/pyproject.toml +0 -0
  97. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/.env +0 -0
  98. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/README.md +0 -0
  99. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/frontend/.gitignore +0 -0
  100. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/frontend/index.html +0 -0
  101. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/frontend/package-lock.json +0 -0
  102. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/frontend/package.json +0 -0
  103. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/frontend/src/App.jsx +0 -0
  104. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/frontend/src/main.jsx +0 -0
  105. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/frontend/src/style.css +0 -0
  106. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/frontend/vite.config.js +0 -0
  107. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/img/cat1.jpeg +0 -0
  108. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/img/dog1.jpeg +0 -0
  109. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/img/elephant1.jpg +0 -0
  110. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/img/giraffe.jpg +0 -0
  111. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/main.py +0 -0
  112. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/pyproject.toml +0 -0
  113. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/image_search/requirements.txt +0 -0
  114. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/manuals_llm_extraction/.env +0 -0
  115. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/manuals_llm_extraction/README.md +0 -0
  116. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/manuals_llm_extraction/main.py +0 -0
  117. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/manuals_llm_extraction/manuals/array.pdf +0 -0
  118. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/manuals_llm_extraction/manuals/base64.pdf +0 -0
  119. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/manuals_llm_extraction/manuals/copy.pdf +0 -0
  120. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/manuals_llm_extraction/manuals/glob.pdf +0 -0
  121. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/manuals_llm_extraction/pyproject.toml +0 -0
  122. {cocoindex-0.1.61/examples/patient_intake_extraction → cocoindex-0.1.63/examples/paper_metadata}/.env.example +0 -0
  123. {cocoindex-0.1.61/examples/pdf_embedding/pdf_files → cocoindex-0.1.63/examples/paper_metadata/papers}/1706.03762v7.pdf +0 -0
  124. {cocoindex-0.1.61/examples/pdf_embedding/pdf_files → cocoindex-0.1.63/examples/paper_metadata/papers}/1810.04805v2.pdf +0 -0
  125. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/patient_intake_extraction/README.md +0 -0
  126. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/patient_intake_extraction/data/README.md +0 -0
  127. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/patient_intake_extraction/data/patient_forms/Patient_Intake_Form_David_Artificial.docx +0 -0
  128. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/patient_intake_extraction/data/patient_forms/Patient_Intake_Form_Emily_Artificial.pdf +0 -0
  129. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/patient_intake_extraction/data/patient_forms/Patient_Intake_Form_Joe_Artificial.pdf +0 -0
  130. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/patient_intake_extraction/data/patient_forms/Patient_Intake_From_Jane_Artificial.docx +0 -0
  131. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/patient_intake_extraction/main.py +0 -0
  132. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/patient_intake_extraction/pyproject.toml +0 -0
  133. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/pdf_embedding/.env +0 -0
  134. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/pdf_embedding/README.md +0 -0
  135. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/pdf_embedding/main.py +0 -0
  136. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/pdf_embedding/pdf_files/rfc8259.pdf +0 -0
  137. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/pdf_embedding/pyproject.toml +0 -0
  138. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/.env +0 -0
  139. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/README.md +0 -0
  140. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/img/cocoinsight.png +0 -0
  141. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/img/neo4j.png +0 -0
  142. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/main.py +0 -0
  143. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/products/p1.json +0 -0
  144. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/products/p2.json +0 -0
  145. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/products/p3.json +0 -0
  146. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/products/p4.json +0 -0
  147. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/products/p5.json +0 -0
  148. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/products/p6.json +0 -0
  149. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/products/p7.json +0 -0
  150. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/products/p8.json +0 -0
  151. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/products/p9.json +0 -0
  152. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/product_recommendation/pyproject.toml +0 -0
  153. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/text_embedding/.env +0 -0
  154. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/text_embedding/README.md +0 -0
  155. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/text_embedding/Text_Embedding.ipynb +0 -0
  156. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/text_embedding/main.py +0 -0
  157. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/text_embedding/markdown_files/1706.03762v7.md +0 -0
  158. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/text_embedding/markdown_files/1810.04805v2.md +0 -0
  159. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/text_embedding/markdown_files/rfc8259.md +0 -0
  160. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/text_embedding/pyproject.toml +0 -0
  161. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/text_embedding_qdrant/.env +0 -0
  162. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/text_embedding_qdrant/README.md +0 -0
  163. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/text_embedding_qdrant/main.py +0 -0
  164. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/text_embedding_qdrant/markdown_files/rfc8259.md +0 -0
  165. {cocoindex-0.1.61 → cocoindex-0.1.63}/examples/text_embedding_qdrant/pyproject.toml +0 -0
  166. {cocoindex-0.1.61 → cocoindex-0.1.63}/pyproject.toml +0 -0
  167. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/__init__.py +0 -0
  168. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/auth_registry.py +0 -0
  169. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/convert.py +0 -0
  170. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/flow.py +0 -0
  171. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/functions.py +0 -0
  172. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/index.py +0 -0
  173. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/lib.py +0 -0
  174. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/llm.py +0 -0
  175. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/op.py +0 -0
  176. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/py.typed +0 -0
  177. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/runtime.py +0 -0
  178. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/setting.py +0 -0
  179. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/setup.py +0 -0
  180. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/sources.py +0 -0
  181. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/targets.py +0 -0
  182. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/tests/__init__.py +0 -0
  183. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/tests/test_convert.py +0 -0
  184. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/tests/test_optional_database.py +0 -0
  185. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/tests/test_typing.py +0 -0
  186. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/typing.py +0 -0
  187. {cocoindex-0.1.61 → cocoindex-0.1.63}/python/cocoindex/utils.py +0 -0
  188. {cocoindex-0.1.61 → cocoindex-0.1.63}/ruff.toml +0 -0
  189. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/base/duration.rs +0 -0
  190. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/base/field_attrs.rs +0 -0
  191. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/base/json_schema.rs +0 -0
  192. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/base/mod.rs +0 -0
  193. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/base/schema.rs +0 -0
  194. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/base/spec.rs +0 -0
  195. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/base/value.rs +0 -0
  196. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/builder/analyzed_flow.rs +0 -0
  197. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/builder/analyzer.rs +0 -0
  198. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/builder/exec_ctx.rs +0 -0
  199. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/builder/flow_builder.rs +0 -0
  200. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/builder/mod.rs +0 -0
  201. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/builder/plan.rs +0 -0
  202. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/execution/db_tracking.rs +0 -0
  203. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/execution/db_tracking_setup.rs +0 -0
  204. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/execution/dumper.rs +0 -0
  205. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/execution/evaluator.rs +0 -0
  206. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/execution/indexing_status.rs +0 -0
  207. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/execution/live_updater.rs +0 -0
  208. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/execution/memoization.rs +0 -0
  209. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/execution/mod.rs +0 -0
  210. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/execution/row_indexer.rs +0 -0
  211. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/execution/source_indexer.rs +0 -0
  212. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/execution/stats.rs +0 -0
  213. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/lib.rs +0 -0
  214. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/lib_context.rs +0 -0
  215. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/llm/anthropic.rs +0 -0
  216. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/llm/gemini.rs +0 -0
  217. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/llm/litellm.rs +0 -0
  218. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/llm/mod.rs +0 -0
  219. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/llm/ollama.rs +0 -0
  220. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/llm/openai.rs +0 -0
  221. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/llm/openrouter.rs +0 -0
  222. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/llm/vllm.rs +0 -0
  223. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/llm/voyage.rs +0 -0
  224. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/factory_bases.rs +0 -0
  225. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/functions/embed_text.rs +0 -0
  226. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/functions/extract_by_llm.rs +0 -0
  227. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/functions/mod.rs +0 -0
  228. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/functions/parse_json.rs +0 -0
  229. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/functions/split_recursively.rs +0 -0
  230. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/interface.rs +0 -0
  231. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/mod.rs +0 -0
  232. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/py_factory.rs +0 -0
  233. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/registration.rs +0 -0
  234. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/registry.rs +0 -0
  235. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/sdk.rs +0 -0
  236. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/sources/amazon_s3.rs +0 -0
  237. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/sources/google_drive.rs +0 -0
  238. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/sources/local_file.rs +0 -0
  239. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/sources/mod.rs +0 -0
  240. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/targets/kuzu.rs +0 -0
  241. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/targets/mod.rs +0 -0
  242. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/targets/neo4j.rs +0 -0
  243. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/targets/qdrant.rs +0 -0
  244. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/targets/shared/mod.rs +0 -0
  245. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/targets/shared/property_graph.rs +0 -0
  246. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/ops/targets/shared/table_columns.rs +0 -0
  247. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/prelude.rs +0 -0
  248. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/py/convert.rs +0 -0
  249. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/py/mod.rs +0 -0
  250. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/server.rs +0 -0
  251. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/service/error.rs +0 -0
  252. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/service/flows.rs +0 -0
  253. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/service/mod.rs +0 -0
  254. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/settings.rs +0 -0
  255. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/setup/auth_registry.rs +0 -0
  256. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/setup/components.rs +0 -0
  257. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/setup/db_metadata.rs +0 -0
  258. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/setup/driver.rs +0 -0
  259. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/setup/mod.rs +0 -0
  260. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/setup/states.rs +0 -0
  261. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/utils/concur_control.rs +0 -0
  262. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/utils/db.rs +0 -0
  263. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/utils/fingerprint.rs +0 -0
  264. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/utils/immutable.rs +0 -0
  265. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/utils/mod.rs +0 -0
  266. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/utils/retryable.rs +0 -0
  267. {cocoindex-0.1.61 → cocoindex-0.1.63}/src/utils/yaml_ser.rs +0 -0
@@ -1040,7 +1040,7 @@ dependencies = [
1040
1040
 
1041
1041
  [[package]]
1042
1042
  name = "cocoindex"
1043
- version = "0.1.61"
1043
+ version = "0.1.63"
1044
1044
  dependencies = [
1045
1045
  "anyhow",
1046
1046
  "async-openai",
@@ -2,7 +2,7 @@
2
2
  name = "cocoindex"
3
3
  # Version used for local development is always higher than others to take precedence.
4
4
  # Will be overridden for specific release versions.
5
- version = "0.1.61"
5
+ version = "0.1.63"
6
6
  edition = "2024"
7
7
  rust-version = "1.86"
8
8
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cocoindex
3
- Version: 0.1.61
3
+ Version: 0.1.63
4
4
  Requires-Dist: click>=8.1.8
5
5
  Requires-Dist: rich>=14.0.0
6
6
  Requires-Dist: python-dotenv>=1.1.0
@@ -162,6 +162,7 @@ It defines an index flow like this:
162
162
  | [FastAPI Server with Docker](examples/fastapi_server_docker) | Run the semantic search server in a Dockerized FastAPI setup |
163
163
  | [Product Recommendation](examples/product_recommendation) | Build real-time product recommendations with LLM and graph database|
164
164
  | [Image Search with Vision API](examples/image_search) | Generates detailed captions for images using a vision model, embeds them, enables live-updating semantic search via FastAPI and served on a React frontend|
165
+ | [Paper Metadata](examples/paper_metadata) | Index papers in PDF files, and build metadata tables for each paper |
165
166
 
166
167
  More coming and stay tuned 👀!
167
168
 
@@ -139,6 +139,7 @@ It defines an index flow like this:
139
139
  | [FastAPI Server with Docker](examples/fastapi_server_docker) | Run the semantic search server in a Dockerized FastAPI setup |
140
140
  | [Product Recommendation](examples/product_recommendation) | Build real-time product recommendations with LLM and graph database|
141
141
  | [Image Search with Vision API](examples/image_search) | Generates detailed captions for images using a vision model, embeds them, enables live-updating semantic search via FastAPI and served on a React frontend|
142
+ | [Paper Metadata](examples/paper_metadata) | Index papers in PDF files, and build metadata tables for each paper |
142
143
 
143
144
  More coming and stay tuned 👀!
144
145
 
@@ -0,0 +1,60 @@
1
+ # Build embedding index from PDF files and query with natural language
2
+ [![GitHub](https://img.shields.io/github/stars/cocoindex-io/cocoindex?color=5B5BD6)](https://github.com/cocoindex-io/cocoindex)
3
+
4
+
5
+ In this example, we will build a bunch of tables for papers in PDF files, including:
6
+
7
+ - Metadata (title, authors, abstract) for each paper.
8
+ - Author-to-paper mapping, for author-based query.
9
+ - Embeddings for titles and abstract chunks, for semantics search.
10
+
11
+ We appreciate a star ⭐ at [CocoIndex Github](https://github.com/cocoindex-io/cocoindex) if this is helpful.
12
+
13
+ ## Steps
14
+ ### Indexing Flow
15
+
16
+ 1. We will ingest a list of papers in PDF.
17
+ 2. For each file, we:
18
+ - Extract the first page of the paper.
19
+ - Convert the first page to Markdown.
20
+ - Extract metadata (title, authors, abstract) from the first page.
21
+ - Split the abstract into chunks, and compute embeddings for each chunk.
22
+ 3. We will export to the following tables in Postgres with PGVector:
23
+ - Metadata (title, authors, abstract) for each paper.
24
+ - Author-to-paper mapping, for author-based query.
25
+ - Embeddings for titles and abstract chunks, for semantics search.
26
+
27
+
28
+ ## Prerequisite
29
+
30
+ 1. [Install Postgres](https://cocoindex.io/docs/getting_started/installation#-install-postgres) if you don't have one.
31
+
32
+ 2. dependencies:
33
+
34
+ ```bash
35
+ pip install -e .
36
+ ```
37
+ 3. Create a `.env` file from `.env.example`, and fill `OPENAI_API_KEY`.
38
+
39
+ ## Run
40
+
41
+ Update index, which will also setup the tables at the first time:
42
+
43
+ ```bash
44
+ cocoindex update --setup main.py
45
+ ```
46
+
47
+ You can also run the command with `-L`, which will watch for file changes and update the index automatically.
48
+
49
+ ```bash
50
+ cocoindex update --setup -L main.py
51
+ ```
52
+
53
+ ## CocoInsight
54
+ I used CocoInsight (Free beta now) to troubleshoot the index generation and understand the data lineage of the pipeline. It just connects to your local CocoIndex server, with zero pipeline data retention. Run following command to start CocoInsight:
55
+
56
+ ```
57
+ cocoindex server -ci main.py
58
+ ```
59
+
60
+ Then open the CocoInsight UI at [https://cocoindex.io/cocoinsight](https://cocoindex.io/cocoinsight).
@@ -0,0 +1,183 @@
1
+ import cocoindex
2
+ import io
3
+ import tempfile
4
+ import dataclasses
5
+ import datetime
6
+
7
+ from marker.config.parser import ConfigParser
8
+ from marker.converters.pdf import PdfConverter
9
+ from marker.models import create_model_dict
10
+ from marker.output import text_from_rendered
11
+ from functools import cache
12
+ from pypdf import PdfReader, PdfWriter
13
+
14
+
15
+ @cache
16
+ def get_marker_converter() -> PdfConverter:
17
+ config_parser = ConfigParser({})
18
+ return PdfConverter(
19
+ create_model_dict(), config=config_parser.generate_config_dict()
20
+ )
21
+
22
+
23
+ @dataclasses.dataclass
24
+ class PaperBasicInfo:
25
+ num_pages: int
26
+ first_page: bytes
27
+
28
+
29
+ @cocoindex.op.function()
30
+ def extract_basic_info(content: bytes) -> PaperBasicInfo:
31
+ """Extract the first pages of a PDF."""
32
+ reader = PdfReader(io.BytesIO(content))
33
+
34
+ output = io.BytesIO()
35
+ writer = PdfWriter()
36
+ writer.add_page(reader.pages[0])
37
+ writer.write(output)
38
+
39
+ return PaperBasicInfo(num_pages=len(reader.pages), first_page=output.getvalue())
40
+
41
+
42
+ @dataclasses.dataclass
43
+ class Author:
44
+ """One author of the paper."""
45
+
46
+ name: str
47
+ email: str | None
48
+ affiliation: str | None
49
+
50
+
51
+ @dataclasses.dataclass
52
+ class PaperMetadata:
53
+ """
54
+ Metadata for a paper.
55
+ """
56
+
57
+ title: str
58
+ authors: list[Author]
59
+ abstract: str
60
+
61
+
62
+ @cocoindex.op.function(gpu=True, cache=True, behavior_version=2)
63
+ def pdf_to_markdown(content: bytes) -> str:
64
+ """Convert to Markdown."""
65
+
66
+ with tempfile.NamedTemporaryFile(delete=True, suffix=".pdf") as temp_file:
67
+ temp_file.write(content)
68
+ temp_file.flush()
69
+ text, _, _ = text_from_rendered(get_marker_converter()(temp_file.name))
70
+ return text
71
+
72
+
73
+ @cocoindex.transform_flow()
74
+ def text_to_embedding(
75
+ text: cocoindex.DataSlice[str],
76
+ ) -> cocoindex.DataSlice[list[float]]:
77
+ """
78
+ Embed the text using a SentenceTransformer model.
79
+ This is a shared logic between indexing and querying, so extract it as a function.
80
+ """
81
+ return text.transform(
82
+ cocoindex.functions.SentenceTransformerEmbed(
83
+ model="sentence-transformers/all-MiniLM-L6-v2"
84
+ )
85
+ )
86
+
87
+
88
+ @cocoindex.flow_def(name="PaperMetadata")
89
+ def paper_metadata_flow(
90
+ flow_builder: cocoindex.FlowBuilder, data_scope: cocoindex.DataScope
91
+ ) -> None:
92
+ """
93
+ Define an example flow that embeds files into a vector database.
94
+ """
95
+ data_scope["documents"] = flow_builder.add_source(
96
+ cocoindex.sources.LocalFile(path="papers", binary=True),
97
+ refresh_interval=datetime.timedelta(seconds=10),
98
+ )
99
+
100
+ paper_metadata = data_scope.add_collector()
101
+ metadata_embeddings = data_scope.add_collector()
102
+ author_papers = data_scope.add_collector()
103
+
104
+ with data_scope["documents"].row() as doc:
105
+ doc["basic_info"] = doc["content"].transform(extract_basic_info)
106
+ doc["first_page_md"] = doc["basic_info"]["first_page"].transform(
107
+ pdf_to_markdown
108
+ )
109
+ doc["metadata"] = doc["first_page_md"].transform(
110
+ cocoindex.functions.ExtractByLlm(
111
+ llm_spec=cocoindex.LlmSpec(
112
+ api_type=cocoindex.LlmApiType.OPENAI, model="gpt-4o"
113
+ ),
114
+ output_type=PaperMetadata,
115
+ instruction="Please extract the metadata from the first page of the paper.",
116
+ )
117
+ )
118
+ doc["title_embedding"] = text_to_embedding(doc["metadata"]["title"])
119
+ doc["abstract_chunks"] = doc["metadata"]["abstract"].transform(
120
+ cocoindex.functions.SplitRecursively(
121
+ custom_languages=[
122
+ cocoindex.functions.CustomLanguageSpec(
123
+ language_name="abstract",
124
+ separators_regex=[r"[.?!]+\s+", r"[:;]\s+", r",\s+", r"\s+"],
125
+ )
126
+ ]
127
+ ),
128
+ language="abstract",
129
+ chunk_size=500,
130
+ min_chunk_size=200,
131
+ chunk_overlap=150,
132
+ )
133
+
134
+ paper_metadata.collect(
135
+ filename=doc["filename"],
136
+ title=doc["metadata"]["title"],
137
+ authors=doc["metadata"]["authors"],
138
+ abstract=doc["metadata"]["abstract"],
139
+ )
140
+ metadata_embeddings.collect(
141
+ id=cocoindex.GeneratedField.UUID,
142
+ filename=doc["filename"],
143
+ location="title",
144
+ text=doc["metadata"]["title"],
145
+ embedding=doc["title_embedding"],
146
+ )
147
+ with doc["metadata"]["authors"].row() as author:
148
+ author_papers.collect(
149
+ author_name=author["name"],
150
+ filename=doc["filename"],
151
+ )
152
+
153
+ with doc["abstract_chunks"].row() as chunk:
154
+ chunk["embedding"] = text_to_embedding(chunk["text"])
155
+ metadata_embeddings.collect(
156
+ id=cocoindex.GeneratedField.UUID,
157
+ filename=doc["filename"],
158
+ location="abstract",
159
+ text=chunk["text"],
160
+ embedding=chunk["embedding"],
161
+ )
162
+
163
+ paper_metadata.export(
164
+ "paper_metadata",
165
+ cocoindex.targets.Postgres(),
166
+ primary_key_fields=["filename"],
167
+ )
168
+ metadata_embeddings.export(
169
+ "metadata_embeddings",
170
+ cocoindex.targets.Postgres(),
171
+ primary_key_fields=["id"],
172
+ vector_indexes=[
173
+ cocoindex.VectorIndexDef(
174
+ field_name="embedding",
175
+ metric=cocoindex.VectorSimilarityMetric.COSINE_SIMILARITY,
176
+ )
177
+ ],
178
+ )
179
+ author_papers.export(
180
+ "author_papers",
181
+ cocoindex.targets.Postgres(),
182
+ primary_key_fields=["author_name", "filename"],
183
+ )
@@ -0,0 +1,13 @@
1
+ [project]
2
+ name = "paper-metadata"
3
+ version = "0.1.0"
4
+ description = "Build index for papers with both metadata and content embeddings"
5
+ requires-python = ">=3.11"
6
+ dependencies = [
7
+ "cocoindex[embeddings]>=0.1.62",
8
+ "pypdf>=5.7.0",
9
+ "marker-pdf>=1.5.2",
10
+ ]
11
+
12
+ [tool.setuptools]
13
+ packages = []
@@ -0,0 +1,4 @@
1
+ # Postgres database address for cocoindex
2
+ COCOINDEX_DATABASE_URL=postgres://cocoindex:cocoindex@localhost/cocoindex
3
+
4
+ OPENAI_API_KEY=
@@ -1,4 +1,5 @@
1
1
  import atexit
2
+ import asyncio
2
3
  import datetime
3
4
  import importlib.util
4
5
  import os
@@ -18,6 +19,7 @@ from rich.table import Table
18
19
 
19
20
  from . import flow, lib, setting
20
21
  from .setup import flow_names_with_setup
22
+ from .runtime import execution_context
21
23
 
22
24
  # Create ServerSettings lazily upon first call, as environment variables may be loaded from files, etc.
23
25
  COCOINDEX_HOST = "https://cocoindex.io"
@@ -267,6 +269,21 @@ def _setup_flows(
267
269
  setup_bundle.apply(report_to_stdout=not quiet)
268
270
 
269
271
 
272
+ def _show_no_live_update_hint() -> None:
273
+ click.secho(
274
+ "NOTE: No change capture mechanism exists. See https://cocoindex.io/docs/core/flow_methods#live-update for more details.\n",
275
+ fg="yellow",
276
+ )
277
+
278
+
279
+ async def _update_all_flows_with_hint_async(
280
+ options: flow.FlowLiveUpdaterOptions,
281
+ ) -> None:
282
+ await flow.update_all_flows_async(options)
283
+ if options.live_mode:
284
+ _show_no_live_update_hint()
285
+
286
+
270
287
  @cli.command()
271
288
  @click.argument("app_target", type=str)
272
289
  @click.option(
@@ -398,7 +415,7 @@ def update(
398
415
  setup: bool, # pylint: disable=redefined-outer-name
399
416
  force: bool,
400
417
  quiet: bool,
401
- ) -> Any:
418
+ ) -> None:
402
419
  """
403
420
  Update the index to reflect the latest data from data sources.
404
421
 
@@ -408,6 +425,12 @@ def update(
408
425
  app_ref, flow_name = _parse_app_flow_specifier(app_flow_specifier)
409
426
  _load_user_app(app_ref)
410
427
 
428
+ if live:
429
+ click.secho(
430
+ "NOTE: Flow code changes will NOT be reflected until you restart to load the new code.\n",
431
+ fg="yellow",
432
+ )
433
+
411
434
  options = flow.FlowLiveUpdaterOptions(live_mode=live, print_stats=not quiet)
412
435
  if flow_name is None:
413
436
  if setup:
@@ -416,14 +439,15 @@ def update(
416
439
  force=force,
417
440
  quiet=quiet,
418
441
  )
419
- return flow.update_all_flows(options)
442
+ execution_context.run(_update_all_flows_with_hint_async(options))
420
443
  else:
421
444
  fl = flow.flow_by_name(flow_name)
422
445
  if setup:
423
446
  _setup_flows((fl,), force=force, quiet=quiet)
424
447
  with flow.FlowLiveUpdater(fl, options) as updater:
425
448
  updater.wait()
426
- return updater.update_stats()
449
+ if options.live_mode:
450
+ _show_no_live_update_hint()
427
451
 
428
452
 
429
453
  @cli.command()
@@ -597,6 +621,10 @@ def server(
597
621
  ),
598
622
  )
599
623
  else:
624
+ click.secho(
625
+ "NOTE: Flow code changes will NOT be reflected until you restart to load the new code. Use --reload to enable auto-reload.\n",
626
+ fg="yellow",
627
+ )
600
628
  _run_server(*args)
601
629
 
602
630
 
@@ -633,9 +661,6 @@ def _run_server(
633
661
  if address is not None:
634
662
  server_settings.address = address
635
663
 
636
- if COCOINDEX_HOST in cors_origins:
637
- click.echo(f"Open CocoInsight at: {COCOINDEX_HOST}/cocoinsight")
638
-
639
664
  if run_setup:
640
665
  _setup_flows(
641
666
  flow.flows().values(),
@@ -643,14 +668,19 @@ def _run_server(
643
668
  quiet=quiet,
644
669
  )
645
670
 
646
- if live_update:
647
- options = flow.FlowLiveUpdaterOptions(live_mode=True, print_stats=not quiet)
648
- flow.update_all_flows(options)
649
-
650
671
  lib.start_server(server_settings)
651
672
 
673
+ if COCOINDEX_HOST in cors_origins:
674
+ click.echo(f"Open CocoInsight at: {COCOINDEX_HOST}/cocoinsight")
675
+
652
676
  click.secho("Press Ctrl+C to stop the server.", fg="yellow")
653
677
 
678
+ if live_update:
679
+ options = flow.FlowLiveUpdaterOptions(live_mode=True, print_stats=not quiet)
680
+ asyncio.run_coroutine_threadsafe(
681
+ _update_all_flows_with_hint_async(options), execution_context.event_loop
682
+ )
683
+
654
684
  shutdown_event = threading.Event()
655
685
 
656
686
  def handle_signal(signum: int, frame: FrameType | None) -> None:
@@ -197,8 +197,7 @@ impl ExportContext {
197
197
  .map(|f| format!("\"{}\"", f.name))
198
198
  .collect::<Vec<_>>()
199
199
  .join(", ");
200
- let value_fields = value_fields_schema
201
- .iter()
200
+ let all_fields = (key_fields_schema.iter().chain(value_fields_schema.iter()))
202
201
  .map(|f| format!("\"{}\"", f.name))
203
202
  .collect::<Vec<_>>()
204
203
  .join(", ");
@@ -211,15 +210,15 @@ impl ExportContext {
211
210
  Ok(Self {
212
211
  db_ref,
213
212
  db_pool,
213
+ upsert_sql_prefix: format!("INSERT INTO {table_name} ({all_fields}) VALUES "),
214
+ upsert_sql_suffix: if value_fields_schema.is_empty() {
215
+ format!(" ON CONFLICT ({key_fields}) DO NOTHING;")
216
+ } else {
217
+ format!(" ON CONFLICT ({key_fields}) DO UPDATE SET {set_value_fields};")
218
+ },
219
+ delete_sql_prefix: format!("DELETE FROM {table_name} WHERE "),
214
220
  key_fields_schema,
215
221
  value_fields_schema,
216
- upsert_sql_prefix: format!(
217
- "INSERT INTO {table_name} ({key_fields}, {value_fields}) VALUES "
218
- ),
219
- upsert_sql_suffix: format!(
220
- " ON CONFLICT ({key_fields}) DO UPDATE SET {set_value_fields};"
221
- ),
222
- delete_sql_prefix: format!("DELETE FROM {table_name} WHERE "),
223
222
  })
224
223
  }
225
224
  }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes