();
36 | private IAttachment attachment;
37 | private ITransaction transaction;
38 | private Routine routine;
39 | private ValuesImpl inValues;
40 | private ValuesImpl outValues;
41 | private Connection connection;
42 | private ContextImpl contextImpl;
43 |
44 | public static InternalContext get()
45 | {
46 | return tls.get();
47 | }
48 |
49 | public static InternalContext set(final InternalContext newValue)
50 | {
51 | final InternalContext oldValue = tls.get();
52 | tls.set(newValue);
53 | return oldValue;
54 | }
55 |
56 | public static ContextImpl getContextImpl()
57 | {
58 | final InternalContext context = get();
59 | return context.contextImpl;
60 | }
61 |
62 | public static InternalContext create(final IStatus status, final IExternalContext context, final Routine routine,
63 | final ValuesImpl inValues, final ValuesImpl outValues) throws FbException
64 | {
65 | final InternalContext internalContext = new InternalContext();
66 | internalContext.setup(status, context, routine, 0, inValues, outValues);
67 | return internalContext;
68 | }
69 |
70 | public static InternalContext createTrigger(final IStatus status, final IExternalContext context,
71 | final Routine routine, final int action, final ValuesImpl oldValues, final ValuesImpl newValues)
72 | throws FbException
73 | {
74 | final InternalContext internalContext = new InternalContext();
75 | internalContext.setup(status, context, routine, action, oldValues, newValues);
76 | return internalContext;
77 | }
78 |
79 | private void setup(final IStatus status, final IExternalContext context, final Routine routine,
80 | final int triggerAction, final ValuesImpl inValues, final ValuesImpl outValues) throws FbException
81 | {
82 | attachment = context.getAttachment(status);
83 | transaction = context.getTransaction(status);
84 |
85 | this.routine = routine;
86 | this.inValues = inValues;
87 | this.outValues = outValues;
88 |
89 | if (routine == null)
90 | contextImpl = null;
91 | else
92 | {
93 | switch (routine.type)
94 | {
95 | case FUNCTION:
96 | contextImpl = new FunctionContextImpl(this);
97 | break;
98 |
99 | case PROCEDURE:
100 | contextImpl = new ProcedureContextImpl(this);
101 | break;
102 |
103 | case TRIGGER:
104 | contextImpl = new TriggerContextImpl(this, triggerAction);
105 | break;
106 | }
107 | }
108 | }
109 |
110 | public IAttachment getAttachment()
111 | {
112 | return attachment;
113 | }
114 |
115 | public ITransaction getTransaction()
116 | {
117 | return transaction;
118 | }
119 |
120 | public Routine getRoutine()
121 | {
122 | return routine;
123 | }
124 |
125 | public ValuesImpl getInValues()
126 | {
127 | return inValues;
128 | }
129 |
130 | public ValuesImpl getOutValues()
131 | {
132 | return outValues;
133 | }
134 |
135 | public Connection getConnection() throws SQLException
136 | {
137 | if (connection == null)
138 | {
139 | final Properties properties = new Properties();
140 | properties.setProperty("encoding", "utf8");
141 |
142 | connection = DriverManager.getConnection("jdbc:default:connection", properties);
143 | }
144 |
145 | return connection;
146 | }
147 |
148 | @Override
149 | public void close() throws Exception
150 | {
151 | if (connection != null)
152 | connection.close();
153 | connection = null;
154 |
155 | transaction.release();
156 | transaction = null;
157 |
158 | attachment.release();
159 | attachment = null;
160 |
161 | routine = null;
162 | contextImpl = null;
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/src/fbjava-tests/src/main/java/example/Procedures.java:
--------------------------------------------------------------------------------
1 | /*
2 | * FB/Java plugin
3 | *
4 | * Distributable under LGPL license.
5 | * You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html
6 | *
7 | * This program is distributed in the hope that it will be useful,
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | * LGPL License for more details.
11 | *
12 | * This file was created by members of the Firebird development team.
13 | * All individual contributions remain the Copyright (C) of those
14 | * individuals. Contributors to this file are either listed here or
15 | * can be obtained from a git log command.
16 | *
17 | * All rights reserved.
18 | */
19 | package example;
20 |
21 | import java.math.BigDecimal;
22 | import java.sql.SQLException;
23 |
24 | import org.firebirdsql.fbjava.CallableRoutineContext;
25 | import org.firebirdsql.fbjava.ExternalResultSet;
26 | import org.firebirdsql.fbjava.ProcedureContext;
27 | import org.firebirdsql.fbjava.Values;
28 | import org.firebirdsql.fbjava.ValuesMetadata;
29 |
30 |
31 | public class Procedures
32 | {
33 | public static void p1()
34 | {
35 | }
36 |
37 | public static void p2(int i)
38 | {
39 | }
40 |
41 | public static void p3(int i, int[] o)
42 | {
43 | o[0] = i;
44 | }
45 |
46 | public static ExternalResultSet p4(int i, int[] o)
47 | {
48 | o[0] = i;
49 |
50 | return new ExternalResultSet() {
51 | @Override
52 | public boolean fetch() throws Exception
53 | {
54 | return ++o[0] <= i + 5;
55 | }
56 | };
57 | }
58 |
59 | public static ExternalResultSet p5(int start, int end, int[] o)
60 | {
61 | o[0] = start - 1;
62 |
63 | return new ExternalResultSet() {
64 | @Override
65 | public boolean fetch() throws Exception
66 | {
67 | return ++o[0] <= end;
68 | }
69 | };
70 | }
71 |
72 | public static ExternalResultSet p6(int start, int end, int[] o)
73 | {
74 | o[0] = start - 1;
75 |
76 | return new ExternalResultSet() {
77 | @Override
78 | public boolean fetch() throws Exception
79 | {
80 | if (o[0] == 10)
81 | throw new Exception("Can't go beyond 10.");
82 |
83 | return ++o[0] <= end;
84 | }
85 | };
86 | }
87 |
88 | public static ExternalResultSet p7(String property, String[] result)
89 | {
90 | return new ExternalResultSet() {
91 | boolean first = true;
92 |
93 | @Override
94 | public boolean fetch() throws Exception
95 | {
96 | if (first)
97 | {
98 | result[0] = System.getProperty(property);
99 | first = false;
100 | return true;
101 | }
102 | else
103 | return false;
104 | }
105 | };
106 | }
107 |
108 | public static void p8(int i1, int i2, String[] o1, int[] o2, int[] o3) throws SQLException
109 | {
110 | CallableRoutineContext context = CallableRoutineContext.get();
111 | o1[0] = context.getInputMetadata().getParameterCount() + ", " + context.getOutputMetadata().getParameterCount();
112 | }
113 |
114 | public static void p9(int i1, Integer i2, String[] o1) throws SQLException
115 | {
116 | CallableRoutineContext context = CallableRoutineContext.get();
117 | ValuesMetadata input = context.getInputMetadata();
118 | ValuesMetadata output = context.getOutputMetadata();
119 |
120 | o1[0] = Functions.getValuesInfo(input, 1) + ", " + Functions.getValuesInfo(input, 2) + ", " +
121 | Functions.getValuesInfo(output, 1);
122 | }
123 |
124 | public static void p10(Object i1, Object i2, String[] o1) throws SQLException
125 | {
126 | CallableRoutineContext context = CallableRoutineContext.get();
127 | ValuesMetadata input = context.getInputMetadata();
128 | ValuesMetadata output = context.getOutputMetadata();
129 |
130 | o1[0] = Functions.getValuesInfo(input, 1) + ", " + Functions.getValuesInfo(input, 2) + ", " +
131 | Functions.getValuesInfo(output, 1);
132 | }
133 |
134 | public static void p11(Object i1, Object i2, String[] o1) throws SQLException
135 | {
136 | ProcedureContext context = ProcedureContext.get();
137 | ValuesMetadata inputMetadata = context.getInputMetadata();
138 | ValuesMetadata outputMetadata = context.getOutputMetadata();
139 | Values input = context.getInputValues();
140 | Values output = context.getOutputValues();
141 |
142 | if (o1[0] != output.getObject(1))
143 | throw new RuntimeException("Error");
144 |
145 | o1[0] = "a";
146 |
147 | if (o1[0] != output.getObject(1))
148 | throw new RuntimeException("Error");
149 |
150 | output.setObject(1, "b");
151 |
152 | if (o1[0] != output.getObject(1))
153 | throw new RuntimeException("Error");
154 |
155 | output.setObject(1,
156 | Functions.getValues(inputMetadata, input) + " / " + Functions.getValues(outputMetadata, output));
157 | }
158 |
159 | public static ExternalResultSet p12()
160 | {
161 | ProcedureContext context = ProcedureContext.get();
162 | Values outValues = context.getOutputValues();
163 |
164 | BigDecimal i = (BigDecimal) context.getInputValues().getObject(1);
165 | outValues.setObject(1, i);
166 |
167 | return new ExternalResultSet() {
168 | @Override
169 | public boolean fetch() throws Exception
170 | {
171 | BigDecimal o = ((BigDecimal) outValues.getObject(1)).add(BigDecimal.ONE);
172 | outValues.setObject(1, o);
173 | return o.subtract(i).intValue() <= 5;
174 | }
175 | };
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/apidocs/org/firebirdsql/fbjava/class-use/TriggerContext.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Uses of Interface org.firebirdsql.fbjava.TriggerContext (fbjava 1.0.0-beta-1 API)
8 |
9 |
10 |
11 |
12 |
22 |
25 |
26 |
43 |
70 |
71 |
74 |
102 |
103 |
120 |
121 |
122 | - Prev
123 | - Next
124 |
125 |
129 |
132 |
133 |
143 |
144 |
145 |
146 |
147 |
148 | Copyright © 2020. All rights reserved.
149 |
150 |
151 |
--------------------------------------------------------------------------------
/apidocs/org/firebirdsql/fbjava/class-use/FunctionContext.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Uses of Interface org.firebirdsql.fbjava.FunctionContext (fbjava 1.0.0-beta-1 API)
8 |
9 |
10 |
11 |
12 |
22 |
25 |
26 |
43 |
70 |
71 |
74 |
102 |
103 |
120 |
121 |
122 | - Prev
123 | - Next
124 |
125 |
129 |
132 |
133 |
143 |
144 |
145 |
146 |
147 |
148 | Copyright © 2020. All rights reserved.
149 |
150 |
151 |
--------------------------------------------------------------------------------
/apidocs/org/firebirdsql/fbjava/class-use/ProcedureContext.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Uses of Interface org.firebirdsql.fbjava.ProcedureContext (fbjava 1.0.0-beta-1 API)
8 |
9 |
10 |
11 |
12 |
22 |
25 |
26 |
43 |
70 |
71 |
74 |
102 |
103 |
120 |
121 |
122 | - Prev
123 | - Next
124 |
125 |
129 |
132 |
133 |
143 |
144 |
145 |
146 |
147 |
148 | Copyright © 2020. All rights reserved.
149 |
150 |
151 |
--------------------------------------------------------------------------------
/src/fbjava-impl/src/main/resources/org/firebirdsql/fbjava/install.sql:
--------------------------------------------------------------------------------
1 | create sequence fb$java$seq!
2 |
3 | create exception fb$java$ex ''!
4 |
5 | create table fb$java$jar (
6 | id bigint not null
7 | constraint fb$java$jar_pk primary key
8 | using asc index fb$java$jar_id,
9 | name varchar(64) character set utf8 not null
10 | constraint fb$java$jar_name_uk unique
11 | using asc index fb$java$jar_name,
12 | owner varchar(31) character set utf8 not null
13 | )!
14 |
15 | create table fb$java$jar_entry (
16 | id bigint not null
17 | constraint fb$java$jar_entry_pk primary key
18 | using asc index fb$java$jar_entry_id,
19 | jar bigint not null
20 | constraint fb$java$jar_entry_jar_fk references fb$java$jar
21 | using asc index fb$java$jar_entry_jar,
22 | name varchar(253) character set utf8 not null
23 | constraint fb$java$jar_entry_name_uk unique
24 | using asc index fb$java$jar_entry_name,
25 | content blob not null
26 | )!
27 |
28 | create view fb$java$user_jar as
29 | select id, name
30 | from fb$java$jar
31 | where owner = current_user!
32 |
33 | create view fb$java$user_jar_entry as
34 | select je.id, je.jar, je.name, je.content
35 | from fb$java$jar_entry je
36 | join fb$java$user_jar uj
37 | on uj.id = je.jar!
38 |
39 | create trigger fb$java$jar_bi
40 | before insert on fb$java$jar
41 | as
42 | begin
43 | if (new.owner <> current_user) then
44 | exception fb$java$ex 'Attempt to store a jar in another user name';
45 | end!
46 |
47 | create trigger fb$java$jar_entry_bi
48 | before insert on fb$java$jar_entry
49 | as
50 | declare user_jar integer;
51 | begin
52 | select 1 from fb$java$user_jar where id = new.jar into user_jar;
53 |
54 | if (user_jar is null) then
55 | exception fb$java$ex 'Attempt to store a jar entry on a jar from another user';
56 | end!
57 |
58 | create package sqlj
59 | as
60 | begin
61 | procedure install_jar (
62 | url varchar(256) character set utf8 not null,
63 | name type of column fb$java$jar.name not null
64 | );
65 |
66 | procedure remove_jar (
67 | name type of column fb$java$jar.name not null
68 | );
69 |
70 | procedure update_jar (
71 | url varchar(256) character set utf8 not null,
72 | name type of column fb$java$jar.name not null
73 | );
74 |
75 | procedure replace_jar (
76 | url varchar(256) character set utf8 not null,
77 | name type of column fb$java$jar.name not null
78 | );
79 |
80 | procedure read_jar (
81 | name type of column fb$java$jar_entry.name not null
82 | ) returns (
83 | content type of column fb$java$jar_entry.content --not null
84 | );
85 |
86 | procedure list_dir (
87 | name type of column fb$java$jar_entry.name not null
88 | ) returns (
89 | child type of column fb$java$jar_entry.name
90 | );
91 | end!
92 |
93 | create package body sqlj
94 | as
95 | begin
96 | procedure verbose_install_jar (
97 | url varchar(256) character set utf8 not null,
98 | name type of column fb$java$jar.name not null
99 | ) returns (
100 | class_name type of column fb$java$jar_entry.name not null
101 | )
102 | external name 'org.firebirdsql.fbjava.Deployer.verboseInstallJar(String, String, String[])' engine java;
103 |
104 | procedure verbose_remove_jar (
105 | name type of column fb$java$jar.name not null
106 | ) returns (
107 | class_name type of column fb$java$jar_entry.name not null
108 | )
109 | as
110 | declare owner type of column fb$java$jar.owner;
111 | begin
112 | select owner from fb$java$jar where name = :name into owner;
113 |
114 | if (owner is null) then
115 | exception fb$java$ex 'Attempt to remove uninstalled JAR';
116 | else if (owner <> current_user and current_user <> 'SYSDBA') then
117 | exception fb$java$ex 'Cannot remove a JAR from another user';
118 |
119 | for select name from fb$java$jar_entry
120 | where jar = (select id from fb$java$jar where name = :name)
121 | into class_name
122 | as cursor c do
123 | begin
124 | delete from fb$java$jar_entry where current of c;
125 | suspend;
126 | end
127 |
128 | delete from fb$java$jar where name = :name;
129 | end
130 |
131 | procedure install_jar (
132 | url varchar(256) character set utf8 not null,
133 | name type of column fb$java$jar.name not null
134 | )
135 | as
136 | declare dummy integer;
137 | begin
138 | for select 1 from verbose_install_jar(:url, :name) into dummy do
139 | begin
140 | end
141 | end
142 |
143 | procedure remove_jar (
144 | name type of column fb$java$jar.name not null
145 | )
146 | as
147 | declare dummy integer;
148 | begin
149 | for select 1 from verbose_remove_jar(:name) into dummy do
150 | begin
151 | end
152 | end
153 |
154 | procedure update_jar (
155 | url varchar(256) character set utf8 not null,
156 | name type of column fb$java$jar.name not null
157 | )
158 | as
159 | begin
160 | execute procedure remove_jar(name);
161 | execute procedure install_jar(url, name);
162 | end
163 |
164 | procedure replace_jar (
165 | url varchar(256) character set utf8 not null,
166 | name type of column fb$java$jar.name not null
167 | )
168 | as
169 | begin
170 | begin
171 | execute procedure remove_jar(name);
172 | when any do
173 | begin
174 | end
175 | end
176 |
177 | execute procedure install_jar(url, name);
178 | end
179 |
180 | procedure read_jar (
181 | name type of column fb$java$jar_entry.name not null
182 | ) returns (
183 | content type of column fb$java$jar_entry.content --not null
184 | )
185 | as
186 | declare owner type of column fb$java$jar.owner;
187 | begin
188 | select je.content, j.owner
189 | from fb$java$jar_entry je
190 | join fb$java$jar j
191 | on j.id = je.jar
192 | where je.name = :name
193 | into content, owner;
194 |
195 | if (owner <> current_user and current_user <> 'SYSDBA') then
196 | exception fb$java$ex 'Cannot read a JAR from another user';
197 |
198 | if (content is not null) then
199 | suspend;
200 | end
201 |
202 | procedure list_dir (
203 | name type of column fb$java$jar_entry.name not null
204 | ) returns (
205 | child type of column fb$java$jar_entry.name
206 | )
207 | as
208 | declare len integer;
209 | begin
210 | len = char_length(name);
211 | if (not len = 0) then
212 | begin
213 | if (substring(name from len for 1) <> '/') then
214 | begin
215 | name = name || '/';
216 | len = len + 1;
217 | end
218 | end
219 |
220 | for select distinct substring(je.name from :len + 1 for
221 | position('/', je.name || '/', :len + 1) - (:len + 1))
222 | from fb$java$jar_entry je
223 | join fb$java$jar j
224 | on j.id = je.jar
225 | where je.name starting with :name and
226 | not (owner <> current_user and current_user <> 'SYSDBA')
227 | into child
228 | do
229 | begin
230 | suspend;
231 | end
232 | end
233 | end!
234 |
235 | grant all on table fb$java$jar to package sqlj!
236 | grant all on table fb$java$jar_entry to package sqlj!
237 |
238 | grant insert on table fb$java$jar to public!
239 | grant insert on table fb$java$jar_entry to public!
240 |
241 | grant select on fb$java$user_jar to public!
242 | grant select on fb$java$user_jar_entry to public!
243 |
244 | grant execute on package sqlj to public!
245 |
--------------------------------------------------------------------------------