PostgreSQL Source Code: contrib/jsonb_plpython/jsonb_plpython.c Source File (original) (raw)

2

6#include "utils/fmgrprotos.h"

9

11 .name = "jsonb_plpython",

12 .version = PG_VERSION

13);

14

15

16typedef char *(*PLyObject_AsString_t) (PyObject *plrv);

18

21

22

23

24

25

27

31

32typedef PyObject *(*PLyUnicode_FromStringAndSize_t)

33 (const char *s, Py_ssize_t size);

35

36

37

38

39void

41{

42

46 true, NULL);

50 true, NULL);

54 true, NULL);

55}

56

57

58#define PLyObject_AsString (PLyObject_AsString_p)

59#define PLyUnicode_FromStringAndSize (PLyUnicode_FromStringAndSize_p)

60#undef PLy_elog

61#define PLy_elog (PLy_elog_impl_p)

62

63

64

65

66

67

68static PyObject *

70{

72

74}

75

76

77

78

79

80

81static void

83{

86 jbvElem->val.string.len = strlen(jbvElem->val.string.val);

87}

88

89

90

91

92

93

94static PyObject *

96{

97 switch (jsonbValue->type)

98 {

100 Py_RETURN_NONE;

101

104

106 {

108 char *str;

109

112

114 }

115

118

120 if (jsonbValue->val.boolean)

121 Py_RETURN_TRUE;

122 else

123 Py_RETURN_FALSE;

124

125 default:

126 elog(ERROR, "unexpected jsonb value type: %d", jsonbValue->type);

127 return NULL;

128 }

129}

130

131

132

133

134

135

136static PyObject *

138{

142 PyObject *result;

143

146

147 switch (r)

148 {

150 if (v.val.array.rawScalar)

151 {

153

157 elog(ERROR, "unexpected jsonb token: %d", r);

158

160 }

161 else

162 {

163 PyObject *volatile elem = NULL;

164

165 result = PyList_New(0);

166 if (!result)

167 return NULL;

168

170 {

172 {

174 continue;

175

177

178 PyList_Append(result, elem);

179 Py_XDECREF(elem);

180 elem = NULL;

181 }

182 }

184 {

185 Py_XDECREF(elem);

186 Py_XDECREF(result);

188 }

190 }

191 break;

192

194 {

195 PyObject *volatile result_v = PyDict_New();

196 PyObject *volatile key = NULL;

197 PyObject *volatile val = NULL;

198

199 if (!result_v)

200 return NULL;

201

203 {

205 {

207 continue;

208

210 if (key)

211 {

212 Py_XDECREF(result_v);

213 result_v = NULL;

214 break;

215 }

216

218 elog(ERROR, "unexpected jsonb token: %d", r);

219

221 if (val)

222 {

223 Py_XDECREF(key);

224 key = NULL;

225 Py_XDECREF(result_v);

226 result_v = NULL;

227 break;

228 }

229

230 PyDict_SetItem(result_v, key, val);

231

232 Py_XDECREF(key);

233 key = NULL;

234 Py_XDECREF(val);

235 val = NULL;

236 }

237 }

239 {

240 Py_XDECREF(result_v);

241 Py_XDECREF(key);

242 Py_XDECREF(val);

244 }

246

247 result = result_v;

248 }

249 break;

250

251 default:

252 elog(ERROR, "unexpected jsonb token: %d", r);

253 return NULL;

254 }

255

256 return result;

257}

258

259

260

261

262

263

264static void

266{

267 Py_ssize_t pcount;

268 PyObject *volatile items;

269

270 pcount = PyMapping_Size(obj);

271 items = PyMapping_Items(obj);

272

274 {

275 Py_ssize_t i;

276

278

279 for (i = 0; i < pcount; i++)

280 {

282 PyObject *item = PyList_GetItem(items, i);

283 PyObject *key = PyTuple_GetItem(item, 0);

284 PyObject *value = PyTuple_GetItem(item, 1);

285

286

287 if (key == Py_None)

288 {

290 jbvKey.val.string.len = 0;

291 jbvKey.val.string.val = "";

292 }

293 else

294 {

295

297 }

298

301 }

302

304 }

306 {

307 Py_DECREF(items);

308 }

310}

311

312

313

314

315

316

317

318static void

320{

321 Py_ssize_t i;

322 Py_ssize_t pcount;

323 PyObject *volatile value = NULL;

324

325 pcount = PySequence_Size(obj);

326

328

330 {

331 for (i = 0; i < pcount; i++)

332 {

333 value = PySequence_GetItem(obj, i);

335

337 Py_XDECREF(value);

339 }

340 }

342 {

343 Py_XDECREF(value);

345 }

347

349}

350

351

352

353

354

355

