The Forum for Discussion about The Third Manifesto and Related Matters

Please or Register to create posts and topics.

Almost (but not quite) an ANNOUNCE

Quote from tobega on September 12, 2021, 7:30 pm
Quote from Dave Voorhis on September 12, 2021, 4:47 pm
Quote from tobega on September 12, 2021, 8:01 am
Quote from Dave Voorhis on September 11, 2021, 8:23 pm
Quote from tobega on September 11, 2021, 6:46 pm
Dave, this looks pretty great!
Thanks!
...

One thing that would make it even better is named parameters in the QueryDefinition ...

Antc mentioned that too, and I agree that it would be good. At the moment, it's a very minimal skin around existing JDBC facilities. But as I mentioned in my reply to Antc, I could, I suppose, lightly wrap it with some text-replacement machinery, though I'm trying to use existing JDBC/Streams facilities wherever possible without altering or adding layers to them. But I can see the value. Must (continue to) think on this.

Great!

I also forgot the second part of the ask, to have a query builder instead of positional arguments when running the query.

MyTableQuery01.builder().min(6).max(12).query(database)
.forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database) .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

My concern is that approach implies run-time error checking and thus run-time failures. E.g., what if you write MyTableQuery01.builder().query(database) ?

Or, MyTableQuery01.builder().min(6).query(database) ?

Presumably, the compiler accepts it and it doesn't fail until runtime?

If the query is invoked as MyTableQuery01.query(database, 6, 12), the compiler obligates both parameters be supplied (and checks their type, of course.) It's also less verbose and it's just another Java method invocation like all the others.

I could maybe make it so it has to be something like MyTableQuery01.query(database, MyTableQuery01.min(6), MyTableQuery01.max(12)), but I'm not sure you'd be gaining over the  additional verbosity, unless you're already regularly doing that sort of thing with all/many of your Java methods.

Ah, that's a good point, of course. I suppose YMMV but in my experience it is more common to confuse which integer is which, rather than trying to supply a string instead of an integer.

There are various possible run-time mistakes that type checking won't catch, either way. It'll essentially trade one set for another.

Though in thinking on it, a bigger obstacle is the verbosity. I imagine invoking a query that regularly requires saying MyTableQuery01.builder().min(p).max(q).query(database) will annoy the user-developer enough to wrap it in something that makes invocations look like regular method invocations, e.g., MyTableQuery02.maxminQuery(database, p, q).

So might as well start with that.

I sympathise with the attempt to turn Java's parameters-are-positional-only method invocation syntax into something that supports parameter-named arguments, but that's a broader issue for Java in general. I'm not sure it's within the scope of Wrapd to fix Java in general, or even aspects of Java. Its goal is only to fix the usual Java-to-SQL-DBMS pain points, such as making query invocation easier by making query invocations into plain old Java method calls. That plain old Java method calls lack passing arguments by parameter name?

That's for Java to fix.

Although here we also need to supply all parameters. There are ways to do that in a typesafe way, by returning a new type for receiving every parameter, but that probably isn't worth the effort. So how bad is a runtime crash? If it happens because I supplied too few parameters, it will crash on the first test I try, with a clear error message, so really not a huge problem.

Indeed, but annoying enough in development to try to avoid it, I think. But the goal is really to make query invocations into conventional method calls.

What it could benefit from, though, is to make sure parameters can have sensible names, so that IDEs that show parameter names at call point (e.g., IntelliJ IDEA) can help with query methods too.

I'm the forum administrator and lead developer of Rel. Email me at dave@armchair.mb.ca with the Subject 'TTM Forum'. Download Rel from https://reldb.org
Quote from Dave Voorhis on September 12, 2021, 9:01 pm
Quote from tobega on September 12, 2021, 7:30 pm
Quote from Dave Voorhis on September 12, 2021, 4:47 pm
Quote from tobega on September 12, 2021, 8:01 am
Quote from Dave Voorhis on September 11, 2021, 8:23 pm
Quote from tobega on September 11, 2021, 6:46 pm
Dave, this looks pretty great!
Thanks!
...

One thing that would make it even better is named parameters in the QueryDefinition ...

Antc mentioned that too, and I agree that it would be good. At the moment, it's a very minimal skin around existing JDBC facilities. But as I mentioned in my reply to Antc, I could, I suppose, lightly wrap it with some text-replacement machinery, though I'm trying to use existing JDBC/Streams facilities wherever possible without altering or adding layers to them. But I can see the value. Must (continue to) think on this.

