dolt icon indicating copy to clipboard operation
dolt copied to clipboard

JSON default column normalization issue causing merge conflict

Open druvv opened this issue 2 years ago • 2 comments

Customer ran into a schema conflict on a JSON column that defines a default value. The repro is still being investigated.

druvv avatar Sep 26 '22 18:09 druvv

The specific error message reported by the customer is:

ERROR 1105 (HY000): schema conflict found, merge aborted. Please alter schema to prevent schema conflicts before merging.
schema conflicts for table $table:
	different column definitions for our column $col and their column $col

This error is thrown when $col has changed in both branches with differring schema. The type of $col must not have been changed otherwise a new tag would have been generated. The factors that affect column equality are tag, type, primary key membership, column constraints, and the column's default value.

I focused on trying to produce a situation where the column's default value looks identical in the information schema, but is not equivalent in dolt merge.

The first thing I checked was to see if information schema normalized the json value when being printed. But that is not the case. I created a json column with the default of {"hi": 1} on one branch and {"hi": 1} (an extra space) on another branch. A conflict was thrown when merged, but the information schema also showed the extra space.

I also investigated how the column defaults are being pulled from postgres, but in the end couldn't find anything obviously wrong.

I am suspicious about some of the customer code that dumps the column default to a json file and the reads it back before running an alter statement. I would like to inspect the exact bytes of the default value on both branches.

druvv avatar Sep 26 '22 23:09 druvv

Investigating further, the customer's database clearly shows two different values in storage. On one branch the value is ("{\"free\": 1}") and on another the value is ('{"free": 1}').

We iterated on a couple different sql statements on the latest Dolt and version v0.41.5 (which is prior to a recent change in the area) and could not get the value in storage to equal ("{\"free\": 1}"). The string is formatted to ('{"free": 1}') in the latest version before being put into storage.

The fix for now, is to re-set the column default.

dolt sql <<SQL
ALTER TABLE $table_name ALTER COLUMN $col_name SET DEFAULT ('{"free": 1}');
SQL

If necessary, a filter-branch query could be useful to rewrite the column default value in storage across all commits in the history.

druvv avatar Oct 19 '22 20:10 druvv

I'm going to resolve this because it's a compatibnility with really old versions bug.

timsehn avatar Mar 03 '23 23:03 timsehn