MCPcopy Create free account
hub / github.com/ajitpratap0/GoSQLX / Tokenize

Method Tokenize

pkg/sql/tokenizer/tokenizer.go:422–531  ·  view source on GitHub ↗

Tokenize converts raw SQL bytes into a slice of tokens with position information. This is the main entry point for tokenization. It performs zero-copy tokenization directly on the input byte slice and returns tokens with precise start/end positions. Performance: 8M+ tokens/sec sustained throughput

(input []byte)

Source from the content-addressed store, hash-verified

420// tokens, _ := tkz.Tokenize([]byte(sql))
421// // Correctly tokenizes Unicode identifiers and string literals
422func (t *Tokenizer) Tokenize(input []byte) ([]models.TokenWithSpan, error) {
423 // Record start time for metrics
424 startTime := time.Now()
425
426 // Validate input size to prevent DoS attacks
427 if len(input) > MaxInputSize {
428 err := errors.InputTooLargeError(int64(len(input)), MaxInputSize, models.Location{Line: 1, Column: 0})
429 metrics.RecordTokenization(time.Since(startTime), len(input), err)
430 return nil, err
431 }
432
433 // Reset state
434 t.Reset()
435 t.input = input
436
437 // Pre-allocate line starts slice - reuse if possible
438 estimatedLines := len(input)/50 + 1 // Estimate 50 chars per line + 1 for initial 0
439 if cap(t.lineStarts) < estimatedLines {
440 t.lineStarts = make([]int, 0, estimatedLines)
441 } else {
442 t.lineStarts = t.lineStarts[:0]
443 }
444 t.lineStarts = append(t.lineStarts, 0)
445
446 // Pre-scan input to build line start indices
447 for i := 0; i < len(t.input); i++ {
448 if t.input[i] == '\n' {
449 t.lineStarts = append(t.lineStarts, i+1)
450 }
451 }
452
453 // Pre-allocate token slice with better capacity estimation
454 // More accurate estimation based on typical SQL token density
455 estimatedTokens := len(input) / 4
456 if estimatedTokens < 16 {
457 estimatedTokens = 16 // At least 16 tokens
458 }
459 tokens := make([]models.TokenWithSpan, 0, estimatedTokens)
460
461 // Get a buffer from the pool for string operations
462 buf := getBuffer()
463 defer putBuffer(buf)
464
465 var tokenErr error
466 func() {
467 // Ensure proper cleanup even if we panic
468 defer func() {
469 if r := recover(); r != nil {
470 tokenErr = errors.TokenizerPanicError(r, t.getCurrentPosition())
471 }
472 }()
473
474 for t.pos.Index < len(t.input) {
475 t.skipWhitespace()
476
477 if t.pos.Index >= len(t.input) {
478 break
479 }

Callers 15

LintStringMethod · 0.80
makeCtxFunction · 0.80
makeCtxFunction · 0.80
makeContextFunction · 0.80
testSQLFileFunction · 0.80
parseSQLFunction · 0.80

Calls 12

ResetMethod · 0.95
getCurrentPositionMethod · 0.95
skipWhitespaceMethod · 0.95
nextTokenMethod · 0.95
toSQLPositionMethod · 0.95
InputTooLargeErrorFunction · 0.92
RecordTokenizationFunction · 0.92
TokenizerPanicErrorFunction · 0.92
TokenLimitReachedErrorFunction · 0.92
getBufferFunction · 0.85
putBufferFunction · 0.85
StringMethod · 0.45

Tested by 15

makeCtxFunction · 0.64
makeCtxFunction · 0.64
makeContextFunction · 0.64
testSQLFileFunction · 0.64
parseSQLFunction · 0.64