Great!

I also forgot the second part of the ask, to have a query builder instead of positional arguments when running the query.

MyTableQuery01.builder().min(6).max(12).query(database)
.forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database) .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

My concern is that approach implies run-time error checking and thus run-time failures. E.g., what if you write MyTableQuery01.builder().query(database) ?

Or, MyTableQuery01.builder().min(6).query(database) ?

Presumably, the compiler accepts it and it doesn't fail until runtime?

If the query is invoked as MyTableQuery01.query(database, 6, 12), the compiler obligates both parameters be supplied (and checks their type, of course.) It's also less verbose and it's just another Java method invocation like all the others.

I could maybe make it so it has to be something like MyTableQuery01.query(database, MyTableQuery01.min(6), MyTableQuery01.max(12)), but I'm not sure you'd be gaining over the  additional verbosity, unless you're already regularly doing that sort of thing with all/many of your Java methods.

Ah, that's a good point, of course. I suppose YMMV but in my experience it is more common to confuse which integer is which, rather than trying to supply a string instead of an integer.

There are various possible run-time mistakes that type checking won't catch, either way. It'll essentially trade one set for another.

Though in thinking on it, a bigger obstacle is the verbosity. I imagine invoking a query that regularly requires saying MyTableQuery01.builder().min(p).max(q).query(database) will annoy the user-developer enough to wrap it in something that makes invocations look like regular method invocations, e.g., MyTableQuery02.maxminQuery(database, p, q).

So might as well start with that.

I sympathise with the attempt to turn Java's parameters-are-positional-only method invocation syntax into something that supports parameter-named arguments, but that's a broader issue for Java in general. I'm not sure it's within the scope of Wrapd to fix Java in general, or even aspects of Java. Its goal is only to fix the usual Java-to-SQL-DBMS pain points, such as making query invocation easier by making query invocations into plain old Java method calls. That plain old Java method calls lack passing arguments by parameter name?

That's for Java to fix.

Although here we also need to supply all parameters. There are ways to do that in a typesafe way, by returning a new type for receiving every parameter, but that probably isn't worth the effort. So how bad is a runtime crash? If it happens because I supplied too few parameters, it will crash on the first test I try, with a clear error message, so really not a huge problem.

Indeed, but annoying enough in development to try to avoid it, I think. But the goal is really to make query invocations into conventional method calls.

What it could benefit from, though, is to make sure parameters can have sensible names, so that IDEs that show parameter names at call point (e.g., IntelliJ IDEA) can help with query methods too.

Makes sense

Quote from tobega on September 12, 2021, 8:01 am
Quote from Dave Voorhis on September 11, 2021, 8:23 pm
Quote from tobega on September 11, 2021, 6:46 pm
Dave, this looks pretty great!
Thanks!
...

One thing that would make it even better is named parameters in the QueryDefinition ...

Antc mentioned that too, and I agree that it would be good. At the moment, it's a very minimal skin around existing JDBC facilities. But as I mentioned in my reply to Antc, I could, I suppose, lightly wrap it with some text-replacement machinery, though I'm trying to use existing JDBC/Streams facilities wherever possible without altering or adding layers to them. But I can see the value. Must (continue to) think on this.

Great!

I also forgot the second part of the ask, to have a query builder instead of positional arguments when running the query.

MyTableQuery01.builder().min(6).max(12).query(database)
.forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database) .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

Your 'builder' notation is a violation of a fundamental D language rule : that update operators return no values.  Your .min() and .max() things are clearly update operators, yet they still return some value (a pointer to the updated object).

Quote from Erwin on September 14, 2021, 5:56 pm
Quote from tobega on September 12, 2021, 8:01 am
Quote from Dave Voorhis on September 11, 2021, 8:23 pm
Quote from tobega on September 11, 2021, 6:46 pm
Dave, this looks pretty great!
Thanks!
...

One thing that would make it even better is named parameters in the QueryDefinition ...

Antc mentioned that too, and I agree that it would be good. At the moment, it's a very minimal skin around existing JDBC facilities. But as I mentioned in my reply to Antc, I could, I suppose, lightly wrap it with some text-replacement machinery, though I'm trying to use existing JDBC/Streams facilities wherever possible without altering or adding layers to them. But I can see the value. Must (continue to) think on this.

