How to handle jOOQ depreciation warning on procedure that returns a trigger? - postgresql

I use the following stored procedure to maintain the edit time on a few tables via triggers on those tables:
CREATE OR REPLACE FUNCTION maintain_edit_time()
RETURNS TRIGGER AS $t_edit_time$
BEGIN
NEW.edit_timestamp = NOW();
RETURN NEW;
END;
$t_edit_time$ LANGUAGE plpgsql;
When generating jOOQ objects for the database in question, I get the following generated code:
/**
* #deprecated Unknown data type. Please define an explicit {#link org.jooq.Binding} to specify how this type should be handled. Deprecation can be turned off using <deprecationOnUnknownTypes/> in your code generator configuration.
*/
#java.lang.Deprecated
public static Object maintainEditTime(Configuration configuration) {
MaintainEditTime f = new MaintainEditTime();
f.execute(configuration);
return f.getReturnValue();
}
/**
* #deprecated Unknown data type. Please define an explicit {#link org.jooq.Binding} to specify how this type should be handled. Deprecation can be turned off using <deprecationOnUnknownTypes/> in your code generator configuration.
*/
#java.lang.Deprecated
public static Field<Object> maintainEditTime() {
MaintainEditTime f = new MaintainEditTime();
return f.asField();
}
I assume this is because I do not have a jOOQ binding between TRIGGER and a Java object. However, I do not have a clue what I would define this binding as, nor do I have any need for a binding to exist.
Left alone, though, this generates a compile warning. What's the cleanest, easiest way to resolve this?
Options seem to include turning off deprecation, using ignoreProcedureReturnValues, or creating a binding. Ideally, I'd like to simply not generate a Java object for this procedure, but I could not find a way to do that.
Using ignoreProcedureReturnValues globally effects the project just because of this, which is fine for now, I don't have other procedures at all, much less others with a return value. But, I hate to limit future use. Also, I'm unclear one what the comment "This feature is deprecated as of jOOQ 3.6.0 and will be removed again in jOOQ 4.0." means on the jOOQ site under this flag. Is the flag going away, or is support for stored procedure return types going away? A brief dig through the jOOQ github issues didn't yield me an answer.
Tempted to simply turn off deprecation. This also seems like a global and not beneficial change, but it would serve the purpose.
If I created a binding, I have no idea what it would do, or how to define it since TRIGGER really isn't a sensible thing to bind a Java object to. I assume I'd specify as TRIGGER in the forcedType element, but then the Java binding seems like a waste of time at best and misleading at worst.

You've already found the perfect solution, which you documented in your own answer. I'll answer your various other questions here, for completeness' sake
Using ignoreProcedureReturnValues globally effects the project just because of this, which is fine for now, I don't have other procedures at all, much less others with a return value. But, I hate to limit future use. Also, I'm unclear one what the comment "This feature is deprecated as of jOOQ 3.6.0 and will be removed again in jOOQ 4.0." means on the jOOQ site under this flag. Is the flag going away, or is support for stored procedure return types going away? A brief dig through the jOOQ github issues didn't yield me an answer.
That flag has been introduced because of a backwards incompatible change in the code generator that affected only SQL Server: https://github.com/jOOQ/jOOQ/issues/4106
In SQL Server, procedures always return an INT value, just like functions. This change allowed for fetching this INT value using jOOQ generated code. In some cases, it was desireable to not have this feature enabled when upgrading from jOOQ 3.5 to 3.6. Going forward, we'll always generate this INT return type on SQL Server stored procedures.
This is why the flag has been deprecated from the beginning, as we don't encourage its use, except for backwards compatibility usage. It probably won't help you here.
Stored procedure support is definitely not going to be deprecated.
Tempted to simply turn off deprecation. This also seems like a global and not beneficial change, but it would serve the purpose.
Why not. A quick workaround. You don't have to use all the generated code. The deprecation is there to indicate that calling this generated procedure probably won't work out of the box, so its use is discouraged.
If I created a binding, I have no idea what it would do, or how to define it since TRIGGER really isn't a sensible thing to bind a Java object to. I assume I'd specify as TRIGGER in the forcedType element, but then the Java binding seems like a waste of time at best and misleading at worst.
Indeed, that wouldn't really add much value to your use cases as you will never directly call the trigger function in PostgreSQL.
Again, your own solution using <exclude> is the ideal solution here. In the future, we might offer a new code generation configuration flag that allows for turning on/off the generation of trigger functions, with the default being off: https://github.com/jOOQ/jOOQ/issues/9270