358{

361

363 {

365

371 }

373 {

375 (errcode(ERRCODE_DATATYPE_MISMATCH),

376 errmsg("could not convert value \"%s\" to jsonb", str)));

377 }

379

381

382

383

384

385

388 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),

389 errmsg("cannot convert NaN to jsonb")));

392 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),

393 errmsg("cannot convert infinity to jsonb")));

394

396 jbvNum->val.numeric = num;

397

398 return jbvNum;

399}

400

401

402

403

404

405

406static void

408{

410

411 if (!PyUnicode_Check(obj))

412 {

413 if (PySequence_Check(obj))

414 {

416 return;

417 }

418 else if (PyMapping_Check(obj))

419 {

421 return;

422 }

423 }

424

426

427 if (obj == Py_None)

429 else if (PyUnicode_Check(obj))

431

432

433

434

435

436 else if (PyBool_Check(obj))

437 {

439 out->val.boolean = (obj == Py_True);

440 }

441 else if (PyNumber_Check(obj))

443 else

445 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

446 errmsg("Python type \"%s\" cannot be transformed to jsonb",

448

450 {

451

453 }

454 else

455 {

456

457

458

459

460

461 jsonb_state->result = out;

462 }

463}

464

465

466

467

468

469

473{

476

479}

480

481

482

483

484

485

489{

490 PyObject *result;

492

493

494

495

496

497

499 {

500 PyObject *decimal_module = PyImport_ImportModule("cdecimal");

501

502 if (!decimal_module)

503 {

504 PyErr_Clear();

505 decimal_module = PyImport_ImportModule("decimal");

506 }

507 Assert(decimal_module);

509 }

510

512 if (!result)

513 PLy_elog(ERROR, "transformation from jsonb to Python failed");

514

516}

Datum numeric_out(PG_FUNCTION_ARGS)

Datum numeric_in(PG_FUNCTION_ARGS)

bool numeric_is_nan(Numeric num)

bool numeric_is_inf(Numeric num)

#define AssertVariableIsOfType(varname, typename)

void * load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle)

int errcode(int sqlerrcode)

int errmsg(const char *fmt,...)

#define ereport(elevel,...)

#define palloc_object(type)

#define PG_GETARG_POINTER(n)

#define DirectFunctionCall1(func, arg1)

#define DirectFunctionCall3(func, arg1, arg2, arg3)

#define PG_RETURN_POINTER(x)

Assert(PointerIsAligned(start, uint64))

#define PG_GETARG_JSONB_P(x)

static void PLyMapping_ToJsonbValue(PyObject *obj, JsonbInState *jsonb_state)

#define PLyUnicode_FromStringAndSize

static void PLyObject_ToJsonbValue(PyObject *obj, JsonbInState *jsonb_state, bool is_elem)

PG_MODULE_MAGIC_EXT(.name="jsonb_plpython",.version=PG_VERSION)

static PLy_elog_impl_t PLy_elog_impl_p

static JsonbValue * PLyNumber_ToJsonbValue(PyObject *obj, JsonbValue *jbvNum)

PyObject *(* PLyUnicode_FromStringAndSize_t)(const char *s, Py_ssize_t size)

Datum plpython_to_jsonb(PG_FUNCTION_ARGS)

void(* PLy_elog_impl_t)(int elevel, const char *fmt,...)

static PyObject * PLyObject_FromJsonbValue(JsonbValue *jsonbValue)

PG_FUNCTION_INFO_V1(plpython_to_jsonb)

static PLyObject_AsString_t PLyObject_AsString_p

static void PLySequence_ToJsonbValue(PyObject *obj, JsonbInState *jsonb_state)

char *(* PLyObject_AsString_t)(PyObject *plrv)

static PyObject * decimal_constructor

Datum jsonb_to_plpython(PG_FUNCTION_ARGS)

static PLyUnicode_FromStringAndSize_t PLyUnicode_FromStringAndSize_p

static void PLyUnicode_ToJsonbValue(PyObject *obj, JsonbValue *jbvElem)

static PyObject * PLyObject_FromJsonbContainer(JsonbContainer *jsonb)

#define PLyObject_AsString

static PyObject * PLyUnicode_FromJsonbValue(JsonbValue *jbv)

void pushJsonbValue(JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *jbval)

JsonbIterator * JsonbIteratorInit(JsonbContainer *container)

JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)

Jsonb * JsonbValueToJsonb(JsonbValue *val)

void pfree(void *pointer)

static Numeric DatumGetNumeric(Datum X)

static Datum NumericGetDatum(Numeric X)

void PLy_elog_impl(int elevel, const char *fmt,...)

static Datum PointerGetDatum(const void *X)

static Datum ObjectIdGetDatum(Oid X)

static char * DatumGetCString(Datum X)

static Datum CStringGetDatum(const char *X)

static Datum Int32GetDatum(int32 X)

JsonbParseState * parseState