vim-dadbod icon indicating copy to clipboard operation
vim-dadbod copied to clipboard

mongo adapter starts with many blank lines

Open llimllib opened this issue 2 years ago • 11 comments

When I run a mongo query, my preview window looks like this:

readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > 
readme@adama > [
  [ 'Awesome Fresh Chair', ObjectId("644a7fd89f2af185ac856ec1") ],
  [ 'Unbranded Metal Shoes', ObjectId("644a7ff9f797ad86ec568966") ],
  [ 'Intelligent Metal Bacon', ObjectId("644a7ffdf797ad86ec56898a") ],
  [ 'Handmade Rubber Car', ObjectId("644a8001f797ad86ec5689ae") ],
  [ 'Licensed Concrete Fish', ObjectId("644a8813178bc88ea5e99c03") ],
  [
    'Handcrafted Concrete Bacon',
    ObjectId("644a8817178bc88ea5e99c27")
  ],
  [ 'Generic Rubber Sausages', ObjectId("644a881b178bc88ea5e99c4b") ],
  [ 'bananas', ObjectId("644a88a98c6a4b4cd9e5749d") ]
]
readme@adama > 

I have mongosh installed, and running the query this way (which, as best as I can tell, matches the way the mongo adapter is running it?) doesn't show any of the readme@adama business:

$ mongosh mongodb://localhost/readme --quiet --eval 'db.projects.find().map(p => [p.name, p._id]);'
[
  [ 'Awesome Fresh Chair', ObjectId("644a7fd89f2af185ac856ec1") ],
  [ 'Unbranded Metal Shoes', ObjectId("644a7ff9f797ad86ec568966") ],
  [ 'Intelligent Metal Bacon', ObjectId("644a7ffdf797ad86ec56898a") ],
  [ 'Handmade Rubber Car', ObjectId("644a8001f797ad86ec5689ae") ],
  [ 'Licensed Concrete Fish', ObjectId("644a8813178bc88ea5e99c03") ],
  [
    'Handcrafted Concrete Bacon',
    ObjectId("644a8817178bc88ea5e99c27")
  ],
  [ 'Generic Rubber Sausages', ObjectId("644a881b178bc88ea5e99c4b") ],
  [ 'bananas', ObjectId("644a88a98c6a4b4cd9e5749d") ]
]

Is there any way to suppress the leading empty lines?

llimllib avatar Apr 27 '23 16:04 llimllib

I got the same issue and found it due to

https://github.com/tpope/vim-dadbod/blob/fb30422b7bee7e2fa4205a4d226f01477f4fc593/autoload/db.vim#L511

it adds the same number blank lines before the real script so MongoDB responded the same lines of prompt, @tpope can you kindly share why is needed to repeat the blank lines before the actual script?

kezhenxu94 avatar May 25 '24 11:05 kezhenxu94

I thought --quiet got rid of the prompt. Is this a behavior change in mongosh compared to mongo? Is there another flag we could use?

tpope avatar May 26 '24 03:05 tpope

It seems like mongosh treats redirected files as interactive input, while it treats named .js files as executable (and will not echo the output by default):

# with a redirected file, mongosh processes it as interactive input, including the leading `\n\n\n` 
$ mongosh $DATABASE_URL --quiet <<< $'\n\n\ndb.projects.find().map(p => [p.name, p._id]);'
readme> 

readme> 

readme> 

readme> db.projects.find().map(p => [p.name, p._id]);
[
  [ 'testing', ObjectId('6605a863b3cee3d7239712be') ],
  [ 'testing-no-superhub', ObjectId('660af5bb1765ca4e3fb0a183') ],
  [ 'test', ObjectId('6628f802f8e230315e58b684') ]
]

# note that I had to add `console.log` here, otherwise it executes but doesn't print
$ echo $'\n\n\nconsole.log(db.projects.find().map(p => [p.name, p._id]));' > /tmp/f.js
$ mongosh $DATABASE_URL --quiet /tmp/f.js                                                 
[
  [ 'testing', ObjectId('6605a863b3cee3d7239712be') ],
  [ 'testing-no-superhub', ObjectId('660af5bb1765ca4e3fb0a183') ],
  [ 'test', ObjectId('6628f802f8e230315e58b684') ]
]

