qcubed / orm

QCubed ORM Repository
MIT License
1 stars 7 forks source link

Multi-Field Join in QQuery #5

Open willypowwow opened 7 years ago

willypowwow commented 7 years ago

This isn't truly an issue, but there I've been unable to get a question answered out in the usual places. My company has acquired an application which runs on an older version of QCubed. It's a very robust application with many users and generally works very well. We currently have a problem that we cannot seem to solve with QQuery.

We have two tables that are related by two fields. A SQL join of these would look like this:

FROM appWork a INNER JOIN cfgTaskRestult c ON a.TaskId = c.TaskId AND a.StatusId = c.StatusId.

We include this in QQuery like this:

QQ::Equal(Appwork->TaskId, Appwork->TaskIdObject->CfgtaskstatusresulAsTaskID->TaskId QQ::Equal(Appwork->StatusId, Appwork->StatusIdObject->CfgtaskstatusresulAsStatusID->TaskId

Unfortunately, this creates two separate Joins and two table aliases, one joining on TaskId and one on StatusId. Is there any way around this?

Thanks.

spekary commented 7 years ago

I need your complete query, including conditions and clauses. QQuery builds the joins as it encounters the need for them. It might see a join in a condition, or a clause, or in a subquery or conditional join, etc.

Joins are generally done with Expand clauses. Late in v2 I added conditions to expand clauses, so look at the 2nd parameter of an Expand clauses to add the condition you seek, provided you have upgraded to somwhere close to the latest v2. Something like this:

$clause[] = QQ::Expand(QQN::AppWork()->CfgTaskResult, QQ::AndCondition(QQ::Equal(QQN::Appwork()->TaskId, QQN::Appwork()->TaskIdObject->CfgtaskstatusresulAsTaskID->TaskId),
QQ::Equal(QQN::Appwork()->StatusId, QQN::Appwork()->StatusIdObject->CfgtaskstatusresulAsStatusID->TaskId)));

Note that for this to work, you will need a foreign key from AppWork to CfgTaskResult through TaskId. If you can't do that, then your only hope is a custom SQL query.

willypowwow commented 6 years ago

The conditional Expand did the trick, in case anyone else is watching this. Sorry for the late reply.

spekary commented 6 years ago

Great! You might look at porting to the latest, version 4 of QCubed. But its great to hear the someone is using it well.

Also, for anyone listening, I have started a concerted effort to port QCubed to the Go language. I have made significant progress, but much more needs to be done (as in every open-source project). If your company is interested in moving your app forward, you might consider that as well.

vaibhav-kaushal commented 6 years ago

@spekary Why GoLang? What are the parameters you evaluated for the same?

The reason why I ask is: I wanted to do the same on Swift which is much more popular in terms of adoption because of well known reasons (iOS + Mac devs already use it and there are great frameworks being built around it already).

spekary commented 6 years ago

When I looked, Swift was Mac only, and did not have many 3rd party libaries that would be typical for PHP and web development. I like Go because of

  1. Large developer community
  2. Easy learning curve and some built-in structures and work-flow that make coding quick. Compile time is usually about a second after I make changes, so its easy to work with.
  3. Web services are a popular use for Golang. WebSockets are pretty easy, making multi-user live update possible.
  4. Built-in documentation system, that isn't all that powerful, but is functional enough and more importantly, easy to use, so it will get done.
  5. Strongly typed. Many errors get caught at compile time.
  6. Some tools developed at the core of Go for code generation, so generation is emerging as part of the ecosystem.
  7. The Jetbrains people created a nice IDE with source level debugging capabilities.
  8. Its compiled, and the runtime is very fast. You connect your web app direct to a tcp socket. Apache is not needed (though its possible to put Apache or something like it in front of the Go app if needed.)
  9. Garbage collection.
  10. Go App Services supports it in a low-cost mode.

That said, there are some limitations:

  1. Inheritance is difficult. Its possible, and I created a programming pattern to make virtual functions work, but this limitation makes true frameworks like QCubed a little awkward. Go only uses interfaces.
  2. Large frameworks are discouraged by the community. Go programmers like to use Go in microservices as the back end for mobile and web apps. The community frowns on large frameworks. I don't really care what the community thinks on this.
  3. No built-in serialization of objects, though there is library support for serializing objects. Currently I am just keeping formstate in memory. It isn't a big deal, I think a server can support about 1000 simultaneous users pretty easily this way. But if someone wants to distribute the app across multiple servers, then formstate will need to be serialized into a database. This is not too difficult, but I am going to wait until I am running a server that actually has that many users before I do the work.
  4. The Go developed template language is kind of limitted and not all that fast since the scripts are interpretted. I developed a template language and app that compiles the template into Go code, and allows you to switch into and out of Go code sort of like how PHP lets you. It is working fine.
  5. Go has a concept of exporting structures and functions, but not a permission system (like private, protected and public functions and objects). It also does not allow circular imports, where two namespaces use functions or structures from the other. This can create some frustration when architecting a project, as you have cross-purposes when you create a namespace. A single namespace is used for organizing code both logically and on disk, defining API interfaces, and organizing documentation. So, you cannot just create a namespace to provide some organization, as that also creates an API interface that cannot have circular references. I think this might be the biggest frustration I have with Go, 2nd only to the lack of built-in virtual function support.

What are your thoughts on Swift?

vaibhav-kaushal commented 6 years ago

Let's take this into another discussion.