Great!

I also forgot the second part of the ask, to have a query builder instead of positional arguments when running the query.

MyTableQuery01.builder().min(6).max(12).query(database)
.forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database) .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

Your 'builder' notation is a violation of a fundamental D language rule : that update operators return no values.  Your .min() and .max() things are clearly update operators, yet they still return some value (a pointer to the updated object).

No, unless I've misunderstood the construct, in D terms min(...) selects the 'min' argument, max(...) selects the 'max' argument, and query(database) runs the query -- which is parametric, with 'max' and 'min' parameters, against the database specified by 'database'. There are no updates in the D sense.

But what I'm working on here isn't a D anyway. It's an alternative to heavyweight ORMs and awkward JDBC, which makes SQL easier to integrate into Java. It's a, uh, NoD product.

I'm the forum administrator and lead developer of Rel. Email me at dave@armchair.mb.ca with the Subject 'TTM Forum'. Download Rel from https://reldb.org
Quote from Dave Voorhis on September 12, 2021, 9:01 pm
Quote from tobega on September 12, 2021, 7:30 pm
Quote from Dave Voorhis on September 12, 2021, 4:47 pm
Quote from tobega on September 12, 2021, 8:01 am
Quote from Dave Voorhis on September 11, 2021, 8:23 pm
Quote from tobega on September 11, 2021, 6:46 pm
Dave, this looks pretty great!
Thanks!
...

One thing that would make it even better is named parameters in the QueryDefinition ...

Antc mentioned that too, and I agree that it would be good. At the moment, it's a very minimal skin around existing JDBC facilities. But as I mentioned in my reply to Antc, I could, I suppose, lightly wrap it with some text-replacement machinery, though I'm trying to use existing JDBC/Streams facilities wherever possible without altering or adding layers to them. But I can see the value. Must (continue to) think on this.

Great!

I also forgot the second part of the ask, to have a query builder instead of positional arguments when running the query.

MyTableQuery01.builder().min(6).max(12).query(database)
.forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database) .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

My concern is that approach implies run-time error checking and thus run-time failures. E.g., what if you write MyTableQuery01.builder().query(database) ?

Or, MyTableQuery01.builder().min(6).query(database) ?

Presumably, the compiler accepts it and it doesn't fail until runtime?

If the query is invoked as MyTableQuery01.query(database, 6, 12), the compiler obligates both parameters be supplied (and checks their type, of course.) It's also less verbose and it's just another Java method invocation like all the others.

I could maybe make it so it has to be something like MyTableQuery01.query(database, MyTableQuery01.min(6), MyTableQuery01.max(12)), but I'm not sure you'd be gaining over the  additional verbosity, unless you're already regularly doing that sort of thing with all/many of your Java methods.

Ah, that's a good point, of course. I suppose YMMV but in my experience it is more common to confuse which integer is which, rather than trying to supply a string instead of an integer.

There are various possible run-time mistakes that type checking won't catch, either way. It'll essentially trade one set for another.

Though in thinking on it, a bigger obstacle is the verbosity. I imagine invoking a query that regularly requires saying MyTableQuery01.builder().min(p).max(q).query(database) will annoy the user-developer enough to wrap it in something that makes invocations look like regular method invocations, e.g., MyTableQuery02.maxminQuery(database, p, q).

So might as well start with that.

I sympathise with the attempt to turn Java's parameters-are-positional-only method invocation syntax into something that supports parameter-named arguments, but that's a broader issue for Java in general. I'm not sure it's within the scope of Wrapd to fix Java in general, or even aspects of Java. Its goal is only to fix the usual Java-to-SQL-DBMS pain points, such as making query invocation easier by making query invocations into plain old Java method calls. That plain old Java method calls lack passing arguments by parameter name?

That's for Java to fix.

Although here we also need to supply all parameters. There are ways to do that in a typesafe way, by returning a new type for receiving every parameter, but that probably isn't worth the effort. So how bad is a runtime crash? If it happens because I supplied too few parameters, it will crash on the first test I try, with a clear error message, so really not a huge problem.

Indeed, but annoying enough in development to try to avoid it, I think. But the goal is really to make query invocations into conventional method calls.

