JOOQ MYSQL QUERY - jooq

select question.*,
question_option.id
from question
left join question_option on question_option.question_id = question.id;
how do i write question.* in jooq instead of specifying all the entity vaiables

You can use field() or asterisk() methods from the JOOQ generated objects which are extended from TableImpl.
For example, if you just want to query the fields of a record:
dsl.select(QUESTION.fields()).from...
If you need fields from the join too:
dsl.select(QUESTION.asterisk(), QUESTION_OPTION.ID).from...

I assume that you generate the metamodel so you can use
dsl.select(QUESTION.fields()), QUESTION_OPTION.ID)...

Related

Querying a composite key with multiple IN values with jOOQ

I have the following query:
SELECT *
FROM table
WHERE (id, other_id, status)
IN (
(1, 'XYZ', 'OK'),
(2, 'ZXY', 'OK') -- , ...
);
Is it possible to construct this query in a type-safe manner using jOOQ, preferably without generating composite keys? Is it possible to do this using jOOQ 3.11?
My apologies, it seems my Google-fu was not up to par. The opposite of this question can be found here: Use JOOQ to do a delete specifying multiple columns in a "not in" clause
For completeness' sake, so that other Google searches might be more immediately helpful, the solution is:
// can be populated using DSL.row(...); for each entry
Collection<? extends Row3<Long, String, String>> values = ...
dslContext.selectFrom(TABLE)
.where(DSL.row(ID, OTHER_ID, STATUS).in(values))
.fetch();
Relevant jOOQ documentation: https://www.jooq.org/doc/3.14/manual/sql-building/conditional-expressions/in-predicate-degree-n/
Your own answer already shows how to do this with a 1:1 translation from SQL to jOOQ using the IN predicate for degrees > 1.
Starting from jOOQ 3.14, there is also the option of using the new <embeddablePrimaryKeys/> flag in the code generator, which will produce embeddable types for all primary keys (and foreign keys referencing them). This will help never forget a key column on these queries, which is especially useful for joins.
Your query would look like this:
ctx.selectFrom(TABLE)
.where(TABLE.PK_NAME.in(
new PkNameRecord(1, "XYZ", "OK"),
new PkNameRecord(2, "ZXY", "OK")))
.fetch();
The query generated behind the scenes is the same as yours, using the 3 constraint columns for the predicate. If you add or remove a constraint from the key, the query will no longer compile. A join would look like this:
ctx.select()
.from(TABLE)
.join(OTHER_TABLE)
.on(TABLE.PK_NAME.eq(OTHER_TABLE.FK_NAME))
.fetch();
Or an implicit join would look like this:
ctx.select(OTHER_TABLE.table().fields(), OTHER_TABLE.fields())
.from(OTHER_TABLE)
.fetch();

Howto expose a native SQL function as a predicate

I have a table in my database which stores a list of string values as a jsonb field.
create table rabbits_json (
rabbit_id bigserial primary key,
name text,
info jsonb not null
);
insert into rabbits_json (name, info) values
('Henry','["lettuce","carrots"]'),
('Herald','["carrots","zucchini"]'),
('Helen','["lettuce","cheese"]');
I want to filter my rows checking if info contains a given value.
In SQL, I would use ? operator:
select * from rabbits_json where info ? 'carrots';
If my googling skills are fine today, I believe that this is not implemented yet in JOOQ:
https://github.com/jOOQ/jOOQ/issues/9997
How can I use a native predicate in my query to write an equivalent query in JOOQ?
For anything that's not supported natively in jOOQ, you should use plain SQL templating, e.g.
Condition condition = DSL.condition("{0} ? {1}", RABBITS_JSON.INFO, DSL.val("carrots"));
Unfortunately, in this specific case, you will run into this issue here. With JDBC PreparedStatement, you still cannot use ? for other usages than bind variables. As a workaround, you can:
Use Settings.statementType == STATIC_STATEMENT to prevent using a PreparedStatement in this case
Use the jsonb_exists_any function (not indexable) instead of ?, see https://stackoverflow.com/a/38370973/521799

Node Mysql Escaping - Mysql.Escape() / Mysql.EscapeId()

