meerschaum 1.5.11__tar.gz → 1.5.18__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 (233) hide show
  1. {meerschaum-1.5.11/meerschaum.egg-info → meerschaum-1.5.18}/PKG-INFO +1 -1
  2. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/arguments/_parser.py +0 -5
  3. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/_default.py +1 -1
  4. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/_version.py +1 -1
  5. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/APIConnector.py +1 -0
  6. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/_pipes.py +9 -1
  7. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/sql/SQLConnector.py +15 -2
  8. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/sql/_fetch.py +38 -6
  9. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/sql/_pipes.py +138 -53
  10. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/sql/_plugins.py +33 -22
  11. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/sql/_sql.py +68 -19
  12. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/sql/_users.py +21 -16
  13. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/sql/tables/__init__.py +1 -1
  14. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/Pipe/__init__.py +4 -3
  15. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/Pipe/_attributes.py +7 -0
  16. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/Pipe/_data.py +127 -3
  17. meerschaum-1.5.18/meerschaum/core/Pipe/_dtypes.py +102 -0
  18. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/Pipe/_fetch.py +21 -8
  19. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/Pipe/_sync.py +146 -26
  20. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/misc.py +242 -12
  21. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/packages/__init__.py +0 -30
  22. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/packages/_packages.py +1 -0
  23. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/sql.py +3 -2
  24. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/typing.py +2 -0
  25. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/venv/__init__.py +0 -25
  26. {meerschaum-1.5.11 → meerschaum-1.5.18/meerschaum.egg-info}/PKG-INFO +1 -1
  27. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum.egg-info/SOURCES.txt +1 -4
  28. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum.egg-info/requires.txt +1 -0
  29. meerschaum-1.5.11/meerschaum/core/Pipe/_dtypes.py +0 -202
  30. meerschaum-1.5.11/tests/test_pipes.py +0 -403
  31. meerschaum-1.5.11/tests/test_sql.py +0 -103
  32. meerschaum-1.5.11/tests/test_users.py +0 -23
  33. {meerschaum-1.5.11 → meerschaum-1.5.18}/LICENSE +0 -0
  34. {meerschaum-1.5.11 → meerschaum-1.5.18}/NOTICE +0 -0
  35. {meerschaum-1.5.11 → meerschaum-1.5.18}/README.md +0 -0
  36. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/__init__.py +0 -0
  37. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/__main__.py +0 -0
  38. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/__init__.py +0 -0
  39. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/arguments/__init__.py +0 -0
  40. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/arguments/_parse_arguments.py +0 -0
  41. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/docs/__init__.py +0 -0
  42. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/docs/index.py +0 -0
  43. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/entry.py +0 -0
  44. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/gui/__init__.py +0 -0
  45. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/gui/app/__init__.py +0 -0
  46. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/gui/app/_windows.py +0 -0
  47. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/gui/app/actions.py +0 -0
  48. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/gui/app/pipes.py +0 -0
  49. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/shell/Shell.py +0 -0
  50. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/shell/ShellCompleter.py +0 -0
  51. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/shell/ValidAutoSuggest.py +0 -0
  52. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/shell/__init__.py +0 -0
  53. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/shell/resources/__init__.py +0 -0
  54. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/term/TermPageHandler.py +0 -0
  55. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/term/__init__.py +0 -0
  56. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/_internal/term/tools.py +0 -0
  57. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/__init__.py +0 -0
  58. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/api.py +0 -0
  59. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/bootstrap.py +0 -0
  60. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/clear.py +0 -0
  61. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/copy.py +0 -0
  62. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/delete.py +0 -0
  63. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/drop.py +0 -0
  64. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/edit.py +0 -0
  65. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/install.py +0 -0
  66. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/login.py +0 -0
  67. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/os.py +0 -0
  68. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/python.py +0 -0
  69. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/register.py +0 -0
  70. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/reload.py +0 -0
  71. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/setup.py +0 -0
  72. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/sh.py +0 -0
  73. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/show.py +0 -0
  74. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/sql.py +0 -0
  75. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/stack.py +0 -0
  76. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/start.py +0 -0
  77. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/stop.py +0 -0
  78. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/sync.py +0 -0
  79. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/uninstall.py +0 -0
  80. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/upgrade.py +0 -0
  81. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/actions/verify.py +0 -0
  82. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/__init__.py +0 -0
  83. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/_chain.py +0 -0
  84. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/_events.py +0 -0
  85. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/_oauth2.py +0 -0
  86. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/_websockets.py +0 -0
  87. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/__init__.py +0 -0
  88. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/actions.py +0 -0
  89. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/assets/__init__.py +0 -0
  90. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/assets/ansi_up.js +0 -0
  91. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/assets/banner_1920x320.png +0 -0
  92. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/assets/favicon.ico +0 -0
  93. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/assets/logo_48x48.png +0 -0
  94. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/assets/logo_500x500.png +0 -0
  95. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/callbacks/__init__.py +0 -0
  96. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/callbacks/dashboard.py +0 -0
  97. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/callbacks/login.py +0 -0
  98. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/callbacks/plugins.py +0 -0
  99. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/callbacks/register.py +0 -0
  100. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/components.py +0 -0
  101. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/connectors.py +0 -0
  102. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/graphs.py +0 -0
  103. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/jobs.py +0 -0
  104. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/keys.py +0 -0
  105. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/pages/__init__.py +0 -0
  106. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/pages/dashboard.py +0 -0
  107. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/pages/error.py +0 -0
  108. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/pages/login.py +0 -0
  109. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/pages/plugins.py +0 -0
  110. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/pages/register.py +0 -0
  111. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/pipes.py +0 -0
  112. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/plugins.py +0 -0
  113. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/sync.py +0 -0
  114. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/users.py +0 -0
  115. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/dash/websockets.py +0 -0
  116. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/models/__init__.py +0 -0
  117. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/models/_interfaces.py +0 -0
  118. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/models/_locations.py +0 -0
  119. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/models/_metrics.py +0 -0
  120. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/models/_pipes.py +0 -0
  121. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/__init__.py +0 -0
  122. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/static/__init__.py +0 -0
  123. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/static/css/__init__.py +0 -0
  124. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/static/css/bootstrap.min.css +0 -0
  125. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/static/css/dash.css +0 -0
  126. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/static/css/dbc_dark.css +0 -0
  127. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/static/css/styles.css +0 -0
  128. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/static/ico/__init__.py +0 -0
  129. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/static/ico/logo.ico +0 -0
  130. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/static/js/__init__.py +0 -0
  131. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/static/js/action_button.js +0 -0
  132. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/static/js/main.js +0 -0
  133. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/static/png/__init__.py +0 -0
  134. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/templates/__init__.py +0 -0
  135. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/templates/index.html +0 -0
  136. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/templates/old_index.html +0 -0
  137. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/templates/secret.html +0 -0
  138. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/resources/templates/termpage.html +0 -0
  139. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/routes/__init__.py +0 -0
  140. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/routes/_actions.py +0 -0
  141. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/routes/_connectors.py +0 -0
  142. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/routes/_index.py +0 -0
  143. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/routes/_login.py +0 -0
  144. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/routes/_misc.py +0 -0
  145. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/routes/_pipes.py +0 -0
  146. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/routes/_plugins.py +0 -0
  147. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/routes/_users.py +0 -0
  148. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/routes/_version.py +0 -0
  149. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/api/tables/__init__.py +0 -0
  150. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/__init__.py +0 -0
  151. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/_edit.py +0 -0
  152. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/_environment.py +0 -0
  153. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/_formatting.py +0 -0
  154. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/_jobs.py +0 -0
  155. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/_patch.py +0 -0
  156. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/_paths.py +0 -0
  157. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/_preprocess.py +0 -0
  158. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/_read_config.py +0 -0
  159. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/_shell.py +0 -0
  160. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/_sync.py +0 -0
  161. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/resources/__init__.py +0 -0
  162. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/stack/__init__.py +0 -0
  163. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/stack/grafana/__init__.py +0 -0
  164. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/stack/mosquitto/__init__.py +0 -0
  165. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/stack/mosquitto/resources/__init__.py +0 -0
  166. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/stack/resources/__init__.py +0 -0
  167. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/config/static/__init__.py +0 -0
  168. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/Connector.py +0 -0
  169. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/__init__.py +0 -0
  170. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/__init__.py +0 -0
  171. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/_actions.py +0 -0
  172. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/_delete.py +0 -0
  173. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/_fetch.py +0 -0
  174. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/_get.py +0 -0
  175. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/_login.py +0 -0
  176. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/_misc.py +0 -0
  177. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/_patch.py +0 -0
  178. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/_plugins.py +0 -0
  179. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/_post.py +0 -0
  180. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/_uri.py +0 -0
  181. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/api/_users.py +0 -0
  182. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/parse.py +0 -0
  183. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/plugin/PluginConnector.py +0 -0
  184. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/plugin/__init__.py +0 -0
  185. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/poll.py +0 -0
  186. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/sql/__init__.py +0 -0
  187. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/sql/_cli.py +0 -0
  188. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/sql/_create_engine.py +0 -0
  189. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/sql/_uri.py +0 -0
  190. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/sql/tables/types.py +0 -0
  191. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/connectors/sql/tools.py +0 -0
  192. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/Pipe/_bootstrap.py +0 -0
  193. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/Pipe/_clear.py +0 -0
  194. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/Pipe/_delete.py +0 -0
  195. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/Pipe/_drop.py +0 -0
  196. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/Pipe/_edit.py +0 -0
  197. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/Pipe/_register.py +0 -0
  198. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/Pipe/_show.py +0 -0
  199. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/Plugin/__init__.py +0 -0
  200. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/User/_User.py +0 -0
  201. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/User/__init__.py +0 -0
  202. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/core/__init__.py +0 -0
  203. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/plugins/_Plugin.py +0 -0
  204. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/plugins/__init__.py +0 -0
  205. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/__init__.py +0 -0
  206. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/daemon/Daemon.py +0 -0
  207. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/daemon/Log.py +0 -0
  208. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/daemon/__init__.py +0 -0
  209. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/daemon/_names.py +0 -0
  210. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/debug.py +0 -0
  211. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/formatting/__init__.py +0 -0
  212. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/formatting/_jobs.py +0 -0
  213. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/formatting/_pipes.py +0 -0
  214. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/formatting/_pprint.py +0 -0
  215. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/formatting/_shell.py +0 -0
  216. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/get_pipes.py +0 -0
  217. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/interactive.py +0 -0
  218. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/networking.py +0 -0
  219. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/packages/lazy_loader.py +0 -0
  220. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/pool.py +0 -0
  221. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/process.py +0 -0
  222. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/prompt.py +0 -0
  223. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/schedule.py +0 -0
  224. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/threading.py +0 -0
  225. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/venv/_Venv.py +0 -0
  226. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/warnings.py +0 -0
  227. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum/utils/yaml.py +0 -0
  228. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum.egg-info/dependency_links.txt +0 -0
  229. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum.egg-info/entry_points.txt +0 -0
  230. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum.egg-info/top_level.txt +0 -0
  231. {meerschaum-1.5.11 → meerschaum-1.5.18}/meerschaum.egg-info/zip-safe +0 -0
  232. {meerschaum-1.5.11 → meerschaum-1.5.18}/setup.cfg +0 -0
  233. {meerschaum-1.5.11 → meerschaum-1.5.18}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: meerschaum