What it could benefit from, though, is to make sure parameters can have sensible names, so that IDEs that show parameter names at call point (e.g., IntelliJ IDEA) can help with query methods too.

No matter how you toss or turn it, java's approach to DML is still the good old "data sublanguage" approach.  If you want the compiler to capture DML errors, then the compiler must parse and try and understand the DML.  DML is not part of the Java language spec, so no "bare" Java compiler will ever support that.  Since there is no plug to "plug anything/whatever into" the Java compiler, the only remaining option is "adding precompilers to the mix".  DJ, much analogous to SQLJ.  To my mind, that's the full complete and final analysis of what the problem is.  And why TTM was ever written in the first place.

If you want the compiler to capture errors like "this relvar does not exist", then the compiler must know of the schema.  And if the compile succeeds, measures must still be included in the binary that is produced by the compiler to ascertain that the schema that the program is running against at run-time is indeed the same as (or at least "compatible with", for some meaning of "compatible") the one that the compiler got to see when it produced the binary.  For seasoned DB2 Z/OS users, I'm referring to the "query timestamp mismatch" error.  You can make the compiler "catch more errors" but the price to pay is a higher risk of "this binary was not compiled against this schema" runtime errors.

Quote from Dave Voorhis on September 14, 2021, 6:14 pm
Quote from Erwin on September 14, 2021, 5:56 pm
Quote from tobega on September 12, 2021, 8:01 am
Quote from Dave Voorhis on September 11, 2021, 8:23 pm
Quote from tobega on September 11, 2021, 6:46 pm
Dave, this looks pretty great!
Thanks!
...

One thing that would make it even better is named parameters in the QueryDefinition ...

Antc mentioned that too, and I agree that it would be good. At the moment, it's a very minimal skin around existing JDBC facilities. But as I mentioned in my reply to Antc, I could, I suppose, lightly wrap it with some text-replacement machinery, though I'm trying to use existing JDBC/Streams facilities wherever possible without altering or adding layers to them. But I can see the value. Must (continue to) think on this.

Great!

I also forgot the second part of the ask, to have a query builder instead of positional arguments when running the query.

MyTableQuery01.builder().min(6).max(12).query(database)
.forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database) .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

Your 'builder' notation is a violation of a fundamental D language rule : that update operators return no values.  Your .min() and .max() things are clearly update operators, yet they still return some value (a pointer to the updated object).

No, unless I've misunderstood the construct, in D terms min(...) selects the 'min' argument, max(...) selects the 'max' argument, and query(database) runs the query -- which is parametric, with 'max' and 'min' parameters, against the database specified by 'database'. There are no updates in the D sense.

But what I'm working on here isn't a D anyway. It's an alternative to heavyweight ORMs and awkward JDBC, which makes SQL easier to integrate into Java. It's a, uh, NoD product.

It's clearly intended to make the 'builded' thing remember the value for the 'min' parameter (think 'setMin') and remember the value for the 'max' parameter (think 'setMax') so that the .query() method can actually run.  I'm probably looking at the provided example more from the traditional Java way and wondering "What can Java do with this" while you are looking more from, eurhm, well, some other angle but if you're real about "trying to make it work in Java" you might ponder the possibility that my angle is the better one ...

Since it crossed my mind, you might have been thinking of the 'min()' method as returning a "query with the min parameter set" (and hence not "changing state" in anything at all in the sense that I was thinking of) and ditto for the 'max()' method which then begs the question of "what type is a query with both parameters set", which then begs the question of whether the lattice model of TTM IM does not apply here in some way (for any meaning of 'some' - but at the very least that 'some meaning' should make it possible for the system to detect and ascertain that the .query() method can only be invoked for queries that have set both - and then 'both' translates to 'all parameters needed' for the more general case of parametric queries).

Quote from Erwin on September 14, 2021, 6:40 pm
Quote from Dave Voorhis on September 12, 2021, 9:01 pm
Quote from tobega on September 12, 2021, 7:30 pm
Quote from Dave Voorhis on September 12, 2021, 4:47 pm
Quote from tobega on September 12, 2021, 8:01 am
Quote from Dave Voorhis on September 11, 2021, 8:23 pm
Quote from tobega on September 11, 2021, 6:46 pm
Dave, this looks pretty great!
Thanks!
...

One thing that would make it even better is named parameters in the QueryDefinition ...

