microsoft / microsoft/Qcodes

Adding metadata dict more than one level deep creates invalid run

Open
#1,444 5 comments 0 reactions 0 assignees View on GitHub
bug new dataset
Dominant language
Python
Stars
459
Forks
359
Avg merge
3d 6h
Merged PRs (30d)
73

Description

```python
import qcodes as qc
from qcodes import ParamSpec, new_data_set, new_experiment
dataSet = new_data_set("sweep gate")
exp = new_experiment("majorana-qbuit", sample_name="flying brdige")
parameter_a = ParamSpec("a", "numeric")
parameter_b = ParamSpec("b", "numeric", key="value", number=1)
parameter_c = ParamSpec("c", "array")
dataSet = new_data_set("sweep gate", specs=[parameter_a,parameter_b,parameter_c], metadata={'a': {'b': 1}})
```
results in

```
Rolling back due to unhandled exception
Traceback (most recent call last):
File "c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py", line 819, in atomic
yield conn
File "c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py", line 781, in atomic_transaction
c = transaction(atomic_conn, sql, *args)
File "c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py", line 756, in transaction
c.execute(sql, args)
sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported type.

---------------------------------------------------------------------------
InterfaceError Traceback (most recent call last)
c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in atomic(conn)
818 conn.cursor().execute('BEGIN')
--> 819 yield conn
820 except Exception as e:

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in atomic_transaction(conn, sql, *args)
780 with atomic(conn) as atomic_conn:
--> 781 c = transaction(atomic_conn, sql, *args)
782 return c

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in transaction(conn, sql, *args)
755 if len(args) > 0:
--> 756 c.execute(sql, args)
757 else:

InterfaceError: Error binding parameter 0 - probably unsupported type.

The above exception was the direct cause of the following exception:

RuntimeError Traceback (most recent call last)
in
----> 1 dataSet = new_data_set("sweep gate", specs=[parameter_a,parameter_b,parameter_c], metadata={'a': {'b': 1}})
2 exp

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\data_set.py in new_data_set(name, exp_id, specs, values, metadata, conn)
1080 d = DataSet(path_to_db=None, run_id=None, conn=conn,
1081 name=name, specs=specs, values=values,
-> 1082 metadata=metadata, exp_id=exp_id)
1083
1084 return d

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\data_set.py in __init__(self, path_to_db, run_id, conn, exp_id, name, specs, values, metadata)
268 _, run_id, __ = create_run(self.conn, exp_id, name,
269 generate_guid(),
--> 270 specs, values, metadata)
271 # this is really the UUID (an ever increasing count in the db)
272 self._run_id = run_id

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in create_run(conn, exp_id, name, guid, parameters, values, metadata)
2297 parameters)
2298 if metadata:
-> 2299 add_meta_data(conn, run_id, metadata)
2300 _update_experiment_run_counter(conn, exp_id, run_counter)
2301 _create_run_table(conn, formatted_name, parameters, values)

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in add_meta_data(conn, row_id, metadata, table_name)
2394 """
2395 try:
-> 2396 insert_meta_data(conn, row_id, table_name, metadata)
2397 except sqlite3.OperationalError as e:
2398 # this means that the column already exists

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in insert_meta_data(conn, row_id, table_name, metadata)
2362 for key in metadata.keys():
2363 insert_column(conn, table_name, key)
-> 2364 update_meta_data(conn, row_id, table_name, metadata)
2365
2366

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in update_meta_data(conn, row_id, table_name, metadata)
2376 - metadata: the metadata to add
2377 """
-> 2378 update_where(conn, table_name, 'rowid', row_id, **metadata)
2379
2380

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in update_where(conn, table, where_column, where_value, **updates)
989 {where_column} = ?
990 """
--> 991 atomic_transaction(conn, query, *values, where_value)
992
993

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in atomic_transaction(conn, sql, *args)
779 """
780 with atomic(conn) as atomic_conn:
--> 781 c = transaction(atomic_conn, sql, *args)
782 return c
783

~\AppData\Local\Continuum\miniconda3\envs\qcodes\lib\contextlib.py in __exit__(self, type, value, traceback)
97 value = type()
98 try:
---> 99 self.gen.throw(type, value, traceback)
100 except StopIteration as exc:
101 # Suppress StopIteration *unless* it's the same exception that

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in atomic(conn)
821 conn.rollback()
822 log.exception("Rolling back due to unhandled exception")
--> 823 raise RuntimeError("Rolling back due to unhandled exception") from e
824 else:
825 if is_outmost:

RuntimeError: Rolling back due to unhandled exception

```
Subsequent runs then fail even without the metadata because 2 rows with the same run_id are created