Well, after noting that an ideal way to do this would be to ignore that procedure, I did find how to ignore the procedure by name in the generally excellent jOOQ website documentation. Don't know how I missed in on first pass. If I needed to call this procedure in Java, I'm unclear which of the above options I would have used.
Luckily, there was no need for this procedure to be referenced in code, and I excluded it as shown below in in the jOOQ XML configuration.
<excludes>
databasechangelog.*
| maintain_edit_time
</excludes>

Related

How to avoid not used function to be wiped out by optimizer

While compiling and Xcode swift project for MacOS, not used functions are removed from the binary (removed by the optimizer I guess). Is there a way to tell the compiler to not remove unused functions, perhaps with a compiler option (--force-attribute?) so that even with optimization enabled those functions remain in the binary?
I know that if a global function is declared as public (public func test()) then it's not removed even if not used (Since it can be used by other modules), but I can't use public since that would export the symbol for that function.
Any suggestion?
If this is indeed removed by the optimiser, then the answer is two-fold.
The optimiser removes only things that it can prove are safely removable. So to make it not remove something, you remove something that the optimiser uses to prove removability.
For example, you can change the visibility of a function in the .bc file by running a pass that makes the functions externally callable. When a function is private to the .bc file (also called module) and not used, then the compiler can prove that nothing will ever call it. If it's visible beyong the .bc file, then the compiler must assume that something can come along later and call it, so the function has to be left alive.
This is really the generic answer to how to prevent an optimisation: Prevent the compiler from inferring that the optimisation is safe.
Writing and invoking a suitable pass is left as an exercise for the reader. Writing should be perhaps 20 lines of code, invoking… might be simple, or not, it depends on your setting. Quite often you can add a call to opt to your build system.
As I discovered, the solution here is to use a magic compiler flag -enable-private-imports (described here: "...Allows this module's internal and private API to be accessed") which basically add the function name to the list #llvm.used that you can see in the bitcode, the purpose of the list is:
If a symbol appears in the #llvm.used list, then the compiler,
assembler, and linker are required to treat the symbol as if there is
a reference to the symbol that it cannot see (which is why they have
to be named)
(cit.) As described here.
This solves my original problem as the private function even if not used anywhere and not being public, during compilation is not stripped out by the optimiser.

How does Js.cast() perform its type checking?

I'm using GWT 2.9 with elemental2-1.0.0-RC1.
The following code throws a ClassCastException at runtime:
DocumentRange documentRange = Js.cast(DomGlobal.document); // Fails
Range range = documentRange.createRange(); // Never reaches here
When I change to use an Js.uncheckedCast() instead, it succeeds:
DocumentRange documentRange = Js.uncheckedCast(DomGlobal.document);
Range range = documentRange.createRange(); // Works
The documentation for Js.uncheckedCast() says:
"You should always prefer regular casting over this (unless you know what you are doing!)."
I don't know why I'm having to use it, so I'm feeling nervous. Can someone explain how Js.cast() performs its type-checking and why I need to use an Js.uncheckedCast() in this instance?
Js.cast() is a way to cheat a bit, and do something that the Java language will not permit, but might actually be legal. Ignoring "how it actually works", the idea is that you can now get past issues where Java would complain, even if it turns out to be legit.
An example could be where you take a java.lang.Double or double and want to treat it as a JsNumber so you can call toPrecision(2) on it. Since java.lang.Double is final, it isn't legal to cast to an unrelated type, but Java doesn't know that in GWT, Double is really just a js Number. So, instead you can perform the cast with Js.cast(). The compiler will insert a runtime type check in there, verifying at runtime that your number is in fact a JS Number instance.
Another example could be trying to extend some native type that elemental2 provides, either to implement a workaround for a missing feature, or to do something browser-specific. Your new class may not extend the existing class - from JS's perspective this is okay, you are just describing the API that you know will exist at runtime. As such, we need to avoid the Java language check of "does this cast even make sense?", and just tell the compiler to try it.
On the other hand, you can "lie" to the compiler with Js.uncheckedCast(). This is used in cases where you are even asking the runtime to skip the check, and just pretend that it will work. This can let you do weird things, like treating Strings as if they were arrays, or solve cross-frame problems. No runtime check will be emitted, so instead you might just get a TypeError if a method/property is missing, instead of a proper ClassCastException.
In elemental2-dom 1.0.0-RC1, there is a class called DocumentRange, but it doesnt really make any sense - it is declared as a class, which means it can be type checked in JS, but the browser spec says that it should be an "interface" (which in JS-land means that it just is a description of a type, rather than something you can typecheck). https://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level2-DocumentRange-method-createRange
This bug is inherited from closure-compiler, which claims that this has a constructor: https://github.com/google/closure-compiler/blob/6a418aa/externs/browser/w3c_range.js#L241-L251
The fix is for closure-compiler to refer to this as an interface, and for a new release of elemental2 to be made so you can use this.
There are two workarounds you can make here. The first is to cheat with Js.uncheckedCast(DomGlobal.document) and say "yes, I know that the Document is not instanceof DocumentRange, but that's because there is no such class as DocumentRange, so just pretend it worked so I can call createRange() on it". This is what you are doing already - it hides the fact there is a bug, but at the end of the day it works.
The "correct" answer is to declare your own DocumentRange, and do a Js.cast() to that instead. This is still gross - you have to keep your new interface around until closure gets fixed, and then elemental2 gets released, and then you have to remember to clean it up.
In this case, I would suggest lying to GWT and using Js.uncheckedCast() - there is only a single method on here, and it is unlikely to change in a meaningful way.

