Bug #88166 .find() method function not parsing SearchConditionStr correctly

Submitted: 20 Oct 2017 11:50 Modified: 23 Apr 2018 5:37
Reporter: Andy Fusniak Email Updates:
Status: No Feedback Impact on me:
None 
Category:Connector for Node.js Severity:S1 (Critical)
Version:8.0.8 OS:MacOS (node v6.11.4)
Assigned to: CPU Architecture:Any
Tags: NodeJS, XDevAPI

[20 Oct 2017 11:50] Andy Fusniak
Description:
Function {
  message: 'Parse error on line 1:\nname like :name AND age <\n-----^\nExpecting \'.\', \'(\', got \'like\'',
  hash: 
   { text: 'like',
     token: 'like',
     line: 0,
     loc: { first_line: 1, last_line: 1, first_column: 0, last_column: 4 },
     expected: [ '\'.\'', '\'(\'' ] } }

How to repeat:
// --------------------------------------------------
// Connecting to MySQL Server and working with a Collection

const mysqlx = require('@mysql/xdevapi');

// Connect to server
mysqlx.getSession( {
  host: 'localhost', port: '33060',
  dbUser: 'root',
  dbPassword: 'mysql',
  ssl: false
}).then(function(session) {
  return session.getSchema('test1137');
}).then(function(db) {
  // Create a new collection 'my_collection'
  return db.createCollection('my_collection');
}).then(function(myColl) {
  // Insert documents
  return Promise.all([
    myColl.add({name: 'Sakila', age: 15}).execute(),
    myColl.add({name: 'Susanne', age: 24}).execute(),
    myColl.add({name: 'Mike', age: 39}).execute()
  ]).then(function() {
    // Find a document
    return myColl.find('name like :name AND age < :age')
      .bind({ name: 'S*', age: 20 }).limit(1).execute();
  }).then(function(docs) {
    // Print document
    console.log(docs.fetchOne());

    // Drop the collection
    return myColl.drop();
  });
}).catch(function(err) {
  // Handle error
  console.error(err);
});
[20 Oct 2017 19:10] Andy Fusniak
I've changed the string passed to the .find() method to

'$.name like :name && $.age < :age'

and this appears to satisfy the parser. However, the callback function passed to the .execute() method returns undefined (I'm not sure why the .execute() method takes a callback as this seems to break the convention of the module that appears to use Promise-based asynchronous control flow). 

The MySQL logs show a syntactically valid SQL query. When trying the query manually at the mysqlsh prompt the following output can be seen: 

mysql-sql> SELECT doc FROM `test1137`.`my_collection` WHERE (JSON_UNQUOTE(JSON_EXTRACT(doc,'$.name')) LIKE ('S*' AND (JSON_EXTRACT(doc,'$.age') < 20))) LIMIT 1;                                        ;
Empty set, 3 warnings (0.00 sec)
Warning (code 1292): Truncated incorrect DOUBLE value: 'S*'
Warning (code 1292): Truncated incorrect DOUBLE value: 'S*'
Warning (code 1292): Truncated incorrect DOUBLE value: 'S*'
mysql-sql>

I'm raising this to a Critical since without any means of searching the collections using Node.js means this module is unfortunately unusable.

// --------------------------------------------------
// Connecting to MySQL Server and working with a Collection

const mysqlx = require('@mysql/xdevapi');

// Connect to server
mysqlx.getSession( {
  host: 'localhost', port: '33060',
  dbUser: 'root',
  dbPassword: 'mysql',
  ssl: false
}).then(function(session) {
  return session.getSchema('test1137');
}).then(function(db) {
  // Create a new collection 'my_collection'
  return db.createCollection('my_collection');
}).then(function(myColl) {
  // Insert documents
  return Promise.all([
    myColl.add({name: 'Sakila', age: 15}).execute(),
    myColl.add({name: 'Susanne', age: 24}).execute(),
    myColl.add({name: 'Mike', age: 39}).execute()
  ]).then(function() {
    // Find a document
    let p = myColl.find('$.name like :name && $.age < :age')
      .bind({ name: 'S*', age: 20 }).limit(1).execute(function exResult(docs) {
        console.log(docs);
        process.exit();
      });
    console.log(p);
    return p;
  }).then(function(docs) {
    // Print document
    console.log(docs.fetchOne());

    // Drop the collection
    return myColl.drop();
  });
}).catch(function(err) {
  // Handle error
  console.error(err);
});
[2 Feb 2018 18:37] Rui Quelhas
Hi Andy,

sorry for the late reply, this got lost in the cracks somehow.

As you mentioned, the API relies on a kind of push-based cursor (in the form of a callback) to harvest resultset data (the Promise is just returned when the operation effectively finishes). So, in order to pick up the matching documents with `find()`, you would need to provide a callback that would do the work.

Looking at your test case, the callback will be called with undefined since you are using an incorrect LIKE pattern. You should use 'S%' instead of 'S*'. Also, the `drop()` method is no longer part of the API since 8.0.7. To drop a collection you can use `db.dropCollection('my_collection')`.
[24 Apr 2018 1:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.054 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.