start on proper database table definitions#75
Conversation
…forms checks on DB table defining class attributes of the Saveable classes
|
Hi Scott As we discussed this should be a RFC type PR and review, I have not make any comments on code what-so-ever, we can do that later. First I will add my thoughts on a couple of you questions above and then describe what I found during my experimentation.
Agree completely.
I've actually made that an exercise, as the DBML language that dbdiagram.io uses is very simple, it was relatively straight forward for translate the knowledge I was able to extract into a diagram. More on that below.
I would suggest breaking the last part off, because it can and it keep PR's smaller. As far as the questions for the reviewer, I will give quick answers here and go in more detail below.
Almost I think. Some things, mostly centered around the naming of id columns end up being very implicit and mostly contained in the code the that generates the DB schema. I think that information really should be contained in the classes, but that I also think there are ways to do that.
I think it does. Again there are a few things that are a little implicit, which I think we should consider making explicit, but other that that then yes.
Yeah, I noticed this. Now, I'm embarrassed to say that for this problem I only read the beginning of the message above and thought I had al the information I needed, so I missed the point towards the end where you describe that the two ids are really the same. Thus, the idea I propose for this is not right on, but still contains what I consider are some sensible points and it can be adapted. Details in the experimentation on the next comment... |
|
I did a bunch of experimentation with this, because I wanted to really test whether all the necessary information was there. This experimentation (and some extra stuff) is the #83 PR. I added a new tool
On the naming of id columns As you can see, quite a bit of the complexity in the tool actually centers around the naming of id columns and figuring out what the id column was named in another table, for the cases where you need to name them as foreign keys. As you can see, if is possible to define rules for this, that ends up with a reasonable result, but in my view it puts too much of the logic inside the schema extractor. So, instead of all this, how about just explicitely listing the id columns, their name and which columns = [
Column("measurement_id", ctype=int, attribute_name_="id", primary_key=True, foreign_key=("measurements", "id"))
Column("technique", ctype=str)
]Doing it this way, although we provide some information, which is redundant, the name and the reference would be completely explicit and the only thing the schema builder would have to do was to check if the reference is valid. Besides from that, it keeps the locality of the information very high, which is something I have begun thinking a lot about: How much other code do I need to know about to read this line, and how far aways is it? In the existing implementation, you would need to have a look at the rules in builder to figure what all the columns would become, while reading the column spec, while in what I propose, it would be right there. This is BTW not really unique or my idea, you often see this kind of Column spec in ORM and the like. The point is of course, that we would want to implement as little of that stuff as we can get away with, but it might be necessary to expand it a little.
We discussed the fact that we should now allow a table to define columns and not also change the components I skipped this one in schema builder. Basically, we end up in problems there, because the usual naming rules for id columns don't apply. I imagine that this table would have a multi column primary key (see below), like I did for the other linker tables, but we would need some way to specify the names. It could be a simple as extending the OwnedObjectList with an optional An interesting problem however is that I don't know if SQL allows you to form a two column primary key to foreign keys of the same column. If not, here we would need a separate throw away id column. multi column primary key So, SQL and as far as I can see, also sqlite, allows multi column primary keys. The rule for a tables primary key simply is that it has to be unique for every row. I think for linker tables that would always be the case, i.e. we would never have more than one link between the same two objects, so we might as well exploit that and avoid having to add a auto incrementing Multiple inheritance So, you mentioned the problems with the multiple inheritance classes. Since, as mentioned above, you can have multiple column primary keys, we could actually easily do real multiple inheritance in the DB schema. I made an example of this in the last commit of the PR. If you don't like it, I can just pop that off and you can merge the rest. However, in that feature I missed the last part of your comment where you mention that while the ECMS object, will link to two objects, each of those in term will actually have the same ID. So, I would propose a small change to my proposal. I still would suggest to make it possible to list two classes in the I hope all of this makes sense and is useful. I have one more comment about DB normalization, but I think it is a point that we have been over before and that you ruled down, so I don't think it is important right now. I will add that later this evening, these comments should be sufficient to start work with it. |
Metaprogramming proposed changed
|
You anticipated almost all of my suggestions in comments to #83 in your comment above :)
Hopefully then we'll get exactly the desired db generation while simplifying the code. Whether we simplify the knowledge required of an ixdat developer to write a new |
|
I think all of your comments about the route you intend to go with the implementation sounds good. Although I cannot completely wrap my head around all of them, since it has been a while since the initial review. I will have to review them as code when it is ready.
True. OTOH if we wanted to make it easier to do, without adding all the bits that make it serializable, we could re-introduce something like what you commented on, with a secret |

Hi @KennethNielsen ,
This is a start of proper table dfinitions. I've tried to explain the logic in comments. See if it makes sense!
This much, for example, works:
Where the first 6 are "inherited" form
Measurementand the last one is "inherited" fromECMeasurement.I've redone the table definition class attributes in data_series.py, measurements.py, techniques/ec.py, techniques/ms.py, and techniques/ecms.py.

This is the dbdiagram of the database that one can hopefully derive from if: https://dbdiagram.io/d/601bedcb80d742080a392b99, image attached.
I've tried to use the SQLite type names there. Note that in ixdat classes, columns are typed according to their python type, and it is up to the backend to figure out how to translate between available types.
Things left to do after this PR:
Saveable.as_dict()to build the full dictionary represenation (usingfull_columns()andfull_owned_object_lists()) and ensure all the owned objects are represented and in memorySaveable,Backend, andDBDirectoryBackendworking with the new column tablesQuestions for review of this request-for-comment PR:
ECMSCalibrationwhich inherits fromECCalibrationandMSCalibration. However, itsidis a foreign key that can only refer to one of ec_calibrations.id and ms_calibrations.id (even though both of those are foreign keys refering to calibrations.id). Ideally we'd have the same id appear in all thee tables ec_calibrations, ms_calibrations, and ecms_calibrations, and ecms_calibrations would only need the two columns id and L (working distance, the only attribute in an ECMSCalibration which isn't in an MSCalibration or ECCalibration). However, if the table-defining class attributes are also to be used to build the dictionary representations of objects, then everything needs to be there.Looking forward to your comments on this!