Antc mentioned that too, and I agree that it would be good. At the moment, it's a very minimal skin around existing JDBC facilities. But as I mentioned in my reply to Antc, I could, I suppose, lightly wrap it with some text-replacement machinery, though I'm trying to use existing JDBC/Streams facilities wherever possible without altering or adding layers to them. But I can see the value. Must (continue to) think on this.

Great!

I also forgot the second part of the ask, to have a query builder instead of positional arguments when running the query.

MyTableQuery01.builder().min(6).max(12).query(database)
.forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database) .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

My concern is that approach implies run-time error checking and thus run-time failures. E.g., what if you write MyTableQuery01.builder().query(database) ?

Or, MyTableQuery01.builder().min(6).query(database) ?

Presumably, the compiler accepts it and it doesn't fail until runtime?

If the query is invoked as MyTableQuery01.query(database, 6, 12), the compiler obligates both parameters be supplied (and checks their type, of course.) It's also less verbose and it's just another Java method invocation like all the others.

I could maybe make it so it has to be something like MyTableQuery01.query(database, MyTableQuery01.min(6), MyTableQuery01.max(12)), but I'm not sure you'd be gaining over the  additional verbosity, unless you're already regularly doing that sort of thing with all/many of your Java methods.

Ah, that's a good point, of course. I suppose YMMV but in my experience it is more common to confuse which integer is which, rather than trying to supply a string instead of an integer.

There are various possible run-time mistakes that type checking won't catch, either way. It'll essentially trade one set for another.

Though in thinking on it, a bigger obstacle is the verbosity. I imagine invoking a query that regularly requires saying MyTableQuery01.builder().min(p).max(q).query(database) will annoy the user-developer enough to wrap it in something that makes invocations look like regular method invocations, e.g., MyTableQuery02.maxminQuery(database, p, q).

So might as well start with that.

I sympathise with the attempt to turn Java's parameters-are-positional-only method invocation syntax into something that supports parameter-named arguments, but that's a broader issue for Java in general. I'm not sure it's within the scope of Wrapd to fix Java in general, or even aspects of Java. Its goal is only to fix the usual Java-to-SQL-DBMS pain points, such as making query invocation easier by making query invocations into plain old Java method calls. That plain old Java method calls lack passing arguments by parameter name?

That's for Java to fix.

Although here we also need to supply all parameters. There are ways to do that in a typesafe way, by returning a new type for receiving every parameter, but that probably isn't worth the effort. So how bad is a runtime crash? If it happens because I supplied too few parameters, it will crash on the first test I try, with a clear error message, so really not a huge problem.

Indeed, but annoying enough in development to try to avoid it, I think. But the goal is really to make query invocations into conventional method calls.

What it could benefit from, though, is to make sure parameters can have sensible names, so that IDEs that show parameter names at call point (e.g., IntelliJ IDEA) can help with query methods too.

No matter how you toss or turn it, java's approach to DML is still the good old "data sublanguage" approach.

Yes, exactly.

But if you're using Java and SQL -- which is a pretty sizable and mostly unavoidable proportion of the IT world -- you have some pretty awful choices for using one with the other. On one end of the spectrum, you have ORMs like Hibernate, which hide you from SQL and SQL from you, but which are hulking, complicated, often surprisingly slow, full of quirks and gotchas, and despite hiding SQL re-create it in the form of HQL (Hibernate Query Language) which has all the problems of SQL without being SQL.

Ugh.

At the other end of the scale is JDBC, the lowest-level Java SQL API. That means assembling queries out of strings -- or strings and prepared statements -- sending them to the DBMS, and getting back record sets that must be awkwardly iterated. No Java Streams, no type safety, multitudinous opportunity for blunders and SQL injection and run-time errors.

Ugh.

In between are various attempts at reaching an acceptable compromise between the completely-sheltered behemoth that is Hibernate (and its ilk) on one end, vs the completely-exposed cutting edge that is JDBC on the other.

