How can I use DEFAULT values via knex insert? - javascript

My goal is to dynamically insert data into a table via knex.
Code looks like this:
const knexService = require("../knexService.js")
async function insertObjectToKnex() {
const insertObject = {
id: "DEFAULT",
someKey: "someValue"
};
await knexService.db("table").insert(inserObject);
}
On DEFAULT the next free id should be used as database id - table is configured and it works with raw sql. With knex.js I get the following error:
invalid input syntax for type integer: "DEFAULT"
Using the useNullAsDefault: true, config is not possible, because the id is not nullable.
How can I trigger the default value in knex - I did not find anything in the documentation or with google, that could at least give a hint to this issue!

While it is not mentioned in the documentation of knex.js one should simply not add fields with a DEFAULT assignement to a query. This will set the default value to the row column.

Related

Supabase - Upsert & multiple onConflict constraints

I cannot figure out how to proceed with an Upsert & "multiple" onConflict constraints. I want to push a data batch in a Supabase table.
My data array would be structured as follows:
items = [
{ date: "2023-01-26", url: "https://wwww.hello.com"},
{ date: "2023-01-26", url: "https://wwww.goodbye.com"},
...]
I would like to use the Upsert method to push this new batch in my Supabase table, unless if it already exists. To check if it already exists, I would like to use the date, and the url as onConflict criteria, if I understood well.
When I'm running this method
const { error } = await supabase
.from('items')
.upsert(items, { onConflict: ['date','url'] })
.select();
I'm having the following error:
{
code: '42P10',
details: null,
hint: null,
message: 'there is no unique or exclusion constraint matching the ON CONFLICT specification'
}
What am I missing? Where am I wrong?
You can pass more than one column in the upsert into by adding a column in a string (instead of using an array):
const { data, error } = await supabase
.from('items')
.upsert(items, { onConflict: 'date, url'} )
Postgres performs unique index inference as mentioned in https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT
It is necessary to have unique or indexes for this to work, as you can read in the documentation above:
INSERT into tables that lack unique indexes will not be blocked by
concurrent activity. Tables with unique indexes might block if
concurrent sessions perform actions that lock or modify rows matching
the unique index values being inserted; the details are covered in
Section 64.5. ON CONFLICT can be used to specify an alternative action
to raising a unique constraint or exclusion constraint violation
error.

How to decode transaction input data using `ethers.utils.defaultAbiCoder`

I'm fetching transaction data using Etherscan API. This is the example result I'm getting:
{
blockNumber: '7409930',
timeStamp: '1639151980',
hash: '...',
nonce: '4124',
...
input: '0x9d90e4c8000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000093238bb66b5d15b4152c5db574e3397ff1b1a450',
contractAddress: '',
cumulativeGasUsed: '403775',
gasUsed: '1162315',
confirmations: '191308'
}
I now need to figure out the event type (contract method, e.g. TransferOwnership, stakeTokens,...) for this transaction. This data is stored in input property of this object.
I managed to accomplish this using abi-decoder library, but I want to accomplish the same thing using ethers's utility method (whichever).
My current implementation:
const abiDecoder = require("abi-decoder");
abiDecoder.addABI(contractAbi);
// "item" is transaction data, input property is encoded stuff from which I want to get the contract method used by this transaction
const decodedInput = abiDecoder.decodeMethod(item.input);
// contract method
console.log(decodedInput.name);
I was reading through ether's documentation (https://docs.ethers.io/v5/api/utils/abi/coder/), but I can't figure it out.
you can try what is recommended in this: https://github.com/ethers-io/ethers.js/issues/423 . but if you are interacting with BSC, this is not possible due to the error input data too big causing Error in Big Number Number can only safely store up to 53 bits

TypeORM createQueryBuilder: Is possible to use table name as string instead of entity

