I am new and have a procedure which needs to be simplified.
It has multiple if and inserts and I want to simplify it.
BEGIN
IF oldProductType IS NOT NULL AND PRODUCTTYPE != oldProductType THEN
groupIdVal := prcChangeGroupIdSeq.NEXTVAL;
INSERT INTO CHANGE_GROUP VALUES(groupIdVal,projectid,user_id,SYSDATE);
insert into change_log (id, groupId, type, field, oldvalue, newvalue, fieldtypeid)
values (prcChangeLogIdSeq.NEXTVAL, groupIdVal, 'project', 'Product Type', oldProductType, PRODUCTTYPE, '');
UPDATE ab_project SET product_type = PRODUCTTYPE where project_id = PROJECTID;
END IF;
IF oldProgramManager IS NOT NULL AND PROGRAMMANAGER != oldProgramManager THEN
groupIdVal := prcChangeGroupIdSeq.NEXTVAL;
INSERT INTO CHANGE_GROUP VALUES(groupIdVal,projectid,user_id,SYSDATE);
insert into change_log (id, groupId, type, field, oldvalue, newvalue, fieldtypeid)
values (prcChangeLogIdSeq.NEXTVAL, groupIdVal, 'project', 'Program Manager', oldProgramManager, PROGRAMMANAGER, '');
UPDATE ab_project SET program_manager = PROGRAMMANAGER where project_id = PROJECTID;
END IF;
IF oldProductManager IS NOT NULL AND PRODUCTMANAGER != oldProductManager THEN
groupIdVal := prcChangeGroupIdSeq.NEXTVAL;
INSERT INTO CHANGE_GROUP VALUES(groupIdVal,projectid,user_id,SYSDATE);
insert into change_log (id, groupId, type, field, oldvalue, newvalue, fieldtypeid)
values (prcChangeLogIdSeq.NEXTVAL, groupIdVal, 'project', 'Product Manager', oldProductManager, PRODUCTMANAGER, '');
UPDATE ab_project SET product_manager = PRODUCTMANAGER where project_id = PROJECTID;
END IF;
IF oldProductName IS NOT NULL AND PRODUCTNAME != oldProductName THEN
groupIdVal := prcChangeGroupIdSeq.NEXTVAL;
INSERT INTO CHANGE_GROUP VALUES(groupIdVal,projectid,user_id,SYSDATE);
insert into change_log (id, groupId, type, field, oldvalue, newvalue, fieldtypeid)
values (prcChangeLogIdSeq.NEXTVAL, groupIdVal, 'project', 'Product Name', oldProductName, PRODUCTNAME, '');
UPDATE ab_project SET product_name = PRODUCTNAME where project_id = PROJECTID;
END IF;
IF oldDescription IS NOT NULL AND PRODUCTDESCRIPTION != oldDescription THEN
groupIdVal := prcChangeGroupIdSeq.NEXTVAL;
INSERT INTO CHANGE_GROUP VALUES(groupIdVal,projectid,user_id,SYSDATE);
insert into change_log (id, groupId, type, field, oldvalue, newvalue, fieldtypeid)
values (prcChangeLogIdSeq.NEXTVAL, groupIdVal, 'project', 'Product Description', oldDescription, PRODUCTDESCRIPTION, '');
UPDATE ab_project SET product_description = PRODUCTDESCRIPTION where project_id = PROJECTID;
END IF;
IF oldRequestType IS NOT NULL AND REQUESTTYPE != oldRequestType THEN
groupIdVal := prcChangeGroupIdSeq.NEXTVAL;
INSERT INTO CHANGE_GROUP VALUES(groupIdVal,projectid,user_id,SYSDATE);
insert into change_log (id, groupId, type, field, oldvalue, newvalue, fieldtypeid)
values (prcChangeLogIdSeq.NEXTVAL, groupIdVal, 'project', 'Request Type', oldRequestType, REQUESTTYPE, '');
UPDATE ab_project SET request_type = REQUESTTYPE where project_id = PROJECTID;
END IF;
IF oldOtherProduct IS NOT NULL AND OTHERPRODUCT != oldOtherProduct THEN
groupIdVal := prcChangeGroupIdSeq.NEXTVAL;
INSERT INTO CHANGE_GROUP VALUES(groupIdVal,projectid,user_id,SYSDATE);
insert into change_log (id, groupId, type, field, oldvalue, newvalue, fieldtypeid)
values (prcChangeLogIdSeq.NEXTVAL, groupIdVal, 'project', 'Other Product', oldOtherProduct, OTHERPRODUCT, '');
UPDATE ab_project SET Other_Product = OTHERPRODUCT where project_id = PROJECTID;
END IF;
IF oldBusinessRationale IS NOT NULL AND BUSINESSRATIONALE != oldBusinessRationale THEN
groupIdVal := prcChangeGroupIdSeq.NEXTVAL;
INSERT INTO CHANGE_GROUP VALUES(groupIdVal,projectid,user_id,SYSDATE);
insert into change_log (id, groupId, type, field, oldvalue, newvalue, fieldtypeid)
values (prcChangeLogIdSeq.NEXTVAL, groupIdVal, 'project', 'Business Rationale', oldBusinessRationale, BUSINESSRATIONALE, '');
UPDATE ab_project SET business_rationale = BUSINESSRATIONALE where project_id = PROJECTID;
END IF;
IF oldSoftwareDependency IS NOT NULL AND SOFTWAREDEPENDENCY != oldSoftwareDependency THEN
groupIdVal := prcChangeGroupIdSeq.NEXTVAL;
INSERT INTO CHANGE_GROUP VALUES(groupIdVal,projectid,user_id,SYSDATE);
insert into change_log (id, groupId, type, field, oldvalue, newvalue, fieldtypeid)
values (prcChangeLogIdSeq.NEXTVAL, groupIdVal, 'project', 'Software Dependency', oldSoftwareDependency, SOFTWAREDEPENDENCY, '');
UPDATE ab_project SET software_dependency = SOFTWAREDEPENDENCY where project_id = PROJECTID;
END IF;
IF OldOtherDependency IS NOT NULL AND OTHERDEPENDENCY != OldOtherDependency THEN
groupIdVal := prcChangeGroupIdSeq.NEXTVAL;
INSERT INTO CHANGE_GROUP VALUES(groupIdVal,projectid,user_id,SYSDATE);
insert into change_log (id, groupId, type, field, oldvalue, newvalue, fieldtypeid)
values (prcChangeLogIdSeq.NEXTVAL, groupIdVal, 'project', 'Other Dependency', OldOtherDependency, OTHERDEPENDENCY, '');
UPDATE ab_project SET other_dependency = OTHERDEPENDENCY where project_id = PROJECTID;
END IF;
IF OldReleaseCycleID IS NOT NULL AND RELEASECYCLEID != OldReleaseCycleID THEN
groupIdVal := prcChangeGroupIdSeq.NEXTVAL;
INSERT INTO CHANGE_GROUP VALUES(groupIdVal,projectid,user_id,SYSDATE);
insert into change_log (id, groupId, type, field, oldvalue, newvalue, fieldtypeid)
values (prcChangeLogIdSeq.NEXTVAL, groupIdVal, 'project', 'Release Cycle ID', OldReleaseCycleID, RELEASECYCLEID, '');
UPDATE ab_project SET release_cycle_id = RELEASECYCLEID where project_id = PROJECTID;
END IF;
commit;
exception
when others then
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' - Error - '||SQLERRM);
end;
CASE is probably what you want
Related
I could not capture that error that comes from the stored procedure that I created.
create procedure sp_users
#option int = 0,
#nom_user varchar(50) = null,
#ema_user varchar(50) = null
as
begin
set nocount on
begin try
if #option = 2
begin
if not exists (select * from tb_users where ema_user = #ema_user)
begin
insert into tb_users values (#nom_user,#ema_user)
end
else
begin
raiserror('The email already exists',16,1)
end
end
end try
begin catch
declare #errorMessage varchar(100), #errorSeverity int, #errorState int
set #errorMessage = error_message()
set #errorSeverity = error_severity()
set #errorState = error_state()
raiserror(#errorMessage,#errorSeverity,#errorState)
end catch
end
when I enter an email that already exists, it shows me the message.
Msg 50000, Level 16, State 1, Procedure sp_users, Line 71 [Batch Start Line 81]
The email already exists
this is the code that I made in spring boot
#Service
public class CrudUserService implements CrudUserDAO{
#PersistenceContext
private EntityManager em;
#SuppressWarnings({ "unchecked" })
#Override
public ValidateApiResponse MntUser(Integer op, String nom, String ema) {
ValidateApiResponse vapi = new ValidateApiResponse();
Session session = em.unwrap(Session.class);
try {
ProcedureCall call = session.createStoredProcedureCall("sp_users");
call.registerParameter(1, Integer.class, ParameterMode.IN);
call.registerParameter(2, String.class, ParameterMode.IN).enablePassingNulls(true);
call.registerParameter(3, String.class, ParameterMode.IN).enablePassingNulls(true);
call.setParameter(1, op);
call.setParameter(2, nom);
call.setParameter(3, ema);
call.execute();
vapi.dTable = call.getResultList();
vapi.Attr = "OK";
} catch (Exception e) {
//vapi.Attr = "";
//vapi.Error = e.getMessage();
System.out.println(e.getMessage());
} finally {
session.close();
}
return vapi;
}
}
when I try to capture the error in spring boot I get this in the console. it shows me the message, but I can't capture that message from SqlExceptionHelper.
2019-12-30 19:19:22.892 WARN 10504 --- [nio-8090-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 50000, SQLState: S0001
2019-12-30 19:19:22.893 ERROR 10504 --- [nio-8090-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : The email already exists
org.hibernate.exception.SQLGrammarException: Error calling CallableStatement.getMoreResults
I have already solved it, but creating an output parameter.
procedure
create proc sp_users
#option int = 0,
#nom_user varchar(50) = null,
#ema_user varchar(50) = null,
#message_error varchar(50) = null output
as
begin
set nocount on
begin try
if #option = 2
begin
if not exists(select * from tb_users where ema_user = #ema_user)
begin
insert into tb_users values(#nom_user,#ema_user)
end
else
begin
set #message_error = 'The email already exists'
raiserror(#message,16,1)
end
end
end try
begin catch
print error_message()
end catch
end
spring boot
#Service
public class CrudUserService implements CrudUserDAO {
#PersistenceContext
private EntityManager em;
#SuppressWarnings({ "unchecked" })
#Override
public ValidateApiResponse MntUser(Integer op, String nom, String ema) {
ValidateApiResponse vapi = new ValidateApiResponse();
Session session = em.unwrap(Session.class);
ProcedureCall call = session.createStoredProcedureCall("sp_users");
call.registerParameter(1, Integer.class, ParameterMode.IN);
call.registerParameter(2, String.class, ParameterMode.IN).enablePassingNulls(true);
call.registerParameter(3, String.class, ParameterMode.IN).enablePassingNulls(true);
call.registerParameter(4, String.class, ParameterMode.OUT).enablePassingNulls(true);
call.setParameter(1, op);
call.setParameter(2, nom);
call.setParameter(3, ema);
call.execute();
String message = (String) call.getOutputParameterValue(4);
if (message == "" || message == null) {
vapi.dTable = call.getResultList();
vapi.Attr = "OK";
} else {
vapi.Attr = "";
vapi.Error = message;
}
return vapi;
}
}
This is the message I get when I enter an email that already exists.
"Msj": "Internal Server Error",
"MsjDetail": "The email already exists",
"dtCollection": [],
"MsjCode": 500
I am trying to do a very simple task with Linq and already stuck. It's really horrible but I guess, it's better to know using this post. I've two tables. One is Products and another is Ratings. Here is the demo script:
CREATE TABLE [dbo].[Products](
[ProductID] [int] IDENTITY(1,1) PRIMARY KEY,
[ProductName] [varchar](40) NULL,
[Price] [float] NULL,
[Details] [varchar](max) NULL,
[CategoryID] [int] NULL
)
INSERT [dbo].[Products] ([ProductID], [ProductName], [Price], [Details], [CategoryID]) VALUES (1, N'Denim', 1200, NULL, 1)
INSERT [dbo].[Products] ([ProductID], [ProductName], [Price], [Details], [CategoryID]) VALUES (2, N'Denim 2', 220, NULL, 1)
INSERT [dbo].[Products] ([ProductID], [ProductName], [Price], [Details], [CategoryID]) VALUES (3, N'Pringles', 240, NULL, 2)
INSERT [dbo].[Products] ([ProductID], [ProductName], [Price], [Details], [CategoryID]) VALUES (4, N'Pringles 2', 260, NULL, 2)
INSERT [dbo].[Products] ([ProductID], [ProductName], [Price], [Details], [CategoryID]) VALUES (5, N'Pringles 3', 240, NULL, 2)
CREATE TABLE [dbo].[Ratings](
[AutoId] [int] IDENTITY(1,1) PRIMARY KEY,
[ProductId] [int] NOT NULL,
[UserRating] [float] NOT NULL
)
INSERT [dbo].[Ratings] ([AutoId], [ProductId], [UserRating]) VALUES (4, 2, 1.5)
INSERT [dbo].[Ratings] ([AutoId], [ProductId], [UserRating]) VALUES (5, 4, 2.5)
INSERT [dbo].[Ratings] ([AutoId], [ProductId], [UserRating]) VALUES (6, 1, 5)
INSERT [dbo].[Ratings] ([AutoId], [ProductId], [UserRating]) VALUES (7, 2, 2.5)
And the output should be the following:
ProductId - ProductName - User Rating
1 - Denim - 5
2 - Denim 2 - 2
3 - Pringles - 0
4 - Pringles 2 - 2.5
5 - Pringles 3 - 0
This is the rating system of a project and I am trying to get the above output using Linq. With the following Sql, I got the result:
SELECT m.ProductId, m.ProductName, ISNULL(SUM(k.UserRating) / COUNT(k.ProductId), 0) AS 'User Rating' FROM Products m
LEFT JOIN Ratings k ON k.ProductId = m.ProductID
GROUP BY m.ProductID, m.ProductName
Unfortunately, with the following Linq, I get only the rating details that exist in the Ratings table:
var con = (from c in db.Ratings
join d in db.Products on c.ProductId equals d.ProductID into ps
from rt in ps.DefaultIfEmpty()
group new { c, ps } by new { rt.ProductID, rt.ProductName } into g
select new ProductRating
{
ProductId = g.Key.ProductID,
ProductName = g.Key.ProductName,
Total = g.Sum(c => c.c.UserRating) / g.Count()
}).ToList();
Note: My goal is to get the rating details (sum of a product's rating) that don't exist in the Ratings table (Should return '0' if no data) along with the ratings details that exist.
Update 1 - Class ProductRating:
public class ProductRating {
public int ProductId { get; set; }
public string ProductName { get; set; }
public double Total { get; set; } //Property for the rating
}
Update 2 - Class Products and Ratings:
public partial class Products
{
public int ProductID { get; set; }
public string ProductName { get; set; }
public Nullable<double> Price { get; set; }
public string Details { get; set; }
public Nullable<int> CategoryID { get; set; }
public ICollection<Ratings> Rating { get; set; }
}
public partial class Ratings
{
public int AutoId { get; set; }
public int ProductId { get; set; }
public double UserRating { get; set; }
}
Used the following the Linq query and got this error - The specified type member 'Rating' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported:
var con = db.Products.Select(c => new ProductRating
{
ProductId = c.ProductID,
ProductName = c.ProductName,
Total = c.Rating.Average(d => (double?)d.UserRating) ?? 0
}).ToList();
Update 3: Now getting this error - error 2016: The value specified for the condition is not compatible with the type of the member and this is how I tried for the navigation property:
Note: I've modified Andrés Robinet's query and it worked though using the Join.
from c in db.Ratings
join d in db.Products on c.ProductId equals d.ProductID into ps
from rt in ps.DefaultIfEmpty()
is the LINQ equivalent of the SQL Ratings LEFT OUTER JOIN Products, i.e. exactly the opposite of your SQL query.
While the LINQ query can be modified to match the SQL query, it doesn't make sense because EF provides a much better way which totally eliminates the need of using joins in the LINQ query - the so called navigation properties (see Don’t use Linq’s Join. Navigate!).
Normally the Product class would have a collection navigation property
public ICollection<Rating> Ratings { get; set; }
representing the one to many relationship between Product and Rating, and the equivalent LINQ query using it would be simply:
var result = db.Products
.Select(p => new ProductRating
{
ProductId = p.ProductId,
ProductName = p.ProductName,
Total = p.Ratings.Average(r => (double?)r.UserRating) ?? 0
}).ToList();
Update: In case you haven't set up correctly the relationship in the entity model, you could use the manual join equivalent of the above query by replacing the navigation property accessor with group join:
var result = (
from p in db.Products
join r in db.Ratings on p.ProductId equals r.ProductId into ratings
select new ProductRating
{
ProductId = p.ProductId,
ProductName = p.ProductName,
Total = ratings.Average(r => (double?)r.UserRating) ?? 0
}).ToList();
You have to start with the Product. Also, the order of your joins in your Linq expression is the opposite than in your SQL. And, the group ... by ... needs just rt.UserRating as the value selector
var con = (from d in db.Products
join c in db.Ratings on d.ProductId equals c.ProductId into ps
from rt in ps.DefaultIfEmpty()
group new { rt.UserRating } by new { d.ProductId, d.ProductName } into g
select new ProductRating
{
ProductId = g.Key.ProductId,
ProductName = g.Key.ProductName,
Total = g.Sum(r => r.UserRating) / g.Count()
})
.ToList();
Also, this would break if g.Count() is zero. But you have a few choices anyways:
Add more complexity to the query and pray for EF to be able to translate it into SQL
select new ProductRating
{
ProductName = g.Key.ProductName,
Total = g.Count() > 0 ? (g.Sum(r => r.UserRating) / g.Count()) : 0
}
Redefine ProductRating or use a helper DTO, so that it takes Sum and Count properties (calculate the average on-demand, let's say, you can still have a Total property)
select new ProductRating
{
ProductName = g.Key.ProductName,
SumRating = g.Sum(r => r.UserRating),
CountRating = g.Count()
}
Your LINQ statement has an inner join, whereas your SQL has a left join.
I have the following service method:
public Page<ProductSalesReportLineDto> getReport(
Unit unit, Organization customer, Organization supplier, Date startDate, Date endDate, Pageable pageable
){
List<ProductSalesReportLineDto> lines = new ArrayList<ProductSalesReportLineDto>();
String sql = "SELECT product.id, product.code as code, product.barcode as barcode, product_name.name__text AS name, " +
"SUM(order_line.quantity) as quantity, SUM(order_line.commissioned_price_price * order_line.quantity) as price " +
"FROM product LEFT JOIN order_line ON order_line.product_id = product.id " +
"JOIN `order` ON order_line.order_id = order.id " +
"JOIN product_name ON product_name.product_id = product.id " +
"WHERE product_name.name__locale = \"en-US\" " +
"AND (:customer is null OR :customer='' OR `order`.customer_id = :customer) " +
"AND (:supplier is null OR :supplier='' OR `order`.supplier_id = :supplier) " +
"AND (:startDate is null OR :startDate='' OR `order`.date >= :startDate) " +
"AND (:endDate is null OR :endDate='' OR `order`.date <= :endDate) " +
"AND (:unit is null OR :unit='' OR product.unit = :unit) " +
"GROUP BY product.id, product_name.name__text " +
"LIMIT :offset, :pageSize";
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("offset", pageable.getOffset());
parameters.put("pageSize", pageable.getPageSize());
parameters.put("customer", customer != null ? customer.id : null);
parameters.put("supplier", supplier != null ? supplier.id : null);
parameters.put("startDate", startDate);
parameters.put("endDate", endDate);
parameters.put("unit", unit);
List<Map<String, Object>> rows = namedParameterJdbcTemplate.queryForList(sql, parameters);
for (Map<String, Object> row : rows) {
ProductSalesReportLineDto line = new ProductSalesReportLineDto();
line.productName = row.get("name") != null ? row.get("name").toString() : "";
line.productCode = row.get("code") != null ? row.get("code").toString() : "";
line.productBarcode = row.get("barcode") != null ? row.get("barcode").toString() : "";
line.quantity = row.get("quantity") != null ? Double.parseDouble(row.get("quantity").toString()) : 0;
line.price = row.get("price") != null ? Double.parseDouble(row.get("price").toString()) : 0;
lines.add(line);
}
Page<ProductSalesReportLineDto> page = new PageImpl<ProductSalesReportLineDto>(lines);
return page;
}
The parameters come from a #RestController method:
public #ResponseBody
ResponseEntity<?> get(
#RequestParam(value = "unit", required = false) Unit unit,
#RequestParam(value = "customer", required = false) Organization customer,
#RequestParam(value = "supplier", required = false) Organization supplier,
#DateTimeFormat(pattern = "yyyyy-MM-dd") #RequestParam(value = "startDate", required = false) Date startDate,
#DateTimeFormat(pattern = "yyyyy-MM-dd") #RequestParam(value = "endDate", required = false) Date endDate,
Pageable pageable
)
And Unit is an enum type field on Product:
#Enumerated(EnumType.STRING)
public Unit unit;
public enum Unit {
ROLL("ROLL", "ROLL", AbstractUnit.ONE),
METRE("METRE", Units.METRE.getSymbol(), Units.METRE),
KILOGRAM("KILOGRAM", Units.KILOGRAM.getSymbol(), Units.KILOGRAM),
PIECE("PIECE", "PIECE", AbstractUnit.ONE),
SAMPLE("SAMPLE", "SAMPLE", AbstractUnit.ONE);
I cannot retrieve products by unit using this query. With MySql the query works fine and it returns records. For example:
SELECT product.id, product.code as code, product.barcode as barcode, product_name.name__text AS name, SUM(order_line.quantity) as quantity, SUM(order_line.commissioned_price_price) as price FROM product LEFT JOIN order_line ON order_line.product_id = product.id JOIN `order` ON order_line.order_id = `order`.id JOIN product_name ON product_name.product_id = product.id WHERE product_name.name__locale = "en-US" AND (null is null OR null='' OR `order`.customer_id = null) AND (null is null OR null='' OR `order`.supplier_id = null) AND (null is null OR null='' OR `order`.date >= null) AND (null is null OR null='' OR `order`.date <= null) AND ("ROLL" is null OR "ROLL"='' OR product.unit = "ROLL") GROUP BY product.id, product_name.name__text
This query returns one row. When I run the same query via the rest interface and NamedParameterJdbcTemplate it returns no records. Can anybody tell what I am missing?
Following code also returns one row:
String sql2 = "SELECT * FROM product WHERE product.unit = :unit";
Map<String, Object> parameters2 = new HashMap<String, Object>();
parameters2.put("unit", "ROLL");
List<Map<String, Object>> rows2 = namedParameterJdbcTemplate.queryForList(sql2, parameters2);
Given the following sqlite table
CREATE TABLE `ComponentNameLookup` (
`Id` INTEGER PRIMARY KEY AUTOINCREMENT,
`ComponentId` INTEGER NOT NULL,
`ComponentName` TEXT NOT NULL,
`Culture` TEXT
);
insert into ComponentNameLookup
(Id,ComponentId,ComponentName,Culture)
values
(1, 0, 'Logger', NULL ),
(2, 1, 'Transport', NULL ),
(3, 2, 'Error Handler', NULL ),
(4, 3, 'Persistance', NULL ),
(5, 0, 'Registrador', 'es-ES'),
(6, 1, 'Transporte', 'es' ),
(7, 2, 'Controlador de errores', 'es-ES'),
(8, 3, 'Persistencia', 'es-ES'),
(9, 1, 'Транспорт', 'ru' ),
(10, 2, 'Обработчик ошибок', 'ru-RU')
And the Linq Query
void Main()
{
string cultureString = Thread.CurrentThread.CurrentCulture.Name;
string languageName = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;
cultureString = "es-ES";
languageName = "es";
var localized = context.ComponentNameLookups
.Where(x => x.Culture == cultureString || x.Culture == languageName || x.Culture == null)
.GroupBy(c => c.ComponentId)
.Select(g => new KeyValue<int?, string>{
Key = g.Key,
Value = g
.OrderByDescending(x => x.Culture.Length)
.Select(c => c.ComponentName)
.FirstOrDefault(),
})
;
localized.ToArray();
}
public class KeyValue<T1, T2> {
public T1 Key;
public T2 Value;
}
I get the error
System.Data.Entity.Core.EntityCommandCompilationException: An error occurred while preparing the command definition. See the inner exception for details. ---> System.NotSupportedException: APPLY joins are not supported
Something like this shouldn't need to be an APPLY JOIN. Is there any other way I can do this query using LINQ?
I can't test on SqlLite, but the query has (although different) issue with MySQL (it runs fine with SqlServer), so you can try replacing
.OrderByDescending(x => x.Culture.Length)
with
.Where(c => c.Culture.Length == g.Max(e => e.Culture.Length))
which fixes MySQL issue and eliminates the OUTER APPLY from SqlServer query, so it might work for SqlLite as well.
This is the error stack when i try to insert a user details into a table
Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near "RETURNING"
Position: 52
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2182)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1911)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:618)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:468)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:414)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:98)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:98)
at org.springframework.jdbc.core.JdbcTemplate$3.doInPreparedStatement(JdbcTemplate.java:903)
at org.springframework.jdbc.core.JdbcTemplate$3.doInPreparedStatement(JdbcTemplate.java:900)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:629)
I am using stored procedures to make all my db interation
CREATE OR REPLACE FUNCTION ezhire."insert_user"
(
in_name character varying,
in_email character varying,
in_image_url character varying,
in_provider character varying
)
RETURNS integer AS $$
DECLARE
out_inserted_id integer;
BEGIN
WITH rows as (
INSERT INTO ezhire.user(name, email, image_url, provider)
VALUES(in_name, in_email, in_image_url, in_provider)
RETURNING id
)
SELECT id INTO out_inserted_id FROM rows;
RETURN out_inserted_id;
END;
$$ LANGUAGE plpgsql
I am unable to figure out what is going wrong..
Change the WITH part like below
WITH test as (
INSERT INTO ezhire.user(name, email, image_url, provider)
VALUES(in_name, in_email, in_image_url, in_provider)
RETURNING id as recentid
)
SELECT recentid INTO out_inserted_id FROM test;
(OR) make it without WITH clause like
CREATE OR REPLACE FUNCTION ezhire."insert_user"
(
in_name character varying,
in_email character varying,
in_image_url character varying,
in_provider character varying
)
RETURNS integer AS $$
DECLARE
out_inserted_id integer;
BEGIN
INSERT INTO ezhire.user(name, email, image_url, provider)
VALUES(in_name, in_email, in_image_url, in_provider)
RETURNING id INTO out_inserted_id;
RETURN out_inserted_id;
END;
$$ LANGUAGE plpgsql
You basically have two options here:
PL/pgSQL
You need to supply a target for the id value:
CREATE OR REPLACE FUNCTION ezhire."insert_user"
(
in_name character varying,
in_email character varying,
in_image_url character varying,
in_provider character varying
)
RETURNS integer AS $$
DECLARE
out_inserted_id integer;
BEGIN
INSERT INTO ezhire.user(name, email, image_url, provider)
VALUES (in_name, in_email, in_image_url, in_provider)
RETURNING id INTO out_inserted_id;
RETURN out_inserted_id;
END;
$$ LANGUAGE plpgsql;
SQL function
Seeing that you only do pure SQL in the function, use a SQL language function which is faster and simpler to write:
CREATE OR REPLACE FUNCTION ezhire."insert_user"
(
in_name character varying,
in_email character varying,
in_image_url character varying,
in_provider character varying
)
RETURNS integer AS $$
INSERT INTO ezhire.user(name, email, image_url, provider)
VALUES (in_name, in_email, in_image_url, in_provider)
RETURNING id;
$$ LANGUAGE sql;
The problem was in my spring code:
Need to change this code
public Role createRole(final Role role){
KeyHolder holder = new GeneratedKeyHolder();
PreparedStatementCreator psc = new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(
java.sql.Connection conn) throws SQLException {
PreparedStatement pstmt = conn.prepareStatement(
QUERIES.ROLE.INSERT_ROLE, new String[] { "id" });
int i = 1;
pstmt.setString(i++, role.getName());
pstmt.setString(i++, role.getAbbreviation());
pstmt.setString(i++, role.getInfo());
return pstmt;
}
};
logger.info(psc.toString());
jdbcTemplate.update(psc, holder);
Integer userId = holder.getKey().intValue();
role.setId(userId);
return role;
}
To this:
public Role createRole(final Role role) {
PreparedStatementCreator psc = new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection conn)
throws SQLException {
PreparedStatement pstmt = conn
.prepareStatement(QUERIES.ROLE.INSERT_ROLE);
int i = 1;
pstmt.setString(i++, role.getName());
pstmt.setString(i++, role.getAbbreviation());
pstmt.setString(i++, role.getInfo());
logger.debug(pstmt.toString());
return pstmt;
}
};
Integer roleId = jdbcTemplate.query(psc,
new ResultSetExtractor<Integer>() {
#Override
public Integer extractData(ResultSet rs)
throws SQLException, DataAccessException {
if (rs.next()) {
return rs.getInt("insert_role");
}
return null;
}
});
role.setId(roleId);
return role;
}