This thread introduced mine, called Wrapd. (https://wrapd.org)

It takes a somewhat different approach:

  1. All queries are predefined in what are effectively a combination of unit test and code generator. They are run to verify query correctness, and they simultaneously generate the Java code to encapsulate their result sets.
  2. Each collection of predefined queries is used to generate a database abstraction layer, where each query is mapped to a conventional Java method call that invokes the query and returns its result. If the query is parametric, the method call has corresponding parameters which are type-checked.
  3. The result of SELECT queries (and recordset-returning stored procedure invocations) can be used with Java Streams, using attributes that are natively available. I.e., the value of attribute x in row row is obtained via row.x and type-checked at compile-time, not row.getValue("x") and only type-checked at run-time.

If you want the compiler to capture DML errors, then the compiler must parse and try and understand the DML.  DML is not part of the Java language spec, so no "bare" Java compiler will ever support that.  Since there is no plug to "plug anything/whatever into" the Java compiler, the only remaining option is "adding precompilers to the mix".  DJ, much analogous to SQLJ.  To my mind, that's the full complete and final analysis of what the problem is.  And why TTM was ever written in the first place.

If you want the compiler to capture errors like "this relvar does not exist", then the compiler must know of the schema.

Exactly. There are precompilers in the mix, though they're part of the Wrapd library and invoked with conventional Java calls, rather than being standalone compilers.

Not only does Wrapd use that facility to generate code from the schema, it provides controlled schema migration in the Java code (if desired), so schema migration and Java code generation (corresponding to the migrated schema) can be safely integrated.

And if the compile succeeds, measures must still be included in the binary that is produced by the compiler to ascertain that the schema that the program is running against at run-time is indeed the same as (or at least "compatible with", for some meaning of "compatible") the one that the compiler got to see when it produced the binary.

Exactly. The same facilities that are used to generate Java code from queries at development time can be run to validate Java code against queries at run-time.

For seasoned DB2 Z/OS users, I'm referring to the "query timestamp mismatch" error.  You can make the compiler "catch more errors" but the price to pay is a higher risk of "this binary was not compiled against this schema" runtime errors.

Yes. I'm working on facilities to deal with that in a conventional Java/SQL development environment.

I'm the forum administrator and lead developer of Rel. Email me at dave@armchair.mb.ca with the Subject 'TTM Forum'. Download Rel from https://reldb.org
Quote from Erwin on September 14, 2021, 7:15 pm
Quote from Dave Voorhis on September 14, 2021, 6:14 pm
Quote from Erwin on September 14, 2021, 5:56 pm
Quote from tobega on September 12, 2021, 8:01 am
Quote from Dave Voorhis on September 11, 2021, 8:23 pm
Quote from tobega on September 11, 2021, 6:46 pm
Dave, this looks pretty great!
Thanks!
...

One thing that would make it even better is named parameters in the QueryDefinition ...

Antc mentioned that too, and I agree that it would be good. At the moment, it's a very minimal skin around existing JDBC facilities. But as I mentioned in my reply to Antc, I could, I suppose, lightly wrap it with some text-replacement machinery, though I'm trying to use existing JDBC/Streams facilities wherever possible without altering or adding layers to them. But I can see the value. Must (continue to) think on this.

Great!

I also forgot the second part of the ask, to have a query builder instead of positional arguments when running the query.

MyTableQuery01.builder().min(6).max(12).query(database)
.forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database) .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

Your 'builder' notation is a violation of a fundamental D language rule : that update operators return no values.  Your .min() and .max() things are clearly update operators, yet they still return some value (a pointer to the updated object).

No, unless I've misunderstood the construct, in D terms min(...) selects the 'min' argument, max(...) selects the 'max' argument, and query(database) runs the query -- which is parametric, with 'max' and 'min' parameters, against the database specified by 'database'. There are no updates in the D sense.

But what I'm working on here isn't a D anyway. It's an alternative to heavyweight ORMs and awkward JDBC, which makes SQL easier to integrate into Java. It's a, uh, NoD product.

It's clearly intended to make the 'builded' thing remember the value for the 'min' parameter (think 'setMin') and remember the value for the 'max' parameter (think 'setMax') so that the .query() method can actually run.  I'm probably looking at the provided example more from the traditional Java way and wondering "What can Java do with this" while you are looking more from, eurhm, well, some other angle but if you're real about "trying to make it work in Java" you might ponder the possibility that my angle is the better one ...

Since it crossed my mind, you might have been thinking of the 'min()' method as returning a "query with the min parameter set" (and hence not "changing state" in anything at all in the sense that I was thinking of) and ditto for the 'max()' method which then begs the question of "what type is a query with both parameters set", which then begs the question of whether the lattice model of TTM IM does not apply here in some way (for any meaning of 'some' - but at the very least that 'some meaning' should make it possible for the system to detect and ascertain that the .query() method can only be invoked for queries that have set both - and then 'both' translates to 'all parameters needed' for the more general case of parametric queries).