In my current scenario, a third party will be creating tables dynamically on my DB, and storing the table name as a varchar and column names as jsonb in other table which is defined as an Entity in my NestJS backend.
This is so I can keep track (and query) these tables, since I have no control over its creation.
For this purpose I'd like to use TypeORM's createQueryBuilder instead of using raw queries as its easier for me to play with abstraction.
As far as I know TypeORMs createQueryBuilder needs a defined Entity in the from clause.
Something like this:
return await getManager()
.createQueryBuilder()
.select('*')
.from(MyDefinedModel, 'modelAlias')
.getRawMany();
}
So I'd like to do something like:
const tableName = await getDynamicallyGenetaredTableNames().getFirstOne()
// now tableName points to a string that is a table name, i.e 'table-data-192239'
return await getManager()
.createQueryBuilder()
.select('*')
.from(tableName, 'tableAlias')
.getRawMany();
So passing the table name I point to the right table, but TypeORM (and TS) complains because that tableName is a string, and not an Entity (Class) type
I really don't want to type-cast and start doing nasty things if there is something cleaner to achieve this.
I didn't find any solution in the official docs
Any brilliant ideas out there?
Thanks, y'all
We can pass table name instead of Entity for getRepository.
let tableName = 'user';
let query = getRepository(tableName).createQueryBuilder(tableName);
You can select from a table by its table name without defining an entity before like this:
const res = await manager
.createQueryBuilder()
.select()
.from("tableName", null)
.where("tableName.id = :id", { id: 1 })
.getRawMany();
Be sure that you set the second parameter of the from() explicitly to null.
You could try using a raw query:
import { getManager } from 'typeorm'
const tableName = await getDynamicallyGenetaredTableNames().getFirstOne()
// Use the table name in a raw SQL query
const result = await getManager().query(`SELECT * FROM ${tableName}`)

how to query column in SQL database via UPPER case conversion IN NODE.js javascript code..

Hi I've recently updated my SEQUELIZE node package from v3 to v4.
In my code I used to query my user table via the following sytnax
var option = {
where: ["upper(email) = ?", ssousername.toUpperCase()]
};
This would effectively query my user table converting all user emails in DB to uppercase.
When upgrading to V4 I am now given the following error thrown by the above query
Unhandled rejection Error: Support for literal replacements in the `where` object has been removed.
I cannot find any documentation as to how I should syntactically format my former query executed via a node.js backend in order to produce the following SQL query
SELECT UPPER(email) AS email
FROM dashboard."user" WHERE email='user#email.com';
Would love some help , Thanks!
They are working on deprecating all string operators I think. Under querying it seems to suggest doing it like this:
let option = {
where: sequelize.where(
sequelize.fn('upper', sequelize.col('email')),
ssousername.toUpperCase()
),
};

In a Nodejs Sequelize model, how to obtain type information of attributes?

I have a working model with Postgres and sequelize in NodeJS. Say the model is Person and has name and age fields. Now I want to dynamically inspect the model class and obtain information about it's attributes, like their name and most of all type.
Using Person.attributes
I get some information:
name:
{ type:
{ options: [Object],
_binary: undefined,
_length: 255 },
But as you can see the type object does not inform about name being a varchar or boolean.
Does anyone know, how to get this information with sequelize
You can iterate over rawAtributes of Model
for( let key in Model.rawAttributes ){
console.log('Field: ', key); // this is name of the field
console.log('Type: ', Model.rawAttributes[key].type.key); // Sequelize type of field
}
So the example for name being a Sequelize.STRING would be
Field: name
Type: STRING
Or you can do almost the same iteration but instead using Model.rawAttributes[key].type.key you can use Model.rawAttributes[key].type.toSql(), which would generate this result
Field: name
Type: VARCHAR(255)
EDIT
Accessing defaultValue of field:
Model.rawAttributes[field].defaultValue
Checking if field allows NULL values:
Model.rawAttributes[field].allowNull
You are looking for native type information, it seems.
I'm not familiar with Sequelize, except I know it uses node-postgres driver underneath, which automatically provides the type information with every query that you make.
Below is a simple example of dynamically getting type details for any_table, using pg-promise:
var pgp = require('pg-promise')(/*initialization options*/);
var db = pgp(/*connection details*/);
db.result('SELECT * FROM any_table LIMIT 0', [], a => a.fields)
.then(fields => {
// complete details for each column
})
.catch(error => {
// an error occurred
});
There are several fields available for each column there, including name and dataTypeID that you are looking for ;)
As an update, following the answer that does use Sequelize for it...
The difference is that here we get direct raw values as they are provided by PostgreSQL, so dataTypeID is raw type Id exactly as PostgreSQL supports it, while TYPE: STRING is an interpreted type as implemented by Sequelize. Also, we are getting the type details dynamically here, versus statically in that Sequelize example.
item.rawAttributes[key].type.key === this.DataTypes.JSONB.key;
#piotrbienias Is above comparison valid ?
(Sorry for writing here as I can't add comments)

Categories

Resources