--quiet saves you the whole connection info stanza, but doesn't silence the prompt when mongo thinks it's doing interactive input. WIthout the newlines, you still get the prompt:

$ mongosh $DATABASE_URL --quiet <<< $'db.projects.find().map(p => [p.name, p._id]);'      
readme> db.projects.find().map(p => [p.name, p._id]);
[
  [ 'testing', ObjectId('6605a863b3cee3d7239712be') ],
  [ 'testing-no-superhub', ObjectId('660af5bb1765ca4e3fb0a183') ],
  [ 'test', ObjectId('6628f802f8e230315e58b684') ]
]
readme> 

If you use --eval rather than a file redirection, mongosh does not show the prompt:

$ mongosh $DATABASE_URL --quiet --eval $'\n\n\ndb.projects.find().map(p => [p.name, p._id]);'
[
  [ 'testing', ObjectId('6605a863b3cee3d7239712be') ],
  [ 'testing-no-superhub', ObjectId('660af5bb1765ca4e3fb0a183') ],
  [ 'test', ObjectId('6628f802f8e230315e58b684') ]
]

llimllib avatar May 27 '24 01:05 llimllib

We can switch it to pass a filename. Please try this patch and confirm it fixes the issue:

diff --git i/autoload/db/adapter/mongodb.vim w/autoload/db/adapter/mongodb.vim
index a54fd6f..2ae9a6b 100644
--- i/autoload/db/adapter/mongodb.vim
+++ w/autoload/db/adapter/mongodb.vim
@@ -30,8 +30,8 @@ function! db#adapter#mongodb#interactive(url) abort
         \ db#url#as_argv(url, '--host ', '--port ', '', '-u ', '-p ', '')
 endfunction
 
-function! db#adapter#mongodb#filter(url) abort
-  return db#adapter#mongodb#interactive(a:url) + ['--quiet']
+function! db#adapter#mongodb#input(url, in) abort
+  return db#adapter#mongodb#interactive(a:url) + ['--quiet', a:in]
 endfunction
 
 function! db#adapter#mongodb#complete_opaque(url) abort

tpope avatar May 27 '24 23:05 tpope

With that change, the blank lines are gone, but then I have to add console.log(...) to all my queries to get any output - it would be a lot nicer to have the --eval behavior of printing the output automatically.

(I understand that mongo doesn't make this easy, and appreciate your time looking into it)

llimllib avatar May 28 '24 01:05 llimllib

Unfortunately it may be a while before I have enough time to install MongoDB and investigate myself. What about something like --query 'eval(<read from stdin>)'? Can someone figure out the <read from stdin> part?

tpope avatar May 30 '24 17:05 tpope

From the shell, you can use $(cat <file>):

$ printf "\n\n\ndb.projects.find().map(p => [p.name, p._id]);" >| query.js            
$ mongosh $DATABASE_URL --quiet --eval "$(cat query.js)"                  
[
  [ 'testing', ObjectId('6605a863b3cee3d7239712be') ],
  [ 'testing-no-superhub', ObjectId('660af5bb1765ca4e3fb0a183') ],
  [ 'test', ObjectId('6628f802f8e230315e58b684') ]
]

I don't follow the execution of the process in vimscript, so I'm not sure if that's possible here?

llimllib avatar May 31 '24 15:05 llimllib

We don't use the shell, but we could effectively the same thing by calling readfile() and passing it as an argument. Not a great solution, command line arguments have constraints like size limits and then you can end up with a whole dang file in ps aux.

tpope avatar May 31 '24 15:05 tpope

Agreed. As far as I can tell, mongosh is completely impervious to sensible stdin handling though

llimllib avatar May 31 '24 15:05 llimllib

I really wish the usual "- means read from stdin" behavior worked, but no joy:

$ cat query.js| mongosh $DATABASE_URL --quiet --eval -
SyntaxError: Unexpected token (1:1)

> 1 | -
    |  ^

I looked in their github repo, but they have issues disabled and appear to use jira so I don't know where I'd file an issue with an enhancement request

llimllib avatar May 31 '24 15:05 llimllib

You could maybe abuse massage() for this. A lot of adapters use it to add trailing semicolons, but maybe wrapping with console.log() could be sufficient? I guess it wouldn't cover cases with internal semicolons.

tpope avatar May 31 '24 15:05 tpope