PhpStorm 8.0 - How enable code completion in another file?

I implement MyClass containing the method method() and I store the instance in $_ENV['key'] in test.php. Also in test.php the code completion works when I type $_ENV['key']->.
In test2.php I include test.php and the code completion does not work any more for $_ENV['key']->.
Does anyone know how to enable this in PhpStorm?
AFAIK type tracking for arrays works within the same file only.
You can bypass it via intermediate variable (yes, it's not a nicest solution) and small PHPDoc comment, like this:
/** #var MyClass $myVar */
$myVar = $_ENV['key'];
$myVar->
P.S.
In general, I'd suggest not using global arrays this way (or even not using global vars at all -- only very basic stuff during bootstrap, if possible). Instead (based on your code) I may suggest using some static class (as one of the alternatives) with dedicated field where you can easily give type hint (via PHPDoc) to a class field -- this way IDE will always know hat type it is. Current PHP versions (5.5 and especially 5.6) work with objects nearly as fast as with arrays, even leading in (smaller) memory consumption.
Obviously, such suggestion does not really apply if this code is not yours.

What does the Google GIN method : bind(Class class)

I've read some documentation and downloaded samples but I still got a question.
In most sample, the GIN module uses something like :
bind(MainActivityMapper.class);
bind(VerticalMasterActivityMapper.class);
I don't understand what it does? If I remove it from the sample code, everything works perfectly.
Thanks for any answer.
Someone pointed me to the GUICE page : http://google-guice.googlecode.com/git/javadoc/com/google/inject/Binder.html
There is no reason for it to be different in Gin.
Here is what it says for this particular case :
This statement does essentially nothing; it "binds the
class to itself" and does not change Guice's default behavior. You may
still want to use this if you prefer your Module class to serve as an
explicit manifest for the services it provides. Also, in rare cases,
Guice may be unable to validate a binding at injector creation time
unless it is given explicitly.
Note: I'm not sure wether or not I should Accept my own answer, so I'll leave it as is.

WCF Data Service with EF fails to expose imported functions

(I am also using .NET 4.0 and VS 2010.)
I created a function import returning a complex type, as explained at http://msdn.microsoft.com/en-us/library/bb896231.aspx. The function import and new complex type appear in my .edmx file and in the Designer.cs file. However, the function does not appear when I view the service in the browser, and when I add or update a service reference in the client project, the function does not appear there either - as is to be expected, given the first result.
Creating an imported function and using it seems conceptually very simple and straightforward, and one would think it would just work, as Microsoft's step-by-step instructions appear to suggest: http://msdn.microsoft.com/en-us/library/cc716672.aspx#Y798 (which article shows the SP returning entity types - I tried this also, and it doesn't work for me either).
This blog post shows the addition of a method to the DataService class, which Microsoft's instructions omit: http://www.codegain.com/articles/wcf/miscellaneous/how-to-use-stored-procedure-in-wcf-data-service.aspx I tried adding one method returning a list of entity types and another returning a list of complex types, and still had no success. I still could not access the functions, either directly via the browser or from the client application via a service reference.
Thanks in advance for any help with this.
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
MS would do well to add a note to the walkthroughs stating that the above bit of code must be there. (It may be better to enable each operation explicitly than to use "*".)
http://www.codegain.com/articles/wcf/miscellaneous/how-to-use-stored-procedure-in-wcf-data-service.aspx shows that line of code. Also, something it is there in the code, commented out, when one creates the WCF Data Service. Some of us like to delete commented-out code that we aren't using and that seems irrelevant - perhaps doing so a bit prematurely, sometimes.