osmanraifgunes osmanraifgunes - 5 days ago 4
Node.js Question

Sequelize js upsert controls if primary key is null

I am trying to use upsert method of sequelize js with postgresql. I am generating model by sequelize-auto js

My table is like :

CREATE SEQUENCE TBL_CITY_LANG_SEQ;
CREATE TABLE TBL_CITY_LANG(
ID BIGINT DEFAULT NEXTVAL ('TBL_CITY_LANG_SEQ') NOT NULL,
CITY_NAME VARCHAR(150) NOT NULL,
CITY_ID BIGINT NOT NULL,
LANGUAGE_ID BIGINT NOT NULL,
DB_EDIT_DATE TIMESTAMP(3) NOT NULL,
DB_USER_ID BIGINT NOT NULL,
DB_STATUS_ID INT NOT NULL,
CONSTRAINT PK_TBL_CITY_LANG_SEQ PRIMARY KEY
(
ID
),
CONSTRAINT IX_TBL_CITY_LANG_SEQ UNIQUE
(
LANGUAGE_ID,
CITY_ID
));


And sequelize upsert usage :

cityTable.upsert(myjson).then(function (result) {
resolve(result);
});


SQL execute LOG is :

CREATE OR REPLACE FUNCTION pg_temp.sequelize_upsert() RETURNS integer AS $func$

BEGIN INSERT INTO "tbl_city_lang" ("id","city_name","city_id","language_id","db_edit_date","db_user_id","db_status_id") VALUES (1,'istanbul 1','19','1','2015-03-03','2','1');

RETURN 1;

EXCEPTION WHEN unique_violation

THEN UPDATE "tbl_city_lang" SET "id"=1,"city_name"='istanbul 1',"city_id"='19',"language_id"='1',"db_edit_date"='2015-03-03',"db_user_id"='2',"db_status_id"='1' WHERE (("id" IS NULL AND "city_id" = '19')); RETURN 2;

END;

$func$ LANGUAGE plpgsql;

SELECT * FROM pg_temp.sequelize_upsert();


It does not give error but also does not update. Ithink the problem is deriving from the where condition of script. But the table should have primary key but updatable by unique constaint.


WHERE (("id" IS NULL AND "city_id" = '19'))


But the table should have primary key but updatable by unique constraint.

Answer

This problem was deriving from sequelize-auto. I edited source code.

edit inside lib/dialects/index.js

From :

return 'SELECT \
      o.conname AS constraint_name, \
      (SELECT nspname FROM pg_namespace WHERE oid=m.relnamespace) AS source_schema, \
      m.relname AS source_table, \
      (SELECT a.attname FROM pg_attribute a WHERE a.attrelid = m.oid AND a.attnum = o.conkey[1] AND a.attisdropped = false) AS source_column, \
      (SELECT nspname FROM pg_namespace WHERE oid=f.relnamespace) AS target_schema, \
      f.relname AS target_table, \
      (SELECT a.attname FROM pg_attribute a WHERE a.attrelid = f.oid AND a.attnum = o.confkey[1] AND a.attisdropped = false) AS target_column, \
      o.contype, \
      (SELECT d.adsrc AS extra FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_attrdef d ON (a.attrelid, a.attnum) = (d.adrelid,  d.adnum) \ WHERE NOT a.attisdropped AND a.attnum > 0 AND a.attrelid = o.conrelid \ LIMIT 1) \
    FROM pg_constraint o \
    LEFT JOIN pg_class c ON c.oid = o.conrelid \
    LEFT JOIN pg_class f ON f.oid = o.confrelid \
    LEFT JOIN pg_class m ON m.oid = o.conrelid \
    WHERE o.conrelid = (SELECT oid FROM pg_class WHERE relname = \'' + tableName + '\' LIMIT 1)'

To :

SELECT \
      o.conname AS constraint_name, \
      (SELECT nspname FROM pg_namespace WHERE oid=m.relnamespace) AS source_schema, \
      m.relname AS source_table, \
      pga.attname AS source_column, \
      (SELECT nspname FROM pg_namespace WHERE oid=f.relnamespace) AS target_schema, \
      f.relname AS target_table, \
      (SELECT a.attname FROM pg_attribute a WHERE a.attrelid = f.oid AND a.attnum = o.confkey[1] AND a.attisdropped = false) AS target_column, \
      o.contype, \
      (SELECT d.adsrc AS extra FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_attrdef d ON (a.attrelid, a.attnum) = (d.adrelid,  d.adnum) \ WHERE NOT a.attisdropped AND a.attnum > 0 AND a.attrelid = o.conrelid \ LIMIT 1) \
    FROM pg_constraint o \
    LEFT JOIN pg_attribute pga ON  pga.attrelid = o.conindid \
    LEFT JOIN pg_class c ON c.oid = o.conrelid \
    LEFT JOIN pg_class f ON f.oid = o.confrelid \
    LEFT JOIN pg_class m ON m.oid = o.conrelid \
    WHERE o.conrelid = (SELECT oid FROM pg_class WHERE relname = \'' + tableName + '\' LIMIT 1)'

edit inside lib/index.js

From :

 else if (attr === "primaryKey") {
             if (self.tables[table][field][attr] === true && (! _.has(self.tables[table][field], 'foreignKey') || (_.has(self.tables[table][field], 'foreignKey') && !! self.tables[table][field].foreignKey.isPrimaryKey)))
              text[table] += spaces + spaces + spaces + "primaryKey: true";
            else return true
          }

To :

else if (attr === "primaryKey") {
             if (self.tables[table][field][attr] === true && self.tables[table][field].foreignKey.contype == 'u' )
              text[table] += spaces + spaces + spaces + "unique: '" + self.tables[table][field].foreignKey.constraint_name + "'";

             if (self.tables[table][field][attr] === true && (! _.has(self.tables[table][field], 'foreignKey') || (_.has(self.tables[table][field], 'foreignKey') && !! self.tables[table][field].foreignKey.isPrimaryKey)))
              text[table] += spaces + spaces + spaces + "primaryKey: true";
            else return true
          }

Regenerate models and works.