I've essentially rejected the build()... syntax for query invocations, so it's moot.

I appreciate where @tobega was going with it -- turning a bit of Java from its current passing parameters by position (only) into passing parameters by name -- but in Wrapd, predefined queries (ideally all of them are predefined) are invoked with conventional Java method calls.

That means passing parameters by position -- only -- until Java itself gains passing parameters by name.

At least I should be able to provide the means sensibly name parameters on the query invocation methods, so IDEs that show you the parameter names as you're writing invocations (e.g., IntelliJ IDEA) can show them.

I'm the forum administrator and lead developer of Rel. Email me at dave@armchair.mb.ca with the Subject 'TTM Forum'. Download Rel from https://reldb.org
Quote from Dave Voorhis on September 14, 2021, 6:14 pm
Quote from Erwin on September 14, 2021, 5:56 pm
Quote from tobega on September 12, 2021, 8:01 am
Quote from Dave Voorhis on September 11, 2021, 8:23 pm
Quote from tobega on September 11, 2021, 6:46 pm
Dave, this looks pretty great!
Thanks!
...

One thing that would make it even better is named parameters in the QueryDefinition ...

Antc mentioned that too, and I agree that it would be good. At the moment, it's a very minimal skin around existing JDBC facilities. But as I mentioned in my reply to Antc, I could, I suppose, lightly wrap it with some text-replacement machinery, though I'm trying to use existing JDBC/Streams facilities wherever possible without altering or adding layers to them. But I can see the value. Must (continue to) think on this.

Great!

I also forgot the second part of the ask, to have a query builder instead of positional arguments when running the query.

MyTableQuery01.builder().min(6).max(12).query(database)
.forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database) .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

Your 'builder' notation is a violation of a fundamental D language rule : that update operators return no values.  Your .min() and .max() things are clearly update operators, yet they still return some value (a pointer to the updated object).

No, unless I've misunderstood the construct, in D terms min(...) selects the 'min' argument, max(...) selects the 'max' argument, and query(database) runs the query -- which is parametric, with 'max' and 'min' parameters, against the database specified by 'database'. There are no updates in the D sense.

But what I'm working on here isn't a D anyway. It's an alternative to heavyweight ORMs and awkward JDBC, which makes SQL easier to integrate into Java. It's a, uh, NoD product.

 

Quote from Dave Voorhis on September 14, 2021, 6:14 pm
Quote from Erwin on September 14, 2021, 5:56 pm
Quote from tobega on September 12, 2021, 8:01 am
Quote from Dave Voorhis on September 11, 2021, 8:23 pm
Quote from tobega on September 11, 2021, 6:46 pm
Dave, this looks pretty great!
Thanks!
...

One thing that would make it even better is named parameters in the QueryDefinition ...

Antc mentioned that too, and I agree that it would be good. At the moment, it's a very minimal skin around existing JDBC facilities. But as I mentioned in my reply to Antc, I could, I suppose, lightly wrap it with some text-replacement machinery, though I'm trying to use existing JDBC/Streams facilities wherever possible without altering or adding layers to them. But I can see the value. Must (continue to) think on this.

Great!

I also forgot the second part of the ask, to have a query builder instead of positional arguments when running the query.

MyTableQuery01.builder().min(6).max(12).query(database)
.forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database) .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

Your 'builder' notation is a violation of a fundamental D language rule : that update operators return no values.  Your .min() and .max() things are clearly update operators, yet they still return some value (a pointer to the updated object).

No, unless I've misunderstood the construct, in D terms min(...) selects the 'min' argument, max(...) selects the 'max' argument, and query(database) runs the query -- which is parametric, with 'max' and 'min' parameters, against the database specified by 'database'. There are no updates in the D sense.

But what I'm working on here isn't a D anyway. It's an alternative to heavyweight ORMs and awkward JDBC, which makes SQL easier to integrate into Java. It's a, uh, NoD product.

The formulation of your response does not fly.  "In D terms", .min() cannot possibly "select the 'min' argument" because if it did, the return value would [have to] be the same type as [that of] "the 'min' argument" and then the .max() would more than just presumably not apply.