I am using mysql-node: https://github.com/mysqljs/mysql but I am a little confused about default sanitization, Mysql.Escape() vs Mysql.EscapeId() and the use of ? vs ??. The docs says?
Default Sanitization
When you pass an Object to .escape() or .query(), .escapeId() is used
to avoid SQL injection in object keys.
I see the term Object, so does that mean I should still escape queries like this?
UPDATE table SET updated_at = userInput WHERE name = userInput.
Mysql.Escape() vs Mysql.EscapeId()
What is the difference between these two functions. The docs says mysql.escape uses mysql.escapeId. I know they both sanitize input but is there a case where you use one or the other?
? vs ??
The docs use ? and ?? interchangeably. Do they mean the same thing?
The documentation describes what escape() and escapeId() do. Use escape() when you need to escape values. Use escapeId() when you need to escape identifiers (e.g., table, database, or column names).
I talked to the maintainer of mysqljs and confirmed that this package doesn't escape queries by default.
When you pass an Object to .escape() or .query(), .escapeId() is used
to avoid SQL injection in object keys.
The statement above means queries will be escaped if you use one of the following methods.
let args = { name: 'myname' otherVals: 'blah blah'};
mysql.query('Insert INTO table SET ?',args);
let name = 'test';
mysql.query('INSERT INTO table SET name = ?', [name]);
For the second part of the questions: ?? and escapeId is used for identifiers and ? and escape() is used for values.

Waterline - Postgres - DataTypes

I am having difficulties with Waterline models and creating the Postgres tables related to those models.
No matter what I do to create a varchar(n) in the table through a model, it converts the attribute to text. And bigint also is being converted to integer!
Should I change the ORM?
Is there a way to do that?
You can do a more pleasant approach, using Waterline to "RUD" in "CRUD" but not to "C" - create! This because Waterline can be very "bad" at creating intermediary tables, primary keys (composite keys) and etc. So what I do today is this:
Compose a full .sql file archive to create indexes and tables.
Create the database once. (Alter if needed).
Declare all the tables as models. Just insert the type, primary key (if it is a single one) and lifecycle callbacks.
Make sure that config/models.js is set to migrate : safe.
Conclusion: I can insert, read and delete rows with Waterline, but I don't trust it (performance-wise) to create my tables. Sequelize on the other hand is a much more mature ORM and can be used if you need it. For me the hybrid waterline + SQL is sufficient.
EDIT: My models dont have any aggregation (like my_pets: { model: pet} ), just row names and types, as simple as possible.
Sails supported datatype:
String, text, integer, float, date, datetime, boolean, binary, array, json, mediumtext, longtext, objectid
If you need to specify exact length -> varchar(n), you need to use supported data type as shown above, or sails provide option called query.
Model.query() method which you can use to perform any kind of query you want.
var queryString='CREATE TABLE if not exists sailsusers.test (id INT NOT NULL,name VARCHAR(45) NULL,PRIMARY KEY (id))'
Test.query(queryString,function(err,a){
if(err)
return console.log(err);
console.log(a,'\n',b);
res.ok();
});

Storing schema-less complex json object in Cassandra

I have a schema-less json object that I wish to store in Cassandra DB using spring-cassandra. I learned that Cassandra supports Map type but Cassandra doesn't accept Map<String, Object> as a data model.
I need to query on the fields of the json so storing it as a blob is out of question. Is there anyway I can do this?
PS: I've looked at Storing JSON object in CASSANDRA, the answer didn't seem applicable to my use case as my json could be very complex.
Did you look at UDT (user-defined-type) ?
You can define an UDT like this:
CREATE TYPE my_json(
property1 text,
property2 int,
property3 map<text, text>,
property4 map<int, another_json_type>,
...
)
And then in Java use Map<String, UserType>
Note: UserType comes from the Java driver: https://github.com/datastax/java-driver/blob/2.1/driver-core/src/main/java/com/datastax/driver/core/UserType.java
You cannot create an user type n Java, you can only get it from the metadata of your table, see this: https://github.com/datastax/java-driver/blob/3.0/driver-core/src/test/java/com/datastax/driver/core/UserTypesTest.java#L62-L81
1) one solution from me is, integrate solr search and index this table first.
2) Later write a solr analyser to parse the json and put under various fields in solr while indexing.
3) Next step is use solr supported query like select * from table where solr_query = "{search expression syntax}"

Resources