3
- Version: 1.5.11
3
+ Version: 1.5.18
4
4
  Summary: Sync Time-Series Pipes with Meerschaum
5
5
  Home-page: https://meerschaum.io
6
6
  Author: Bennett Meares
@@ -234,11 +234,6 @@ groups['sync'].add_argument(
234
234
  "Specify the chunksize for syncing and retrieving data. Defaults to 900."
235
235
  ),
236
236
  )
237
- groups['sync'].add_argument(
238
- '--sync-chunks', action='store_true',
239
- help="Sync chunks while fetching data instead of waiting until all have arrived. " +
240
- "Similar to --async. WARNING! This can be very dangerous when used with --async.",
241
- )
242
237
  groups['sync'].add_argument(
243
238
  '--skip-check-existing', '--allow-duplicates', action='store_true',
244
239
  help = (
@@ -59,7 +59,7 @@ default_system_config = {
59
59
  'pandas' : 'pandas',
60
60
  },
61
61
  'sql' : {
62
- 'chunksize' : 1000000,
62
+ 'chunksize' : 100000,
63
63
  'poolclass' : 'sqlalchemy.pool.QueuePool',
64
64
  'create_engine' : {
65
65
  'method' : 'multi',
@@ -2,4 +2,4 @@
2
2
  Specify the Meerschaum release version.
3
3
  """
4
4
 
5
- __version__ = "1.5.11"
5
+ __version__ = "1.5.18"
@@ -22,6 +22,7 @@ class APIConnector(Connector):
22
22
  """
23
23
 
24
24
  IS_INSTANCE: bool = True
25
+ IS_THREAD_SAFE: bool = False
25
26
 
26
27
  from ._delete import delete
27
28
  from ._post import post
@@ -336,7 +336,15 @@ def get_pipe_data(
336
336
  except Exception as e:
337
337
  warn(str(e))
338
338
  return None
339
- df = parse_df_datetimes(df, debug=debug)
339
+ df = parse_df_datetimes(
340
+ df,
341
+ ignore_cols = [
342
+ col
343
+ for col, dtype in pipe.dtypes.items()
344
+ if 'datetime' not in str(dtype)
345
+ ],
346
+ debug = debug,
347
+ )
340
348
  return df
341
349
 
342
350
 
@@ -224,15 +224,28 @@ class SQLConnector(Connector):
224
224
  return self._engine
225
225
 
226
226
  @property
227
- def DATABASE_URL(self):
227
+ def DATABASE_URL(self) -> str:
228
+ """
229
+ Return the URI connection string (alias for `SQLConnector.URI`.
230
+ """
228
231
  _ = self.engine
229
232
  return str(self._engine_str)
230
233
 
231
234
  @property
232
- def URI(self):
235
+ def URI(self) -> str:
236
+ """
237
+ Return the URI connection string.
238
+ """
233
239
  _ = self.engine
234
240
  return str(self._engine_str)
235
241
 
242
+ @property
243
+ def IS_THREAD_SAFE(self) -> str:
244
+ """
245
+ Return whether this connector may be multithreaded.
246
+ """
247
+ return self.flavor not in ('duckdb',)
248
+
236
249
  @property
237
250
  def metadata(self):
238
251
  from meerschaum.utils.packages import attempt_import
@@ -19,9 +19,10 @@ def fetch(
19
19
  end: Union[datetime.datetime, str, None] = None,
20
20
  chunk_hook: Optional[Callable[[pd.DataFrame], Any]] = None,
21
21
  chunksize: Optional[int] = -1,
22
+ workers: Optional[int] = None,
22
23
  debug: bool = False,
23
24
  **kw: Any
24
- ) -> Union['pd.DataFrame', None]:
25
+ ) -> Union['pd.DataFrame', List[Any], None]:
25
26
  """Execute the SQL definition and return a Pandas DataFrame.
26
27
 
27
28
  Parameters
@@ -46,13 +47,24 @@ def fetch(
46
47
  The latest datetime to search for data.
47
48
  If `end` is `None`, do not bound
48
49
 
50
+ chunk_hook: Callable[[pd.DataFrame], Any], default None
51
+ A function to pass to `SQLConnector.read()` that accepts a Pandas DataFrame.
52
+
53
+ chunksize: Optional[int], default -1
54
+ How many rows to load into memory at once (when `chunk_hook` is provided).
55
+ Otherwise the entire result set is loaded into memory.
56
+
57
+ workers: Optional[int], default None
58
+ How many threads to use when consuming the generator (when `chunk_hook is provided).
59
+ Defaults to the number of cores.
60
+
49
61
  debug: bool, default False
50
62
  Verbosity toggle.
51
63
 
52
64
  Returns
53
65
  -------
54
66
  A pandas DataFrame or `None`.
55
-
67
+ If `chunk_hook` is not None, return a list of the hook function's results.
56
68
  """
57
69
  meta_def = self.get_pipe_metadef(
58
70
  pipe,
@@ -61,12 +73,32 @@ def fetch(
61
73
  debug = debug,
62
74
  **kw
63
75
  )
64
- df = self.read(meta_def, chunk_hook=chunk_hook, chunksize=chunksize, debug=debug)
76
+ as_hook_results = chunk_hook is not None
77
+ chunks = self.read(
78
+ meta_def,
79
+ chunk_hook = chunk_hook,
80
+ as_hook_results = as_hook_results,
81
+ chunksize = chunksize,
82
+ workers = workers,
83
+ debug = debug,
84
+ )
65
85
  ### if sqlite, parse for datetimes
66
- if self.flavor == 'sqlite':
86
+ if not as_hook_results and self.flavor == 'sqlite':
67
87
  from meerschaum.utils.misc import parse_df_datetimes
68
- df = parse_df_datetimes(df, debug=debug)
69
- return df
88
+ ignore_cols = [
89
+ col
90
+ for col, dtype in pipe.dtypes.items()
91
+ if 'datetime' not in str(dtype)
92
+ ]
93
+ return (
94
+ parse_df_datetimes(
95
+ chunk,
96
+ ignore_cols = ignore_cols,
97
+ debug = debug,
98
+ )
99
+ for chunk in chunks
100
+ )
101
+ return chunks
70
102
 
71
103
 
72
104
  def get_pipe_metadef(
@@ -25,7 +25,7 @@ def register_pipe(
25
25
 
26
26
  ### ensure pipes table exists
27
27
  from meerschaum.connectors.sql.tables import get_tables
28
- pipes = get_tables(mrsm_instance=self, create=(not pipe.temporary), debug=debug)['pipes']
28
+ pipes_tbl = get_tables(mrsm_instance=self, create=(not pipe.temporary), debug=debug)['pipes']
29
29
 
30
30
  if pipe.get_id(debug=debug) is not None:
31
31
  return False, f"{pipe} is already registered."
@@ -61,7 +61,7 @@ def register_pipe(
61
61
  else parameters
62
62
  ),
63
63
  }
64
- query = sqlalchemy.insert(pipes).values(**values)
64
+ query = sqlalchemy.insert(pipes_tbl).values(**values)
65
65
  result = self.exec(query, debug=debug)
66
66
  if result is None:
67
67
  return False, f"Failed to register {pipe}."
@@ -111,7 +111,7 @@ def edit_pipe(
111
111
 
112
112
  ### ensure pipes table exists
113
113
  from meerschaum.connectors.sql.tables import get_tables
114
- pipes = get_tables(mrsm_instance=self, create=(not pipe.temporary), debug=debug)['pipes']
114
+ pipes_tbl = get_tables(mrsm_instance=self, create=(not pipe.temporary), debug=debug)['pipes']
115
115
 
116
116
  import json
117
117
  sqlalchemy = attempt_import('sqlalchemy')
@@ -123,8 +123,8 @@ def edit_pipe(
123
123
  else parameters
124
124
  ),
125
125
  }
126
- q = sqlalchemy.update(pipes).values(**values).where(
127
- pipes.c.pipe_id == pipe.id
126
+ q = sqlalchemy.update(pipes_tbl).values(**values).where(
127
+ pipes_tbl.c.pipe_id == pipe.id
128
128
  )
129
129
 
130
130
  result = self.exec(q, debug=debug)
@@ -214,7 +214,7 @@ def fetch_pipes_keys(
214
214
  return []
215
215
 
216
216
  from meerschaum.connectors.sql.tables import get_tables
217
- pipes = get_tables(mrsm_instance=self, create=False, debug=debug)['pipes']
217
+ pipes_tbl = get_tables(mrsm_instance=self, create=False, debug=debug)['pipes']
218
218
 
219
219
  _params = {}
220
220
  for k, v in parameters.items():
@@ -226,30 +226,30 @@ def fetch_pipes_keys(
226
226
  ### If a param begins with '_', negate it instead.
227
227
  _where = [
228
228
  (
229
- (pipes.c[key] == val) if not str(val).startswith(negation_prefix)
230
- else (pipes.c[key] != key)
229
+ (pipes_tbl.c[key] == val) if not str(val).startswith(negation_prefix)
230
+ else (pipes_tbl.c[key] != key)
231
231
  ) for key, val in _params.items()
232
- if not isinstance(val, (list, tuple)) and key in pipes.c
232
+ if not isinstance(val, (list, tuple)) and key in pipes_tbl.c
233
233
  ]
234
234
  select_cols = (
235
- [pipes.c.connector_keys, pipes.c.metric_key, pipes.c.location_key]
236
- + ([pipes.c.parameters] if tags else [])
235
+ [pipes_tbl.c.connector_keys, pipes_tbl.c.metric_key, pipes_tbl.c.location_key]
236
+ + ([pipes_tbl.c.parameters] if tags else [])
237
237
  )
238
238
 
239
239
  q = sqlalchemy.select(*select_cols).where(sqlalchemy.and_(True, *_where))
240
240
 
241
241
  ### Parse IN params and add OR IS NULL if None in list.
242
242
  for c, vals in cols.items():
243
- if not isinstance(vals, (list, tuple)) or not vals or not c in pipes.c:
243
+ if not isinstance(vals, (list, tuple)) or not vals or not c in pipes_tbl.c:
244
244
  continue
245
245
  _in_vals, _ex_vals = separate_negation_values(vals)
246
246
  ### Include params (positive)
247
247
  q = (
248
- q.where(pipes.c[c].in_(_in_vals)) if None not in _in_vals
249
- else q.where(sqlalchemy.or_(pipes.c[c].in_(_in_vals), pipes.c[c].is_(None)))
248
+ q.where(pipes_tbl.c[c].in_(_in_vals)) if None not in _in_vals
249
+ else q.where(sqlalchemy.or_(pipes_tbl.c[c].in_(_in_vals), pipes_tbl.c[c].is_(None)))
250
250
  ) if _in_vals else q
251
251
  ### Exclude params (negative)
252
- q = q.where(pipes.c[c].not_in(_ex_vals)) if _ex_vals else q
252
+ q = q.where(pipes_tbl.c[c].not_in(_ex_vals)) if _ex_vals else q
253
253
 
254
254
  ### Finally, parse tags.
255
255
  _in_tags, _ex_tags = separate_negation_values(tags)
@@ -257,7 +257,7 @@ def fetch_pipes_keys(
257
257
  for nt in _in_tags:
258
258
  ors.append(
259
259
  sqlalchemy.cast(
260
- pipes.c['parameters'],
260
+ pipes_tbl.c['parameters'],
261
261
  sqlalchemy.String,
262
262
  ).like(f'%"tags":%"{nt}"%')
263
263
  )
@@ -266,17 +266,17 @@ def fetch_pipes_keys(
266
266
  for xt in _ex_tags:
267
267
  ors.append(
268
268
  sqlalchemy.cast(
269
- pipes.c['parameters'],
269
+ pipes_tbl.c['parameters'],
270
270
  sqlalchemy.String,
271
271
  ).not_like(f'%"tags":%"{xt}"%')
272
272
  )
273
273
  q = q.where(sqlalchemy.and_(sqlalchemy.or_(*ors).self_group())) if ors else q
274
- loc_asc = sqlalchemy.asc(pipes.c['location_key'])
274
+ loc_asc = sqlalchemy.asc(pipes_tbl.c['location_key'])
275
275
  if self.flavor not in OMIT_NULLSFIRST_FLAVORS:
276
276
  loc_asc = sqlalchemy.nullsfirst(loc_asc)
277
277
  q = q.order_by(
278
- sqlalchemy.asc(pipes.c['connector_keys']),
279
- sqlalchemy.asc(pipes.c['metric_key']),
278
+ sqlalchemy.asc(pipes_tbl.c['connector_keys']),
279
+ sqlalchemy.asc(pipes_tbl.c['metric_key']),
280
280
  loc_asc,
281
281
  )
282
282
 
@@ -565,9 +565,9 @@ def delete_pipe(
565
565
 
566
566
  ### ensure pipes table exists
567
567
  from meerschaum.connectors.sql.tables import get_tables
568
- pipes = get_tables(mrsm_instance=self, create=(not pipe.temporary), debug=debug)['pipes']
568
+ pipes_tbl = get_tables(mrsm_instance=self, create=(not pipe.temporary), debug=debug)['pipes']
569
569
 
570
- q = sqlalchemy.delete(pipes).where(pipes.c.pipe_id == pipe.id)
570
+ q = sqlalchemy.delete(pipes_tbl).where(pipes_tbl.c.pipe_id == pipe.id)
571
571
  if not self.exec(q, debug=debug):
572
572
  return False, f"Failed to delete registration for {pipe}."
573
573
 
@@ -733,9 +733,30 @@ def get_pipe_data(
733
733
  from meerschaum.utils.misc import parse_df_datetimes
734
734
  from meerschaum.utils.packages import import_pandas
735
735
  pd = import_pandas()
736
- ### NOTE: We have to consume the iterator here to ensure that datatimes are parsed correctly
737
- df = parse_df_datetimes(df, debug=debug) if isinstance(df, pd.DataFrame) else (
738
- [parse_df_datetimes(c, debug=debug) for c in df]
736
+ ### NOTE: We have to consume the iterator here to ensure that datetimes are parsed correctly
737
+ df = (
738
+ parse_df_datetimes(
739
+ df,
740
+ ignore_cols = [
741
+ col
742
+ for col, dtype in pipe.dtypes.items()
743
+ if 'datetime' not in str(dtype)
744
+ ],
745
+ debug = debug,
746
+ ) if isinstance(df, pd.DataFrame) else (
747
+ [
748
+ parse_df_datetimes(
749
+ c,
750
+ ignore_cols = [
751
+ col
752
+ for col, dtype in pipe.dtypes.items()
753
+ if 'datetime' not in str(dtype)
754
+ ],
755
+ debug = debug,
756
+ )
757
+ for c in df
758
+ ]
759
+ )
739
760
  )
740
761
  for col, typ in dtypes.items():
741
762
  if typ != 'json':
@@ -947,15 +968,15 @@ def get_pipe_id(
947
968
  import json
948
969
  sqlalchemy = attempt_import('sqlalchemy')
949
970
  from meerschaum.connectors.sql.tables import get_tables
950
- pipes = get_tables(mrsm_instance=self, create=(not pipe.temporary), debug=debug)['pipes']
971
+ pipes_tbl = get_tables(mrsm_instance=self, create=(not pipe.temporary), debug=debug)['pipes']
951
972
 
952
- query = sqlalchemy.select(pipes.c.pipe_id).where(
953
- pipes.c.connector_keys == pipe.connector_keys
973
+ query = sqlalchemy.select(pipes_tbl.c.pipe_id).where(
974
+ pipes_tbl.c.connector_keys == pipe.connector_keys
954
975
  ).where(
955
- pipes.c.metric_key == pipe.metric_key
976
+ pipes_tbl.c.metric_key == pipe.metric_key
956
977
  ).where(
957
- (pipes.c.location_key == pipe.location_key) if pipe.location_key is not None
958
- else pipes.c.location_key.is_(None)
978
+ (pipes_tbl.c.location_key == pipe.location_key) if pipe.location_key is not None
979
+ else pipes_tbl.c.location_key.is_(None)
959
980
  )
960
981
  _id = self.value(query, debug=debug, silent=pipe.temporary)
961
982
  if _id is not None:
@@ -980,10 +1001,10 @@ def get_pipe_attributes(
980
1001
  if pipe.get_id(debug=debug) is None:
981
1002
  return {}
982
1003
 
983
- pipes = get_tables(mrsm_instance=self, create=(not pipe.temporary), debug=debug)['pipes']
1004
+ pipes_tbl = get_tables(mrsm_instance=self, create=(not pipe.temporary), debug=debug)['pipes']
984
1005
 
985
1006
  try:
986
- q = sqlalchemy.select(pipes).where(pipes.c.pipe_id == pipe.id)
1007
+ q = sqlalchemy.select(pipes_tbl).where(pipes_tbl.c.pipe_id == pipe.id)
987
1008
  if debug:
988
1009
  dprint(q)
989
1010
  attributes = (
@@ -1113,14 +1134,13 @@ def sync_pipe(
1113
1134
  if alter_cols_queries:
1114
1135
  if not self.exec_queries(alter_cols_queries, debug=debug):
1115
1136
  warn(f"Failed to alter columns for {pipe}.")
1116
-
1137
+ else:
1138
+ pipe.infer_dtypes(persist=True)
1117
1139
 
1118
1140
  unseen_df, update_df, delta_df = (
1119
1141
  pipe.filter_existing(
1120
1142
  df,
1121
1143
  chunksize = chunksize,
1122
- begin = begin,
1123
- end = end,
1124
1144
  debug = debug,
1125
1145
  **kw
1126
1146
  ) if check_existing else (df, None, df)
@@ -1373,6 +1393,8 @@ def sync_pipe_inplace(
1373
1393
  if alter_cols_queries:
1374
1394
  if not self.exec_queries(alter_cols_queries, debug=debug):
1375
1395
  warn(f"Failed to alter columns for {pipe}.")
1396
+ else:
1397
+ pipe.infer_dtypes(persist=True)
1376
1398
 
1377
1399
  if not check_existing:
1378
1400
  new_count = self.value(f"SELECT COUNT(*) FROM {new_table_name}", debug=debug)
@@ -1396,6 +1418,8 @@ def sync_pipe_inplace(
1396
1418
  pipe,
1397
1419
  begin = begin,
1398
1420
  end = end,
1421
+ begin_add_minutes = -1,
1422
+ end_add_minutes = 1,
1399
1423
  params = params,
1400
1424
  debug = debug,
1401
1425
  order = None,
@@ -1403,7 +1427,7 @@ def sync_pipe_inplace(
1403
1427
 
1404
1428
  create_backtrack_query = (
1405
1429
  (
1406
- f"WITH backtrack_def AS ({backtrack_def})\n"
1430
+ f"WITH backtrack_def AS (\n{backtrack_def}\n)\n"
1407
1431
  + f"SELECT *\nINTO {backtrack_table_name}\nFROM backtrack_def"
1408
1432
  ) if self.flavor not in ('sqlite', 'oracle', 'mysql', 'mariadb', 'duckdb')
1409
1433
  else (
@@ -2314,7 +2338,12 @@ def get_add_columns_queries(
2314
2338
  if not pipe.exists(debug=debug):
2315
2339
  return []
2316
2340
  import copy
2317
- from meerschaum.utils.sql import get_pd_type, get_db_type, sql_item_name
2341
+ from meerschaum.utils.sql import (
2342
+ get_pd_type,
2343
+ get_db_type,
2344
+ sql_item_name,
2345
+ SINGLE_ALTER_TABLE_FLAVORS,
2346
+ )
2318
2347
  from meerschaum.utils.misc import flatten_list
2319
2348
  table_obj = self.get_pipe_table(pipe, debug=debug)
2320
2349
  df_cols_types = (
@@ -2346,13 +2375,25 @@ def get_add_columns_queries(
2346
2375
  ) for col in new_cols
2347
2376
  }
2348
2377
 
2349
- query = "ALTER TABLE " + sql_item_name(pipe.target, self.flavor)
2378
+ alter_table_query = "ALTER TABLE " + sql_item_name(pipe.target, self.flavor)
2379
+ queries = []
2350
2380
  for col, typ in new_cols_types.items():
2351
- query += "\nADD " + sql_item_name(col, self.flavor) + " " + typ + ","
2352
- query = query[:-1]
2381
+ add_col_query = "\nADD " + sql_item_name(col, self.flavor) + " " + typ + ","
2382
+
2383
+ if self.flavor in SINGLE_ALTER_TABLE_FLAVORS:
2384
+ queries.append(alter_table_query + add_col_query[:-1])
2385
+ else:
2386
+ alter_table_query += add_col_query
2387
+
2388
+ ### For most flavors, only one query is required.
2389
+ ### This covers SQLite which requires one query per column.
2390
+ if not queries:
2391
+ queries.append(alter_table_query[:-1])
2392
+
2353
2393
  if self.flavor != 'duckdb':
2354
- return [query]
2394
+ return queries
2355
2395
 
2396
+ ### NOTE: For DuckDB, we must drop and rebuild the indices.
2356
2397
  drop_index_queries = list(flatten_list(
2357
2398
  [q for ix, q in self.get_drop_index_queries(pipe, debug=debug).items()]
2358
2399
  ))
@@ -2360,7 +2401,7 @@ def get_add_columns_queries(
2360
2401
  [q for ix, q in self.get_create_index_queries(pipe, debug=debug).items()]
2361
2402
  ))
2362
2403
 
2363
- return drop_index_queries + [query] + create_index_queries
2404
+ return drop_index_queries + queries + create_index_queries
2364
2405
 
2365
2406
 
2366
2407
  def get_alter_columns_queries(
@@ -2385,13 +2426,13 @@ def get_alter_columns_queries(
2385
2426
  -------
2386
2427
  A list of the `ALTER TABLE` SQL query or queries to be executed on the provided connector.
2387
2428
  """
2388
- if self.flavor == 'sqlite':
2389
- return []
2390
2429
  if not pipe.exists(debug=debug):
2391
2430
  return []
2392
2431
  from meerschaum.utils.sql import get_pd_type, get_db_type, sql_item_name
2393
- from meerschaum.utils.misc import flatten_list
2432
+ from meerschaum.utils.misc import flatten_list, generate_password
2394
2433
  table_obj = self.get_pipe_table(pipe, debug=debug)
2434
+ target = pipe.target
2435
+ session_id = generate_password(3)
2395
2436
  df_cols_types = (
2396
2437
  {col: str(typ) for col, typ in df.dtypes.items()}
2397
2438
  if not isinstance(df, dict) else df
@@ -2411,15 +2452,59 @@ def get_alter_columns_queries(
2411
2452
  for col in altered_cols
2412
2453
  }
2413
2454
 
2455
+ if self.flavor == 'sqlite':
2456
+ temp_table_name = '_' + session_id + '_' + target
2457
+ rename_query = (
2458
+ "ALTER TABLE "
2459
+ + sql_item_name(target, self.flavor)
2460
+ + " RENAME TO "
2461
+ + sql_item_name(temp_table_name, self.flavor)
2462
+ )
2463
+ create_query = (
2464
+ "CREATE TABLE "
2465
+ + sql_item_name(target, self.flavor)
2466
+ + " (\n"
2467
+ )
2468
+ for col_name, col_obj in table_obj.columns.items():
2469
+ create_query += (
2470
+ sql_item_name(col_name, self.flavor)
2471
+ + " "
2472
+ + (str(col_obj.type) if col_name not in altered_cols else text_type)
2473
+ + ",\n"
2474
+ )
2475
+ create_query = create_query[:-2] + "\n)"
2476
+
2477
+ insert_query = (
2478
+ "INSERT INTO "
2479
+ + sql_item_name(target, self.flavor)
2480
+ + "\nSELECT\n"
2481
+ )
2482
+ for col_name, col_obj in table_obj.columns.items():
2483
+ new_col_str = (
2484
+ sql_item_name(col_name, self.flavor)
2485
+ if col_name not in altered_cols
2486
+ else f"CAST({sql_item_name(col_name, self.flavor)} AS {text_type})"
2487
+ )
2488
+ insert_query += new_col_str + ",\n"
2489
+ insert_query = insert_query[:-2] + f"\nFROM {sql_item_name(temp_table_name, self.flavor)}"
2490
+
2491
+ drop_query = f"DROP TABLE {sql_item_name(temp_table_name, self.flavor)}"
2492
+ return [
2493
+ rename_query,
2494
+ create_query,
2495
+ insert_query,
2496
+ drop_query,
2497
+ ]
2498
+
2414
2499
  queries = []
2415
2500
  if self.flavor == 'oracle':
2416
- add_query = "ALTER TABLE " + sql_item_name(pipe.target, self.flavor)
2501
+ add_query = "ALTER TABLE " + sql_item_name(target, self.flavor)
2417
2502
  for col, typ in altered_cols_types.items():
2418
2503
  add_query += "\nADD " + sql_item_name(col + '_temp', self.flavor) + " " + typ + ","
2419
2504
  add_query = add_query[:-1]
2420
2505
  queries.append(add_query)
2421
2506
 
2422
- populate_temp_query = "UPDATE " + sql_item_name(pipe.target, self.flavor)
2507
+ populate_temp_query = "UPDATE " + sql_item_name(target, self.flavor)
2423
2508
  for col, typ in altered_cols_types.items():
2424
2509
  populate_temp_query += (
2425
2510
  "\nSET " + sql_item_name(col + '_temp', self.flavor)
@@ -2428,7 +2513,7 @@ def get_alter_columns_queries(
2428
2513
  populate_temp_query = populate_temp_query[:-1]
2429
2514
  queries.append(populate_temp_query)
2430
2515
 
2431
- set_old_cols_to_null_query = "UPDATE " + sql_item_name(pipe.target, self.flavor)
2516
+ set_old_cols_to_null_query = "UPDATE " + sql_item_name(target, self.flavor)
2432
2517
  for col, typ in altered_cols_types.items():
2433
2518
  set_old_cols_to_null_query += (
2434
2519
  "\nSET " + sql_item_name(col, self.flavor)
@@ -2437,7 +2522,7 @@ def get_alter_columns_queries(
2437
2522
  set_old_cols_to_null_query = set_old_cols_to_null_query[:-1]
2438
2523
  queries.append(set_old_cols_to_null_query)
2439
2524
 
2440
- alter_type_query = "ALTER TABLE " + sql_item_name(pipe.target, self.flavor)
2525
+ alter_type_query = "ALTER TABLE " + sql_item_name(target, self.flavor)
2441
2526
  for col, typ in altered_cols_types.items():
2442
2527
  alter_type_query += (
2443
2528
  "\nMODIFY " + sql_item_name(col, self.flavor) + ' '
@@ -2446,7 +2531,7 @@ def get_alter_columns_queries(
2446
2531
  alter_type_query = alter_type_query[:-1]
2447
2532
  queries.append(alter_type_query)
2448
2533
 
2449
- set_old_to_temp_query = "UPDATE " + sql_item_name(pipe.target, self.flavor)
2534
+ set_old_to_temp_query = "UPDATE " + sql_item_name(target, self.flavor)
2450
2535
  for col, typ in altered_cols_types.items():
2451
2536
  set_old_to_temp_query += (
2452
2537
  "\nSET " + sql_item_name(col, self.flavor)
@@ -2455,7 +2540,7 @@ def get_alter_columns_queries(
2455
2540
  set_old_to_temp_query = set_old_to_temp_query[:-1]
2456
2541
  queries.append(set_old_to_temp_query)
2457
2542
 
2458
- drop_temp_query = "ALTER TABLE " + sql_item_name(pipe.target, self.flavor)
2543
+ drop_temp_query = "ALTER TABLE " + sql_item_name(target, self.flavor)
2459
2544
  for col, typ in altered_cols_types.items():
2460
2545
  drop_temp_query += (
2461
2546
  "\nDROP COLUMN " + sql_item_name(col + '_temp', self.flavor) + ','
@@ -2466,7 +2551,7 @@ def get_alter_columns_queries(
2466
2551
  return queries
2467
2552
 
2468
2553
 
2469
- query = "ALTER TABLE " + sql_item_name(pipe.target, self.flavor)
2554
+ query = "ALTER TABLE " + sql_item_name(target, self.flavor)
2470
2555
  for col, typ in altered_cols_types.items():
2471
2556
  alter_col_prefix = (
2472
2557
  'ALTER' if self.flavor not in ('mysql', 'mariadb', 'oracle')