Quote from Erwin on September 14, 2021, 7:44 pm
Quote from Dave Voorhis on September 14, 2021, 6:14 pm
Quote from Erwin on September 14, 2021, 5:56 pm
Quote from tobega on September 12, 2021, 8:01 am
Quote from Dave Voorhis on September 11, 2021, 8:23 pm
Quote from tobega on September 11, 2021, 6:46 pm
Dave, this looks pretty great!
Thanks!
...

One thing that would make it even better is named parameters in the QueryDefinition ...

Antc mentioned that too, and I agree that it would be good. At the moment, it's a very minimal skin around existing JDBC facilities. But as I mentioned in my reply to Antc, I could, I suppose, lightly wrap it with some text-replacement machinery, though I'm trying to use existing JDBC/Streams facilities wherever possible without altering or adding layers to them. But I can see the value. Must (continue to) think on this.

Great!

I also forgot the second part of the ask, to have a query builder instead of positional arguments when running the query.

MyTableQuery01.builder().min(6).max(12).query(database)
.forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database) .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

Your 'builder' notation is a violation of a fundamental D language rule : that update operators return no values.  Your .min() and .max() things are clearly update operators, yet they still return some value (a pointer to the updated object).

No, unless I've misunderstood the construct, in D terms min(...) selects the 'min' argument, max(...) selects the 'max' argument, and query(database) runs the query -- which is parametric, with 'max' and 'min' parameters, against the database specified by 'database'. There are no updates in the D sense.

But what I'm working on here isn't a D anyway. It's an alternative to heavyweight ORMs and awkward JDBC, which makes SQL easier to integrate into Java. It's a, uh, NoD product.

 

Quote from Dave Voorhis on September 14, 2021, 6:14 pm
Quote from Erwin on September 14, 2021, 5:56 pm
Quote from tobega on September 12, 2021, 8:01 am
Quote from Dave Voorhis on September 11, 2021, 8:23 pm
Quote from tobega on September 11, 2021, 6:46 pm
Dave, this looks pretty great!
Thanks!
...

One thing that would make it even better is named parameters in the QueryDefinition ...

Antc mentioned that too, and I agree that it would be good. At the moment, it's a very minimal skin around existing JDBC facilities. But as I mentioned in my reply to Antc, I could, I suppose, lightly wrap it with some text-replacement machinery, though I'm trying to use existing JDBC/Streams facilities wherever possible without altering or adding layers to them. But I can see the value. Must (continue to) think on this.

Great!

I also forgot the second part of the ask, to have a query builder instead of positional arguments when running the query.

MyTableQuery01.builder().min(6).max(12).query(database)
.forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database) .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));
MyTableQuery01.builder().min(6).max(12).query(database)
              .forEach(tuple -> System.out.println("x = " + tuple.x + ", y = " + tuple.y));

 

Your 'builder' notation is a violation of a fundamental D language rule : that update operators return no values.  Your .min() and .max() things are clearly update operators, yet they still return some value (a pointer to the updated object).

No, unless I've misunderstood the construct, in D terms min(...) selects the 'min' argument, max(...) selects the 'max' argument, and query(database) runs the query -- which is parametric, with 'max' and 'min' parameters, against the database specified by 'database'. There are no updates in the D sense.

But what I'm working on here isn't a D anyway. It's an alternative to heavyweight ORMs and awkward JDBC, which makes SQL easier to integrate into Java. It's a, uh, NoD product.

The formulation of your response does not fly.  "In D terms", .min() cannot possibly "select the 'min' argument" because if it did, the return value would [have to] be the same as [that of] "the 'min' argument" and then the .max() would more than just presumably not apply.

It just means min(...) "selects" the 'Min' parameter value and max(...) "selects" the 'Max' parameter value. It doesn't update anything. It's not an update query, there is no visible state change (other than constructing the query invocation in Java, I guess.)

I was attempting an analogy that appears to have fallen flat. But it doesn't matter, because the MyQuery.builder().max(12).min(6).query(database) syntax will not be used.

Instead, it will be MyQuery.query(database, 6, 12), or similar. I.e., a conventional Java method call, which it is.

I'm the forum administrator and lead developer of Rel. Email me at dave@armchair.mb.ca with the Subject 'TTM Forum'. Download Rel from https://reldb.org