|
1 | 1 | using System;
|
| 2 | +using System.Collections; |
2 | 3 | using System.Collections.Generic;
|
3 | 4 | using System.Data;
|
4 | 5 | using System.Data.Common;
|
| 6 | +using System.Linq; |
5 | 7 | using System.Text;
|
6 | 8 | using NHibernate.Dialect.Function;
|
| 9 | +using NHibernate.Engine; |
7 | 10 | using NHibernate.SqlCommand;
|
| 11 | +using NHibernate.Type; |
8 | 12 | using NHibernate.Util;
|
9 | 13 |
|
10 | 14 | namespace NHibernate.Dialect
|
@@ -109,6 +113,7 @@ protected virtual void RegisterFunctions()
|
109 | 113 | RegisterFunction("trim", new AnsiTrimEmulationFunction());
|
110 | 114 | RegisterFunction("replace", new StandardSafeSQLFunction("replace", NHibernateUtil.String, 3));
|
111 | 115 | RegisterFunction("chr", new StandardSQLFunction("char", NHibernateUtil.Character));
|
| 116 | + RegisterFunction("locate", new LocateFunction()); |
112 | 117 |
|
113 | 118 | RegisterFunction("mod", new ModulusFunctionTemplate(false));
|
114 | 119 |
|
@@ -513,5 +518,72 @@ protected override bool CastingIsRequired(string sqlType)
|
513 | 518 | return true;
|
514 | 519 | }
|
515 | 520 | }
|
| 521 | + |
| 522 | + [Serializable] |
| 523 | + private class LocateFunction : ISQLFunction, ISQLFunctionExtended |
| 524 | + { |
| 525 | + // Since v5.3 |
| 526 | + [Obsolete("Use GetReturnType method instead.")] |
| 527 | + public IType ReturnType(IType columnType, IMapping mapping) |
| 528 | + { |
| 529 | + return NHibernateUtil.Int32; |
| 530 | + } |
| 531 | + |
| 532 | + /// <inheritdoc /> |
| 533 | + public IType GetReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError) |
| 534 | + { |
| 535 | +#pragma warning disable 618 |
| 536 | + return ReturnType(argumentTypes.FirstOrDefault(), mapping); |
| 537 | +#pragma warning restore 618 |
| 538 | + } |
| 539 | + |
| 540 | + /// <inheritdoc /> |
| 541 | + public IType GetEffectiveReturnType(IEnumerable<IType> argumentTypes, IMapping mapping, bool throwOnError) |
| 542 | + { |
| 543 | + return GetReturnType(argumentTypes, mapping, throwOnError); |
| 544 | + } |
| 545 | + |
| 546 | + /// <inheritdoc /> |
| 547 | + public string Name => "instr"; |
| 548 | + |
| 549 | + public bool HasArguments => true; |
| 550 | + |
| 551 | + public bool HasParenthesesIfNoArguments => true; |
| 552 | + |
| 553 | + public SqlString Render(IList args, ISessionFactoryImplementor factory) |
| 554 | + { |
| 555 | + if (args.Count != 2 && args.Count != 3) |
| 556 | + { |
| 557 | + throw new QueryException("'locate' function takes 2 or 3 arguments. Provided count: " + args.Count); |
| 558 | + } |
| 559 | + |
| 560 | + if (args.Count == 2) |
| 561 | + { |
| 562 | + return new SqlString("instr(", args[1], ", ", args[0], ")"); |
| 563 | + } |
| 564 | + |
| 565 | + var text = args[1]; |
| 566 | + var value = args[0]; |
| 567 | + var startIndex = args[2]; |
| 568 | + //ifnull( |
| 569 | + // nullif( |
| 570 | + // instr(substr(text, startIndex), value) |
| 571 | + // , 0) |
| 572 | + // + startIndex -1 |
| 573 | + //, 0) |
| 574 | + return |
| 575 | + new SqlString( |
| 576 | + "ifnull(nullif(instr(substr(", |
| 577 | + text, |
| 578 | + ", ", |
| 579 | + startIndex, |
| 580 | + "), ", |
| 581 | + value, |
| 582 | + "), 0) + ", |
| 583 | + startIndex, |
| 584 | + " -1, 0)" |
| 585 | + ); |
| 586 | + } |
| 587 | + } |
516 | 588 | }
|
517 | 589 | }
|
0 commit comments