I've a Dropwizard application using JDBI and SQL Server. I would like to get all SQL statements logged with their parameters but I don't seem to be able to.
This is what's usually recommended to do:
logging:
level: INFO
loggers:
"org.skife": TRACE
"com.microsoft.sqlserver.jdbc": TRACE
But this only logs statements, without the parameters:
TRACE [2016-07-08 16:40:27,711] org.skife.jdbi.v2.DBI: statement:[/* LocationDAO.detail */ EXEC [api].[GetCountryCodes] #CountryId = ?] took 487 millis
DEBUG [2016-07-08 16:37:44,499] com.microsoft.sqlserver.jdbc.Connection: ENTRY /* LocationDAO.detail */ EXEC [api].[GetCountryCodes] #CountryId = ?
Is there any way to get the actual statement run against the database?
Using p6spy seems to be the easiest way to go. Just add the dependency:
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>2.3.1</version>
</dependency>
On the database config, use the p6spy class instead and slightly modify your connection url
database:
driverClass: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:sqlserver://10.0.82.95;Database=psprd1
Related
Would you please let me know a script which enables an existing operator to be added onto SQL agent job?
Assuming you have My Operator set up, the following will alert that operator by Email on job failure. You can change #notify_level_email to the condition you desire
sp_update_job
USE [msdb];
EXEC msdb.dbo.sp_update_job #job_name='My Job',
#notify_level_email=2, /* notify on failure */
#notify_email_operator_name=N'My Operator';
We can turn on all of the SQL related logging with the following settings in spring:
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.type=trace
If we have a standalone hibernate/springdata command like
myEntityRepository.save(myEntity);
OR
enityManager.persist(myEntity);
then it is easy to debug what happened just by reading the generated SQL from the log.
But, how would you debug when there isn't any explicit ORM action like here:
#Transactional
void doHundredOfTask(Long id){
MyEntity myEntity = myEntityRepository.findById(id);
// here comes ton of action on the entity like settings field,setting/adding to collection
// myEntity.setField1()..
//myEntity.setField2()
// ....
// myEntity.setField_N()
// myEntity.getSomeList.get(0).setSomeField()
// no ORM action
}
At the end we don't explicitly save anything but after the transaction hibernate will flush the changes, hence a massive amount of SQL will occur in the log. If you have a ton of action on the entity and on it's associations then it is extremly hard to debug why a given SQL was triggered.
Is there a way to assign the generated SQL to the triggering code in the log?
edit: Right know all I can do is splitting up the code to smaller chunks / or commenting out some part of it. But this process is slow..
p6spy can print a stacktrace for each executed SQL statement. Here is configuration to enable this: stacktrace=true.
How to configure p6spy for maven project:
Add p6spy dependency
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.9.1</version>
</dependency>
Wrap the jdbc connection with p6spy:
spring.datasource.url=jdbc:p6spy:mysql://localhost:3306/xxx
spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver
Add spy.properties config src/main/resources/spy.properties
stacktrace=true
appender=com.p6spy.engine.spy.appender.Slf4JLogger
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat
You can remove the properties bellow:
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true
With this configuration, p6spy will output SQL and the stacktrace. E.g.:
select x0_.id as id1_7_ from X x0_
15:10:16.166 default [main] INFO c.p.e.spy.appender.Slf4JLogger[logException]-39 -
java.lang.Exception: null
at com.p6spy.engine.common.P6LogQuery.doLog(P6LogQuery.java:126)
...
at org.hibernate.loader.Loader.getResultSet(Loader.java:2341)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2094)
...
at com.springapp.Test.test(Test.java:36)
...
I have a simple REST service that take a date as pathvariable and executes a query. I am using java.time.LocalDate class to store the date and passing the parameter as below:
<select id="getRecordsUpdatedAfterDate" parameterType="java.time.LocalDate" resultType="String">
SELECT ID FROM table WHERE REC_UPDT_DT > #{recUpdtDt, jdbcType=DATE}
</select>
But I am not getting any response back from the service. In the logs I have this:
2020-04-06 10:16:16.187 DEBUG 11928 --- [nio-8080-exec-2] .c.t.g.a.m.P.getRecordsUpdatedAfterDate: ==> Preparing: SELECT ID FROM table WHERE REC_UPDT_DT > ?
2020-04-06 10:16:16.188 DEBUG 11928 --- [nio-8080-exec-2] .c.t.g.a.m.P.getRecordsUpdatedAfterDate: ==> Parameters: 2020-01-01(LocalDate)
But nothing after this and there is no response either.
Anything I am doing wrong? I am using mybatis 3.5.2, and Spring Boot.
if you execute the same query in the datasource you get a single string object ?
Maybe is because the dataType oor because you get more than one result.
Add your table definition to check ID Type.
Add this dependency
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-typehandlers-jsr310</artifactId>
<version>1.0.2</version>
I have two service programs: mySrvPgm and myErr
mySrvPgm has a procedure which contains:
/free
...
exec sql INSERT INTO TABLE VALUES(:RECORD_FMT);
if sqlError() = *ON;
//handle error
endif;
...
/end-free
myErr has a procedure sqlError:
/free
exec sql GET DIAGNOSTICS CONDITION 1
:state = RETURNED_SQLSTATE;
...
/end-free
Background info: I am using XMLSERVICE to call the given procedure in mySrvPgm from PHP. I am not using a persistent connection. myErr is bound-by-reference via a binding directory used by mySrvPgm. Its activation is set to *IMMED, its activation group is set to *CALLER.
The problem: Assume there is an error on the INSERT statement in mySvrPgm. The first time sqlError() is called it will return SQLSTATE 00000 despite the error. All subsequent calls to sqlError() return the expected SQLSTATE.
A workaround: I added a procedure to myErr called initSQL:
/free
exec sql SET SCHEMA MYLIB;
/end-free
If I call initSQL() before the INSERT statement in mySrvPgm, sqlError() functions correctly. It doesn't have to be SET SCHEMA, it can be another GET DIAGNOSTICS statement. However, if it does not contain an executable SQL statement it does not help.
The question: I believe the myErr service program is activating properly and has the correct scope, but I am wondering if there is something more I need to do to activate the SQL part of it. Is there some way to set it up so SQL auto-initializes when the service program is activated, or do I have to execute an unneeded SQL statement in order to get it started?
There is some more background information available here.
Thank you for reading.
What version an release of the OS? Are you upto date on PTFs?
Honestly, seems to me that it's possibly a bug. Or the manual(s) need clarification.. I'd open a PMR.
I was looking at the source of sys.sp_dbcmptlevel in SQL Server 2005.
In the source, there is this line I do not understand how it works.
EXEC %%DatabaseEx(Name = #dbname).SetCompatibility(Level = #input_cmptlevel)
It doesn't appear that DatabaseEx is a stored procedure.
-- does not return any result
select *
from sys.procedures
where [name] like '%DatabaseEx%'
So my questions are
What is DatabaseEx and what does it do?
What is %% before DatabaseEx?
I think the best answer here is that it's not documented, and not supported, so don't rely on it. While it's interesting to know how SQL Server works internally, anything you do with that knowledge has the potential to break in a future hotfix, service pack or release.
Interesting find.
System SP's also refer to %%Object, %%Relation, %%ColumnEx, %%LinkedServer, %%Owner, %%CurrentDatabase(), %%ErrorMessage, %%Module, %%DatabaseRef, %%LocalLogin, %%Alias, %%ServerConfiguration, %%IndexOrStats, %%ScalarType (etc)
My interpretation is that the %%() retrieves some kind of (COM?) object based on filter criteria, followed by a method call.
-- Note: database #dbname may not exist anymore
-- Change compatibility level
-- If invoke gets error, exception will abort this proc.
EXEC %%DatabaseEx(Name = #dbname).SetCompatibility(Level = #input_cmptlevel)
it looks like a way to refer to a variable database as an object and make config changes