```
dataSet = new_data_set("sweep gate", specs=[parameter_a,parameter_b,parameter_c])
```
fails with:
```
Rolling back due to unhandled exception
Traceback (most recent call last):
File "c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py", line 819, in atomic
yield conn
File "c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py", line 1964, in _insert_run
*parameters)
File "c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py", line 2168, in _add_parameters_to_layout_and_deps
run_id = one(transaction(conn, sql), 'run_id')
File "c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py", line 285, in one
raise RuntimeError("Expected only one row")
RuntimeError: Expected only one row

---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in atomic(conn)
818 conn.cursor().execute('BEGIN')
--> 819 yield conn
820 except Exception as e:

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in _insert_run(conn, exp_id, name, guid, parameters)
1963 _add_parameters_to_layout_and_deps(conn, formatted_name,
-> 1964 *parameters)
1965

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in _add_parameters_to_layout_and_deps(conn, formatted_name, *parameter)
2167 """
-> 2168 run_id = one(transaction(conn, sql), 'run_id')
2169 layout_args = []

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in one(curr, column)
284 if len(res) > 1:
--> 285 raise RuntimeError("Expected only one row")
286 elif len(res) == 0:

RuntimeError: Expected only one row

The above exception was the direct cause of the following exception:

RuntimeError Traceback (most recent call last)
in
----> 1 dataSet = new_data_set("sweep gate", specs=[parameter_a,parameter_b,parameter_c])

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\data_set.py in new_data_set(name, exp_id, specs, values, metadata, conn)
1080 d = DataSet(path_to_db=None, run_id=None, conn=conn,
1081 name=name, specs=specs, values=values,
-> 1082 metadata=metadata, exp_id=exp_id)
1083
1084 return d

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\data_set.py in __init__(self, path_to_db, run_id, conn, exp_id, name, specs, values, metadata)
268 _, run_id, __ = create_run(self.conn, exp_id, name,
269 generate_guid(),
--> 270 specs, values, metadata)
271 # this is really the UUID (an ever increasing count in the db)
272 self._run_id = run_id

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in create_run(conn, exp_id, name, guid, parameters, values, metadata)
2295 name,
2296 guid,
-> 2297 parameters)
2298 if metadata:
2299 add_meta_data(conn, run_id, metadata)

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in _insert_run(conn, exp_id, name, guid, parameters)
1986 time.time(),
1987 False,
-> 1988 desc_str)
1989 run_id = curr.lastrowid
1990 return run_counter, formatted_name, run_id

~\AppData\Local\Continuum\miniconda3\envs\qcodes\lib\contextlib.py in __exit__(self, type, value, traceback)
97 value = type()
98 try:
---> 99 self.gen.throw(type, value, traceback)
100 except StopIteration as exc:
101 # Suppress StopIteration *unless* it's the same exception that

c:\users\jenielse\source\repos\qcodes\qcodes\dataset\sqlite_base.py in atomic(conn)
821 conn.rollback()
822 log.exception("Rolling back due to unhandled exception")
--> 823 raise RuntimeError("Rolling back due to unhandled exception") from e
824 else:
825 if is_outmost:

RuntimeError: Rolling back due to unhandled exception

```

Contributor guide

Open the contributing guide

Research direction

Start with the metadata path in qcodes/dataset/sqlite_base.py, especially add_meta_data, insert_meta_data, update_meta_data, and the atomic transaction helpers; review how data_set.py calls create_run. Run the nested-metadata reproduction, then repeat the subsequent new_data_set call. Done means nested metadata does not create an invalid run and later runs succeed.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, sqlite
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.